diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..1abc2639
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,190 @@
+name: CI
+
+on:
+ push: # trigger on commits to the `main` branch (no PRs)
+ branches:
+ - main
+ paths-ignore:
+ - '.github/workflows/x-*.yml'
+ workflow_dispatch: # and manually-triggered runs
+
+permissions:
+ # only allowed to read source code (ref. https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs)
+ contents: read
+
+concurrency:
+ # cancel pending runs when a PR gets updated
+ group: "${{ github.head_ref || github.run_id }}-${{ github.actor }}"
+ cancel-in-progress: true
+
+jobs:
+ build:
+ name: "CI - ${{ matrix.name }}"
+
+ strategy:
+ matrix:
+ include:
+ - name: "Ubuntu ARM64"
+ os: ubuntu-24-arm64-gh
+ env:
+ OS: "linux"
+ NUGET_RID: "linux-arm64"
+
+ - name: "Ubuntu x64"
+ os: ubuntu-latest
+ env:
+ OS: "linux"
+ NUGET_RID: "linux-x64"
+
+ - name: "macOS ARM64"
+ os: macos-14
+ env:
+ OS: "apple"
+ NUGET_RID: "osx"
+
+ - name: "Windows x64"
+ os: windows-latest
+ env:
+ OS: "windows"
+ NUGET_RID: "win-x64"
+ NUGET_PACK_DOTNET_LIB: "1"
+
+ #- name: "Windows ARM64"
+ # os: windows-11-arm64-gh
+ # env:
+ # OS: "windows"
+ # NUGET_RID: "win-arm64"
+
+ runs-on: "${{ matrix.os }}"
+
+ defaults:
+ run:
+ shell: "${{ matrix.env.OS == 'windows' && 'pwsh' || 'bash' }}"
+
+ env:
+ DOTNET_NOLOGO: 1
+ DOTNET_CLI_TELEMETRY_OPTOUT: 1
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
+ VCPKG_DISABLE_METRICS: 1
+ NUGET_BASE_VERSION: "0.0"
+ ROYALVNC_BUILD_DEBUG: 0
+ SWIFT_VERSION: "6.0.2"
+
+ steps:
+ #- name: setup tools (win-arm64)
+ # if: "success() && matrix.env.NUGET_RID == 'win-arm64'"
+ # shell: powershell
+ # run: |
+ # # Install choco
+ # Set-ExecutionPolicy Bypass -Scope Process -Force
+ # [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 # Enable TLS1.2
+ # Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
+ # "C:\ProgramData\Chocolatey\bin" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
+ #
+ # # Install pwsh
+ # choco install -y --no-progress powershell-core
+ # "C:\Program Files\PowerShell\7" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
+ #
+ # # Install git
+ # choco install -y --no-progress git
+ # "C:\Program Files\Git\cmd" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
+ #
+ # # Install dotnet
+ # Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://dot.net/v1/dotnet-install.ps1'))
+ # "C:\Program Files\dotnet" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
+
+ - name: checkout
+ uses: actions/checkout@v4
+
+ # setup build environment
+
+ - name: setup environment (Apple)
+ if: "success() && matrix.env.OS == 'apple'"
+ run: |
+ sudo xcode-select --switch /Applications/Xcode_16.0.app
+
+ - name: setup VC++ environment (Windows)
+ if: "success() && matrix.env.OS == 'windows'"
+ uses: compnerd/gha-setup-vsdevenv@v6
+
+ - name: setup Swift (Windows)
+ if: "success() && matrix.env.OS == 'windows'"
+ uses: compnerd/gha-setup-swift@v0.2.3
+ with:
+ branch: "swift-${{ env.SWIFT_VERSION }}-release"
+ tag: "${{ env.SWIFT_VERSION }}-RELEASE"
+
+ # build RoyalVNCKit
+
+ - name: build RoyalVNCKit (Apple)
+ if: "success() && matrix.env.OS == 'apple'"
+ run: |
+ swift package clean --configuration release
+
+ swift build --configuration release --arch arm64
+ swift build --configuration release --arch x86_64
+
+ mkdir -p .build/universal-apple-macosx/release
+
+ lipo -create \
+ .build/arm64-apple-macosx/release/libRoyalVNCKit.dylib \
+ .build/x86_64-apple-macosx/release/libRoyalVNCKit.dylib \
+ -output .build/universal-apple-macosx/release/libRoyalVNCKit.dylib
+
+ - name: build RoyalVNCKit
+ if: "success() && matrix.env.OS != 'apple'"
+ run: |
+ swift package clean --configuration release
+ swift build --configuration release
+
+ # .NET bindings and NuGet package artifacts
+
+ - name: build .NET bindings
+ run: |
+ dotnet build --configuration Release Bindings/dotnet/RoyalApps.RoyalVNCKit.sln
+
+ - name: create native NuGet package
+ if: "success() && matrix.env.NUGET_RID != ''"
+ env:
+ NUGET_VERSION: "${{ env.NUGET_BASE_VERSION }}.${{ github.run_number }}"
+ NUGET_RID: "${{ matrix.env.NUGET_RID }}"
+ NUGET_GIT_COMMIT: "${{ github.sha }}"
+ NUGET_SWIFT_RT_VERSION: "${{ env.SWIFT_VERSION }}"
+ run: |
+ pwsh Bindings/dotnet/nuget-pack-native.ps1
+
+ #- name: test AOT build and interop
+ # if: "success() && matrix.env.NUGET_RID != ''"
+ # env:
+ # NUGET_VERSION: "${{ env.NUGET_BASE_VERSION }}.${{ github.run_number }}"
+ # NUGET_RID: "${{ matrix.env.NUGET_RID }}"
+ # run: |
+ # pwsh Bindings/dotnet/nuget-test-aot.ps1
+
+ - name: create NuGet package
+ if: "success() && matrix.env.NUGET_PACK_DOTNET_LIB == '1'"
+ env:
+ NUGET_VERSION: "${{ env.NUGET_BASE_VERSION }}.${{ github.run_number }}"
+ NUGET_GIT_COMMIT: "${{ github.sha }}"
+ run: |
+ pwsh Bindings/dotnet/nuget-pack-dotnet.ps1
+
+ - name: publish native NuGet packages
+ if: "success() && matrix.env.NUGET_RID != ''"
+ uses: actions/upload-artifact@v4
+ with:
+ name: "RoyalApps.RoyalVNCKit.native.${{ matrix.env.NUGET_RID }}"
+ retention-days: 5
+ if-no-files-found: "error"
+ path: |
+ Bindings/dotnet/RoyalApps.RoyalVNCKit.native/bin/Release/RoyalApps.*.nupkg
+
+ - name: publish NuGet package
+ if: "success() && matrix.env.NUGET_PACK_DOTNET_LIB == '1'"
+ uses: actions/upload-artifact@v4
+ with:
+ name: "RoyalApps.RoyalVNCKit"
+ retention-days: 5
+ if-no-files-found: "error"
+ path: |
+ Bindings/dotnet/RoyalApps.RoyalVNCKit/bin/Release/RoyalApps.RoyalVNCKit.*.nupkg
diff --git a/.github/workflows/x-win-arm64.yml b/.github/workflows/x-win-arm64.yml
new file mode 100644
index 00000000..738f842a
--- /dev/null
+++ b/.github/workflows/x-win-arm64.yml
@@ -0,0 +1,165 @@
+name: Experiment-Windows-ARM64
+on:
+ workflow_dispatch: # manually-triggered runs
+
+permissions:
+ # only allowed to read source code (ref. https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs)
+ contents: read
+
+concurrency:
+ # cancel pending runs when a PR gets updated
+ group: "${{ github.head_ref || github.run_id }}-${{ github.actor }}"
+ cancel-in-progress: true
+
+jobs:
+ build:
+ name: "X-Win - ${{ matrix.name }}"
+
+ strategy:
+ matrix:
+ include:
+ - name: "Windows ARM64"
+ os: windows-11-arm64-gh
+ env:
+ OS: "windows"
+ NUGET_RID: "win-arm64"
+
+ runs-on: "${{ matrix.os }}"
+
+ defaults:
+ run:
+ shell: "${{ matrix.env.OS == 'windows' && 'pwsh' || 'bash' }}"
+
+ env:
+ DOTNET_NOLOGO: 1
+ DOTNET_CLI_TELEMETRY_OPTOUT: 1
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
+ VCPKG_DISABLE_METRICS: 1
+ NUGET_BASE_VERSION: "0.0"
+ ROYALVNC_BUILD_DEBUG: 0
+ SWIFT_VERSION: "6.0.2"
+
+ steps:
+ - name: test
+ shell: cmd
+ run: |
+ set
+ where winget
+ winget --version
+ exit 1
+
+ - name: setup tools (win-arm64)
+ if: "success() && matrix.env.NUGET_RID == 'win-arm64'"
+ shell: powershell
+ run: |
+ # Install choco
+ Set-ExecutionPolicy Bypass -Scope Process -Force
+ [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 # Enable TLS1.2
+ Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
+ "C:\ProgramData\Chocolatey\bin" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
+
+ # Install pwsh
+ choco install -y --no-progress powershell-core
+ "C:\Program Files\PowerShell\7" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
+
+ # Install git
+ choco install -y --no-progress git
+ "C:\Program Files\Git\cmd" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
+
+ # Install dotnet
+ Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://dot.net/v1/dotnet-install.ps1'))
+ "C:\Program Files\dotnet" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
+
+ - name: checkout
+ uses: actions/checkout@v4
+
+ # setup build environment
+
+ - name: setup environment (Apple)
+ if: "success() && matrix.env.OS == 'apple'"
+ run: |
+ sudo xcode-select --switch /Applications/Xcode_16.0.app
+
+ - name: setup VC++ environment (Windows)
+ if: "success() && matrix.env.OS == 'windows'"
+ uses: compnerd/gha-setup-vsdevenv@v6
+
+ - name: setup Swift (Windows)
+ if: "success() && matrix.env.OS == 'windows'"
+ uses: compnerd/gha-setup-swift@v0.2.3
+ with:
+ branch: "swift-${{ env.SWIFT_VERSION }}-release"
+ tag: "${{ env.SWIFT_VERSION }}-RELEASE"
+
+ # build RoyalVNCKit
+
+ - name: build RoyalVNCKit (Apple)
+ if: "success() && matrix.env.OS == 'apple'"
+ run: |
+ swift package clean --configuration release
+ swift build --configuration release --arch arm64
+ swift build --configuration release --arch x86_64
+
+ mkdir -p .build/universal-apple-macosx/release
+ lipo -create \
+ .build/arm64-apple-macosx/release/libRoyalVNCKit.dylib \
+ .build/x86_64-apple-macosx/release/libRoyalVNCKit.dylib \
+ -output .build/universal-apple-macosx/release/libRoyalVNCKit.dylib
+
+ - name: build RoyalVNCKit
+ if: "success() && matrix.env.OS != 'apple'"
+ run: |
+ swift package clean --configuration release
+ swift build --configuration release
+
+ # .NET bindings and NuGet package artifacts
+
+ - name: build .NET bindings
+ run: |
+ dotnet build --configuration Release Bindings/dotnet/RoyalApps.RoyalVNCKit.sln
+
+ - name: create native NuGet package
+ if: "success() && matrix.env.NUGET_RID != ''"
+ env:
+ NUGET_VERSION: "${{ env.NUGET_BASE_VERSION }}.${{ github.run_number }}"
+ NUGET_RID: "${{ matrix.env.NUGET_RID }}"
+ NUGET_GIT_COMMIT: "${{ github.sha }}"
+ NUGET_SWIFT_RT_VERSION: "${{ env.SWIFT_VERSION }}"
+ run: |
+ pwsh Bindings/dotnet/nuget-pack-native.ps1
+
+ #- name: test AOT build and interop
+ # if: "success() && matrix.env.NUGET_RID != ''"
+ # env:
+ # NUGET_VERSION: "${{ env.NUGET_BASE_VERSION }}.${{ github.run_number }}"
+ # NUGET_RID: "${{ matrix.env.NUGET_RID }}"
+ # run: |
+ # pwsh Bindings/dotnet/nuget-test-aot.ps1
+
+ - name: create NuGet package
+ if: "success() && matrix.env.NUGET_PACK_DOTNET_LIB == '1'"
+ env:
+ NUGET_VERSION: "${{ env.NUGET_BASE_VERSION }}.${{ github.run_number }}"
+ NUGET_GIT_COMMIT: "${{ github.sha }}"
+ run: |
+ pwsh Bindings/dotnet/nuget-pack-dotnet.ps1
+
+ - name: publish native NuGet packages
+ if: "success() && matrix.env.NUGET_RID != ''"
+ uses: actions/upload-artifact@v4
+ with:
+ name: "RoyalApps.RoyalVNCKit.native.${{ matrix.env.NUGET_RID }}"
+ retention-days: 5
+ if-no-files-found: "error"
+ path: |
+ Bindings/dotnet/RoyalApps.RoyalVNCKit.native/bin/Release/RoyalApps.*.nupkg
+
+ - name: publish NuGet package
+ if: "success() && matrix.env.NUGET_PACK_DOTNET_LIB == '1'"
+ uses: actions/upload-artifact@v4
+ with:
+ name: "RoyalApps.RoyalVNCKit"
+ retention-days: 5
+ if-no-files-found: "error"
+ path: |
+ Bindings/dotnet/RoyalApps.RoyalVNCKit/bin/Release/RoyalApps.RoyalVNCKit.*.nupkg
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/RoyalVNCKitCDemo.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/RoyalVNCKitCDemo.xcscheme
new file mode 100644
index 00000000..a6abc5ca
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/RoyalVNCKitCDemo.xcscheme
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/RoyalVNCKitDemo.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/RoyalVNCKitDemo.xcscheme
new file mode 100644
index 00000000..2c42de2a
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/RoyalVNCKitDemo.xcscheme
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 00000000..e58b4b5c
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,41 @@
+{
+ "configurations": [
+ {
+ "type": "lldb",
+ "request": "launch",
+ "args": [],
+ "cwd": "${workspaceFolder:royalvnc}",
+ "name": "Debug RoyalVNCKitDemo",
+ "program": "${workspaceFolder:royalvnc}/.build/debug/RoyalVNCKitDemo",
+ "preLaunchTask": "swift: Build Debug RoyalVNCKitDemo"
+ },
+ {
+ "type": "lldb",
+ "request": "launch",
+ "args": [],
+ "cwd": "${workspaceFolder:royalvnc}",
+ "name": "Release RoyalVNCKitDemo",
+ "program": "${workspaceFolder:royalvnc}/.build/release/RoyalVNCKitDemo",
+ "preLaunchTask": "swift: Build Release RoyalVNCKitDemo"
+ },
+
+ {
+ "type": "lldb",
+ "request": "launch",
+ "args": [],
+ "cwd": "${workspaceFolder:royalvnc}",
+ "name": "Debug RoyalVNCKitCDemo",
+ "program": "${workspaceFolder:royalvnc}/.build/debug/RoyalVNCKitCDemo",
+ "preLaunchTask": "swift: Build Debug RoyalVNCKitCDemo"
+ },
+ {
+ "type": "lldb",
+ "request": "launch",
+ "args": [],
+ "cwd": "${workspaceFolder:royalvnc}",
+ "name": "Release RoyalVNCKitCDemo",
+ "program": "${workspaceFolder:royalvnc}/.build/release/RoyalVNCKitCDemo",
+ "preLaunchTask": "swift: Build Release RoyalVNCKitCDemo"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Bindings/dotnet/.gitignore b/Bindings/dotnet/.gitignore
new file mode 100644
index 00000000..a255f993
--- /dev/null
+++ b/Bindings/dotnet/.gitignore
@@ -0,0 +1,399 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.idea/
diff --git a/Bindings/dotnet/Directory.Build.rsp b/Bindings/dotnet/Directory.Build.rsp
new file mode 100644
index 00000000..19ee11fa
--- /dev/null
+++ b/Bindings/dotnet/Directory.Build.rsp
@@ -0,0 +1 @@
+-graph
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit.Demo/Program.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit.Demo/Program.cs
new file mode 100644
index 00000000..b1a88640
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit.Demo/Program.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Text;
+using System.Threading;
+using static System.Console;
+
+namespace RoyalApps.RoyalVNCKit.Demo;
+
+static class Program
+{
+ static int Main(string[] args)
+ {
+ string hostname = args.Length > 0
+ ? args[0]
+ : PromptAndReadInput("Enter hostname: ");
+
+ if (string.IsNullOrWhiteSpace(hostname))
+ {
+ Error.WriteLine("No hostname given -- exiting");
+ return 1;
+ }
+
+ var settings = new DemoSettings
+ {
+ Hostname = hostname,
+ Port = 5900,
+ IsDebugLoggingEnabled = true,
+ IsShared = true,
+ IsScalingEnabled = false,
+ UseDisplayLink = false,
+ InputMode = InputMode.None,
+ IsClipboardRedirectionEnabled = false,
+ ColorDepth = ColorDepth.Bits24,
+ };
+
+ using var vncSettings = new VncSettings(settings);
+ using var connection = new VncConnection(vncSettings);
+
+ using var connectionDelegate = new VncConnectionDelegate();
+ connectionDelegate.AuthenticationRequested = OnAuthenticationRequested;
+ connectionDelegate.ConnectionStateChanged = OnConnectionStateChanged;
+ connectionDelegate.FramebufferCreated = OnFramebufferCreated;
+ connectionDelegate.FramebufferResized = OnFramebufferResized;
+ connectionDelegate.FramebufferUpdated = OnFramebufferUpdated;
+
+ connection.Delegate = connectionDelegate;
+ connection.Connect();
+
+ while (true)
+ {
+ var status = connection.Status;
+ if (status is ConnectionStatus.Disconnected)
+ break;
+
+ Thread.Sleep(millisecondsTimeout: 500);
+ }
+
+ return 0;
+ }
+
+ static bool OnAuthenticationRequested(VncConnection connection, AuthenticationRequest request)
+ {
+ string type = request.AuthenticationType switch
+ {
+ AuthenticationType.Vnc => "VNC",
+ AuthenticationType.AppleRemoteDesktop => "Apple Remote Desktop",
+ AuthenticationType.UltraVncMSLogonII => "UltraVNC MS Logon II",
+ _ => $"Unknown({request.AuthenticationType:D})"
+ };
+
+ WriteLine($"authenticationRequested: {type}");
+
+ if (request.RequiresUsername)
+ request.Username = PromptAndReadInput("Enter username: ");
+
+ if (request.RequiresPassword)
+ request.Password = PromptAndReadPassword("Enter password: ");
+
+ return true;
+ }
+
+ static void OnConnectionStateChanged(VncConnection connection, VncConnectionState state) =>
+ WriteLine(state.DisplayErrorToUser
+ ? $"connectionStateChanged: {state.Status} ({(state.IsAuthenticationError ? "authentication" : "")} error: {state.ErrorDescription})"
+ : $"connectionStateChanged: {state.Status}");
+
+ static void OnFramebufferCreated(VncConnection connection, VncFramebuffer framebuffer) =>
+ WriteLine($"framebufferCreated: {framebuffer.Width:N0}x{framebuffer.Height:N0} ({framebuffer.PixelData.Length:N0} bytes)");
+
+ static void OnFramebufferResized(VncConnection connection, VncFramebuffer framebuffer) =>
+ WriteLine($"framebufferResized: {framebuffer.Width:N0}x{framebuffer.Height:N0} ({framebuffer.PixelData.Length:N0} bytes)");
+
+ static void OnFramebufferUpdated(VncConnection connection, VncFramebuffer _, VncFramebufferRegion region) =>
+ WriteLine($"framebufferUpdated: {region.Width:N0}x{region.Height:N0} at {region.X:N0}, {region.Y:N0}");
+
+ static string PromptAndReadInput(string prompt)
+ {
+ Write(prompt);
+ return ReadLine()!;
+ }
+
+ static string PromptAndReadPassword(string prompt)
+ {
+ Write(prompt);
+ var sb = new StringBuilder();
+ while (true)
+ {
+ var info = ReadKey(true);
+ if (info.Key is ConsoleKey.Enter)
+ {
+ WriteLine();
+ break;
+ }
+
+ if (info.Key is ConsoleKey.Backspace)
+ {
+ if (sb.Length > 0)
+ {
+ Write("\b\0\b");
+ sb.Length--;
+ }
+ continue;
+ }
+
+ Write("*");
+ sb.Append(info.KeyChar);
+ }
+ return sb.ToString();
+ }
+
+ readonly struct DemoSettings : IVncSettings
+ {
+ public string Hostname { get; init; }
+ public ushort Port { get; init; }
+ public InputMode InputMode { get; init; }
+ public ColorDepth ColorDepth { get; init; }
+ public bool IsClipboardRedirectionEnabled { get; init; }
+ public bool IsDebugLoggingEnabled { get; init; }
+ public bool IsScalingEnabled { get; init; }
+ public bool IsShared { get; init; }
+ public bool UseDisplayLink { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit.Demo/RoyalApps.RoyalVNCKit.Demo.csproj b/Bindings/dotnet/RoyalApps.RoyalVNCKit.Demo/RoyalApps.RoyalVNCKit.Demo.csproj
new file mode 100644
index 00000000..cf9d0a7f
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit.Demo/RoyalApps.RoyalVNCKit.Demo.csproj
@@ -0,0 +1,46 @@
+
+
+
+ Exe
+ net8.0
+ Major
+ enable
+ true
+ true
+ true
+ false
+ true
+
+
+
+ <_NativeArch Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'ARM64'">aarch64
+ <_NativeArch Condition="'$(_NativeArch)' == ''">x86_64
+
+ <_NativeCfg Condition="'$(Configuration)' == 'Release'">release
+ <_NativeCfg Condition="'$(_NativeCfg)' == ''">debug
+
+ <_SwiftBuildDir>$([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)..\..\..\.build'))
+
+
+
+ <_NativeLibrary>$(_SwiftBuildDir)$(_NativeArch)-unknown-linux-gnu\$(_NativeCfg)\libRoyalVNCKit.so
+
+
+ <_NativeLibrary>$(_SwiftBuildDir)universal-apple-macosx\$(_NativeCfg)\libRoyalVNCKit.dylib
+
+
+ <_NativeLibrary>$(_SwiftBuildDir)$(_NativeArch)-unknown-windows-msvc\$(_NativeCfg)\RoyalVNCKit.dll
+
+
+
+
+ PreserveNewest
+ PreserveNewest
+ %(Filename)%(Extension)
+
+
+
+
+
+
+
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/README.md b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/README.md
new file mode 100644
index 00000000..1fb3e6e9
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/README.md
@@ -0,0 +1,4 @@
+Internal implementation package not meant for direct consumption. Do not reference directly.
+
+See [`RoyalApps.RoyalVNCKit` package on NuGet](https://www.nuget.org/packages/RoyalApps.RoyalVNCKit)
+or the Git source repository for details.
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/native.nuspec b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/native.nuspec
new file mode 100644
index 00000000..94824ffe
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/native.nuspec
@@ -0,0 +1,21 @@
+
+
+
+ RoyalApps.RoyalVNCKit.native.$NUGET_RID$
+ $NUGET_VERSION$
+ RoyalApps
+ MIT
+ https://licenses.nuget.org/MIT
+ RoyalApps_1024.png
+ README.md
+ https://github.com/royalapplications/royalvnc
+ Internal implementation package not meant for direct consumption. Do not reference directly.
+ RoyalApps RoyalVNCKit VNC native
+
+
+
+
+
+
+
+
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/native.pkgproj b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/native.pkgproj
new file mode 100644
index 00000000..a7252cc3
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/native.pkgproj
@@ -0,0 +1,5 @@
+
+
+ net8.0
+
+
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/windows.SwiftRuntime.nuspec b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/windows.SwiftRuntime.nuspec
new file mode 100644
index 00000000..053f5447
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/windows.SwiftRuntime.nuspec
@@ -0,0 +1,29 @@
+
+
+
+ RoyalApps.native.SwiftRuntime.$NUGET_RID$
+ $NUGET_SWIFT_RT_VERSION$
+ RoyalApps
+ MIT
+ https://licenses.nuget.org/MIT
+ RoyalApps_1024.png
+ README.md
+ https://github.com/royalapplications/royalvnc
+ Internal implementation package not meant for direct consumption. Do not reference directly.
+ RoyalApps RoyalVNCKit VNC native SwiftRuntime
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/windows.nuspec b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/windows.nuspec
new file mode 100644
index 00000000..ec33566b
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit.native/windows.nuspec
@@ -0,0 +1,26 @@
+
+
+
+ RoyalApps.RoyalVNCKit.native.$NUGET_RID$
+ $NUGET_VERSION$
+ RoyalApps
+ MIT
+ https://licenses.nuget.org/MIT
+ RoyalApps_1024.png
+ README.md
+ https://github.com/royalapplications/royalvnc
+ Internal implementation package not meant for direct consumption. Do not reference directly.
+ RoyalApps RoyalVNCKit VNC native
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit.sln b/Bindings/dotnet/RoyalApps.RoyalVNCKit.sln
new file mode 100644
index 00000000..88badd71
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit.sln
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoyalApps.RoyalVNCKit", "RoyalApps.RoyalVNCKit\RoyalApps.RoyalVNCKit.csproj", "{912C63E2-40E1-4F2B-96EE-B7AEFB242F52}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoyalApps.RoyalVNCKit.Demo", "RoyalApps.RoyalVNCKit.Demo\RoyalApps.RoyalVNCKit.Demo.csproj", "{AF2ABA10-FE25-4011-A3CE-99987445778D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution", "Solution", "{213EC7C9-62EC-4390-8845-C965A18AAD86}"
+ ProjectSection(SolutionItems) = preProject
+ Directory.Build.rsp = Directory.Build.rsp
+ nuget-pack-dotnet.ps1 = nuget-pack-dotnet.ps1
+ nuget-pack-native.ps1 = nuget-pack-native.ps1
+ nuget-test-aot.ps1 = nuget-test-aot.ps1
+ nuget-utils.ps1 = nuget-utils.ps1
+ RoyalApps_1024.png = RoyalApps_1024.png
+ RoyalApps.RoyalVNCKit.native\native.nuspec = RoyalApps.RoyalVNCKit.native\native.nuspec
+ RoyalApps.RoyalVNCKit.native\windows.nuspec = RoyalApps.RoyalVNCKit.native\windows.nuspec
+ RoyalApps.RoyalVNCKit.native\windows.SwiftRuntime.nuspec = RoyalApps.RoyalVNCKit.native\windows.SwiftRuntime.nuspec
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {912C63E2-40E1-4F2B-96EE-B7AEFB242F52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {912C63E2-40E1-4F2B-96EE-B7AEFB242F52}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {912C63E2-40E1-4F2B-96EE-B7AEFB242F52}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {912C63E2-40E1-4F2B-96EE-B7AEFB242F52}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AF2ABA10-FE25-4011-A3CE-99987445778D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AF2ABA10-FE25-4011-A3CE-99987445778D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AF2ABA10-FE25-4011-A3CE-99987445778D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AF2ABA10-FE25-4011-A3CE-99987445778D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit.sln.DotSettings b/Bindings/dotnet/RoyalApps.RoyalVNCKit.sln.DotSettings
new file mode 100644
index 00000000..be3b36c6
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit.sln.DotSettings
@@ -0,0 +1,7 @@
+
+ II
+ MS
+ VNC
+ True
+ True
+ True
\ No newline at end of file
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/AuthenticationRequest.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/AuthenticationRequest.cs
new file mode 100644
index 00000000..16da6554
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/AuthenticationRequest.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Diagnostics;
+
+namespace RoyalApps.RoyalVNCKit;
+
+public sealed class AuthenticationRequest
+{
+ public AuthenticationType AuthenticationType { get; }
+ public bool RequiresUsername { get; }
+ public bool RequiresPassword { get; }
+ public string? Username { get; set; }
+ public string? Password { get; set; }
+
+ internal AuthenticationRequest(
+ AuthenticationType authenticationType,
+ bool requiresUsername,
+ bool requiresPassword
+ )
+ {
+ Debug.Assert(Enum.IsDefined(authenticationType));
+ AuthenticationType = authenticationType;
+ RequiresUsername = requiresUsername;
+ RequiresPassword = requiresPassword;
+ }
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/AuthenticationType.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/AuthenticationType.cs
new file mode 100644
index 00000000..b43288ef
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/AuthenticationType.cs
@@ -0,0 +1,9 @@
+namespace RoyalApps.RoyalVNCKit;
+
+// keep in sync with Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
+public enum AuthenticationType
+{
+ Vnc = 0,
+ AppleRemoteDesktop = 1,
+ UltraVncMSLogonII = 2,
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/ColorDepth.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/ColorDepth.cs
new file mode 100644
index 00000000..ff751fdc
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/ColorDepth.cs
@@ -0,0 +1,9 @@
+namespace RoyalApps.RoyalVNCKit;
+
+// keep in sync with Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
+public enum ColorDepth
+{
+ Bits8 = 8,
+ Bits16 = 16,
+ Bits24 = 24,
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/ConnectionStatus.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/ConnectionStatus.cs
new file mode 100644
index 00000000..9757cc98
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/ConnectionStatus.cs
@@ -0,0 +1,10 @@
+namespace RoyalApps.RoyalVNCKit;
+
+// keep in sync with Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
+public enum ConnectionStatus
+{
+ Disconnected = 0,
+ Connecting = 1,
+ Connected = 2,
+ Disconnecting = 3,
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/InputMode.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/InputMode.cs
new file mode 100644
index 00000000..44f995fe
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/InputMode.cs
@@ -0,0 +1,10 @@
+namespace RoyalApps.RoyalVNCKit;
+
+// keep in sync with Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
+public enum InputMode
+{
+ None = 0,
+ ForwardKeyboardShortcutsIfNotInUseLocally = 1,
+ ForwardKeyboardShortcutsEvenIfInUseLocally = 2,
+ ForwardAllKeyboardShortcutsAndHotkeys = 3,
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/KeySymbol.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/KeySymbol.cs
new file mode 100644
index 00000000..ac9a296e
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/KeySymbol.cs
@@ -0,0 +1,2359 @@
+namespace RoyalApps.RoyalVNCKit;
+
+// keep in sync with Sources/RoyalVNCKit/Input/X11KeySymbols.swift
+public enum KeySymbol : uint
+{
+ // ReSharper disable InconsistentNaming
+ XK_VoidSymbol = 0xffffff, /* Void symbol */
+
+ // MARK: - XK_MISCELLANY
+ /*
+ * TTY function keys, cleverly chosen to map to ASCII, for convenience of
+ * programming, but could have been arbitrary (at the cost of lookup
+ * tables in client code).
+ */
+
+ XK_BackSpace = 0xff08, /* Back space, back char */
+ XK_Tab = 0xff09,
+ XK_Linefeed = 0xff0a, /* Linefeed, LF */
+ XK_Clear = 0xff0b,
+ XK_Return = 0xff0d, /* Return, enter */
+ XK_Pause = 0xff13, /* Pause, hold */
+ XK_Scroll_Lock = 0xff14,
+ XK_Sys_Req = 0xff15,
+ XK_Escape = 0xff1b,
+ XK_Delete = 0xffff, /* Delete, rubout */
+
+ /* International & multi-key character composition */
+
+ XK_Multi_key = 0xff20, /* Multi-key character compose */
+ XK_Codeinput = 0xff37,
+ XK_SingleCandidate = 0xff3c,
+ XK_MultipleCandidate = 0xff3d,
+ XK_PreviousCandidate = 0xff3e,
+
+ /* Japanese keyboard support */
+
+ XK_Kanji = 0xff21, /* Kanji, Kanji convert */
+ XK_Muhenkan = 0xff22, /* Cancel Conversion */
+ XK_Henkan_Mode = 0xff23, /* Start/Stop Conversion */
+ XK_Henkan = 0xff23, /* Alias for Henkan_Mode */
+ XK_Romaji = 0xff24, /* to Romaji */
+ XK_Hiragana = 0xff25, /* to Hiragana */
+ XK_Katakana = 0xff26, /* to Katakana */
+ XK_Hiragana_Katakana = 0xff27, /* Hiragana/Katakana toggle */
+ XK_Zenkaku = 0xff28, /* to Zenkaku */
+ XK_Hankaku = 0xff29, /* to Hankaku */
+ XK_Zenkaku_Hankaku = 0xff2a, /* Zenkaku/Hankaku toggle */
+ XK_Touroku = 0xff2b, /* Add to Dictionary */
+ XK_Massyo = 0xff2c, /* Delete from Dictionary */
+ XK_Kana_Lock = 0xff2d, /* Kana Lock */
+ XK_Kana_Shift = 0xff2e, /* Kana Shift */
+ XK_Eisu_Shift = 0xff2f, /* Alphanumeric Shift */
+ XK_Eisu_toggle = 0xff30, /* Alphanumeric toggle */
+ XK_Kanji_Bangou = 0xff37, /* Codeinput */
+ XK_Zen_Koho = 0xff3d, /* Multiple/All Candidate(s) */
+ XK_Mae_Koho = 0xff3e, /* Previous Candidate */
+
+ /* = 0xff31 thru = 0xff3f are under XK_KOREAN */
+
+ /* Cursor control & motion */
+
+ XK_Home = 0xff50,
+ XK_Left = 0xff51, /* Move left, left arrow */
+ XK_Up = 0xff52, /* Move up, up arrow */
+ XK_Right = 0xff53, /* Move right, right arrow */
+ XK_Down = 0xff54, /* Move down, down arrow */
+ XK_Prior = 0xff55, /* Prior, previous */
+ XK_Page_Up = 0xff55,
+ XK_Next = 0xff56, /* Next */
+ XK_Page_Down = 0xff56,
+ XK_End = 0xff57, /* EOL */
+ XK_Begin = 0xff58, /* BOL */
+
+ /* Misc functions */
+
+ XK_Select = 0xff60, /* Select, mark */
+ XK_Print = 0xff61,
+ XK_Execute = 0xff62, /* Execute, run, do */
+ XK_Insert = 0xff63, /* Insert, insert here */
+ XK_Undo = 0xff65,
+ XK_Redo = 0xff66, /* Redo, again */
+ XK_Menu = 0xff67,
+ XK_Find = 0xff68, /* Find, search */
+ XK_Cancel = 0xff69, /* Cancel, stop, abort, exit */
+ XK_Help = 0xff6a, /* Help */
+ XK_Break = 0xff6b,
+ XK_Mode_switch = 0xff7e, /* Character set switch */
+ XK_script_switch = 0xff7e, /* Alias for mode_switch */
+ XK_Num_Lock = 0xff7f,
+
+ /* Keypad functions, keypad numbers cleverly chosen to map to ASCII */
+
+ XK_KP_Space = 0xff80, /* Space */
+ XK_KP_Tab = 0xff89,
+ XK_KP_Enter = 0xff8d, /* Enter */
+ XK_KP_F1 = 0xff91, /* PF1, KP_A, ... */
+ XK_KP_F2 = 0xff92,
+ XK_KP_F3 = 0xff93,
+ XK_KP_F4 = 0xff94,
+ XK_KP_Home = 0xff95,
+ XK_KP_Left = 0xff96,
+ XK_KP_Up = 0xff97,
+ XK_KP_Right = 0xff98,
+ XK_KP_Down = 0xff99,
+ XK_KP_Prior = 0xff9a,
+ XK_KP_Page_Up = 0xff9a,
+ XK_KP_Next = 0xff9b,
+ XK_KP_Page_Down = 0xff9b,
+ XK_KP_End = 0xff9c,
+ XK_KP_Begin = 0xff9d,
+ XK_KP_Insert = 0xff9e,
+ XK_KP_Delete = 0xff9f,
+ XK_KP_Equal = 0xffbd, /* Equals */
+ XK_KP_Multiply = 0xffaa,
+ XK_KP_Add = 0xffab,
+ XK_KP_Separator = 0xffac, /* Separator, often comma */
+ XK_KP_Subtract = 0xffad,
+ XK_KP_Decimal = 0xffae,
+ XK_KP_Divide = 0xffaf,
+
+ XK_KP_0 = 0xffb0,
+ XK_KP_1 = 0xffb1,
+ XK_KP_2 = 0xffb2,
+ XK_KP_3 = 0xffb3,
+ XK_KP_4 = 0xffb4,
+ XK_KP_5 = 0xffb5,
+ XK_KP_6 = 0xffb6,
+ XK_KP_7 = 0xffb7,
+ XK_KP_8 = 0xffb8,
+ XK_KP_9 = 0xffb9,
+
+ /*
+ * Auxiliary functions; note the duplicate definitions for left and right
+ * function keys; Sun keyboards and a few other manufacturers have such
+ * function key groups on the left and/or right sides of the keyboard.
+ * We've not found a keyboard with more than 35 function keys total.
+ */
+
+ XK_F1 = 0xffbe,
+ XK_F2 = 0xffbf,
+ XK_F3 = 0xffc0,
+ XK_F4 = 0xffc1,
+ XK_F5 = 0xffc2,
+ XK_F6 = 0xffc3,
+ XK_F7 = 0xffc4,
+ XK_F8 = 0xffc5,
+ XK_F9 = 0xffc6,
+ XK_F10 = 0xffc7,
+ XK_F11 = 0xffc8,
+ XK_L1 = 0xffc8,
+ XK_F12 = 0xffc9,
+ XK_L2 = 0xffc9,
+ XK_F13 = 0xffca,
+ XK_L3 = 0xffca,
+ XK_F14 = 0xffcb,
+ XK_L4 = 0xffcb,
+ XK_F15 = 0xffcc,
+ XK_L5 = 0xffcc,
+ XK_F16 = 0xffcd,
+ XK_L6 = 0xffcd,
+ XK_F17 = 0xffce,
+ XK_L7 = 0xffce,
+ XK_F18 = 0xffcf,
+ XK_L8 = 0xffcf,
+ XK_F19 = 0xffd0,
+ XK_L9 = 0xffd0,
+ XK_F20 = 0xffd1,
+ XK_L10 = 0xffd1,
+ XK_F21 = 0xffd2,
+ XK_R1 = 0xffd2,
+ XK_F22 = 0xffd3,
+ XK_R2 = 0xffd3,
+ XK_F23 = 0xffd4,
+ XK_R3 = 0xffd4,
+ XK_F24 = 0xffd5,
+ XK_R4 = 0xffd5,
+ XK_F25 = 0xffd6,
+ XK_R5 = 0xffd6,
+ XK_F26 = 0xffd7,
+ XK_R6 = 0xffd7,
+ XK_F27 = 0xffd8,
+ XK_R7 = 0xffd8,
+ XK_F28 = 0xffd9,
+ XK_R8 = 0xffd9,
+ XK_F29 = 0xffda,
+ XK_R9 = 0xffda,
+ XK_F30 = 0xffdb,
+ XK_R10 = 0xffdb,
+ XK_F31 = 0xffdc,
+ XK_R11 = 0xffdc,
+ XK_F32 = 0xffdd,
+ XK_R12 = 0xffdd,
+ XK_F33 = 0xffde,
+ XK_R13 = 0xffde,
+ XK_F34 = 0xffdf,
+ XK_R14 = 0xffdf,
+ XK_F35 = 0xffe0,
+ XK_R15 = 0xffe0,
+
+ /* Modifiers */
+
+ XK_Shift_L = 0xffe1, /* Left shift */
+ XK_Shift_R = 0xffe2, /* Right shift */
+ XK_Control_L = 0xffe3, /* Left control */
+ XK_Control_R = 0xffe4, /* Right control */
+ XK_Caps_Lock = 0xffe5, /* Caps lock */
+ XK_Shift_Lock = 0xffe6, /* Shift lock */
+
+ XK_Meta_L = 0xffe7, /* Left meta */
+ XK_Meta_R = 0xffe8, /* Right meta */
+ XK_Alt_L = 0xffe9, /* Left alt */
+ XK_Alt_R = 0xffea, /* Right alt */
+ XK_Super_L = 0xffeb, /* Left super */
+ XK_Super_R = 0xffec, /* Right super */
+ XK_Hyper_L = 0xffed, /* Left hyper */
+ XK_Hyper_R = 0xffee, /* Right hyper */
+
+ /*
+ * Keyboard (XKB) Extension function and modifier keys
+ * (from Appendix C of "The X Keyboard Extension: Protocol Specification")
+ * Byte 3 = = 0xfe
+ */
+
+ // MARK: - XK_XKB_KEYS
+ XK_ISO_Lock = 0xfe01,
+ XK_ISO_Level2_Latch = 0xfe02,
+ XK_ISO_Level3_Shift = 0xfe03,
+ XK_ISO_Level3_Latch = 0xfe04,
+ XK_ISO_Level3_Lock = 0xfe05,
+ XK_ISO_Level5_Shift = 0xfe11,
+ XK_ISO_Level5_Latch = 0xfe12,
+ XK_ISO_Level5_Lock = 0xfe13,
+ XK_ISO_Group_Shift = 0xff7e, /* Alias for mode_switch */
+ XK_ISO_Group_Latch = 0xfe06,
+ XK_ISO_Group_Lock = 0xfe07,
+ XK_ISO_Next_Group = 0xfe08,
+ XK_ISO_Next_Group_Lock = 0xfe09,
+ XK_ISO_Prev_Group = 0xfe0a,
+ XK_ISO_Prev_Group_Lock = 0xfe0b,
+ XK_ISO_First_Group = 0xfe0c,
+ XK_ISO_First_Group_Lock = 0xfe0d,
+ XK_ISO_Last_Group = 0xfe0e,
+ XK_ISO_Last_Group_Lock = 0xfe0f,
+
+ XK_ISO_Left_Tab = 0xfe20,
+ XK_ISO_Move_Line_Up = 0xfe21,
+ XK_ISO_Move_Line_Down = 0xfe22,
+ XK_ISO_Partial_Line_Up = 0xfe23,
+ XK_ISO_Partial_Line_Down = 0xfe24,
+ XK_ISO_Partial_Space_Left = 0xfe25,
+ XK_ISO_Partial_Space_Right = 0xfe26,
+ XK_ISO_Set_Margin_Left = 0xfe27,
+ XK_ISO_Set_Margin_Right = 0xfe28,
+ XK_ISO_Release_Margin_Left = 0xfe29,
+ XK_ISO_Release_Margin_Right = 0xfe2a,
+ XK_ISO_Release_Both_Margins = 0xfe2b,
+ XK_ISO_Fast_Cursor_Left = 0xfe2c,
+ XK_ISO_Fast_Cursor_Right = 0xfe2d,
+ XK_ISO_Fast_Cursor_Up = 0xfe2e,
+ XK_ISO_Fast_Cursor_Down = 0xfe2f,
+ XK_ISO_Continuous_Underline = 0xfe30,
+ XK_ISO_Discontinuous_Underline = 0xfe31,
+ XK_ISO_Emphasize = 0xfe32,
+ XK_ISO_Center_Object = 0xfe33,
+ XK_ISO_Enter = 0xfe34,
+
+ XK_dead_grave = 0xfe50,
+ XK_dead_acute = 0xfe51,
+ XK_dead_circumflex = 0xfe52,
+ XK_dead_tilde = 0xfe53,
+ XK_dead_perispomeni = 0xfe53, /* alias for dead_tilde */
+ XK_dead_macron = 0xfe54,
+ XK_dead_breve = 0xfe55,
+ XK_dead_abovedot = 0xfe56,
+ XK_dead_diaeresis = 0xfe57,
+ XK_dead_abovering = 0xfe58,
+ XK_dead_doubleacute = 0xfe59,
+ XK_dead_caron = 0xfe5a,
+ XK_dead_cedilla = 0xfe5b,
+ XK_dead_ogonek = 0xfe5c,
+ XK_dead_iota = 0xfe5d,
+ XK_dead_voiced_sound = 0xfe5e,
+ XK_dead_semivoiced_sound = 0xfe5f,
+ XK_dead_belowdot = 0xfe60,
+ XK_dead_hook = 0xfe61,
+ XK_dead_horn = 0xfe62,
+ XK_dead_stroke = 0xfe63,
+ XK_dead_abovecomma = 0xfe64,
+ XK_dead_psili = 0xfe64, /* alias for dead_abovecomma */
+ XK_dead_abovereversedcomma = 0xfe65,
+ XK_dead_dasia = 0xfe65, /* alias for dead_abovereversedcomma */
+ XK_dead_doublegrave = 0xfe66,
+ XK_dead_belowring = 0xfe67,
+ XK_dead_belowmacron = 0xfe68,
+ XK_dead_belowcircumflex = 0xfe69,
+ XK_dead_belowtilde = 0xfe6a,
+ XK_dead_belowbreve = 0xfe6b,
+ XK_dead_belowdiaeresis = 0xfe6c,
+ XK_dead_invertedbreve = 0xfe6d,
+ XK_dead_belowcomma = 0xfe6e,
+ XK_dead_currency = 0xfe6f,
+
+ /* extra dead elements for German T3 layout */
+ XK_dead_lowline = 0xfe90,
+ XK_dead_aboveverticalline = 0xfe91,
+ XK_dead_belowverticalline = 0xfe92,
+ XK_dead_longsolidusoverlay = 0xfe93,
+
+ /* dead vowels for universal syllable entry */
+ XK_dead_a = 0xfe80,
+ XK_dead_A = 0xfe81,
+ XK_dead_e = 0xfe82,
+ XK_dead_E = 0xfe83,
+ XK_dead_i = 0xfe84,
+ XK_dead_I = 0xfe85,
+ XK_dead_o = 0xfe86,
+ XK_dead_O = 0xfe87,
+ XK_dead_u = 0xfe88,
+ XK_dead_U = 0xfe89,
+ XK_dead_small_schwa = 0xfe8a,
+ XK_dead_capital_schwa = 0xfe8b,
+
+ XK_dead_greek = 0xfe8c,
+
+ XK_First_Virtual_Screen = 0xfed0,
+ XK_Prev_Virtual_Screen = 0xfed1,
+ XK_Next_Virtual_Screen = 0xfed2,
+ XK_Last_Virtual_Screen = 0xfed4,
+ XK_Terminate_Server = 0xfed5,
+
+ XK_AccessX_Enable = 0xfe70,
+ XK_AccessX_Feedback_Enable = 0xfe71,
+ XK_RepeatKeys_Enable = 0xfe72,
+ XK_SlowKeys_Enable = 0xfe73,
+ XK_BounceKeys_Enable = 0xfe74,
+ XK_StickyKeys_Enable = 0xfe75,
+ XK_MouseKeys_Enable = 0xfe76,
+ XK_MouseKeys_Accel_Enable = 0xfe77,
+ XK_Overlay1_Enable = 0xfe78,
+ XK_Overlay2_Enable = 0xfe79,
+ XK_AudibleBell_Enable = 0xfe7a,
+
+ XK_Pointer_Left = 0xfee0,
+ XK_Pointer_Right = 0xfee1,
+ XK_Pointer_Up = 0xfee2,
+ XK_Pointer_Down = 0xfee3,
+ XK_Pointer_UpLeft = 0xfee4,
+ XK_Pointer_UpRight = 0xfee5,
+ XK_Pointer_DownLeft = 0xfee6,
+ XK_Pointer_DownRight = 0xfee7,
+ XK_Pointer_Button_Dflt = 0xfee8,
+ XK_Pointer_Button1 = 0xfee9,
+ XK_Pointer_Button2 = 0xfeea,
+ XK_Pointer_Button3 = 0xfeeb,
+ XK_Pointer_Button4 = 0xfeec,
+ XK_Pointer_Button5 = 0xfeed,
+ XK_Pointer_DblClick_Dflt = 0xfeee,
+ XK_Pointer_DblClick1 = 0xfeef,
+ XK_Pointer_DblClick2 = 0xfef0,
+ XK_Pointer_DblClick3 = 0xfef1,
+ XK_Pointer_DblClick4 = 0xfef2,
+ XK_Pointer_DblClick5 = 0xfef3,
+ XK_Pointer_Drag_Dflt = 0xfef4,
+ XK_Pointer_Drag1 = 0xfef5,
+ XK_Pointer_Drag2 = 0xfef6,
+ XK_Pointer_Drag3 = 0xfef7,
+ XK_Pointer_Drag4 = 0xfef8,
+ XK_Pointer_Drag5 = 0xfefd,
+
+ XK_Pointer_EnableKeys = 0xfef9,
+ XK_Pointer_Accelerate = 0xfefa,
+ XK_Pointer_DfltBtnNext = 0xfefb,
+ XK_Pointer_DfltBtnPrev = 0xfefc,
+
+ /* Single-Stroke Multiple-Character N-Graph Keysyms For The X Input Method */
+
+ XK_ch = 0xfea0,
+ XK_Ch = 0xfea1,
+ XK_CH = 0xfea2,
+ XK_c_h = 0xfea3,
+ XK_C_h = 0xfea4,
+ XK_C_H = 0xfea5,
+
+ /*
+ * 3270 Terminal Keys
+ * Byte 3 = = 0xfd
+ */
+
+ // MARK: - XK_3270
+ XK_3270_Duplicate = 0xfd01,
+ XK_3270_FieldMark = 0xfd02,
+ XK_3270_Right2 = 0xfd03,
+ XK_3270_Left2 = 0xfd04,
+ XK_3270_BackTab = 0xfd05,
+ XK_3270_EraseEOF = 0xfd06,
+ XK_3270_EraseInput = 0xfd07,
+ XK_3270_Reset = 0xfd08,
+ XK_3270_Quit = 0xfd09,
+ XK_3270_PA1 = 0xfd0a,
+ XK_3270_PA2 = 0xfd0b,
+ XK_3270_PA3 = 0xfd0c,
+ XK_3270_Test = 0xfd0d,
+ XK_3270_Attn = 0xfd0e,
+ XK_3270_CursorBlink = 0xfd0f,
+ XK_3270_AltCursor = 0xfd10,
+ XK_3270_KeyClick = 0xfd11,
+ XK_3270_Jump = 0xfd12,
+ XK_3270_Ident = 0xfd13,
+ XK_3270_Rule = 0xfd14,
+ XK_3270_Copy = 0xfd15,
+ XK_3270_Play = 0xfd16,
+ XK_3270_Setup = 0xfd17,
+ XK_3270_Record = 0xfd18,
+ XK_3270_ChangeScreen = 0xfd19,
+ XK_3270_DeleteWord = 0xfd1a,
+ XK_3270_ExSelect = 0xfd1b,
+ XK_3270_CursorSelect = 0xfd1c,
+ XK_3270_PrintScreen = 0xfd1d,
+ XK_3270_Enter = 0xfd1e,
+
+ /*
+ * Latin 1
+ * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF,
+ * Byte 3 = 0
+ */
+ // MARK: - XK_LATIN1
+ XK_space = 0x0020, /* U+0020 SPACE */
+ XK_exclam = 0x0021, /* U+0021 EXCLAMATION MARK */
+ XK_quotedbl = 0x0022, /* U+0022 QUOTATION MARK */
+ XK_numbersign = 0x0023, /* U+0023 NUMBER SIGN */
+ XK_dollar = 0x0024, /* U+0024 DOLLAR SIGN */
+ XK_percent = 0x0025, /* U+0025 PERCENT SIGN */
+ XK_ampersand = 0x0026, /* U+0026 AMPERSAND */
+ XK_apostrophe = 0x0027, /* U+0027 APOSTROPHE */
+ XK_quoteright = 0x0027, /* deprecated */
+ XK_parenleft = 0x0028, /* U+0028 LEFT PARENTHESIS */
+ XK_parenright = 0x0029, /* U+0029 RIGHT PARENTHESIS */
+ XK_asterisk = 0x002a, /* U+002A ASTERISK */
+ XK_plus = 0x002b, /* U+002B PLUS SIGN */
+ XK_comma = 0x002c, /* U+002C COMMA */
+ XK_minus = 0x002d, /* U+002D HYPHEN-MINUS */
+ XK_period = 0x002e, /* U+002E FULL STOP */
+ XK_slash = 0x002f, /* U+002F SOLIDUS */
+ XK_0 = 0x0030, /* U+0030 DIGIT ZERO */
+ XK_1 = 0x0031, /* U+0031 DIGIT ONE */
+ XK_2 = 0x0032, /* U+0032 DIGIT TWO */
+ XK_3 = 0x0033, /* U+0033 DIGIT THREE */
+ XK_4 = 0x0034, /* U+0034 DIGIT FOUR */
+ XK_5 = 0x0035, /* U+0035 DIGIT FIVE */
+ XK_6 = 0x0036, /* U+0036 DIGIT SIX */
+ XK_7 = 0x0037, /* U+0037 DIGIT SEVEN */
+ XK_8 = 0x0038, /* U+0038 DIGIT EIGHT */
+ XK_9 = 0x0039, /* U+0039 DIGIT NINE */
+ XK_colon = 0x003a, /* U+003A COLON */
+ XK_semicolon = 0x003b, /* U+003B SEMICOLON */
+ XK_less = 0x003c, /* U+003C LESS-THAN SIGN */
+ XK_equal = 0x003d, /* U+003D EQUALS SIGN */
+ XK_greater = 0x003e, /* U+003E GREATER-THAN SIGN */
+ XK_question = 0x003f, /* U+003F QUESTION MARK */
+ XK_at = 0x0040, /* U+0040 COMMERCIAL AT */
+ XK_A = 0x0041, /* U+0041 LATIN CAPITAL LETTER A */
+ XK_B = 0x0042, /* U+0042 LATIN CAPITAL LETTER B */
+ XK_C = 0x0043, /* U+0043 LATIN CAPITAL LETTER C */
+ XK_D = 0x0044, /* U+0044 LATIN CAPITAL LETTER D */
+ XK_E = 0x0045, /* U+0045 LATIN CAPITAL LETTER E */
+ XK_F = 0x0046, /* U+0046 LATIN CAPITAL LETTER F */
+ XK_G = 0x0047, /* U+0047 LATIN CAPITAL LETTER G */
+ XK_H = 0x0048, /* U+0048 LATIN CAPITAL LETTER H */
+ XK_I = 0x0049, /* U+0049 LATIN CAPITAL LETTER I */
+ XK_J = 0x004a, /* U+004A LATIN CAPITAL LETTER J */
+ XK_K = 0x004b, /* U+004B LATIN CAPITAL LETTER K */
+ XK_L = 0x004c, /* U+004C LATIN CAPITAL LETTER L */
+ XK_M = 0x004d, /* U+004D LATIN CAPITAL LETTER M */
+ XK_N = 0x004e, /* U+004E LATIN CAPITAL LETTER N */
+ XK_O = 0x004f, /* U+004F LATIN CAPITAL LETTER O */
+ XK_P = 0x0050, /* U+0050 LATIN CAPITAL LETTER P */
+ XK_Q = 0x0051, /* U+0051 LATIN CAPITAL LETTER Q */
+ XK_R = 0x0052, /* U+0052 LATIN CAPITAL LETTER R */
+ XK_S = 0x0053, /* U+0053 LATIN CAPITAL LETTER S */
+ XK_T = 0x0054, /* U+0054 LATIN CAPITAL LETTER T */
+ XK_U = 0x0055, /* U+0055 LATIN CAPITAL LETTER U */
+ XK_V = 0x0056, /* U+0056 LATIN CAPITAL LETTER V */
+ XK_W = 0x0057, /* U+0057 LATIN CAPITAL LETTER W */
+ XK_X = 0x0058, /* U+0058 LATIN CAPITAL LETTER X */
+ XK_Y = 0x0059, /* U+0059 LATIN CAPITAL LETTER Y */
+ XK_Z = 0x005a, /* U+005A LATIN CAPITAL LETTER Z */
+ XK_bracketleft = 0x005b, /* U+005B LEFT SQUARE BRACKET */
+ XK_backslash = 0x005c, /* U+005C REVERSE SOLIDUS */
+ XK_bracketright = 0x005d, /* U+005D RIGHT SQUARE BRACKET */
+ XK_asciicircum = 0x005e, /* U+005E CIRCUMFLEX ACCENT */
+ XK_underscore = 0x005f, /* U+005F LOW LINE */
+ XK_grave = 0x0060, /* U+0060 GRAVE ACCENT */
+ XK_quoteleft = 0x0060, /* deprecated */
+ XK_a = 0x0061, /* U+0061 LATIN SMALL LETTER A */
+ XK_b = 0x0062, /* U+0062 LATIN SMALL LETTER B */
+ XK_c = 0x0063, /* U+0063 LATIN SMALL LETTER C */
+ XK_d = 0x0064, /* U+0064 LATIN SMALL LETTER D */
+ XK_e = 0x0065, /* U+0065 LATIN SMALL LETTER E */
+ XK_f = 0x0066, /* U+0066 LATIN SMALL LETTER F */
+ XK_g = 0x0067, /* U+0067 LATIN SMALL LETTER G */
+ XK_h = 0x0068, /* U+0068 LATIN SMALL LETTER H */
+ XK_i = 0x0069, /* U+0069 LATIN SMALL LETTER I */
+ XK_j = 0x006a, /* U+006A LATIN SMALL LETTER J */
+ XK_k = 0x006b, /* U+006B LATIN SMALL LETTER K */
+ XK_l = 0x006c, /* U+006C LATIN SMALL LETTER L */
+ XK_m = 0x006d, /* U+006D LATIN SMALL LETTER M */
+ XK_n = 0x006e, /* U+006E LATIN SMALL LETTER N */
+ XK_o = 0x006f, /* U+006F LATIN SMALL LETTER O */
+ XK_p = 0x0070, /* U+0070 LATIN SMALL LETTER P */
+ XK_q = 0x0071, /* U+0071 LATIN SMALL LETTER Q */
+ XK_r = 0x0072, /* U+0072 LATIN SMALL LETTER R */
+ XK_s = 0x0073, /* U+0073 LATIN SMALL LETTER S */
+ XK_t = 0x0074, /* U+0074 LATIN SMALL LETTER T */
+ XK_u = 0x0075, /* U+0075 LATIN SMALL LETTER U */
+ XK_v = 0x0076, /* U+0076 LATIN SMALL LETTER V */
+ XK_w = 0x0077, /* U+0077 LATIN SMALL LETTER W */
+ XK_x = 0x0078, /* U+0078 LATIN SMALL LETTER X */
+ XK_y = 0x0079, /* U+0079 LATIN SMALL LETTER Y */
+ XK_z = 0x007a, /* U+007A LATIN SMALL LETTER Z */
+ XK_braceleft = 0x007b, /* U+007B LEFT CURLY BRACKET */
+ XK_bar = 0x007c, /* U+007C VERTICAL LINE */
+ XK_braceright = 0x007d, /* U+007D RIGHT CURLY BRACKET */
+ XK_asciitilde = 0x007e, /* U+007E TILDE */
+
+ XK_nobreakspace = 0x00a0, /* U+00A0 NO-BREAK SPACE */
+ XK_exclamdown = 0x00a1, /* U+00A1 INVERTED EXCLAMATION MARK */
+ XK_cent = 0x00a2, /* U+00A2 CENT SIGN */
+ XK_sterling = 0x00a3, /* U+00A3 POUND SIGN */
+ XK_currency = 0x00a4, /* U+00A4 CURRENCY SIGN */
+ XK_yen = 0x00a5, /* U+00A5 YEN SIGN */
+ XK_brokenbar = 0x00a6, /* U+00A6 BROKEN BAR */
+ XK_section = 0x00a7, /* U+00A7 SECTION SIGN */
+ XK_diaeresis = 0x00a8, /* U+00A8 DIAERESIS */
+ XK_copyright = 0x00a9, /* U+00A9 COPYRIGHT SIGN */
+ XK_ordfeminine = 0x00aa, /* U+00AA FEMININE ORDINAL INDICATOR */
+ XK_guillemotleft = 0x00ab, /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ XK_notsign = 0x00ac, /* U+00AC NOT SIGN */
+ XK_hyphen = 0x00ad, /* U+00AD SOFT HYPHEN */
+ XK_registered = 0x00ae, /* U+00AE REGISTERED SIGN */
+ XK_macron = 0x00af, /* U+00AF MACRON */
+ XK_degree = 0x00b0, /* U+00B0 DEGREE SIGN */
+ XK_plusminus = 0x00b1, /* U+00B1 PLUS-MINUS SIGN */
+ XK_twosuperior = 0x00b2, /* U+00B2 SUPERSCRIPT TWO */
+ XK_threesuperior = 0x00b3, /* U+00B3 SUPERSCRIPT THREE */
+ XK_acute = 0x00b4, /* U+00B4 ACUTE ACCENT */
+ XK_mu = 0x00b5, /* U+00B5 MICRO SIGN */
+ XK_paragraph = 0x00b6, /* U+00B6 PILCROW SIGN */
+ XK_periodcentered = 0x00b7, /* U+00B7 MIDDLE DOT */
+ XK_cedilla = 0x00b8, /* U+00B8 CEDILLA */
+ XK_onesuperior = 0x00b9, /* U+00B9 SUPERSCRIPT ONE */
+ XK_masculine = 0x00ba, /* U+00BA MASCULINE ORDINAL INDICATOR */
+ XK_guillemotright = 0x00bb, /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ XK_onequarter = 0x00bc, /* U+00BC VULGAR FRACTION ONE QUARTER */
+ XK_onehalf = 0x00bd, /* U+00BD VULGAR FRACTION ONE HALF */
+ XK_threequarters = 0x00be, /* U+00BE VULGAR FRACTION THREE QUARTERS */
+ XK_questiondown = 0x00bf, /* U+00BF INVERTED QUESTION MARK */
+ XK_Agrave = 0x00c0, /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */
+ XK_Aacute = 0x00c1, /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */
+ XK_Acircumflex = 0x00c2, /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+ XK_Atilde = 0x00c3, /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */
+ XK_Adiaeresis = 0x00c4, /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */
+ XK_Aring = 0x00c5, /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */
+ XK_AE = 0x00c6, /* U+00C6 LATIN CAPITAL LETTER AE */
+ XK_Ccedilla = 0x00c7, /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */
+ XK_Egrave = 0x00c8, /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */
+ XK_Eacute = 0x00c9, /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */
+ XK_Ecircumflex = 0x00ca, /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+ XK_Ediaeresis = 0x00cb, /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */
+ XK_Igrave = 0x00cc, /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */
+ XK_Iacute = 0x00cd, /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */
+ XK_Icircumflex = 0x00ce, /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+ XK_Idiaeresis = 0x00cf, /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */
+ XK_ETH = 0x00d0, /* U+00D0 LATIN CAPITAL LETTER ETH */
+ XK_Eth = 0x00d0, /* deprecated */
+ XK_Ntilde = 0x00d1, /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */
+ XK_Ograve = 0x00d2, /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */
+ XK_Oacute = 0x00d3, /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */
+ XK_Ocircumflex = 0x00d4, /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+ XK_Otilde = 0x00d5, /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */
+ XK_Odiaeresis = 0x00d6, /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */
+ XK_multiply = 0x00d7, /* U+00D7 MULTIPLICATION SIGN */
+ XK_Oslash = 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
+ XK_Ooblique = 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
+ XK_Ugrave = 0x00d9, /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */
+ XK_Uacute = 0x00da, /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */
+ XK_Ucircumflex = 0x00db, /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+ XK_Udiaeresis = 0x00dc, /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */
+ XK_Yacute = 0x00dd, /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */
+ XK_THORN = 0x00de, /* U+00DE LATIN CAPITAL LETTER THORN */
+ XK_Thorn = 0x00de, /* deprecated */
+ XK_ssharp = 0x00df, /* U+00DF LATIN SMALL LETTER SHARP S */
+ XK_agrave = 0x00e0, /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */
+ XK_aacute = 0x00e1, /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */
+ XK_acircumflex = 0x00e2, /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */
+ XK_atilde = 0x00e3, /* U+00E3 LATIN SMALL LETTER A WITH TILDE */
+ XK_adiaeresis = 0x00e4, /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */
+ XK_aring = 0x00e5, /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */
+ XK_ae = 0x00e6, /* U+00E6 LATIN SMALL LETTER AE */
+ XK_ccedilla = 0x00e7, /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */
+ XK_egrave = 0x00e8, /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */
+ XK_eacute = 0x00e9, /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */
+ XK_ecircumflex = 0x00ea, /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */
+ XK_ediaeresis = 0x00eb, /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */
+ XK_igrave = 0x00ec, /* U+00EC LATIN SMALL LETTER I WITH GRAVE */
+ XK_iacute = 0x00ed, /* U+00ED LATIN SMALL LETTER I WITH ACUTE */
+ XK_icircumflex = 0x00ee, /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */
+ XK_idiaeresis = 0x00ef, /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */
+ XK_eth = 0x00f0, /* U+00F0 LATIN SMALL LETTER ETH */
+ XK_ntilde = 0x00f1, /* U+00F1 LATIN SMALL LETTER N WITH TILDE */
+ XK_ograve = 0x00f2, /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */
+ XK_oacute = 0x00f3, /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */
+ XK_ocircumflex = 0x00f4, /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */
+ XK_otilde = 0x00f5, /* U+00F5 LATIN SMALL LETTER O WITH TILDE */
+ XK_odiaeresis = 0x00f6, /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */
+ XK_division = 0x00f7, /* U+00F7 DIVISION SIGN */
+ XK_oslash = 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
+ XK_ooblique = 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
+ XK_ugrave = 0x00f9, /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */
+ XK_uacute = 0x00fa, /* U+00FA LATIN SMALL LETTER U WITH ACUTE */
+ XK_ucircumflex = 0x00fb, /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */
+ XK_udiaeresis = 0x00fc, /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */
+ XK_yacute = 0x00fd, /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */
+ XK_thorn = 0x00fe, /* U+00FE LATIN SMALL LETTER THORN */
+ XK_ydiaeresis = 0x00ff, /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */
+
+ /*
+ * Latin 2
+ * Byte 3 = 1
+ */
+
+ // MARK: - XK_LATIN2
+ XK_Aogonek = 0x01a1, /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */
+ XK_breve = 0x01a2, /* U+02D8 BREVE */
+ XK_Lstroke = 0x01a3, /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */
+ XK_Lcaron = 0x01a5, /* U+013D LATIN CAPITAL LETTER L WITH CARON */
+ XK_Sacute = 0x01a6, /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */
+ XK_Scaron = 0x01a9, /* U+0160 LATIN CAPITAL LETTER S WITH CARON */
+ XK_Scedilla = 0x01aa, /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */
+ XK_Tcaron = 0x01ab, /* U+0164 LATIN CAPITAL LETTER T WITH CARON */
+ XK_Zacute = 0x01ac, /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */
+ XK_Zcaron = 0x01ae, /* U+017D LATIN CAPITAL LETTER Z WITH CARON */
+ XK_Zabovedot = 0x01af, /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+ XK_aogonek = 0x01b1, /* U+0105 LATIN SMALL LETTER A WITH OGONEK */
+ XK_ogonek = 0x01b2, /* U+02DB OGONEK */
+ XK_lstroke = 0x01b3, /* U+0142 LATIN SMALL LETTER L WITH STROKE */
+ XK_lcaron = 0x01b5, /* U+013E LATIN SMALL LETTER L WITH CARON */
+ XK_sacute = 0x01b6, /* U+015B LATIN SMALL LETTER S WITH ACUTE */
+ XK_caron = 0x01b7, /* U+02C7 CARON */
+ XK_scaron = 0x01b9, /* U+0161 LATIN SMALL LETTER S WITH CARON */
+ XK_scedilla = 0x01ba, /* U+015F LATIN SMALL LETTER S WITH CEDILLA */
+ XK_tcaron = 0x01bb, /* U+0165 LATIN SMALL LETTER T WITH CARON */
+ XK_zacute = 0x01bc, /* U+017A LATIN SMALL LETTER Z WITH ACUTE */
+ XK_doubleacute = 0x01bd, /* U+02DD DOUBLE ACUTE ACCENT */
+ XK_zcaron = 0x01be, /* U+017E LATIN SMALL LETTER Z WITH CARON */
+ XK_zabovedot = 0x01bf, /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */
+ XK_Racute = 0x01c0, /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */
+ XK_Abreve = 0x01c3, /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */
+ XK_Lacute = 0x01c5, /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */
+ XK_Cacute = 0x01c6, /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */
+ XK_Ccaron = 0x01c8, /* U+010C LATIN CAPITAL LETTER C WITH CARON */
+ XK_Eogonek = 0x01ca, /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */
+ XK_Ecaron = 0x01cc, /* U+011A LATIN CAPITAL LETTER E WITH CARON */
+ XK_Dcaron = 0x01cf, /* U+010E LATIN CAPITAL LETTER D WITH CARON */
+ XK_Dstroke = 0x01d0, /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */
+ XK_Nacute = 0x01d1, /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */
+ XK_Ncaron = 0x01d2, /* U+0147 LATIN CAPITAL LETTER N WITH CARON */
+ XK_Odoubleacute = 0x01d5, /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+ XK_Rcaron = 0x01d8, /* U+0158 LATIN CAPITAL LETTER R WITH CARON */
+ XK_Uring = 0x01d9, /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */
+ XK_Udoubleacute = 0x01db, /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+ XK_Tcedilla = 0x01de, /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */
+ XK_racute = 0x01e0, /* U+0155 LATIN SMALL LETTER R WITH ACUTE */
+ XK_abreve = 0x01e3, /* U+0103 LATIN SMALL LETTER A WITH BREVE */
+ XK_lacute = 0x01e5, /* U+013A LATIN SMALL LETTER L WITH ACUTE */
+ XK_cacute = 0x01e6, /* U+0107 LATIN SMALL LETTER C WITH ACUTE */
+ XK_ccaron = 0x01e8, /* U+010D LATIN SMALL LETTER C WITH CARON */
+ XK_eogonek = 0x01ea, /* U+0119 LATIN SMALL LETTER E WITH OGONEK */
+ XK_ecaron = 0x01ec, /* U+011B LATIN SMALL LETTER E WITH CARON */
+ XK_dcaron = 0x01ef, /* U+010F LATIN SMALL LETTER D WITH CARON */
+ XK_dstroke = 0x01f0, /* U+0111 LATIN SMALL LETTER D WITH STROKE */
+ XK_nacute = 0x01f1, /* U+0144 LATIN SMALL LETTER N WITH ACUTE */
+ XK_ncaron = 0x01f2, /* U+0148 LATIN SMALL LETTER N WITH CARON */
+ XK_odoubleacute = 0x01f5, /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+ XK_rcaron = 0x01f8, /* U+0159 LATIN SMALL LETTER R WITH CARON */
+ XK_uring = 0x01f9, /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */
+ XK_udoubleacute = 0x01fb, /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+ XK_tcedilla = 0x01fe, /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */
+ XK_abovedot = 0x01ff, /* U+02D9 DOT ABOVE */
+
+ /*
+ * Latin 3
+ * Byte 3 = 2
+ */
+
+ // MARK: - XK_LATIN3
+ XK_Hstroke = 0x02a1, /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */
+ XK_Hcircumflex = 0x02a6, /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+ XK_Iabovedot = 0x02a9, /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */
+ XK_Gbreve = 0x02ab, /* U+011E LATIN CAPITAL LETTER G WITH BREVE */
+ XK_Jcircumflex = 0x02ac, /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+ XK_hstroke = 0x02b1, /* U+0127 LATIN SMALL LETTER H WITH STROKE */
+ XK_hcircumflex = 0x02b6, /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */
+ XK_idotless = 0x02b9, /* U+0131 LATIN SMALL LETTER DOTLESS I */
+ XK_gbreve = 0x02bb, /* U+011F LATIN SMALL LETTER G WITH BREVE */
+ XK_jcircumflex = 0x02bc, /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */
+ XK_Cabovedot = 0x02c5, /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */
+ XK_Ccircumflex = 0x02c6, /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+ XK_Gabovedot = 0x02d5, /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */
+ XK_Gcircumflex = 0x02d8, /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+ XK_Ubreve = 0x02dd, /* U+016C LATIN CAPITAL LETTER U WITH BREVE */
+ XK_Scircumflex = 0x02de, /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+ XK_cabovedot = 0x02e5, /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */
+ XK_ccircumflex = 0x02e6, /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */
+ XK_gabovedot = 0x02f5, /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */
+ XK_gcircumflex = 0x02f8, /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */
+ XK_ubreve = 0x02fd, /* U+016D LATIN SMALL LETTER U WITH BREVE */
+ XK_scircumflex = 0x02fe, /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */
+
+ /*
+ * Latin 4
+ * Byte 3 = 3
+ */
+
+ // MARK: - XK_LATIN4
+ XK_kra = 0x03a2, /* U+0138 LATIN SMALL LETTER KRA */
+ XK_kappa = 0x03a2, /* deprecated */
+ XK_Rcedilla = 0x03a3, /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */
+ XK_Itilde = 0x03a5, /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */
+ XK_Lcedilla = 0x03a6, /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */
+ XK_Emacron = 0x03aa, /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */
+ XK_Gcedilla = 0x03ab, /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */
+ XK_Tslash = 0x03ac, /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */
+ XK_rcedilla = 0x03b3, /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */
+ XK_itilde = 0x03b5, /* U+0129 LATIN SMALL LETTER I WITH TILDE */
+ XK_lcedilla = 0x03b6, /* U+013C LATIN SMALL LETTER L WITH CEDILLA */
+ XK_emacron = 0x03ba, /* U+0113 LATIN SMALL LETTER E WITH MACRON */
+ XK_gcedilla = 0x03bb, /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */
+ XK_tslash = 0x03bc, /* U+0167 LATIN SMALL LETTER T WITH STROKE */
+ XK_ENG = 0x03bd, /* U+014A LATIN CAPITAL LETTER ENG */
+ XK_eng = 0x03bf, /* U+014B LATIN SMALL LETTER ENG */
+ XK_Amacron = 0x03c0, /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */
+ XK_Iogonek = 0x03c7, /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */
+ XK_Eabovedot = 0x03cc, /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */
+ XK_Imacron = 0x03cf, /* U+012A LATIN CAPITAL LETTER I WITH MACRON */
+ XK_Ncedilla = 0x03d1, /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */
+ XK_Omacron = 0x03d2, /* U+014C LATIN CAPITAL LETTER O WITH MACRON */
+ XK_Kcedilla = 0x03d3, /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */
+ XK_Uogonek = 0x03d9, /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */
+ XK_Utilde = 0x03dd, /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */
+ XK_Umacron = 0x03de, /* U+016A LATIN CAPITAL LETTER U WITH MACRON */
+ XK_amacron = 0x03e0, /* U+0101 LATIN SMALL LETTER A WITH MACRON */
+ XK_iogonek = 0x03e7, /* U+012F LATIN SMALL LETTER I WITH OGONEK */
+ XK_eabovedot = 0x03ec, /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */
+ XK_imacron = 0x03ef, /* U+012B LATIN SMALL LETTER I WITH MACRON */
+ XK_ncedilla = 0x03f1, /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */
+ XK_omacron = 0x03f2, /* U+014D LATIN SMALL LETTER O WITH MACRON */
+ XK_kcedilla = 0x03f3, /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */
+ XK_uogonek = 0x03f9, /* U+0173 LATIN SMALL LETTER U WITH OGONEK */
+ XK_utilde = 0x03fd, /* U+0169 LATIN SMALL LETTER U WITH TILDE */
+ XK_umacron = 0x03fe, /* U+016B LATIN SMALL LETTER U WITH MACRON */
+
+ /*
+ * Latin 8
+ */
+ // MARK: - XK_LATIN8
+ XK_Wcircumflex = 0x1000174, /* U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX */
+ XK_wcircumflex = 0x1000175, /* U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX */
+ XK_Ycircumflex = 0x1000176, /* U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */
+ XK_ycircumflex = 0x1000177, /* U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX */
+ XK_Babovedot = 0x1001e02, /* U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE */
+ XK_babovedot = 0x1001e03, /* U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE */
+ XK_Dabovedot = 0x1001e0a, /* U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE */
+ XK_dabovedot = 0x1001e0b, /* U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE */
+ XK_Fabovedot = 0x1001e1e, /* U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE */
+ XK_fabovedot = 0x1001e1f, /* U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE */
+ XK_Mabovedot = 0x1001e40, /* U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE */
+ XK_mabovedot = 0x1001e41, /* U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE */
+ XK_Pabovedot = 0x1001e56, /* U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE */
+ XK_pabovedot = 0x1001e57, /* U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE */
+ XK_Sabovedot = 0x1001e60, /* U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE */
+ XK_sabovedot = 0x1001e61, /* U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE */
+ XK_Tabovedot = 0x1001e6a, /* U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE */
+ XK_tabovedot = 0x1001e6b, /* U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE */
+ XK_Wgrave = 0x1001e80, /* U+1E80 LATIN CAPITAL LETTER W WITH GRAVE */
+ XK_wgrave = 0x1001e81, /* U+1E81 LATIN SMALL LETTER W WITH GRAVE */
+ XK_Wacute = 0x1001e82, /* U+1E82 LATIN CAPITAL LETTER W WITH ACUTE */
+ XK_wacute = 0x1001e83, /* U+1E83 LATIN SMALL LETTER W WITH ACUTE */
+ XK_Wdiaeresis = 0x1001e84, /* U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS */
+ XK_wdiaeresis = 0x1001e85, /* U+1E85 LATIN SMALL LETTER W WITH DIAERESIS */
+ XK_Ygrave = 0x1001ef2, /* U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE */
+ XK_ygrave = 0x1001ef3, /* U+1EF3 LATIN SMALL LETTER Y WITH GRAVE */
+
+ /*
+ * Latin 9
+ * Byte 3 = = 0x13
+ */
+
+ // MARK: - XK_LATIN9
+ XK_OE = 0x13bc, /* U+0152 LATIN CAPITAL LIGATURE OE */
+ XK_oe = 0x13bd, /* U+0153 LATIN SMALL LIGATURE OE */
+ XK_Ydiaeresis = 0x13be, /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */
+
+ /*
+ * Katakana
+ * Byte 3 = 4
+ */
+
+ // MARK: - XK_KATAKANA
+ XK_overline = 0x047e, /* U+203E OVERLINE */
+ XK_kana_fullstop = 0x04a1, /* U+3002 IDEOGRAPHIC FULL STOP */
+ XK_kana_openingbracket = 0x04a2, /* U+300C LEFT CORNER BRACKET */
+ XK_kana_closingbracket = 0x04a3, /* U+300D RIGHT CORNER BRACKET */
+ XK_kana_comma = 0x04a4, /* U+3001 IDEOGRAPHIC COMMA */
+ XK_kana_conjunctive = 0x04a5, /* U+30FB KATAKANA MIDDLE DOT */
+ XK_kana_middledot = 0x04a5, /* deprecated */
+ XK_kana_WO = 0x04a6, /* U+30F2 KATAKANA LETTER WO */
+ XK_kana_a = 0x04a7, /* U+30A1 KATAKANA LETTER SMALL A */
+ XK_kana_i = 0x04a8, /* U+30A3 KATAKANA LETTER SMALL I */
+ XK_kana_u = 0x04a9, /* U+30A5 KATAKANA LETTER SMALL U */
+ XK_kana_e = 0x04aa, /* U+30A7 KATAKANA LETTER SMALL E */
+ XK_kana_o = 0x04ab, /* U+30A9 KATAKANA LETTER SMALL O */
+ XK_kana_ya = 0x04ac, /* U+30E3 KATAKANA LETTER SMALL YA */
+ XK_kana_yu = 0x04ad, /* U+30E5 KATAKANA LETTER SMALL YU */
+ XK_kana_yo = 0x04ae, /* U+30E7 KATAKANA LETTER SMALL YO */
+ XK_kana_tsu = 0x04af, /* U+30C3 KATAKANA LETTER SMALL TU */
+ XK_kana_tu = 0x04af, /* deprecated */
+ XK_prolongedsound = 0x04b0, /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+ XK_kana_A = 0x04b1, /* U+30A2 KATAKANA LETTER A */
+ XK_kana_I = 0x04b2, /* U+30A4 KATAKANA LETTER I */
+ XK_kana_U = 0x04b3, /* U+30A6 KATAKANA LETTER U */
+ XK_kana_E = 0x04b4, /* U+30A8 KATAKANA LETTER E */
+ XK_kana_O = 0x04b5, /* U+30AA KATAKANA LETTER O */
+ XK_kana_KA = 0x04b6, /* U+30AB KATAKANA LETTER KA */
+ XK_kana_KI = 0x04b7, /* U+30AD KATAKANA LETTER KI */
+ XK_kana_KU = 0x04b8, /* U+30AF KATAKANA LETTER KU */
+ XK_kana_KE = 0x04b9, /* U+30B1 KATAKANA LETTER KE */
+ XK_kana_KO = 0x04ba, /* U+30B3 KATAKANA LETTER KO */
+ XK_kana_SA = 0x04bb, /* U+30B5 KATAKANA LETTER SA */
+ XK_kana_SHI = 0x04bc, /* U+30B7 KATAKANA LETTER SI */
+ XK_kana_SU = 0x04bd, /* U+30B9 KATAKANA LETTER SU */
+ XK_kana_SE = 0x04be, /* U+30BB KATAKANA LETTER SE */
+ XK_kana_SO = 0x04bf, /* U+30BD KATAKANA LETTER SO */
+ XK_kana_TA = 0x04c0, /* U+30BF KATAKANA LETTER TA */
+ XK_kana_CHI = 0x04c1, /* U+30C1 KATAKANA LETTER TI */
+ XK_kana_TI = 0x04c1, /* deprecated */
+ XK_kana_TSU = 0x04c2, /* U+30C4 KATAKANA LETTER TU */
+ XK_kana_TU = 0x04c2, /* deprecated */
+ XK_kana_TE = 0x04c3, /* U+30C6 KATAKANA LETTER TE */
+ XK_kana_TO = 0x04c4, /* U+30C8 KATAKANA LETTER TO */
+ XK_kana_NA = 0x04c5, /* U+30CA KATAKANA LETTER NA */
+ XK_kana_NI = 0x04c6, /* U+30CB KATAKANA LETTER NI */
+ XK_kana_NU = 0x04c7, /* U+30CC KATAKANA LETTER NU */
+ XK_kana_NE = 0x04c8, /* U+30CD KATAKANA LETTER NE */
+ XK_kana_NO = 0x04c9, /* U+30CE KATAKANA LETTER NO */
+ XK_kana_HA = 0x04ca, /* U+30CF KATAKANA LETTER HA */
+ XK_kana_HI = 0x04cb, /* U+30D2 KATAKANA LETTER HI */
+ XK_kana_FU = 0x04cc, /* U+30D5 KATAKANA LETTER HU */
+ XK_kana_HU = 0x04cc, /* deprecated */
+ XK_kana_HE = 0x04cd, /* U+30D8 KATAKANA LETTER HE */
+ XK_kana_HO = 0x04ce, /* U+30DB KATAKANA LETTER HO */
+ XK_kana_MA = 0x04cf, /* U+30DE KATAKANA LETTER MA */
+ XK_kana_MI = 0x04d0, /* U+30DF KATAKANA LETTER MI */
+ XK_kana_MU = 0x04d1, /* U+30E0 KATAKANA LETTER MU */
+ XK_kana_ME = 0x04d2, /* U+30E1 KATAKANA LETTER ME */
+ XK_kana_MO = 0x04d3, /* U+30E2 KATAKANA LETTER MO */
+ XK_kana_YA = 0x04d4, /* U+30E4 KATAKANA LETTER YA */
+ XK_kana_YU = 0x04d5, /* U+30E6 KATAKANA LETTER YU */
+ XK_kana_YO = 0x04d6, /* U+30E8 KATAKANA LETTER YO */
+ XK_kana_RA = 0x04d7, /* U+30E9 KATAKANA LETTER RA */
+ XK_kana_RI = 0x04d8, /* U+30EA KATAKANA LETTER RI */
+ XK_kana_RU = 0x04d9, /* U+30EB KATAKANA LETTER RU */
+ XK_kana_RE = 0x04da, /* U+30EC KATAKANA LETTER RE */
+ XK_kana_RO = 0x04db, /* U+30ED KATAKANA LETTER RO */
+ XK_kana_WA = 0x04dc, /* U+30EF KATAKANA LETTER WA */
+ XK_kana_N = 0x04dd, /* U+30F3 KATAKANA LETTER N */
+ XK_voicedsound = 0x04de, /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */
+ XK_semivoicedsound = 0x04df, /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+ XK_kana_switch = 0xff7e, /* Alias for mode_switch */
+
+ /*
+ * Arabic
+ * Byte 3 = 5
+ */
+
+ // MARK: - XK_ARABIC
+ XK_Farsi_0 = 0x10006f0, /* U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO */
+ XK_Farsi_1 = 0x10006f1, /* U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE */
+ XK_Farsi_2 = 0x10006f2, /* U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO */
+ XK_Farsi_3 = 0x10006f3, /* U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE */
+ XK_Farsi_4 = 0x10006f4, /* U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR */
+ XK_Farsi_5 = 0x10006f5, /* U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE */
+ XK_Farsi_6 = 0x10006f6, /* U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX */
+ XK_Farsi_7 = 0x10006f7, /* U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN */
+ XK_Farsi_8 = 0x10006f8, /* U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT */
+ XK_Farsi_9 = 0x10006f9, /* U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE */
+ XK_Arabic_percent = 0x100066a, /* U+066A ARABIC PERCENT SIGN */
+ XK_Arabic_superscript_alef = 0x1000670, /* U+0670 ARABIC LETTER SUPERSCRIPT ALEF */
+ XK_Arabic_tteh = 0x1000679, /* U+0679 ARABIC LETTER TTEH */
+ XK_Arabic_peh = 0x100067e, /* U+067E ARABIC LETTER PEH */
+ XK_Arabic_tcheh = 0x1000686, /* U+0686 ARABIC LETTER TCHEH */
+ XK_Arabic_ddal = 0x1000688, /* U+0688 ARABIC LETTER DDAL */
+ XK_Arabic_rreh = 0x1000691, /* U+0691 ARABIC LETTER RREH */
+ XK_Arabic_comma = 0x05ac, /* U+060C ARABIC COMMA */
+ XK_Arabic_fullstop = 0x10006d4, /* U+06D4 ARABIC FULL STOP */
+ XK_Arabic_0 = 0x1000660, /* U+0660 ARABIC-INDIC DIGIT ZERO */
+ XK_Arabic_1 = 0x1000661, /* U+0661 ARABIC-INDIC DIGIT ONE */
+ XK_Arabic_2 = 0x1000662, /* U+0662 ARABIC-INDIC DIGIT TWO */
+ XK_Arabic_3 = 0x1000663, /* U+0663 ARABIC-INDIC DIGIT THREE */
+ XK_Arabic_4 = 0x1000664, /* U+0664 ARABIC-INDIC DIGIT FOUR */
+ XK_Arabic_5 = 0x1000665, /* U+0665 ARABIC-INDIC DIGIT FIVE */
+ XK_Arabic_6 = 0x1000666, /* U+0666 ARABIC-INDIC DIGIT SIX */
+ XK_Arabic_7 = 0x1000667, /* U+0667 ARABIC-INDIC DIGIT SEVEN */
+ XK_Arabic_8 = 0x1000668, /* U+0668 ARABIC-INDIC DIGIT EIGHT */
+ XK_Arabic_9 = 0x1000669, /* U+0669 ARABIC-INDIC DIGIT NINE */
+ XK_Arabic_semicolon = 0x05bb, /* U+061B ARABIC SEMICOLON */
+ XK_Arabic_question_mark = 0x05bf, /* U+061F ARABIC QUESTION MARK */
+ XK_Arabic_hamza = 0x05c1, /* U+0621 ARABIC LETTER HAMZA */
+ XK_Arabic_maddaonalef = 0x05c2, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
+ XK_Arabic_hamzaonalef = 0x05c3, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
+ XK_Arabic_hamzaonwaw = 0x05c4, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
+ XK_Arabic_hamzaunderalef = 0x05c5, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
+ XK_Arabic_hamzaonyeh = 0x05c6, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
+ XK_Arabic_alef = 0x05c7, /* U+0627 ARABIC LETTER ALEF */
+ XK_Arabic_beh = 0x05c8, /* U+0628 ARABIC LETTER BEH */
+ XK_Arabic_tehmarbuta = 0x05c9, /* U+0629 ARABIC LETTER TEH MARBUTA */
+ XK_Arabic_teh = 0x05ca, /* U+062A ARABIC LETTER TEH */
+ XK_Arabic_theh = 0x05cb, /* U+062B ARABIC LETTER THEH */
+ XK_Arabic_jeem = 0x05cc, /* U+062C ARABIC LETTER JEEM */
+ XK_Arabic_hah = 0x05cd, /* U+062D ARABIC LETTER HAH */
+ XK_Arabic_khah = 0x05ce, /* U+062E ARABIC LETTER KHAH */
+ XK_Arabic_dal = 0x05cf, /* U+062F ARABIC LETTER DAL */
+ XK_Arabic_thal = 0x05d0, /* U+0630 ARABIC LETTER THAL */
+ XK_Arabic_ra = 0x05d1, /* U+0631 ARABIC LETTER REH */
+ XK_Arabic_zain = 0x05d2, /* U+0632 ARABIC LETTER ZAIN */
+ XK_Arabic_seen = 0x05d3, /* U+0633 ARABIC LETTER SEEN */
+ XK_Arabic_sheen = 0x05d4, /* U+0634 ARABIC LETTER SHEEN */
+ XK_Arabic_sad = 0x05d5, /* U+0635 ARABIC LETTER SAD */
+ XK_Arabic_dad = 0x05d6, /* U+0636 ARABIC LETTER DAD */
+ XK_Arabic_tah = 0x05d7, /* U+0637 ARABIC LETTER TAH */
+ XK_Arabic_zah = 0x05d8, /* U+0638 ARABIC LETTER ZAH */
+ XK_Arabic_ain = 0x05d9, /* U+0639 ARABIC LETTER AIN */
+ XK_Arabic_ghain = 0x05da, /* U+063A ARABIC LETTER GHAIN */
+ XK_Arabic_tatweel = 0x05e0, /* U+0640 ARABIC TATWEEL */
+ XK_Arabic_feh = 0x05e1, /* U+0641 ARABIC LETTER FEH */
+ XK_Arabic_qaf = 0x05e2, /* U+0642 ARABIC LETTER QAF */
+ XK_Arabic_kaf = 0x05e3, /* U+0643 ARABIC LETTER KAF */
+ XK_Arabic_lam = 0x05e4, /* U+0644 ARABIC LETTER LAM */
+ XK_Arabic_meem = 0x05e5, /* U+0645 ARABIC LETTER MEEM */
+ XK_Arabic_noon = 0x05e6, /* U+0646 ARABIC LETTER NOON */
+ XK_Arabic_ha = 0x05e7, /* U+0647 ARABIC LETTER HEH */
+ XK_Arabic_heh = 0x05e7, /* deprecated */
+ XK_Arabic_waw = 0x05e8, /* U+0648 ARABIC LETTER WAW */
+ XK_Arabic_alefmaksura = 0x05e9, /* U+0649 ARABIC LETTER ALEF MAKSURA */
+ XK_Arabic_yeh = 0x05ea, /* U+064A ARABIC LETTER YEH */
+ XK_Arabic_fathatan = 0x05eb, /* U+064B ARABIC FATHATAN */
+ XK_Arabic_dammatan = 0x05ec, /* U+064C ARABIC DAMMATAN */
+ XK_Arabic_kasratan = 0x05ed, /* U+064D ARABIC KASRATAN */
+ XK_Arabic_fatha = 0x05ee, /* U+064E ARABIC FATHA */
+ XK_Arabic_damma = 0x05ef, /* U+064F ARABIC DAMMA */
+ XK_Arabic_kasra = 0x05f0, /* U+0650 ARABIC KASRA */
+ XK_Arabic_shadda = 0x05f1, /* U+0651 ARABIC SHADDA */
+ XK_Arabic_sukun = 0x05f2, /* U+0652 ARABIC SUKUN */
+ XK_Arabic_madda_above = 0x1000653, /* U+0653 ARABIC MADDAH ABOVE */
+ XK_Arabic_hamza_above = 0x1000654, /* U+0654 ARABIC HAMZA ABOVE */
+ XK_Arabic_hamza_below = 0x1000655, /* U+0655 ARABIC HAMZA BELOW */
+ XK_Arabic_jeh = 0x1000698, /* U+0698 ARABIC LETTER JEH */
+ XK_Arabic_veh = 0x10006a4, /* U+06A4 ARABIC LETTER VEH */
+ XK_Arabic_keheh = 0x10006a9, /* U+06A9 ARABIC LETTER KEHEH */
+ XK_Arabic_gaf = 0x10006af, /* U+06AF ARABIC LETTER GAF */
+ XK_Arabic_noon_ghunna = 0x10006ba, /* U+06BA ARABIC LETTER NOON GHUNNA */
+ XK_Arabic_heh_doachashmee = 0x10006be, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
+ XK_Farsi_yeh = 0x10006cc, /* U+06CC ARABIC LETTER FARSI YEH */
+ XK_Arabic_farsi_yeh = 0x10006cc, /* U+06CC ARABIC LETTER FARSI YEH */
+ XK_Arabic_yeh_baree = 0x10006d2, /* U+06D2 ARABIC LETTER YEH BARREE */
+ XK_Arabic_heh_goal = 0x10006c1, /* U+06C1 ARABIC LETTER HEH GOAL */
+ XK_Arabic_switch = 0xff7e, /* Alias for mode_switch */
+
+ /*
+ * Cyrillic
+ * Byte 3 = 6
+ */
+ // MARK: - XK_CYRILLIC
+ XK_Cyrillic_GHE_bar = 0x1000492, /* U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE */
+ XK_Cyrillic_ghe_bar = 0x1000493, /* U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE */
+ XK_Cyrillic_ZHE_descender = 0x1000496, /* U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */
+ XK_Cyrillic_zhe_descender = 0x1000497, /* U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER */
+ XK_Cyrillic_KA_descender = 0x100049a, /* U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER */
+ XK_Cyrillic_ka_descender = 0x100049b, /* U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER */
+ XK_Cyrillic_KA_vertstroke = 0x100049c, /* U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */
+ XK_Cyrillic_ka_vertstroke = 0x100049d, /* U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE */
+ XK_Cyrillic_EN_descender = 0x10004a2, /* U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER */
+ XK_Cyrillic_en_descender = 0x10004a3, /* U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER */
+ XK_Cyrillic_U_straight = 0x10004ae, /* U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U */
+ XK_Cyrillic_u_straight = 0x10004af, /* U+04AF CYRILLIC SMALL LETTER STRAIGHT U */
+ XK_Cyrillic_U_straight_bar = 0x10004b0, /* U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */
+ XK_Cyrillic_u_straight_bar = 0x10004b1, /* U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE */
+ XK_Cyrillic_HA_descender = 0x10004b2, /* U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER */
+ XK_Cyrillic_ha_descender = 0x10004b3, /* U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER */
+ XK_Cyrillic_CHE_descender = 0x10004b6, /* U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */
+ XK_Cyrillic_che_descender = 0x10004b7, /* U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER */
+ XK_Cyrillic_CHE_vertstroke = 0x10004b8, /* U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */
+ XK_Cyrillic_che_vertstroke = 0x10004b9, /* U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE */
+ XK_Cyrillic_SHHA = 0x10004ba, /* U+04BA CYRILLIC CAPITAL LETTER SHHA */
+ XK_Cyrillic_shha = 0x10004bb, /* U+04BB CYRILLIC SMALL LETTER SHHA */
+
+ XK_Cyrillic_SCHWA = 0x10004d8, /* U+04D8 CYRILLIC CAPITAL LETTER SCHWA */
+ XK_Cyrillic_schwa = 0x10004d9, /* U+04D9 CYRILLIC SMALL LETTER SCHWA */
+ XK_Cyrillic_I_macron = 0x10004e2, /* U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON */
+ XK_Cyrillic_i_macron = 0x10004e3, /* U+04E3 CYRILLIC SMALL LETTER I WITH MACRON */
+ XK_Cyrillic_O_bar = 0x10004e8, /* U+04E8 CYRILLIC CAPITAL LETTER BARRED O */
+ XK_Cyrillic_o_bar = 0x10004e9, /* U+04E9 CYRILLIC SMALL LETTER BARRED O */
+ XK_Cyrillic_U_macron = 0x10004ee, /* U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON */
+ XK_Cyrillic_u_macron = 0x10004ef, /* U+04EF CYRILLIC SMALL LETTER U WITH MACRON */
+
+ XK_Serbian_dje = 0x06a1, /* U+0452 CYRILLIC SMALL LETTER DJE */
+ XK_Macedonia_gje = 0x06a2, /* U+0453 CYRILLIC SMALL LETTER GJE */
+ XK_Cyrillic_io = 0x06a3, /* U+0451 CYRILLIC SMALL LETTER IO */
+ XK_Ukrainian_ie = 0x06a4, /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */
+ XK_Ukranian_je = 0x06a4, /* deprecated */
+ XK_Macedonia_dse = 0x06a5, /* U+0455 CYRILLIC SMALL LETTER DZE */
+ XK_Ukrainian_i = 0x06a6, /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
+ XK_Ukranian_i = 0x06a6, /* deprecated */
+ XK_Ukrainian_yi = 0x06a7, /* U+0457 CYRILLIC SMALL LETTER YI */
+ XK_Ukranian_yi = 0x06a7, /* deprecated */
+ XK_Cyrillic_je = 0x06a8, /* U+0458 CYRILLIC SMALL LETTER JE */
+ XK_Serbian_je = 0x06a8, /* deprecated */
+ XK_Cyrillic_lje = 0x06a9, /* U+0459 CYRILLIC SMALL LETTER LJE */
+ XK_Serbian_lje = 0x06a9, /* deprecated */
+ XK_Cyrillic_nje = 0x06aa, /* U+045A CYRILLIC SMALL LETTER NJE */
+ XK_Serbian_nje = 0x06aa, /* deprecated */
+ XK_Serbian_tshe = 0x06ab, /* U+045B CYRILLIC SMALL LETTER TSHE */
+ XK_Macedonia_kje = 0x06ac, /* U+045C CYRILLIC SMALL LETTER KJE */
+ XK_Ukrainian_ghe_with_upturn = 0x06ad, /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */
+ XK_Byelorussian_shortu = 0x06ae, /* U+045E CYRILLIC SMALL LETTER SHORT U */
+ XK_Cyrillic_dzhe = 0x06af, /* U+045F CYRILLIC SMALL LETTER DZHE */
+ XK_Serbian_dze = 0x06af, /* deprecated */
+ XK_numerosign = 0x06b0, /* U+2116 NUMERO SIGN */
+ XK_Serbian_DJE = 0x06b1, /* U+0402 CYRILLIC CAPITAL LETTER DJE */
+ XK_Macedonia_GJE = 0x06b2, /* U+0403 CYRILLIC CAPITAL LETTER GJE */
+ XK_Cyrillic_IO = 0x06b3, /* U+0401 CYRILLIC CAPITAL LETTER IO */
+ XK_Ukrainian_IE = 0x06b4, /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+ XK_Ukranian_JE = 0x06b4, /* deprecated */
+ XK_Macedonia_DSE = 0x06b5, /* U+0405 CYRILLIC CAPITAL LETTER DZE */
+ XK_Ukrainian_I = 0x06b6, /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
+ XK_Ukranian_I = 0x06b6, /* deprecated */
+ XK_Ukrainian_YI = 0x06b7, /* U+0407 CYRILLIC CAPITAL LETTER YI */
+ XK_Ukranian_YI = 0x06b7, /* deprecated */
+ XK_Cyrillic_JE = 0x06b8, /* U+0408 CYRILLIC CAPITAL LETTER JE */
+ XK_Serbian_JE = 0x06b8, /* deprecated */
+ XK_Cyrillic_LJE = 0x06b9, /* U+0409 CYRILLIC CAPITAL LETTER LJE */
+ XK_Serbian_LJE = 0x06b9, /* deprecated */
+ XK_Cyrillic_NJE = 0x06ba, /* U+040A CYRILLIC CAPITAL LETTER NJE */
+ XK_Serbian_NJE = 0x06ba, /* deprecated */
+ XK_Serbian_TSHE = 0x06bb, /* U+040B CYRILLIC CAPITAL LETTER TSHE */
+ XK_Macedonia_KJE = 0x06bc, /* U+040C CYRILLIC CAPITAL LETTER KJE */
+ XK_Ukrainian_GHE_WITH_UPTURN = 0x06bd, /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */
+ XK_Byelorussian_SHORTU = 0x06be, /* U+040E CYRILLIC CAPITAL LETTER SHORT U */
+ XK_Cyrillic_DZHE = 0x06bf, /* U+040F CYRILLIC CAPITAL LETTER DZHE */
+ XK_Serbian_DZE = 0x06bf, /* deprecated */
+ XK_Cyrillic_yu = 0x06c0, /* U+044E CYRILLIC SMALL LETTER YU */
+ XK_Cyrillic_a = 0x06c1, /* U+0430 CYRILLIC SMALL LETTER A */
+ XK_Cyrillic_be = 0x06c2, /* U+0431 CYRILLIC SMALL LETTER BE */
+ XK_Cyrillic_tse = 0x06c3, /* U+0446 CYRILLIC SMALL LETTER TSE */
+ XK_Cyrillic_de = 0x06c4, /* U+0434 CYRILLIC SMALL LETTER DE */
+ XK_Cyrillic_ie = 0x06c5, /* U+0435 CYRILLIC SMALL LETTER IE */
+ XK_Cyrillic_ef = 0x06c6, /* U+0444 CYRILLIC SMALL LETTER EF */
+ XK_Cyrillic_ghe = 0x06c7, /* U+0433 CYRILLIC SMALL LETTER GHE */
+ XK_Cyrillic_ha = 0x06c8, /* U+0445 CYRILLIC SMALL LETTER HA */
+ XK_Cyrillic_i = 0x06c9, /* U+0438 CYRILLIC SMALL LETTER I */
+ XK_Cyrillic_shorti = 0x06ca, /* U+0439 CYRILLIC SMALL LETTER SHORT I */
+ XK_Cyrillic_ka = 0x06cb, /* U+043A CYRILLIC SMALL LETTER KA */
+ XK_Cyrillic_el = 0x06cc, /* U+043B CYRILLIC SMALL LETTER EL */
+ XK_Cyrillic_em = 0x06cd, /* U+043C CYRILLIC SMALL LETTER EM */
+ XK_Cyrillic_en = 0x06ce, /* U+043D CYRILLIC SMALL LETTER EN */
+ XK_Cyrillic_o = 0x06cf, /* U+043E CYRILLIC SMALL LETTER O */
+ XK_Cyrillic_pe = 0x06d0, /* U+043F CYRILLIC SMALL LETTER PE */
+ XK_Cyrillic_ya = 0x06d1, /* U+044F CYRILLIC SMALL LETTER YA */
+ XK_Cyrillic_er = 0x06d2, /* U+0440 CYRILLIC SMALL LETTER ER */
+ XK_Cyrillic_es = 0x06d3, /* U+0441 CYRILLIC SMALL LETTER ES */
+ XK_Cyrillic_te = 0x06d4, /* U+0442 CYRILLIC SMALL LETTER TE */
+ XK_Cyrillic_u = 0x06d5, /* U+0443 CYRILLIC SMALL LETTER U */
+ XK_Cyrillic_zhe = 0x06d6, /* U+0436 CYRILLIC SMALL LETTER ZHE */
+ XK_Cyrillic_ve = 0x06d7, /* U+0432 CYRILLIC SMALL LETTER VE */
+ XK_Cyrillic_softsign = 0x06d8, /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */
+ XK_Cyrillic_yeru = 0x06d9, /* U+044B CYRILLIC SMALL LETTER YERU */
+ XK_Cyrillic_ze = 0x06da, /* U+0437 CYRILLIC SMALL LETTER ZE */
+ XK_Cyrillic_sha = 0x06db, /* U+0448 CYRILLIC SMALL LETTER SHA */
+ XK_Cyrillic_e = 0x06dc, /* U+044D CYRILLIC SMALL LETTER E */
+ XK_Cyrillic_shcha = 0x06dd, /* U+0449 CYRILLIC SMALL LETTER SHCHA */
+ XK_Cyrillic_che = 0x06de, /* U+0447 CYRILLIC SMALL LETTER CHE */
+ XK_Cyrillic_hardsign = 0x06df, /* U+044A CYRILLIC SMALL LETTER HARD SIGN */
+ XK_Cyrillic_YU = 0x06e0, /* U+042E CYRILLIC CAPITAL LETTER YU */
+ XK_Cyrillic_A = 0x06e1, /* U+0410 CYRILLIC CAPITAL LETTER A */
+ XK_Cyrillic_BE = 0x06e2, /* U+0411 CYRILLIC CAPITAL LETTER BE */
+ XK_Cyrillic_TSE = 0x06e3, /* U+0426 CYRILLIC CAPITAL LETTER TSE */
+ XK_Cyrillic_DE = 0x06e4, /* U+0414 CYRILLIC CAPITAL LETTER DE */
+ XK_Cyrillic_IE = 0x06e5, /* U+0415 CYRILLIC CAPITAL LETTER IE */
+ XK_Cyrillic_EF = 0x06e6, /* U+0424 CYRILLIC CAPITAL LETTER EF */
+ XK_Cyrillic_GHE = 0x06e7, /* U+0413 CYRILLIC CAPITAL LETTER GHE */
+ XK_Cyrillic_HA = 0x06e8, /* U+0425 CYRILLIC CAPITAL LETTER HA */
+ XK_Cyrillic_I = 0x06e9, /* U+0418 CYRILLIC CAPITAL LETTER I */
+ XK_Cyrillic_SHORTI = 0x06ea, /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */
+ XK_Cyrillic_KA = 0x06eb, /* U+041A CYRILLIC CAPITAL LETTER KA */
+ XK_Cyrillic_EL = 0x06ec, /* U+041B CYRILLIC CAPITAL LETTER EL */
+ XK_Cyrillic_EM = 0x06ed, /* U+041C CYRILLIC CAPITAL LETTER EM */
+ XK_Cyrillic_EN = 0x06ee, /* U+041D CYRILLIC CAPITAL LETTER EN */
+ XK_Cyrillic_O = 0x06ef, /* U+041E CYRILLIC CAPITAL LETTER O */
+ XK_Cyrillic_PE = 0x06f0, /* U+041F CYRILLIC CAPITAL LETTER PE */
+ XK_Cyrillic_YA = 0x06f1, /* U+042F CYRILLIC CAPITAL LETTER YA */
+ XK_Cyrillic_ER = 0x06f2, /* U+0420 CYRILLIC CAPITAL LETTER ER */
+ XK_Cyrillic_ES = 0x06f3, /* U+0421 CYRILLIC CAPITAL LETTER ES */
+ XK_Cyrillic_TE = 0x06f4, /* U+0422 CYRILLIC CAPITAL LETTER TE */
+ XK_Cyrillic_U = 0x06f5, /* U+0423 CYRILLIC CAPITAL LETTER U */
+ XK_Cyrillic_ZHE = 0x06f6, /* U+0416 CYRILLIC CAPITAL LETTER ZHE */
+ XK_Cyrillic_VE = 0x06f7, /* U+0412 CYRILLIC CAPITAL LETTER VE */
+ XK_Cyrillic_SOFTSIGN = 0x06f8, /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */
+ XK_Cyrillic_YERU = 0x06f9, /* U+042B CYRILLIC CAPITAL LETTER YERU */
+ XK_Cyrillic_ZE = 0x06fa, /* U+0417 CYRILLIC CAPITAL LETTER ZE */
+ XK_Cyrillic_SHA = 0x06fb, /* U+0428 CYRILLIC CAPITAL LETTER SHA */
+ XK_Cyrillic_E = 0x06fc, /* U+042D CYRILLIC CAPITAL LETTER E */
+ XK_Cyrillic_SHCHA = 0x06fd, /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */
+ XK_Cyrillic_CHE = 0x06fe, /* U+0427 CYRILLIC CAPITAL LETTER CHE */
+ XK_Cyrillic_HARDSIGN = 0x06ff, /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */
+
+ /*
+ * Greek
+ * (based on an early draft of, and not quite identical to, ISO/IEC 8859-7)
+ * Byte 3 = 7
+ */
+
+ // MARK: - XK_GREEK
+ XK_Greek_ALPHAaccent = 0x07a1, /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */
+ XK_Greek_EPSILONaccent = 0x07a2, /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */
+ XK_Greek_ETAaccent = 0x07a3, /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */
+ XK_Greek_IOTAaccent = 0x07a4, /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */
+ XK_Greek_IOTAdieresis = 0x07a5, /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+ XK_Greek_IOTAdiaeresis = 0x07a5, /* old typo */
+ XK_Greek_OMICRONaccent = 0x07a7, /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */
+ XK_Greek_UPSILONaccent = 0x07a8, /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */
+ XK_Greek_UPSILONdieresis = 0x07a9, /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+ XK_Greek_OMEGAaccent = 0x07ab, /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */
+ XK_Greek_accentdieresis = 0x07ae, /* U+0385 GREEK DIALYTIKA TONOS */
+ XK_Greek_horizbar = 0x07af, /* U+2015 HORIZONTAL BAR */
+ XK_Greek_alphaaccent = 0x07b1, /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */
+ XK_Greek_epsilonaccent = 0x07b2, /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */
+ XK_Greek_etaaccent = 0x07b3, /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */
+ XK_Greek_iotaaccent = 0x07b4, /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */
+ XK_Greek_iotadieresis = 0x07b5, /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+ XK_Greek_iotaaccentdieresis = 0x07b6, /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
+ XK_Greek_omicronaccent = 0x07b7, /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */
+ XK_Greek_upsilonaccent = 0x07b8, /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */
+ XK_Greek_upsilondieresis = 0x07b9, /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+ XK_Greek_upsilonaccentdieresis = 0x07ba, /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
+ XK_Greek_omegaaccent = 0x07bb, /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */
+ XK_Greek_ALPHA = 0x07c1, /* U+0391 GREEK CAPITAL LETTER ALPHA */
+ XK_Greek_BETA = 0x07c2, /* U+0392 GREEK CAPITAL LETTER BETA */
+ XK_Greek_GAMMA = 0x07c3, /* U+0393 GREEK CAPITAL LETTER GAMMA */
+ XK_Greek_DELTA = 0x07c4, /* U+0394 GREEK CAPITAL LETTER DELTA */
+ XK_Greek_EPSILON = 0x07c5, /* U+0395 GREEK CAPITAL LETTER EPSILON */
+ XK_Greek_ZETA = 0x07c6, /* U+0396 GREEK CAPITAL LETTER ZETA */
+ XK_Greek_ETA = 0x07c7, /* U+0397 GREEK CAPITAL LETTER ETA */
+ XK_Greek_THETA = 0x07c8, /* U+0398 GREEK CAPITAL LETTER THETA */
+ XK_Greek_IOTA = 0x07c9, /* U+0399 GREEK CAPITAL LETTER IOTA */
+ XK_Greek_KAPPA = 0x07ca, /* U+039A GREEK CAPITAL LETTER KAPPA */
+ XK_Greek_LAMDA = 0x07cb, /* U+039B GREEK CAPITAL LETTER LAMDA */
+ XK_Greek_LAMBDA = 0x07cb, /* U+039B GREEK CAPITAL LETTER LAMDA */
+ XK_Greek_MU = 0x07cc, /* U+039C GREEK CAPITAL LETTER MU */
+ XK_Greek_NU = 0x07cd, /* U+039D GREEK CAPITAL LETTER NU */
+ XK_Greek_XI = 0x07ce, /* U+039E GREEK CAPITAL LETTER XI */
+ XK_Greek_OMICRON = 0x07cf, /* U+039F GREEK CAPITAL LETTER OMICRON */
+ XK_Greek_PI = 0x07d0, /* U+03A0 GREEK CAPITAL LETTER PI */
+ XK_Greek_RHO = 0x07d1, /* U+03A1 GREEK CAPITAL LETTER RHO */
+ XK_Greek_SIGMA = 0x07d2, /* U+03A3 GREEK CAPITAL LETTER SIGMA */
+ XK_Greek_TAU = 0x07d4, /* U+03A4 GREEK CAPITAL LETTER TAU */
+ XK_Greek_UPSILON = 0x07d5, /* U+03A5 GREEK CAPITAL LETTER UPSILON */
+ XK_Greek_PHI = 0x07d6, /* U+03A6 GREEK CAPITAL LETTER PHI */
+ XK_Greek_CHI = 0x07d7, /* U+03A7 GREEK CAPITAL LETTER CHI */
+ XK_Greek_PSI = 0x07d8, /* U+03A8 GREEK CAPITAL LETTER PSI */
+ XK_Greek_OMEGA = 0x07d9, /* U+03A9 GREEK CAPITAL LETTER OMEGA */
+ XK_Greek_alpha = 0x07e1, /* U+03B1 GREEK SMALL LETTER ALPHA */
+ XK_Greek_beta = 0x07e2, /* U+03B2 GREEK SMALL LETTER BETA */
+ XK_Greek_gamma = 0x07e3, /* U+03B3 GREEK SMALL LETTER GAMMA */
+ XK_Greek_delta = 0x07e4, /* U+03B4 GREEK SMALL LETTER DELTA */
+ XK_Greek_epsilon = 0x07e5, /* U+03B5 GREEK SMALL LETTER EPSILON */
+ XK_Greek_zeta = 0x07e6, /* U+03B6 GREEK SMALL LETTER ZETA */
+ XK_Greek_eta = 0x07e7, /* U+03B7 GREEK SMALL LETTER ETA */
+ XK_Greek_theta = 0x07e8, /* U+03B8 GREEK SMALL LETTER THETA */
+ XK_Greek_iota = 0x07e9, /* U+03B9 GREEK SMALL LETTER IOTA */
+ XK_Greek_kappa = 0x07ea, /* U+03BA GREEK SMALL LETTER KAPPA */
+ XK_Greek_lamda = 0x07eb, /* U+03BB GREEK SMALL LETTER LAMDA */
+ XK_Greek_lambda = 0x07eb, /* U+03BB GREEK SMALL LETTER LAMDA */
+ XK_Greek_mu = 0x07ec, /* U+03BC GREEK SMALL LETTER MU */
+ XK_Greek_nu = 0x07ed, /* U+03BD GREEK SMALL LETTER NU */
+ XK_Greek_xi = 0x07ee, /* U+03BE GREEK SMALL LETTER XI */
+ XK_Greek_omicron = 0x07ef, /* U+03BF GREEK SMALL LETTER OMICRON */
+ XK_Greek_pi = 0x07f0, /* U+03C0 GREEK SMALL LETTER PI */
+ XK_Greek_rho = 0x07f1, /* U+03C1 GREEK SMALL LETTER RHO */
+ XK_Greek_sigma = 0x07f2, /* U+03C3 GREEK SMALL LETTER SIGMA */
+ XK_Greek_finalsmallsigma = 0x07f3, /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */
+ XK_Greek_tau = 0x07f4, /* U+03C4 GREEK SMALL LETTER TAU */
+ XK_Greek_upsilon = 0x07f5, /* U+03C5 GREEK SMALL LETTER UPSILON */
+ XK_Greek_phi = 0x07f6, /* U+03C6 GREEK SMALL LETTER PHI */
+ XK_Greek_chi = 0x07f7, /* U+03C7 GREEK SMALL LETTER CHI */
+ XK_Greek_psi = 0x07f8, /* U+03C8 GREEK SMALL LETTER PSI */
+ XK_Greek_omega = 0x07f9, /* U+03C9 GREEK SMALL LETTER OMEGA */
+ XK_Greek_switch = 0xff7e, /* Alias for mode_switch */
+
+ /*
+ * Technical
+ * (from the DEC VT330/VT420 Technical Character Set, http://vt100.net/charsets/technical.html)
+ * Byte 3 = 8
+ */
+
+ // MARK: - XK_TECHNICAL
+ XK_leftradical = 0x08a1, /* U+23B7 RADICAL SYMBOL BOTTOM */
+ XK_topleftradical = 0x08a2, /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/
+ XK_horizconnector = 0x08a3, /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/
+ XK_topintegral = 0x08a4, /* U+2320 TOP HALF INTEGRAL */
+ XK_botintegral = 0x08a5, /* U+2321 BOTTOM HALF INTEGRAL */
+ XK_vertconnector = 0x08a6, /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/
+ XK_topleftsqbracket = 0x08a7, /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */
+ XK_botleftsqbracket = 0x08a8, /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */
+ XK_toprightsqbracket = 0x08a9, /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */
+ XK_botrightsqbracket = 0x08aa, /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */
+ XK_topleftparens = 0x08ab, /* U+239B LEFT PARENTHESIS UPPER HOOK */
+ XK_botleftparens = 0x08ac, /* U+239D LEFT PARENTHESIS LOWER HOOK */
+ XK_toprightparens = 0x08ad, /* U+239E RIGHT PARENTHESIS UPPER HOOK */
+ XK_botrightparens = 0x08ae, /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */
+ XK_leftmiddlecurlybrace = 0x08af, /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */
+ XK_rightmiddlecurlybrace = 0x08b0, /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */
+ XK_topleftsummation = 0x08b1,
+ XK_botleftsummation = 0x08b2,
+ XK_topvertsummationconnector = 0x08b3,
+ XK_botvertsummationconnector = 0x08b4,
+ XK_toprightsummation = 0x08b5,
+ XK_botrightsummation = 0x08b6,
+ XK_rightmiddlesummation = 0x08b7,
+ XK_lessthanequal = 0x08bc, /* U+2264 LESS-THAN OR EQUAL TO */
+ XK_notequal = 0x08bd, /* U+2260 NOT EQUAL TO */
+ XK_greaterthanequal = 0x08be, /* U+2265 GREATER-THAN OR EQUAL TO */
+ XK_integral = 0x08bf, /* U+222B INTEGRAL */
+ XK_therefore = 0x08c0, /* U+2234 THEREFORE */
+ XK_variation = 0x08c1, /* U+221D PROPORTIONAL TO */
+ XK_infinity = 0x08c2, /* U+221E INFINITY */
+ XK_nabla = 0x08c5, /* U+2207 NABLA */
+ XK_approximate = 0x08c8, /* U+223C TILDE OPERATOR */
+ XK_similarequal = 0x08c9, /* U+2243 ASYMPTOTICALLY EQUAL TO */
+ XK_ifonlyif = 0x08cd, /* U+21D4 LEFT RIGHT DOUBLE ARROW */
+ XK_implies = 0x08ce, /* U+21D2 RIGHTWARDS DOUBLE ARROW */
+ XK_identical = 0x08cf, /* U+2261 IDENTICAL TO */
+ XK_radical = 0x08d6, /* U+221A SQUARE ROOT */
+ XK_includedin = 0x08da, /* U+2282 SUBSET OF */
+ XK_includes = 0x08db, /* U+2283 SUPERSET OF */
+ XK_intersection = 0x08dc, /* U+2229 INTERSECTION */
+ XK_union = 0x08dd, /* U+222A UNION */
+ XK_logicaland = 0x08de, /* U+2227 LOGICAL AND */
+ XK_logicalor = 0x08df, /* U+2228 LOGICAL OR */
+ XK_partialderivative = 0x08ef, /* U+2202 PARTIAL DIFFERENTIAL */
+ XK_function = 0x08f6, /* U+0192 LATIN SMALL LETTER F WITH HOOK */
+ XK_leftarrow = 0x08fb, /* U+2190 LEFTWARDS ARROW */
+ XK_uparrow = 0x08fc, /* U+2191 UPWARDS ARROW */
+ XK_rightarrow = 0x08fd, /* U+2192 RIGHTWARDS ARROW */
+ XK_downarrow = 0x08fe, /* U+2193 DOWNWARDS ARROW */
+
+ /*
+ * Special
+ * (from the DEC VT100 Special Graphics Character Set)
+ * Byte 3 = 9
+ */
+
+ // MARK: - XK_SPECIAL
+ XK_blank = 0x09df,
+ XK_soliddiamond = 0x09e0, /* U+25C6 BLACK DIAMOND */
+ XK_checkerboard = 0x09e1, /* U+2592 MEDIUM SHADE */
+ XK_ht = 0x09e2, /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */
+ XK_ff = 0x09e3, /* U+240C SYMBOL FOR FORM FEED */
+ XK_cr = 0x09e4, /* U+240D SYMBOL FOR CARRIAGE RETURN */
+ XK_lf = 0x09e5, /* U+240A SYMBOL FOR LINE FEED */
+ XK_nl = 0x09e8, /* U+2424 SYMBOL FOR NEWLINE */
+ XK_vt = 0x09e9, /* U+240B SYMBOL FOR VERTICAL TABULATION */
+ XK_lowrightcorner = 0x09ea, /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */
+ XK_uprightcorner = 0x09eb, /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */
+ XK_upleftcorner = 0x09ec, /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */
+ XK_lowleftcorner = 0x09ed, /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */
+ XK_crossinglines = 0x09ee, /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+ XK_horizlinescan1 = 0x09ef, /* U+23BA HORIZONTAL SCAN LINE-1 */
+ XK_horizlinescan3 = 0x09f0, /* U+23BB HORIZONTAL SCAN LINE-3 */
+ XK_horizlinescan5 = 0x09f1, /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */
+ XK_horizlinescan7 = 0x09f2, /* U+23BC HORIZONTAL SCAN LINE-7 */
+ XK_horizlinescan9 = 0x09f3, /* U+23BD HORIZONTAL SCAN LINE-9 */
+ XK_leftt = 0x09f4, /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+ XK_rightt = 0x09f5, /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+ XK_bott = 0x09f6, /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+ XK_topt = 0x09f7, /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+ XK_vertbar = 0x09f8, /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
+
+ /*
+ * Publishing
+ * (these are probably from a long forgotten DEC Publishing
+ * font that once shipped with DECwrite)
+ * Byte 3 = = 0x0a
+ */
+
+ // MARK: - XK_PUBLISHING
+ XK_emspace = 0x0aa1, /* U+2003 EM SPACE */
+ XK_enspace = 0x0aa2, /* U+2002 EN SPACE */
+ XK_em3space = 0x0aa3, /* U+2004 THREE-PER-EM SPACE */
+ XK_em4space = 0x0aa4, /* U+2005 FOUR-PER-EM SPACE */
+ XK_digitspace = 0x0aa5, /* U+2007 FIGURE SPACE */
+ XK_punctspace = 0x0aa6, /* U+2008 PUNCTUATION SPACE */
+ XK_thinspace = 0x0aa7, /* U+2009 THIN SPACE */
+ XK_hairspace = 0x0aa8, /* U+200A HAIR SPACE */
+ XK_emdash = 0x0aa9, /* U+2014 EM DASH */
+ XK_endash = 0x0aaa, /* U+2013 EN DASH */
+ XK_signifblank = 0x0aac, /*(U+2423 OPEN BOX)*/
+ XK_ellipsis = 0x0aae, /* U+2026 HORIZONTAL ELLIPSIS */
+ XK_doubbaselinedot = 0x0aaf, /* U+2025 TWO DOT LEADER */
+ XK_onethird = 0x0ab0, /* U+2153 VULGAR FRACTION ONE THIRD */
+ XK_twothirds = 0x0ab1, /* U+2154 VULGAR FRACTION TWO THIRDS */
+ XK_onefifth = 0x0ab2, /* U+2155 VULGAR FRACTION ONE FIFTH */
+ XK_twofifths = 0x0ab3, /* U+2156 VULGAR FRACTION TWO FIFTHS */
+ XK_threefifths = 0x0ab4, /* U+2157 VULGAR FRACTION THREE FIFTHS */
+ XK_fourfifths = 0x0ab5, /* U+2158 VULGAR FRACTION FOUR FIFTHS */
+ XK_onesixth = 0x0ab6, /* U+2159 VULGAR FRACTION ONE SIXTH */
+ XK_fivesixths = 0x0ab7, /* U+215A VULGAR FRACTION FIVE SIXTHS */
+ XK_careof = 0x0ab8, /* U+2105 CARE OF */
+ XK_figdash = 0x0abb, /* U+2012 FIGURE DASH */
+ XK_leftanglebracket = 0x0abc, /*(U+2329 LEFT-POINTING ANGLE BRACKET)*/
+ XK_decimalpoint = 0x0abd, /*(U+002E FULL STOP)*/
+ XK_rightanglebracket = 0x0abe, /*(U+232A RIGHT-POINTING ANGLE BRACKET)*/
+ XK_marker = 0x0abf,
+ XK_oneeighth = 0x0ac3, /* U+215B VULGAR FRACTION ONE EIGHTH */
+ XK_threeeighths = 0x0ac4, /* U+215C VULGAR FRACTION THREE EIGHTHS */
+ XK_fiveeighths = 0x0ac5, /* U+215D VULGAR FRACTION FIVE EIGHTHS */
+ XK_seveneighths = 0x0ac6, /* U+215E VULGAR FRACTION SEVEN EIGHTHS */
+ XK_trademark = 0x0ac9, /* U+2122 TRADE MARK SIGN */
+ XK_signaturemark = 0x0aca, /*(U+2613 SALTIRE)*/
+ XK_trademarkincircle = 0x0acb,
+ XK_leftopentriangle = 0x0acc, /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/
+ XK_rightopentriangle = 0x0acd, /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/
+ XK_emopencircle = 0x0ace, /*(U+25CB WHITE CIRCLE)*/
+ XK_emopenrectangle = 0x0acf, /*(U+25AF WHITE VERTICAL RECTANGLE)*/
+ XK_leftsinglequotemark = 0x0ad0, /* U+2018 LEFT SINGLE QUOTATION MARK */
+ XK_rightsinglequotemark = 0x0ad1, /* U+2019 RIGHT SINGLE QUOTATION MARK */
+ XK_leftdoublequotemark = 0x0ad2, /* U+201C LEFT DOUBLE QUOTATION MARK */
+ XK_rightdoublequotemark = 0x0ad3, /* U+201D RIGHT DOUBLE QUOTATION MARK */
+ XK_prescription = 0x0ad4, /* U+211E PRESCRIPTION TAKE */
+ XK_permille = 0x0ad5, /* U+2030 PER MILLE SIGN */
+ XK_minutes = 0x0ad6, /* U+2032 PRIME */
+ XK_seconds = 0x0ad7, /* U+2033 DOUBLE PRIME */
+ XK_latincross = 0x0ad9, /* U+271D LATIN CROSS */
+ XK_hexagram = 0x0ada,
+ XK_filledrectbullet = 0x0adb, /*(U+25AC BLACK RECTANGLE)*/
+ XK_filledlefttribullet = 0x0adc, /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/
+ XK_filledrighttribullet = 0x0add, /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/
+ XK_emfilledcircle = 0x0ade, /*(U+25CF BLACK CIRCLE)*/
+ XK_emfilledrect = 0x0adf, /*(U+25AE BLACK VERTICAL RECTANGLE)*/
+ XK_enopencircbullet = 0x0ae0, /*(U+25E6 WHITE BULLET)*/
+ XK_enopensquarebullet = 0x0ae1, /*(U+25AB WHITE SMALL SQUARE)*/
+ XK_openrectbullet = 0x0ae2, /*(U+25AD WHITE RECTANGLE)*/
+ XK_opentribulletup = 0x0ae3, /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/
+ XK_opentribulletdown = 0x0ae4, /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/
+ XK_openstar = 0x0ae5, /*(U+2606 WHITE STAR)*/
+ XK_enfilledcircbullet = 0x0ae6, /*(U+2022 BULLET)*/
+ XK_enfilledsqbullet = 0x0ae7, /*(U+25AA BLACK SMALL SQUARE)*/
+ XK_filledtribulletup = 0x0ae8, /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/
+ XK_filledtribulletdown = 0x0ae9, /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/
+ XK_leftpointer = 0x0aea, /*(U+261C WHITE LEFT POINTING INDEX)*/
+ XK_rightpointer = 0x0aeb, /*(U+261E WHITE RIGHT POINTING INDEX)*/
+ XK_club = 0x0aec, /* U+2663 BLACK CLUB SUIT */
+ XK_diamond = 0x0aed, /* U+2666 BLACK DIAMOND SUIT */
+ XK_heart = 0x0aee, /* U+2665 BLACK HEART SUIT */
+ XK_maltesecross = 0x0af0, /* U+2720 MALTESE CROSS */
+ XK_dagger = 0x0af1, /* U+2020 DAGGER */
+ XK_doubledagger = 0x0af2, /* U+2021 DOUBLE DAGGER */
+ XK_checkmark = 0x0af3, /* U+2713 CHECK MARK */
+ XK_ballotcross = 0x0af4, /* U+2717 BALLOT X */
+ XK_musicalsharp = 0x0af5, /* U+266F MUSIC SHARP SIGN */
+ XK_musicalflat = 0x0af6, /* U+266D MUSIC FLAT SIGN */
+ XK_malesymbol = 0x0af7, /* U+2642 MALE SIGN */
+ XK_femalesymbol = 0x0af8, /* U+2640 FEMALE SIGN */
+ XK_telephone = 0x0af9, /* U+260E BLACK TELEPHONE */
+ XK_telephonerecorder = 0x0afa, /* U+2315 TELEPHONE RECORDER */
+ XK_phonographcopyright = 0x0afb, /* U+2117 SOUND RECORDING COPYRIGHT */
+ XK_caret = 0x0afc, /* U+2038 CARET */
+ XK_singlelowquotemark = 0x0afd, /* U+201A SINGLE LOW-9 QUOTATION MARK */
+ XK_doublelowquotemark = 0x0afe, /* U+201E DOUBLE LOW-9 QUOTATION MARK */
+ XK_cursor = 0x0aff,
+
+ /*
+ * APL
+ * Byte 3 = = 0x0b
+ */
+
+ // MARK: - XK_APL
+ XK_leftcaret = 0x0ba3, /*(U+003C LESS-THAN SIGN)*/
+ XK_rightcaret = 0x0ba6, /*(U+003E GREATER-THAN SIGN)*/
+ XK_downcaret = 0x0ba8, /*(U+2228 LOGICAL OR)*/
+ XK_upcaret = 0x0ba9, /*(U+2227 LOGICAL AND)*/
+ XK_overbar = 0x0bc0, /*(U+00AF MACRON)*/
+ XK_downtack = 0x0bc2, /* U+22A4 DOWN TACK */
+ XK_upshoe = 0x0bc3, /*(U+2229 INTERSECTION)*/
+ XK_downstile = 0x0bc4, /* U+230A LEFT FLOOR */
+ XK_underbar = 0x0bc6, /*(U+005F LOW LINE)*/
+ XK_jot = 0x0bca, /* U+2218 RING OPERATOR */
+ XK_quad = 0x0bcc, /* U+2395 APL FUNCTIONAL SYMBOL QUAD */
+ XK_uptack = 0x0bce, /* U+22A5 UP TACK */
+ XK_circle = 0x0bcf, /* U+25CB WHITE CIRCLE */
+ XK_upstile = 0x0bd3, /* U+2308 LEFT CEILING */
+ XK_downshoe = 0x0bd6, /*(U+222A UNION)*/
+ XK_rightshoe = 0x0bd8, /*(U+2283 SUPERSET OF)*/
+ XK_leftshoe = 0x0bda, /*(U+2282 SUBSET OF)*/
+ XK_lefttack = 0x0bdc, /* U+22A3 LEFT TACK */
+ XK_righttack = 0x0bfc, /* U+22A2 RIGHT TACK */
+
+ /*
+ * Hebrew
+ * Byte 3 = = 0x0c
+ */
+
+ // MARK: - XK_HEBREW
+ XK_hebrew_doublelowline = 0x0cdf, /* U+2017 DOUBLE LOW LINE */
+ XK_hebrew_aleph = 0x0ce0, /* U+05D0 HEBREW LETTER ALEF */
+ XK_hebrew_bet = 0x0ce1, /* U+05D1 HEBREW LETTER BET */
+ XK_hebrew_beth = 0x0ce1, /* deprecated */
+ XK_hebrew_gimel = 0x0ce2, /* U+05D2 HEBREW LETTER GIMEL */
+ XK_hebrew_gimmel = 0x0ce2, /* deprecated */
+ XK_hebrew_dalet = 0x0ce3, /* U+05D3 HEBREW LETTER DALET */
+ XK_hebrew_daleth = 0x0ce3, /* deprecated */
+ XK_hebrew_he = 0x0ce4, /* U+05D4 HEBREW LETTER HE */
+ XK_hebrew_waw = 0x0ce5, /* U+05D5 HEBREW LETTER VAV */
+ XK_hebrew_zain = 0x0ce6, /* U+05D6 HEBREW LETTER ZAYIN */
+ XK_hebrew_zayin = 0x0ce6, /* deprecated */
+ XK_hebrew_chet = 0x0ce7, /* U+05D7 HEBREW LETTER HET */
+ XK_hebrew_het = 0x0ce7, /* deprecated */
+ XK_hebrew_tet = 0x0ce8, /* U+05D8 HEBREW LETTER TET */
+ XK_hebrew_teth = 0x0ce8, /* deprecated */
+ XK_hebrew_yod = 0x0ce9, /* U+05D9 HEBREW LETTER YOD */
+ XK_hebrew_finalkaph = 0x0cea, /* U+05DA HEBREW LETTER FINAL KAF */
+ XK_hebrew_kaph = 0x0ceb, /* U+05DB HEBREW LETTER KAF */
+ XK_hebrew_lamed = 0x0cec, /* U+05DC HEBREW LETTER LAMED */
+ XK_hebrew_finalmem = 0x0ced, /* U+05DD HEBREW LETTER FINAL MEM */
+ XK_hebrew_mem = 0x0cee, /* U+05DE HEBREW LETTER MEM */
+ XK_hebrew_finalnun = 0x0cef, /* U+05DF HEBREW LETTER FINAL NUN */
+ XK_hebrew_nun = 0x0cf0, /* U+05E0 HEBREW LETTER NUN */
+ XK_hebrew_samech = 0x0cf1, /* U+05E1 HEBREW LETTER SAMEKH */
+ XK_hebrew_samekh = 0x0cf1, /* deprecated */
+ XK_hebrew_ayin = 0x0cf2, /* U+05E2 HEBREW LETTER AYIN */
+ XK_hebrew_finalpe = 0x0cf3, /* U+05E3 HEBREW LETTER FINAL PE */
+ XK_hebrew_pe = 0x0cf4, /* U+05E4 HEBREW LETTER PE */
+ XK_hebrew_finalzade = 0x0cf5, /* U+05E5 HEBREW LETTER FINAL TSADI */
+ XK_hebrew_finalzadi = 0x0cf5, /* deprecated */
+ XK_hebrew_zade = 0x0cf6, /* U+05E6 HEBREW LETTER TSADI */
+ XK_hebrew_zadi = 0x0cf6, /* deprecated */
+ XK_hebrew_qoph = 0x0cf7, /* U+05E7 HEBREW LETTER QOF */
+ XK_hebrew_kuf = 0x0cf7, /* deprecated */
+ XK_hebrew_resh = 0x0cf8, /* U+05E8 HEBREW LETTER RESH */
+ XK_hebrew_shin = 0x0cf9, /* U+05E9 HEBREW LETTER SHIN */
+ XK_hebrew_taw = 0x0cfa, /* U+05EA HEBREW LETTER TAV */
+ XK_hebrew_taf = 0x0cfa, /* deprecated */
+ XK_Hebrew_switch = 0xff7e, /* Alias for mode_switch */
+
+ /*
+ * Thai
+ * Byte 3 = = 0x0d
+ */
+
+ // MARK: - XK_THAI
+ XK_Thai_kokai = 0x0da1, /* U+0E01 THAI CHARACTER KO KAI */
+ XK_Thai_khokhai = 0x0da2, /* U+0E02 THAI CHARACTER KHO KHAI */
+ XK_Thai_khokhuat = 0x0da3, /* U+0E03 THAI CHARACTER KHO KHUAT */
+ XK_Thai_khokhwai = 0x0da4, /* U+0E04 THAI CHARACTER KHO KHWAI */
+ XK_Thai_khokhon = 0x0da5, /* U+0E05 THAI CHARACTER KHO KHON */
+ XK_Thai_khorakhang = 0x0da6, /* U+0E06 THAI CHARACTER KHO RAKHANG */
+ XK_Thai_ngongu = 0x0da7, /* U+0E07 THAI CHARACTER NGO NGU */
+ XK_Thai_chochan = 0x0da8, /* U+0E08 THAI CHARACTER CHO CHAN */
+ XK_Thai_choching = 0x0da9, /* U+0E09 THAI CHARACTER CHO CHING */
+ XK_Thai_chochang = 0x0daa, /* U+0E0A THAI CHARACTER CHO CHANG */
+ XK_Thai_soso = 0x0dab, /* U+0E0B THAI CHARACTER SO SO */
+ XK_Thai_chochoe = 0x0dac, /* U+0E0C THAI CHARACTER CHO CHOE */
+ XK_Thai_yoying = 0x0dad, /* U+0E0D THAI CHARACTER YO YING */
+ XK_Thai_dochada = 0x0dae, /* U+0E0E THAI CHARACTER DO CHADA */
+ XK_Thai_topatak = 0x0daf, /* U+0E0F THAI CHARACTER TO PATAK */
+ XK_Thai_thothan = 0x0db0, /* U+0E10 THAI CHARACTER THO THAN */
+ XK_Thai_thonangmontho = 0x0db1, /* U+0E11 THAI CHARACTER THO NANGMONTHO */
+ XK_Thai_thophuthao = 0x0db2, /* U+0E12 THAI CHARACTER THO PHUTHAO */
+ XK_Thai_nonen = 0x0db3, /* U+0E13 THAI CHARACTER NO NEN */
+ XK_Thai_dodek = 0x0db4, /* U+0E14 THAI CHARACTER DO DEK */
+ XK_Thai_totao = 0x0db5, /* U+0E15 THAI CHARACTER TO TAO */
+ XK_Thai_thothung = 0x0db6, /* U+0E16 THAI CHARACTER THO THUNG */
+ XK_Thai_thothahan = 0x0db7, /* U+0E17 THAI CHARACTER THO THAHAN */
+ XK_Thai_thothong = 0x0db8, /* U+0E18 THAI CHARACTER THO THONG */
+ XK_Thai_nonu = 0x0db9, /* U+0E19 THAI CHARACTER NO NU */
+ XK_Thai_bobaimai = 0x0dba, /* U+0E1A THAI CHARACTER BO BAIMAI */
+ XK_Thai_popla = 0x0dbb, /* U+0E1B THAI CHARACTER PO PLA */
+ XK_Thai_phophung = 0x0dbc, /* U+0E1C THAI CHARACTER PHO PHUNG */
+ XK_Thai_fofa = 0x0dbd, /* U+0E1D THAI CHARACTER FO FA */
+ XK_Thai_phophan = 0x0dbe, /* U+0E1E THAI CHARACTER PHO PHAN */
+ XK_Thai_fofan = 0x0dbf, /* U+0E1F THAI CHARACTER FO FAN */
+ XK_Thai_phosamphao = 0x0dc0, /* U+0E20 THAI CHARACTER PHO SAMPHAO */
+ XK_Thai_moma = 0x0dc1, /* U+0E21 THAI CHARACTER MO MA */
+ XK_Thai_yoyak = 0x0dc2, /* U+0E22 THAI CHARACTER YO YAK */
+ XK_Thai_rorua = 0x0dc3, /* U+0E23 THAI CHARACTER RO RUA */
+ XK_Thai_ru = 0x0dc4, /* U+0E24 THAI CHARACTER RU */
+ XK_Thai_loling = 0x0dc5, /* U+0E25 THAI CHARACTER LO LING */
+ XK_Thai_lu = 0x0dc6, /* U+0E26 THAI CHARACTER LU */
+ XK_Thai_wowaen = 0x0dc7, /* U+0E27 THAI CHARACTER WO WAEN */
+ XK_Thai_sosala = 0x0dc8, /* U+0E28 THAI CHARACTER SO SALA */
+ XK_Thai_sorusi = 0x0dc9, /* U+0E29 THAI CHARACTER SO RUSI */
+ XK_Thai_sosua = 0x0dca, /* U+0E2A THAI CHARACTER SO SUA */
+ XK_Thai_hohip = 0x0dcb, /* U+0E2B THAI CHARACTER HO HIP */
+ XK_Thai_lochula = 0x0dcc, /* U+0E2C THAI CHARACTER LO CHULA */
+ XK_Thai_oang = 0x0dcd, /* U+0E2D THAI CHARACTER O ANG */
+ XK_Thai_honokhuk = 0x0dce, /* U+0E2E THAI CHARACTER HO NOKHUK */
+ XK_Thai_paiyannoi = 0x0dcf, /* U+0E2F THAI CHARACTER PAIYANNOI */
+ XK_Thai_saraa = 0x0dd0, /* U+0E30 THAI CHARACTER SARA A */
+ XK_Thai_maihanakat = 0x0dd1, /* U+0E31 THAI CHARACTER MAI HAN-AKAT */
+ XK_Thai_saraaa = 0x0dd2, /* U+0E32 THAI CHARACTER SARA AA */
+ XK_Thai_saraam = 0x0dd3, /* U+0E33 THAI CHARACTER SARA AM */
+ XK_Thai_sarai = 0x0dd4, /* U+0E34 THAI CHARACTER SARA I */
+ XK_Thai_saraii = 0x0dd5, /* U+0E35 THAI CHARACTER SARA II */
+ XK_Thai_saraue = 0x0dd6, /* U+0E36 THAI CHARACTER SARA UE */
+ XK_Thai_sarauee = 0x0dd7, /* U+0E37 THAI CHARACTER SARA UEE */
+ XK_Thai_sarau = 0x0dd8, /* U+0E38 THAI CHARACTER SARA U */
+ XK_Thai_sarauu = 0x0dd9, /* U+0E39 THAI CHARACTER SARA UU */
+ XK_Thai_phinthu = 0x0dda, /* U+0E3A THAI CHARACTER PHINTHU */
+ XK_Thai_maihanakat_maitho = 0x0dde,
+ XK_Thai_baht = 0x0ddf, /* U+0E3F THAI CURRENCY SYMBOL BAHT */
+ XK_Thai_sarae = 0x0de0, /* U+0E40 THAI CHARACTER SARA E */
+ XK_Thai_saraae = 0x0de1, /* U+0E41 THAI CHARACTER SARA AE */
+ XK_Thai_sarao = 0x0de2, /* U+0E42 THAI CHARACTER SARA O */
+ XK_Thai_saraaimaimuan = 0x0de3, /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */
+ XK_Thai_saraaimaimalai = 0x0de4, /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */
+ XK_Thai_lakkhangyao = 0x0de5, /* U+0E45 THAI CHARACTER LAKKHANGYAO */
+ XK_Thai_maiyamok = 0x0de6, /* U+0E46 THAI CHARACTER MAIYAMOK */
+ XK_Thai_maitaikhu = 0x0de7, /* U+0E47 THAI CHARACTER MAITAIKHU */
+ XK_Thai_maiek = 0x0de8, /* U+0E48 THAI CHARACTER MAI EK */
+ XK_Thai_maitho = 0x0de9, /* U+0E49 THAI CHARACTER MAI THO */
+ XK_Thai_maitri = 0x0dea, /* U+0E4A THAI CHARACTER MAI TRI */
+ XK_Thai_maichattawa = 0x0deb, /* U+0E4B THAI CHARACTER MAI CHATTAWA */
+ XK_Thai_thanthakhat = 0x0dec, /* U+0E4C THAI CHARACTER THANTHAKHAT */
+ XK_Thai_nikhahit = 0x0ded, /* U+0E4D THAI CHARACTER NIKHAHIT */
+ XK_Thai_leksun = 0x0df0, /* U+0E50 THAI DIGIT ZERO */
+ XK_Thai_leknung = 0x0df1, /* U+0E51 THAI DIGIT ONE */
+ XK_Thai_leksong = 0x0df2, /* U+0E52 THAI DIGIT TWO */
+ XK_Thai_leksam = 0x0df3, /* U+0E53 THAI DIGIT THREE */
+ XK_Thai_leksi = 0x0df4, /* U+0E54 THAI DIGIT FOUR */
+ XK_Thai_lekha = 0x0df5, /* U+0E55 THAI DIGIT FIVE */
+ XK_Thai_lekhok = 0x0df6, /* U+0E56 THAI DIGIT SIX */
+ XK_Thai_lekchet = 0x0df7, /* U+0E57 THAI DIGIT SEVEN */
+ XK_Thai_lekpaet = 0x0df8, /* U+0E58 THAI DIGIT EIGHT */
+ XK_Thai_lekkao = 0x0df9, /* U+0E59 THAI DIGIT NINE */
+
+ /*
+ * Korean
+ * Byte 3 = = 0x0e
+ */
+
+ // MARK: - XK_KOREAN
+
+ XK_Hangul = 0xff31, /* Hangul start/stop(toggle) */
+ XK_Hangul_Start = 0xff32, /* Hangul start */
+ XK_Hangul_End = 0xff33, /* Hangul end, English start */
+ XK_Hangul_Hanja = 0xff34, /* Start Hangul->Hanja Conversion */
+ XK_Hangul_Jamo = 0xff35, /* Hangul Jamo mode */
+ XK_Hangul_Romaja = 0xff36, /* Hangul Romaja mode */
+ XK_Hangul_Codeinput = 0xff37, /* Hangul code input mode */
+ XK_Hangul_Jeonja = 0xff38, /* Jeonja mode */
+ XK_Hangul_Banja = 0xff39, /* Banja mode */
+ XK_Hangul_PreHanja = 0xff3a, /* Pre Hanja conversion */
+ XK_Hangul_PostHanja = 0xff3b, /* Post Hanja conversion */
+ XK_Hangul_SingleCandidate = 0xff3c, /* Single candidate */
+ XK_Hangul_MultipleCandidate = 0xff3d, /* Multiple candidate */
+ XK_Hangul_PreviousCandidate = 0xff3e, /* Previous candidate */
+ XK_Hangul_Special = 0xff3f, /* Special symbols */
+ XK_Hangul_switch = 0xff7e, /* Alias for mode_switch */
+
+ /* Hangul Consonant Characters */
+ XK_Hangul_Kiyeog = 0x0ea1, /* U+3131 HANGUL LETTER KIYEOK */
+ XK_Hangul_SsangKiyeog = 0x0ea2, /* U+3132 HANGUL LETTER SSANGKIYEOK */
+ XK_Hangul_KiyeogSios = 0x0ea3, /* U+3133 HANGUL LETTER KIYEOK-SIOS */
+ XK_Hangul_Nieun = 0x0ea4, /* U+3134 HANGUL LETTER NIEUN */
+ XK_Hangul_NieunJieuj = 0x0ea5, /* U+3135 HANGUL LETTER NIEUN-CIEUC */
+ XK_Hangul_NieunHieuh = 0x0ea6, /* U+3136 HANGUL LETTER NIEUN-HIEUH */
+ XK_Hangul_Dikeud = 0x0ea7, /* U+3137 HANGUL LETTER TIKEUT */
+ XK_Hangul_SsangDikeud = 0x0ea8, /* U+3138 HANGUL LETTER SSANGTIKEUT */
+ XK_Hangul_Rieul = 0x0ea9, /* U+3139 HANGUL LETTER RIEUL */
+ XK_Hangul_RieulKiyeog = 0x0eaa, /* U+313A HANGUL LETTER RIEUL-KIYEOK */
+ XK_Hangul_RieulMieum = 0x0eab, /* U+313B HANGUL LETTER RIEUL-MIEUM */
+ XK_Hangul_RieulPieub = 0x0eac, /* U+313C HANGUL LETTER RIEUL-PIEUP */
+ XK_Hangul_RieulSios = 0x0ead, /* U+313D HANGUL LETTER RIEUL-SIOS */
+ XK_Hangul_RieulTieut = 0x0eae, /* U+313E HANGUL LETTER RIEUL-THIEUTH */
+ XK_Hangul_RieulPhieuf = 0x0eaf, /* U+313F HANGUL LETTER RIEUL-PHIEUPH */
+ XK_Hangul_RieulHieuh = 0x0eb0, /* U+3140 HANGUL LETTER RIEUL-HIEUH */
+ XK_Hangul_Mieum = 0x0eb1, /* U+3141 HANGUL LETTER MIEUM */
+ XK_Hangul_Pieub = 0x0eb2, /* U+3142 HANGUL LETTER PIEUP */
+ XK_Hangul_SsangPieub = 0x0eb3, /* U+3143 HANGUL LETTER SSANGPIEUP */
+ XK_Hangul_PieubSios = 0x0eb4, /* U+3144 HANGUL LETTER PIEUP-SIOS */
+ XK_Hangul_Sios = 0x0eb5, /* U+3145 HANGUL LETTER SIOS */
+ XK_Hangul_SsangSios = 0x0eb6, /* U+3146 HANGUL LETTER SSANGSIOS */
+ XK_Hangul_Ieung = 0x0eb7, /* U+3147 HANGUL LETTER IEUNG */
+ XK_Hangul_Jieuj = 0x0eb8, /* U+3148 HANGUL LETTER CIEUC */
+ XK_Hangul_SsangJieuj = 0x0eb9, /* U+3149 HANGUL LETTER SSANGCIEUC */
+ XK_Hangul_Cieuc = 0x0eba, /* U+314A HANGUL LETTER CHIEUCH */
+ XK_Hangul_Khieuq = 0x0ebb, /* U+314B HANGUL LETTER KHIEUKH */
+ XK_Hangul_Tieut = 0x0ebc, /* U+314C HANGUL LETTER THIEUTH */
+ XK_Hangul_Phieuf = 0x0ebd, /* U+314D HANGUL LETTER PHIEUPH */
+ XK_Hangul_Hieuh = 0x0ebe, /* U+314E HANGUL LETTER HIEUH */
+
+ /* Hangul Vowel Characters */
+ XK_Hangul_A = 0x0ebf, /* U+314F HANGUL LETTER A */
+ XK_Hangul_AE = 0x0ec0, /* U+3150 HANGUL LETTER AE */
+ XK_Hangul_YA = 0x0ec1, /* U+3151 HANGUL LETTER YA */
+ XK_Hangul_YAE = 0x0ec2, /* U+3152 HANGUL LETTER YAE */
+ XK_Hangul_EO = 0x0ec3, /* U+3153 HANGUL LETTER EO */
+ XK_Hangul_E = 0x0ec4, /* U+3154 HANGUL LETTER E */
+ XK_Hangul_YEO = 0x0ec5, /* U+3155 HANGUL LETTER YEO */
+ XK_Hangul_YE = 0x0ec6, /* U+3156 HANGUL LETTER YE */
+ XK_Hangul_O = 0x0ec7, /* U+3157 HANGUL LETTER O */
+ XK_Hangul_WA = 0x0ec8, /* U+3158 HANGUL LETTER WA */
+ XK_Hangul_WAE = 0x0ec9, /* U+3159 HANGUL LETTER WAE */
+ XK_Hangul_OE = 0x0eca, /* U+315A HANGUL LETTER OE */
+ XK_Hangul_YO = 0x0ecb, /* U+315B HANGUL LETTER YO */
+ XK_Hangul_U = 0x0ecc, /* U+315C HANGUL LETTER U */
+ XK_Hangul_WEO = 0x0ecd, /* U+315D HANGUL LETTER WEO */
+ XK_Hangul_WE = 0x0ece, /* U+315E HANGUL LETTER WE */
+ XK_Hangul_WI = 0x0ecf, /* U+315F HANGUL LETTER WI */
+ XK_Hangul_YU = 0x0ed0, /* U+3160 HANGUL LETTER YU */
+ XK_Hangul_EU = 0x0ed1, /* U+3161 HANGUL LETTER EU */
+ XK_Hangul_YI = 0x0ed2, /* U+3162 HANGUL LETTER YI */
+ XK_Hangul_I = 0x0ed3, /* U+3163 HANGUL LETTER I */
+
+ /* Hangul syllable-final (JongSeong) Characters */
+ XK_Hangul_J_Kiyeog = 0x0ed4, /* U+11A8 HANGUL JONGSEONG KIYEOK */
+ XK_Hangul_J_SsangKiyeog = 0x0ed5, /* U+11A9 HANGUL JONGSEONG SSANGKIYEOK */
+ XK_Hangul_J_KiyeogSios = 0x0ed6, /* U+11AA HANGUL JONGSEONG KIYEOK-SIOS */
+ XK_Hangul_J_Nieun = 0x0ed7, /* U+11AB HANGUL JONGSEONG NIEUN */
+ XK_Hangul_J_NieunJieuj = 0x0ed8, /* U+11AC HANGUL JONGSEONG NIEUN-CIEUC */
+ XK_Hangul_J_NieunHieuh = 0x0ed9, /* U+11AD HANGUL JONGSEONG NIEUN-HIEUH */
+ XK_Hangul_J_Dikeud = 0x0eda, /* U+11AE HANGUL JONGSEONG TIKEUT */
+ XK_Hangul_J_Rieul = 0x0edb, /* U+11AF HANGUL JONGSEONG RIEUL */
+ XK_Hangul_J_RieulKiyeog = 0x0edc, /* U+11B0 HANGUL JONGSEONG RIEUL-KIYEOK */
+ XK_Hangul_J_RieulMieum = 0x0edd, /* U+11B1 HANGUL JONGSEONG RIEUL-MIEUM */
+ XK_Hangul_J_RieulPieub = 0x0ede, /* U+11B2 HANGUL JONGSEONG RIEUL-PIEUP */
+ XK_Hangul_J_RieulSios = 0x0edf, /* U+11B3 HANGUL JONGSEONG RIEUL-SIOS */
+ XK_Hangul_J_RieulTieut = 0x0ee0, /* U+11B4 HANGUL JONGSEONG RIEUL-THIEUTH */
+ XK_Hangul_J_RieulPhieuf = 0x0ee1, /* U+11B5 HANGUL JONGSEONG RIEUL-PHIEUPH */
+ XK_Hangul_J_RieulHieuh = 0x0ee2, /* U+11B6 HANGUL JONGSEONG RIEUL-HIEUH */
+ XK_Hangul_J_Mieum = 0x0ee3, /* U+11B7 HANGUL JONGSEONG MIEUM */
+ XK_Hangul_J_Pieub = 0x0ee4, /* U+11B8 HANGUL JONGSEONG PIEUP */
+ XK_Hangul_J_PieubSios = 0x0ee5, /* U+11B9 HANGUL JONGSEONG PIEUP-SIOS */
+ XK_Hangul_J_Sios = 0x0ee6, /* U+11BA HANGUL JONGSEONG SIOS */
+ XK_Hangul_J_SsangSios = 0x0ee7, /* U+11BB HANGUL JONGSEONG SSANGSIOS */
+ XK_Hangul_J_Ieung = 0x0ee8, /* U+11BC HANGUL JONGSEONG IEUNG */
+ XK_Hangul_J_Jieuj = 0x0ee9, /* U+11BD HANGUL JONGSEONG CIEUC */
+ XK_Hangul_J_Cieuc = 0x0eea, /* U+11BE HANGUL JONGSEONG CHIEUCH */
+ XK_Hangul_J_Khieuq = 0x0eeb, /* U+11BF HANGUL JONGSEONG KHIEUKH */
+ XK_Hangul_J_Tieut = 0x0eec, /* U+11C0 HANGUL JONGSEONG THIEUTH */
+ XK_Hangul_J_Phieuf = 0x0eed, /* U+11C1 HANGUL JONGSEONG PHIEUPH */
+ XK_Hangul_J_Hieuh = 0x0eee, /* U+11C2 HANGUL JONGSEONG HIEUH */
+
+ /* Ancient Hangul Consonant Characters */
+ XK_Hangul_RieulYeorinHieuh = 0x0eef, /* U+316D HANGUL LETTER RIEUL-YEORINHIEUH */
+ XK_Hangul_SunkyeongeumMieum = 0x0ef0, /* U+3171 HANGUL LETTER KAPYEOUNMIEUM */
+ XK_Hangul_SunkyeongeumPieub = 0x0ef1, /* U+3178 HANGUL LETTER KAPYEOUNPIEUP */
+ XK_Hangul_PanSios = 0x0ef2, /* U+317F HANGUL LETTER PANSIOS */
+ XK_Hangul_KkogjiDalrinIeung = 0x0ef3, /* U+3181 HANGUL LETTER YESIEUNG */
+ XK_Hangul_SunkyeongeumPhieuf = 0x0ef4, /* U+3184 HANGUL LETTER KAPYEOUNPHIEUPH */
+ XK_Hangul_YeorinHieuh = 0x0ef5, /* U+3186 HANGUL LETTER YEORINHIEUH */
+
+ /* Ancient Hangul Vowel Characters */
+ XK_Hangul_AraeA = 0x0ef6, /* U+318D HANGUL LETTER ARAEA */
+ XK_Hangul_AraeAE = 0x0ef7, /* U+318E HANGUL LETTER ARAEAE */
+
+ /* Ancient Hangul syllable-final (JongSeong) Characters */
+ XK_Hangul_J_PanSios = 0x0ef8, /* U+11EB HANGUL JONGSEONG PANSIOS */
+ XK_Hangul_J_KkogjiDalrinIeung = 0x0ef9, /* U+11F0 HANGUL JONGSEONG YESIEUNG */
+ XK_Hangul_J_YeorinHieuh = 0x0efa, /* U+11F9 HANGUL JONGSEONG YEORINHIEUH */
+
+ /* Korean currency symbol */
+ XK_Korean_Won = 0x0eff, /*(U+20A9 WON SIGN)*/
+
+ /*
+ * Armenian
+ */
+
+ // MARK: - XK_ARMENIAN
+ XK_Armenian_ligature_ew = 0x1000587, /* U+0587 ARMENIAN SMALL LIGATURE ECH YIWN */
+ XK_Armenian_full_stop = 0x1000589, /* U+0589 ARMENIAN FULL STOP */
+ XK_Armenian_verjaket = 0x1000589, /* U+0589 ARMENIAN FULL STOP */
+ XK_Armenian_separation_mark = 0x100055d, /* U+055D ARMENIAN COMMA */
+ XK_Armenian_but = 0x100055d, /* U+055D ARMENIAN COMMA */
+ XK_Armenian_hyphen = 0x100058a, /* U+058A ARMENIAN HYPHEN */
+ XK_Armenian_yentamna = 0x100058a, /* U+058A ARMENIAN HYPHEN */
+ XK_Armenian_exclam = 0x100055c, /* U+055C ARMENIAN EXCLAMATION MARK */
+ XK_Armenian_amanak = 0x100055c, /* U+055C ARMENIAN EXCLAMATION MARK */
+ XK_Armenian_accent = 0x100055b, /* U+055B ARMENIAN EMPHASIS MARK */
+ XK_Armenian_shesht = 0x100055b, /* U+055B ARMENIAN EMPHASIS MARK */
+ XK_Armenian_question = 0x100055e, /* U+055E ARMENIAN QUESTION MARK */
+ XK_Armenian_paruyk = 0x100055e, /* U+055E ARMENIAN QUESTION MARK */
+ XK_Armenian_AYB = 0x1000531, /* U+0531 ARMENIAN CAPITAL LETTER AYB */
+ XK_Armenian_ayb = 0x1000561, /* U+0561 ARMENIAN SMALL LETTER AYB */
+ XK_Armenian_BEN = 0x1000532, /* U+0532 ARMENIAN CAPITAL LETTER BEN */
+ XK_Armenian_ben = 0x1000562, /* U+0562 ARMENIAN SMALL LETTER BEN */
+ XK_Armenian_GIM = 0x1000533, /* U+0533 ARMENIAN CAPITAL LETTER GIM */
+ XK_Armenian_gim = 0x1000563, /* U+0563 ARMENIAN SMALL LETTER GIM */
+ XK_Armenian_DA = 0x1000534, /* U+0534 ARMENIAN CAPITAL LETTER DA */
+ XK_Armenian_da = 0x1000564, /* U+0564 ARMENIAN SMALL LETTER DA */
+ XK_Armenian_YECH = 0x1000535, /* U+0535 ARMENIAN CAPITAL LETTER ECH */
+ XK_Armenian_yech = 0x1000565, /* U+0565 ARMENIAN SMALL LETTER ECH */
+ XK_Armenian_ZA = 0x1000536, /* U+0536 ARMENIAN CAPITAL LETTER ZA */
+ XK_Armenian_za = 0x1000566, /* U+0566 ARMENIAN SMALL LETTER ZA */
+ XK_Armenian_E = 0x1000537, /* U+0537 ARMENIAN CAPITAL LETTER EH */
+ XK_Armenian_e = 0x1000567, /* U+0567 ARMENIAN SMALL LETTER EH */
+ XK_Armenian_AT = 0x1000538, /* U+0538 ARMENIAN CAPITAL LETTER ET */
+ XK_Armenian_at = 0x1000568, /* U+0568 ARMENIAN SMALL LETTER ET */
+ XK_Armenian_TO = 0x1000539, /* U+0539 ARMENIAN CAPITAL LETTER TO */
+ XK_Armenian_to = 0x1000569, /* U+0569 ARMENIAN SMALL LETTER TO */
+ XK_Armenian_ZHE = 0x100053a, /* U+053A ARMENIAN CAPITAL LETTER ZHE */
+ XK_Armenian_zhe = 0x100056a, /* U+056A ARMENIAN SMALL LETTER ZHE */
+ XK_Armenian_INI = 0x100053b, /* U+053B ARMENIAN CAPITAL LETTER INI */
+ XK_Armenian_ini = 0x100056b, /* U+056B ARMENIAN SMALL LETTER INI */
+ XK_Armenian_LYUN = 0x100053c, /* U+053C ARMENIAN CAPITAL LETTER LIWN */
+ XK_Armenian_lyun = 0x100056c, /* U+056C ARMENIAN SMALL LETTER LIWN */
+ XK_Armenian_KHE = 0x100053d, /* U+053D ARMENIAN CAPITAL LETTER XEH */
+ XK_Armenian_khe = 0x100056d, /* U+056D ARMENIAN SMALL LETTER XEH */
+ XK_Armenian_TSA = 0x100053e, /* U+053E ARMENIAN CAPITAL LETTER CA */
+ XK_Armenian_tsa = 0x100056e, /* U+056E ARMENIAN SMALL LETTER CA */
+ XK_Armenian_KEN = 0x100053f, /* U+053F ARMENIAN CAPITAL LETTER KEN */
+ XK_Armenian_ken = 0x100056f, /* U+056F ARMENIAN SMALL LETTER KEN */
+ XK_Armenian_HO = 0x1000540, /* U+0540 ARMENIAN CAPITAL LETTER HO */
+ XK_Armenian_ho = 0x1000570, /* U+0570 ARMENIAN SMALL LETTER HO */
+ XK_Armenian_DZA = 0x1000541, /* U+0541 ARMENIAN CAPITAL LETTER JA */
+ XK_Armenian_dza = 0x1000571, /* U+0571 ARMENIAN SMALL LETTER JA */
+ XK_Armenian_GHAT = 0x1000542, /* U+0542 ARMENIAN CAPITAL LETTER GHAD */
+ XK_Armenian_ghat = 0x1000572, /* U+0572 ARMENIAN SMALL LETTER GHAD */
+ XK_Armenian_TCHE = 0x1000543, /* U+0543 ARMENIAN CAPITAL LETTER CHEH */
+ XK_Armenian_tche = 0x1000573, /* U+0573 ARMENIAN SMALL LETTER CHEH */
+ XK_Armenian_MEN = 0x1000544, /* U+0544 ARMENIAN CAPITAL LETTER MEN */
+ XK_Armenian_men = 0x1000574, /* U+0574 ARMENIAN SMALL LETTER MEN */
+ XK_Armenian_HI = 0x1000545, /* U+0545 ARMENIAN CAPITAL LETTER YI */
+ XK_Armenian_hi = 0x1000575, /* U+0575 ARMENIAN SMALL LETTER YI */
+ XK_Armenian_NU = 0x1000546, /* U+0546 ARMENIAN CAPITAL LETTER NOW */
+ XK_Armenian_nu = 0x1000576, /* U+0576 ARMENIAN SMALL LETTER NOW */
+ XK_Armenian_SHA = 0x1000547, /* U+0547 ARMENIAN CAPITAL LETTER SHA */
+ XK_Armenian_sha = 0x1000577, /* U+0577 ARMENIAN SMALL LETTER SHA */
+ XK_Armenian_VO = 0x1000548, /* U+0548 ARMENIAN CAPITAL LETTER VO */
+ XK_Armenian_vo = 0x1000578, /* U+0578 ARMENIAN SMALL LETTER VO */
+ XK_Armenian_CHA = 0x1000549, /* U+0549 ARMENIAN CAPITAL LETTER CHA */
+ XK_Armenian_cha = 0x1000579, /* U+0579 ARMENIAN SMALL LETTER CHA */
+ XK_Armenian_PE = 0x100054a, /* U+054A ARMENIAN CAPITAL LETTER PEH */
+ XK_Armenian_pe = 0x100057a, /* U+057A ARMENIAN SMALL LETTER PEH */
+ XK_Armenian_JE = 0x100054b, /* U+054B ARMENIAN CAPITAL LETTER JHEH */
+ XK_Armenian_je = 0x100057b, /* U+057B ARMENIAN SMALL LETTER JHEH */
+ XK_Armenian_RA = 0x100054c, /* U+054C ARMENIAN CAPITAL LETTER RA */
+ XK_Armenian_ra = 0x100057c, /* U+057C ARMENIAN SMALL LETTER RA */
+ XK_Armenian_SE = 0x100054d, /* U+054D ARMENIAN CAPITAL LETTER SEH */
+ XK_Armenian_se = 0x100057d, /* U+057D ARMENIAN SMALL LETTER SEH */
+ XK_Armenian_VEV = 0x100054e, /* U+054E ARMENIAN CAPITAL LETTER VEW */
+ XK_Armenian_vev = 0x100057e, /* U+057E ARMENIAN SMALL LETTER VEW */
+ XK_Armenian_TYUN = 0x100054f, /* U+054F ARMENIAN CAPITAL LETTER TIWN */
+ XK_Armenian_tyun = 0x100057f, /* U+057F ARMENIAN SMALL LETTER TIWN */
+ XK_Armenian_RE = 0x1000550, /* U+0550 ARMENIAN CAPITAL LETTER REH */
+ XK_Armenian_re = 0x1000580, /* U+0580 ARMENIAN SMALL LETTER REH */
+ XK_Armenian_TSO = 0x1000551, /* U+0551 ARMENIAN CAPITAL LETTER CO */
+ XK_Armenian_tso = 0x1000581, /* U+0581 ARMENIAN SMALL LETTER CO */
+ XK_Armenian_VYUN = 0x1000552, /* U+0552 ARMENIAN CAPITAL LETTER YIWN */
+ XK_Armenian_vyun = 0x1000582, /* U+0582 ARMENIAN SMALL LETTER YIWN */
+ XK_Armenian_PYUR = 0x1000553, /* U+0553 ARMENIAN CAPITAL LETTER PIWR */
+ XK_Armenian_pyur = 0x1000583, /* U+0583 ARMENIAN SMALL LETTER PIWR */
+ XK_Armenian_KE = 0x1000554, /* U+0554 ARMENIAN CAPITAL LETTER KEH */
+ XK_Armenian_ke = 0x1000584, /* U+0584 ARMENIAN SMALL LETTER KEH */
+ XK_Armenian_O = 0x1000555, /* U+0555 ARMENIAN CAPITAL LETTER OH */
+ XK_Armenian_o = 0x1000585, /* U+0585 ARMENIAN SMALL LETTER OH */
+ XK_Armenian_FE = 0x1000556, /* U+0556 ARMENIAN CAPITAL LETTER FEH */
+ XK_Armenian_fe = 0x1000586, /* U+0586 ARMENIAN SMALL LETTER FEH */
+ XK_Armenian_apostrophe = 0x100055a, /* U+055A ARMENIAN APOSTROPHE */
+
+ /*
+ * Georgian
+ */
+
+ // MARK: - XK_GEORGIAN
+ XK_Georgian_an = 0x10010d0, /* U+10D0 GEORGIAN LETTER AN */
+ XK_Georgian_ban = 0x10010d1, /* U+10D1 GEORGIAN LETTER BAN */
+ XK_Georgian_gan = 0x10010d2, /* U+10D2 GEORGIAN LETTER GAN */
+ XK_Georgian_don = 0x10010d3, /* U+10D3 GEORGIAN LETTER DON */
+ XK_Georgian_en = 0x10010d4, /* U+10D4 GEORGIAN LETTER EN */
+ XK_Georgian_vin = 0x10010d5, /* U+10D5 GEORGIAN LETTER VIN */
+ XK_Georgian_zen = 0x10010d6, /* U+10D6 GEORGIAN LETTER ZEN */
+ XK_Georgian_tan = 0x10010d7, /* U+10D7 GEORGIAN LETTER TAN */
+ XK_Georgian_in = 0x10010d8, /* U+10D8 GEORGIAN LETTER IN */
+ XK_Georgian_kan = 0x10010d9, /* U+10D9 GEORGIAN LETTER KAN */
+ XK_Georgian_las = 0x10010da, /* U+10DA GEORGIAN LETTER LAS */
+ XK_Georgian_man = 0x10010db, /* U+10DB GEORGIAN LETTER MAN */
+ XK_Georgian_nar = 0x10010dc, /* U+10DC GEORGIAN LETTER NAR */
+ XK_Georgian_on = 0x10010dd, /* U+10DD GEORGIAN LETTER ON */
+ XK_Georgian_par = 0x10010de, /* U+10DE GEORGIAN LETTER PAR */
+ XK_Georgian_zhar = 0x10010df, /* U+10DF GEORGIAN LETTER ZHAR */
+ XK_Georgian_rae = 0x10010e0, /* U+10E0 GEORGIAN LETTER RAE */
+ XK_Georgian_san = 0x10010e1, /* U+10E1 GEORGIAN LETTER SAN */
+ XK_Georgian_tar = 0x10010e2, /* U+10E2 GEORGIAN LETTER TAR */
+ XK_Georgian_un = 0x10010e3, /* U+10E3 GEORGIAN LETTER UN */
+ XK_Georgian_phar = 0x10010e4, /* U+10E4 GEORGIAN LETTER PHAR */
+ XK_Georgian_khar = 0x10010e5, /* U+10E5 GEORGIAN LETTER KHAR */
+ XK_Georgian_ghan = 0x10010e6, /* U+10E6 GEORGIAN LETTER GHAN */
+ XK_Georgian_qar = 0x10010e7, /* U+10E7 GEORGIAN LETTER QAR */
+ XK_Georgian_shin = 0x10010e8, /* U+10E8 GEORGIAN LETTER SHIN */
+ XK_Georgian_chin = 0x10010e9, /* U+10E9 GEORGIAN LETTER CHIN */
+ XK_Georgian_can = 0x10010ea, /* U+10EA GEORGIAN LETTER CAN */
+ XK_Georgian_jil = 0x10010eb, /* U+10EB GEORGIAN LETTER JIL */
+ XK_Georgian_cil = 0x10010ec, /* U+10EC GEORGIAN LETTER CIL */
+ XK_Georgian_char = 0x10010ed, /* U+10ED GEORGIAN LETTER CHAR */
+ XK_Georgian_xan = 0x10010ee, /* U+10EE GEORGIAN LETTER XAN */
+ XK_Georgian_jhan = 0x10010ef, /* U+10EF GEORGIAN LETTER JHAN */
+ XK_Georgian_hae = 0x10010f0, /* U+10F0 GEORGIAN LETTER HAE */
+ XK_Georgian_he = 0x10010f1, /* U+10F1 GEORGIAN LETTER HE */
+ XK_Georgian_hie = 0x10010f2, /* U+10F2 GEORGIAN LETTER HIE */
+ XK_Georgian_we = 0x10010f3, /* U+10F3 GEORGIAN LETTER WE */
+ XK_Georgian_har = 0x10010f4, /* U+10F4 GEORGIAN LETTER HAR */
+ XK_Georgian_hoe = 0x10010f5, /* U+10F5 GEORGIAN LETTER HOE */
+ XK_Georgian_fi = 0x10010f6, /* U+10F6 GEORGIAN LETTER FI */
+
+ /*
+ * Azeri (and other Turkic or Caucasian languages)
+ */
+
+ // MARK: - XK_CAUCASUS
+ /* latin */
+ XK_Xabovedot = 0x1001e8a, /* U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE */
+ XK_Ibreve = 0x100012c, /* U+012C LATIN CAPITAL LETTER I WITH BREVE */
+ XK_Zstroke = 0x10001b5, /* U+01B5 LATIN CAPITAL LETTER Z WITH STROKE */
+ XK_Gcaron = 0x10001e6, /* U+01E6 LATIN CAPITAL LETTER G WITH CARON */
+ XK_Ocaron = 0x10001d1, /* U+01D1 LATIN CAPITAL LETTER O WITH CARON */
+ XK_Obarred = 0x100019f, /* U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE */
+ XK_xabovedot = 0x1001e8b, /* U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE */
+ XK_ibreve = 0x100012d, /* U+012D LATIN SMALL LETTER I WITH BREVE */
+ XK_zstroke = 0x10001b6, /* U+01B6 LATIN SMALL LETTER Z WITH STROKE */
+ XK_gcaron = 0x10001e7, /* U+01E7 LATIN SMALL LETTER G WITH CARON */
+ XK_ocaron = 0x10001d2, /* U+01D2 LATIN SMALL LETTER O WITH CARON */
+ XK_obarred = 0x1000275, /* U+0275 LATIN SMALL LETTER BARRED O */
+ XK_SCHWA = 0x100018f, /* U+018F LATIN CAPITAL LETTER SCHWA */
+ XK_schwa = 0x1000259, /* U+0259 LATIN SMALL LETTER SCHWA */
+ XK_EZH = 0x10001b7, /* U+01B7 LATIN CAPITAL LETTER EZH */
+ XK_ezh = 0x1000292, /* U+0292 LATIN SMALL LETTER EZH */
+ /* those are not really Caucasus */
+ /* For Inupiak */
+ XK_Lbelowdot = 0x1001e36, /* U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW */
+ XK_lbelowdot = 0x1001e37, /* U+1E37 LATIN SMALL LETTER L WITH DOT BELOW */
+
+ /*
+ * Vietnamese
+ */
+
+ // MARK: - XK_VIETNAMESE
+ XK_Abelowdot = 0x1001ea0, /* U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW */
+ XK_abelowdot = 0x1001ea1, /* U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW */
+ XK_Ahook = 0x1001ea2, /* U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE */
+ XK_ahook = 0x1001ea3, /* U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE */
+ XK_Acircumflexacute = 0x1001ea4, /* U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */
+ XK_acircumflexacute = 0x1001ea5, /* U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */
+ XK_Acircumflexgrave = 0x1001ea6, /* U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */
+ XK_acircumflexgrave = 0x1001ea7, /* U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */
+ XK_Acircumflexhook = 0x1001ea8, /* U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */
+ XK_acircumflexhook = 0x1001ea9, /* U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */
+ XK_Acircumflextilde = 0x1001eaa, /* U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */
+ XK_acircumflextilde = 0x1001eab, /* U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */
+ XK_Acircumflexbelowdot = 0x1001eac, /* U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */
+ XK_acircumflexbelowdot = 0x1001ead, /* U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */
+ XK_Abreveacute = 0x1001eae, /* U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */
+ XK_abreveacute = 0x1001eaf, /* U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE */
+ XK_Abrevegrave = 0x1001eb0, /* U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */
+ XK_abrevegrave = 0x1001eb1, /* U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE */
+ XK_Abrevehook = 0x1001eb2, /* U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */
+ XK_abrevehook = 0x1001eb3, /* U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */
+ XK_Abrevetilde = 0x1001eb4, /* U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE */
+ XK_abrevetilde = 0x1001eb5, /* U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE */
+ XK_Abrevebelowdot = 0x1001eb6, /* U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */
+ XK_abrevebelowdot = 0x1001eb7, /* U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */
+ XK_Ebelowdot = 0x1001eb8, /* U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW */
+ XK_ebelowdot = 0x1001eb9, /* U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW */
+ XK_Ehook = 0x1001eba, /* U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE */
+ XK_ehook = 0x1001ebb, /* U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE */
+ XK_Etilde = 0x1001ebc, /* U+1EBC LATIN CAPITAL LETTER E WITH TILDE */
+ XK_etilde = 0x1001ebd, /* U+1EBD LATIN SMALL LETTER E WITH TILDE */
+ XK_Ecircumflexacute = 0x1001ebe, /* U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */
+ XK_ecircumflexacute = 0x1001ebf, /* U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */
+ XK_Ecircumflexgrave = 0x1001ec0, /* U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */
+ XK_ecircumflexgrave = 0x1001ec1, /* U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */
+ XK_Ecircumflexhook = 0x1001ec2, /* U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */
+ XK_ecircumflexhook = 0x1001ec3, /* U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */
+ XK_Ecircumflextilde = 0x1001ec4, /* U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */
+ XK_ecircumflextilde = 0x1001ec5, /* U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */
+ XK_Ecircumflexbelowdot = 0x1001ec6, /* U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */
+ XK_ecircumflexbelowdot = 0x1001ec7, /* U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */
+ XK_Ihook = 0x1001ec8, /* U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE */
+ XK_ihook = 0x1001ec9, /* U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE */
+ XK_Ibelowdot = 0x1001eca, /* U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW */
+ XK_ibelowdot = 0x1001ecb, /* U+1ECB LATIN SMALL LETTER I WITH DOT BELOW */
+ XK_Obelowdot = 0x1001ecc, /* U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW */
+ XK_obelowdot = 0x1001ecd, /* U+1ECD LATIN SMALL LETTER O WITH DOT BELOW */
+ XK_Ohook = 0x1001ece, /* U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE */
+ XK_ohook = 0x1001ecf, /* U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE */
+ XK_Ocircumflexacute = 0x1001ed0, /* U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */
+ XK_ocircumflexacute = 0x1001ed1, /* U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */
+ XK_Ocircumflexgrave = 0x1001ed2, /* U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */
+ XK_ocircumflexgrave = 0x1001ed3, /* U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */
+ XK_Ocircumflexhook = 0x1001ed4, /* U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */
+ XK_ocircumflexhook = 0x1001ed5, /* U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */
+ XK_Ocircumflextilde = 0x1001ed6, /* U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */
+ XK_ocircumflextilde = 0x1001ed7, /* U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */
+ XK_Ocircumflexbelowdot = 0x1001ed8, /* U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */
+ XK_ocircumflexbelowdot = 0x1001ed9, /* U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */
+ XK_Ohornacute = 0x1001eda, /* U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE */
+ XK_ohornacute = 0x1001edb, /* U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE */
+ XK_Ohorngrave = 0x1001edc, /* U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE */
+ XK_ohorngrave = 0x1001edd, /* U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE */
+ XK_Ohornhook = 0x1001ede, /* U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */
+ XK_ohornhook = 0x1001edf, /* U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */
+ XK_Ohorntilde = 0x1001ee0, /* U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE */
+ XK_ohorntilde = 0x1001ee1, /* U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE */
+ XK_Ohornbelowdot = 0x1001ee2, /* U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */
+ XK_ohornbelowdot = 0x1001ee3, /* U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW */
+ XK_Ubelowdot = 0x1001ee4, /* U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW */
+ XK_ubelowdot = 0x1001ee5, /* U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW */
+ XK_Uhook = 0x1001ee6, /* U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE */
+ XK_uhook = 0x1001ee7, /* U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE */
+ XK_Uhornacute = 0x1001ee8, /* U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE */
+ XK_uhornacute = 0x1001ee9, /* U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE */
+ XK_Uhorngrave = 0x1001eea, /* U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE */
+ XK_uhorngrave = 0x1001eeb, /* U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE */
+ XK_Uhornhook = 0x1001eec, /* U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */
+ XK_uhornhook = 0x1001eed, /* U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */
+ XK_Uhorntilde = 0x1001eee, /* U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE */
+ XK_uhorntilde = 0x1001eef, /* U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE */
+ XK_Uhornbelowdot = 0x1001ef0, /* U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */
+ XK_uhornbelowdot = 0x1001ef1, /* U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW */
+ XK_Ybelowdot = 0x1001ef4, /* U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW */
+ XK_ybelowdot = 0x1001ef5, /* U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW */
+ XK_Yhook = 0x1001ef6, /* U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE */
+ XK_yhook = 0x1001ef7, /* U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE */
+ XK_Ytilde = 0x1001ef8, /* U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE */
+ XK_ytilde = 0x1001ef9, /* U+1EF9 LATIN SMALL LETTER Y WITH TILDE */
+ XK_Ohorn = 0x10001a0, /* U+01A0 LATIN CAPITAL LETTER O WITH HORN */
+ XK_ohorn = 0x10001a1, /* U+01A1 LATIN SMALL LETTER O WITH HORN */
+ XK_Uhorn = 0x10001af, /* U+01AF LATIN CAPITAL LETTER U WITH HORN */
+ XK_uhorn = 0x10001b0, /* U+01B0 LATIN SMALL LETTER U WITH HORN */
+ XK_combining_tilde = 0x1000303, /* U+0303 COMBINING TILDE */
+ XK_combining_grave = 0x1000300, /* U+0300 COMBINING GRAVE ACCENT */
+ XK_combining_acute = 0x1000301, /* U+0301 COMBINING ACUTE ACCENT */
+ XK_combining_hook = 0x1000309, /* U+0309 COMBINING HOOK ABOVE */
+ XK_combining_belowdot = 0x1000323, /* U+0323 COMBINING DOT BELOW */
+
+ // MARK: - XK_CURRENCY
+ XK_EcuSign = 0x10020a0, /* U+20A0 EURO-CURRENCY SIGN */
+ XK_ColonSign = 0x10020a1, /* U+20A1 COLON SIGN */
+ XK_CruzeiroSign = 0x10020a2, /* U+20A2 CRUZEIRO SIGN */
+ XK_FFrancSign = 0x10020a3, /* U+20A3 FRENCH FRANC SIGN */
+ XK_LiraSign = 0x10020a4, /* U+20A4 LIRA SIGN */
+ XK_MillSign = 0x10020a5, /* U+20A5 MILL SIGN */
+ XK_NairaSign = 0x10020a6, /* U+20A6 NAIRA SIGN */
+ XK_PesetaSign = 0x10020a7, /* U+20A7 PESETA SIGN */
+ XK_RupeeSign = 0x10020a8, /* U+20A8 RUPEE SIGN */
+ XK_WonSign = 0x10020a9, /* U+20A9 WON SIGN */
+ XK_NewSheqelSign = 0x10020aa, /* U+20AA NEW SHEQEL SIGN */
+ XK_DongSign = 0x10020ab, /* U+20AB DONG SIGN */
+ XK_EuroSign = 0x20ac, /* U+20AC EURO SIGN */
+
+ // MARK: - XK_MATHEMATICAL
+ /* one, two and three are defined above. */
+ XK_zerosuperior = 0x1002070, /* U+2070 SUPERSCRIPT ZERO */
+ XK_foursuperior = 0x1002074, /* U+2074 SUPERSCRIPT FOUR */
+ XK_fivesuperior = 0x1002075, /* U+2075 SUPERSCRIPT FIVE */
+ XK_sixsuperior = 0x1002076, /* U+2076 SUPERSCRIPT SIX */
+ XK_sevensuperior = 0x1002077, /* U+2077 SUPERSCRIPT SEVEN */
+ XK_eightsuperior = 0x1002078, /* U+2078 SUPERSCRIPT EIGHT */
+ XK_ninesuperior = 0x1002079, /* U+2079 SUPERSCRIPT NINE */
+ XK_zerosubscript = 0x1002080, /* U+2080 SUBSCRIPT ZERO */
+ XK_onesubscript = 0x1002081, /* U+2081 SUBSCRIPT ONE */
+ XK_twosubscript = 0x1002082, /* U+2082 SUBSCRIPT TWO */
+ XK_threesubscript = 0x1002083, /* U+2083 SUBSCRIPT THREE */
+ XK_foursubscript = 0x1002084, /* U+2084 SUBSCRIPT FOUR */
+ XK_fivesubscript = 0x1002085, /* U+2085 SUBSCRIPT FIVE */
+ XK_sixsubscript = 0x1002086, /* U+2086 SUBSCRIPT SIX */
+ XK_sevensubscript = 0x1002087, /* U+2087 SUBSCRIPT SEVEN */
+ XK_eightsubscript = 0x1002088, /* U+2088 SUBSCRIPT EIGHT */
+ XK_ninesubscript = 0x1002089, /* U+2089 SUBSCRIPT NINE */
+ XK_partdifferential = 0x1002202, /* U+2202 PARTIAL DIFFERENTIAL */
+ XK_emptyset = 0x1002205, /* U+2205 NULL SET */
+ XK_elementof = 0x1002208, /* U+2208 ELEMENT OF */
+ XK_notelementof = 0x1002209, /* U+2209 NOT AN ELEMENT OF */
+ XK_containsas = 0x100220B, /* U+220B CONTAINS AS MEMBER */
+ XK_squareroot = 0x100221A, /* U+221A SQUARE ROOT */
+ XK_cuberoot = 0x100221B, /* U+221B CUBE ROOT */
+ XK_fourthroot = 0x100221C, /* U+221C FOURTH ROOT */
+ XK_dintegral = 0x100222C, /* U+222C DOUBLE INTEGRAL */
+ XK_tintegral = 0x100222D, /* U+222D TRIPLE INTEGRAL */
+ XK_because = 0x1002235, /* U+2235 BECAUSE */
+ XK_approxeq = 0x1002248, /*(U+2248 ALMOST EQUAL TO)*/
+ XK_notapproxeq = 0x1002247, /*(U+2247 NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO)*/
+ XK_notidentical = 0x1002262, /* U+2262 NOT IDENTICAL TO */
+ XK_stricteq = 0x1002263, /* U+2263 STRICTLY EQUIVALENT TO */
+
+ // MARK: - XK_BRAILLE
+ XK_braille_dot_1 = 0xfff1,
+ XK_braille_dot_2 = 0xfff2,
+ XK_braille_dot_3 = 0xfff3,
+ XK_braille_dot_4 = 0xfff4,
+ XK_braille_dot_5 = 0xfff5,
+ XK_braille_dot_6 = 0xfff6,
+ XK_braille_dot_7 = 0xfff7,
+ XK_braille_dot_8 = 0xfff8,
+ XK_braille_dot_9 = 0xfff9,
+ XK_braille_dot_10 = 0xfffa,
+ XK_braille_blank = 0x1002800, /* U+2800 BRAILLE PATTERN BLANK */
+ XK_braille_dots_1 = 0x1002801, /* U+2801 BRAILLE PATTERN DOTS-1 */
+ XK_braille_dots_2 = 0x1002802, /* U+2802 BRAILLE PATTERN DOTS-2 */
+ XK_braille_dots_12 = 0x1002803, /* U+2803 BRAILLE PATTERN DOTS-12 */
+ XK_braille_dots_3 = 0x1002804, /* U+2804 BRAILLE PATTERN DOTS-3 */
+ XK_braille_dots_13 = 0x1002805, /* U+2805 BRAILLE PATTERN DOTS-13 */
+ XK_braille_dots_23 = 0x1002806, /* U+2806 BRAILLE PATTERN DOTS-23 */
+ XK_braille_dots_123 = 0x1002807, /* U+2807 BRAILLE PATTERN DOTS-123 */
+ XK_braille_dots_4 = 0x1002808, /* U+2808 BRAILLE PATTERN DOTS-4 */
+ XK_braille_dots_14 = 0x1002809, /* U+2809 BRAILLE PATTERN DOTS-14 */
+ XK_braille_dots_24 = 0x100280a, /* U+280a BRAILLE PATTERN DOTS-24 */
+ XK_braille_dots_124 = 0x100280b, /* U+280b BRAILLE PATTERN DOTS-124 */
+ XK_braille_dots_34 = 0x100280c, /* U+280c BRAILLE PATTERN DOTS-34 */
+ XK_braille_dots_134 = 0x100280d, /* U+280d BRAILLE PATTERN DOTS-134 */
+ XK_braille_dots_234 = 0x100280e, /* U+280e BRAILLE PATTERN DOTS-234 */
+ XK_braille_dots_1234 = 0x100280f, /* U+280f BRAILLE PATTERN DOTS-1234 */
+ XK_braille_dots_5 = 0x1002810, /* U+2810 BRAILLE PATTERN DOTS-5 */
+ XK_braille_dots_15 = 0x1002811, /* U+2811 BRAILLE PATTERN DOTS-15 */
+ XK_braille_dots_25 = 0x1002812, /* U+2812 BRAILLE PATTERN DOTS-25 */
+ XK_braille_dots_125 = 0x1002813, /* U+2813 BRAILLE PATTERN DOTS-125 */
+ XK_braille_dots_35 = 0x1002814, /* U+2814 BRAILLE PATTERN DOTS-35 */
+ XK_braille_dots_135 = 0x1002815, /* U+2815 BRAILLE PATTERN DOTS-135 */
+ XK_braille_dots_235 = 0x1002816, /* U+2816 BRAILLE PATTERN DOTS-235 */
+ XK_braille_dots_1235 = 0x1002817, /* U+2817 BRAILLE PATTERN DOTS-1235 */
+ XK_braille_dots_45 = 0x1002818, /* U+2818 BRAILLE PATTERN DOTS-45 */
+ XK_braille_dots_145 = 0x1002819, /* U+2819 BRAILLE PATTERN DOTS-145 */
+ XK_braille_dots_245 = 0x100281a, /* U+281a BRAILLE PATTERN DOTS-245 */
+ XK_braille_dots_1245 = 0x100281b, /* U+281b BRAILLE PATTERN DOTS-1245 */
+ XK_braille_dots_345 = 0x100281c, /* U+281c BRAILLE PATTERN DOTS-345 */
+ XK_braille_dots_1345 = 0x100281d, /* U+281d BRAILLE PATTERN DOTS-1345 */
+ XK_braille_dots_2345 = 0x100281e, /* U+281e BRAILLE PATTERN DOTS-2345 */
+ XK_braille_dots_12345 = 0x100281f, /* U+281f BRAILLE PATTERN DOTS-12345 */
+ XK_braille_dots_6 = 0x1002820, /* U+2820 BRAILLE PATTERN DOTS-6 */
+ XK_braille_dots_16 = 0x1002821, /* U+2821 BRAILLE PATTERN DOTS-16 */
+ XK_braille_dots_26 = 0x1002822, /* U+2822 BRAILLE PATTERN DOTS-26 */
+ XK_braille_dots_126 = 0x1002823, /* U+2823 BRAILLE PATTERN DOTS-126 */
+ XK_braille_dots_36 = 0x1002824, /* U+2824 BRAILLE PATTERN DOTS-36 */
+ XK_braille_dots_136 = 0x1002825, /* U+2825 BRAILLE PATTERN DOTS-136 */
+ XK_braille_dots_236 = 0x1002826, /* U+2826 BRAILLE PATTERN DOTS-236 */
+ XK_braille_dots_1236 = 0x1002827, /* U+2827 BRAILLE PATTERN DOTS-1236 */
+ XK_braille_dots_46 = 0x1002828, /* U+2828 BRAILLE PATTERN DOTS-46 */
+ XK_braille_dots_146 = 0x1002829, /* U+2829 BRAILLE PATTERN DOTS-146 */
+ XK_braille_dots_246 = 0x100282a, /* U+282a BRAILLE PATTERN DOTS-246 */
+ XK_braille_dots_1246 = 0x100282b, /* U+282b BRAILLE PATTERN DOTS-1246 */
+ XK_braille_dots_346 = 0x100282c, /* U+282c BRAILLE PATTERN DOTS-346 */
+ XK_braille_dots_1346 = 0x100282d, /* U+282d BRAILLE PATTERN DOTS-1346 */
+ XK_braille_dots_2346 = 0x100282e, /* U+282e BRAILLE PATTERN DOTS-2346 */
+ XK_braille_dots_12346 = 0x100282f, /* U+282f BRAILLE PATTERN DOTS-12346 */
+ XK_braille_dots_56 = 0x1002830, /* U+2830 BRAILLE PATTERN DOTS-56 */
+ XK_braille_dots_156 = 0x1002831, /* U+2831 BRAILLE PATTERN DOTS-156 */
+ XK_braille_dots_256 = 0x1002832, /* U+2832 BRAILLE PATTERN DOTS-256 */
+ XK_braille_dots_1256 = 0x1002833, /* U+2833 BRAILLE PATTERN DOTS-1256 */
+ XK_braille_dots_356 = 0x1002834, /* U+2834 BRAILLE PATTERN DOTS-356 */
+ XK_braille_dots_1356 = 0x1002835, /* U+2835 BRAILLE PATTERN DOTS-1356 */
+ XK_braille_dots_2356 = 0x1002836, /* U+2836 BRAILLE PATTERN DOTS-2356 */
+ XK_braille_dots_12356 = 0x1002837, /* U+2837 BRAILLE PATTERN DOTS-12356 */
+ XK_braille_dots_456 = 0x1002838, /* U+2838 BRAILLE PATTERN DOTS-456 */
+ XK_braille_dots_1456 = 0x1002839, /* U+2839 BRAILLE PATTERN DOTS-1456 */
+ XK_braille_dots_2456 = 0x100283a, /* U+283a BRAILLE PATTERN DOTS-2456 */
+ XK_braille_dots_12456 = 0x100283b, /* U+283b BRAILLE PATTERN DOTS-12456 */
+ XK_braille_dots_3456 = 0x100283c, /* U+283c BRAILLE PATTERN DOTS-3456 */
+ XK_braille_dots_13456 = 0x100283d, /* U+283d BRAILLE PATTERN DOTS-13456 */
+ XK_braille_dots_23456 = 0x100283e, /* U+283e BRAILLE PATTERN DOTS-23456 */
+ XK_braille_dots_123456 = 0x100283f, /* U+283f BRAILLE PATTERN DOTS-123456 */
+ XK_braille_dots_7 = 0x1002840, /* U+2840 BRAILLE PATTERN DOTS-7 */
+ XK_braille_dots_17 = 0x1002841, /* U+2841 BRAILLE PATTERN DOTS-17 */
+ XK_braille_dots_27 = 0x1002842, /* U+2842 BRAILLE PATTERN DOTS-27 */
+ XK_braille_dots_127 = 0x1002843, /* U+2843 BRAILLE PATTERN DOTS-127 */
+ XK_braille_dots_37 = 0x1002844, /* U+2844 BRAILLE PATTERN DOTS-37 */
+ XK_braille_dots_137 = 0x1002845, /* U+2845 BRAILLE PATTERN DOTS-137 */
+ XK_braille_dots_237 = 0x1002846, /* U+2846 BRAILLE PATTERN DOTS-237 */
+ XK_braille_dots_1237 = 0x1002847, /* U+2847 BRAILLE PATTERN DOTS-1237 */
+ XK_braille_dots_47 = 0x1002848, /* U+2848 BRAILLE PATTERN DOTS-47 */
+ XK_braille_dots_147 = 0x1002849, /* U+2849 BRAILLE PATTERN DOTS-147 */
+ XK_braille_dots_247 = 0x100284a, /* U+284a BRAILLE PATTERN DOTS-247 */
+ XK_braille_dots_1247 = 0x100284b, /* U+284b BRAILLE PATTERN DOTS-1247 */
+ XK_braille_dots_347 = 0x100284c, /* U+284c BRAILLE PATTERN DOTS-347 */
+ XK_braille_dots_1347 = 0x100284d, /* U+284d BRAILLE PATTERN DOTS-1347 */
+ XK_braille_dots_2347 = 0x100284e, /* U+284e BRAILLE PATTERN DOTS-2347 */
+ XK_braille_dots_12347 = 0x100284f, /* U+284f BRAILLE PATTERN DOTS-12347 */
+ XK_braille_dots_57 = 0x1002850, /* U+2850 BRAILLE PATTERN DOTS-57 */
+ XK_braille_dots_157 = 0x1002851, /* U+2851 BRAILLE PATTERN DOTS-157 */
+ XK_braille_dots_257 = 0x1002852, /* U+2852 BRAILLE PATTERN DOTS-257 */
+ XK_braille_dots_1257 = 0x1002853, /* U+2853 BRAILLE PATTERN DOTS-1257 */
+ XK_braille_dots_357 = 0x1002854, /* U+2854 BRAILLE PATTERN DOTS-357 */
+ XK_braille_dots_1357 = 0x1002855, /* U+2855 BRAILLE PATTERN DOTS-1357 */
+ XK_braille_dots_2357 = 0x1002856, /* U+2856 BRAILLE PATTERN DOTS-2357 */
+ XK_braille_dots_12357 = 0x1002857, /* U+2857 BRAILLE PATTERN DOTS-12357 */
+ XK_braille_dots_457 = 0x1002858, /* U+2858 BRAILLE PATTERN DOTS-457 */
+ XK_braille_dots_1457 = 0x1002859, /* U+2859 BRAILLE PATTERN DOTS-1457 */
+ XK_braille_dots_2457 = 0x100285a, /* U+285a BRAILLE PATTERN DOTS-2457 */
+ XK_braille_dots_12457 = 0x100285b, /* U+285b BRAILLE PATTERN DOTS-12457 */
+ XK_braille_dots_3457 = 0x100285c, /* U+285c BRAILLE PATTERN DOTS-3457 */
+ XK_braille_dots_13457 = 0x100285d, /* U+285d BRAILLE PATTERN DOTS-13457 */
+ XK_braille_dots_23457 = 0x100285e, /* U+285e BRAILLE PATTERN DOTS-23457 */
+ XK_braille_dots_123457 = 0x100285f, /* U+285f BRAILLE PATTERN DOTS-123457 */
+ XK_braille_dots_67 = 0x1002860, /* U+2860 BRAILLE PATTERN DOTS-67 */
+ XK_braille_dots_167 = 0x1002861, /* U+2861 BRAILLE PATTERN DOTS-167 */
+ XK_braille_dots_267 = 0x1002862, /* U+2862 BRAILLE PATTERN DOTS-267 */
+ XK_braille_dots_1267 = 0x1002863, /* U+2863 BRAILLE PATTERN DOTS-1267 */
+ XK_braille_dots_367 = 0x1002864, /* U+2864 BRAILLE PATTERN DOTS-367 */
+ XK_braille_dots_1367 = 0x1002865, /* U+2865 BRAILLE PATTERN DOTS-1367 */
+ XK_braille_dots_2367 = 0x1002866, /* U+2866 BRAILLE PATTERN DOTS-2367 */
+ XK_braille_dots_12367 = 0x1002867, /* U+2867 BRAILLE PATTERN DOTS-12367 */
+ XK_braille_dots_467 = 0x1002868, /* U+2868 BRAILLE PATTERN DOTS-467 */
+ XK_braille_dots_1467 = 0x1002869, /* U+2869 BRAILLE PATTERN DOTS-1467 */
+ XK_braille_dots_2467 = 0x100286a, /* U+286a BRAILLE PATTERN DOTS-2467 */
+ XK_braille_dots_12467 = 0x100286b, /* U+286b BRAILLE PATTERN DOTS-12467 */
+ XK_braille_dots_3467 = 0x100286c, /* U+286c BRAILLE PATTERN DOTS-3467 */
+ XK_braille_dots_13467 = 0x100286d, /* U+286d BRAILLE PATTERN DOTS-13467 */
+ XK_braille_dots_23467 = 0x100286e, /* U+286e BRAILLE PATTERN DOTS-23467 */
+ XK_braille_dots_123467 = 0x100286f, /* U+286f BRAILLE PATTERN DOTS-123467 */
+ XK_braille_dots_567 = 0x1002870, /* U+2870 BRAILLE PATTERN DOTS-567 */
+ XK_braille_dots_1567 = 0x1002871, /* U+2871 BRAILLE PATTERN DOTS-1567 */
+ XK_braille_dots_2567 = 0x1002872, /* U+2872 BRAILLE PATTERN DOTS-2567 */
+ XK_braille_dots_12567 = 0x1002873, /* U+2873 BRAILLE PATTERN DOTS-12567 */
+ XK_braille_dots_3567 = 0x1002874, /* U+2874 BRAILLE PATTERN DOTS-3567 */
+ XK_braille_dots_13567 = 0x1002875, /* U+2875 BRAILLE PATTERN DOTS-13567 */
+ XK_braille_dots_23567 = 0x1002876, /* U+2876 BRAILLE PATTERN DOTS-23567 */
+ XK_braille_dots_123567 = 0x1002877, /* U+2877 BRAILLE PATTERN DOTS-123567 */
+ XK_braille_dots_4567 = 0x1002878, /* U+2878 BRAILLE PATTERN DOTS-4567 */
+ XK_braille_dots_14567 = 0x1002879, /* U+2879 BRAILLE PATTERN DOTS-14567 */
+ XK_braille_dots_24567 = 0x100287a, /* U+287a BRAILLE PATTERN DOTS-24567 */
+ XK_braille_dots_124567 = 0x100287b, /* U+287b BRAILLE PATTERN DOTS-124567 */
+ XK_braille_dots_34567 = 0x100287c, /* U+287c BRAILLE PATTERN DOTS-34567 */
+ XK_braille_dots_134567 = 0x100287d, /* U+287d BRAILLE PATTERN DOTS-134567 */
+ XK_braille_dots_234567 = 0x100287e, /* U+287e BRAILLE PATTERN DOTS-234567 */
+ XK_braille_dots_1234567 = 0x100287f, /* U+287f BRAILLE PATTERN DOTS-1234567 */
+ XK_braille_dots_8 = 0x1002880, /* U+2880 BRAILLE PATTERN DOTS-8 */
+ XK_braille_dots_18 = 0x1002881, /* U+2881 BRAILLE PATTERN DOTS-18 */
+ XK_braille_dots_28 = 0x1002882, /* U+2882 BRAILLE PATTERN DOTS-28 */
+ XK_braille_dots_128 = 0x1002883, /* U+2883 BRAILLE PATTERN DOTS-128 */
+ XK_braille_dots_38 = 0x1002884, /* U+2884 BRAILLE PATTERN DOTS-38 */
+ XK_braille_dots_138 = 0x1002885, /* U+2885 BRAILLE PATTERN DOTS-138 */
+ XK_braille_dots_238 = 0x1002886, /* U+2886 BRAILLE PATTERN DOTS-238 */
+ XK_braille_dots_1238 = 0x1002887, /* U+2887 BRAILLE PATTERN DOTS-1238 */
+ XK_braille_dots_48 = 0x1002888, /* U+2888 BRAILLE PATTERN DOTS-48 */
+ XK_braille_dots_148 = 0x1002889, /* U+2889 BRAILLE PATTERN DOTS-148 */
+ XK_braille_dots_248 = 0x100288a, /* U+288a BRAILLE PATTERN DOTS-248 */
+ XK_braille_dots_1248 = 0x100288b, /* U+288b BRAILLE PATTERN DOTS-1248 */
+ XK_braille_dots_348 = 0x100288c, /* U+288c BRAILLE PATTERN DOTS-348 */
+ XK_braille_dots_1348 = 0x100288d, /* U+288d BRAILLE PATTERN DOTS-1348 */
+ XK_braille_dots_2348 = 0x100288e, /* U+288e BRAILLE PATTERN DOTS-2348 */
+ XK_braille_dots_12348 = 0x100288f, /* U+288f BRAILLE PATTERN DOTS-12348 */
+ XK_braille_dots_58 = 0x1002890, /* U+2890 BRAILLE PATTERN DOTS-58 */
+ XK_braille_dots_158 = 0x1002891, /* U+2891 BRAILLE PATTERN DOTS-158 */
+ XK_braille_dots_258 = 0x1002892, /* U+2892 BRAILLE PATTERN DOTS-258 */
+ XK_braille_dots_1258 = 0x1002893, /* U+2893 BRAILLE PATTERN DOTS-1258 */
+ XK_braille_dots_358 = 0x1002894, /* U+2894 BRAILLE PATTERN DOTS-358 */
+ XK_braille_dots_1358 = 0x1002895, /* U+2895 BRAILLE PATTERN DOTS-1358 */
+ XK_braille_dots_2358 = 0x1002896, /* U+2896 BRAILLE PATTERN DOTS-2358 */
+ XK_braille_dots_12358 = 0x1002897, /* U+2897 BRAILLE PATTERN DOTS-12358 */
+ XK_braille_dots_458 = 0x1002898, /* U+2898 BRAILLE PATTERN DOTS-458 */
+ XK_braille_dots_1458 = 0x1002899, /* U+2899 BRAILLE PATTERN DOTS-1458 */
+ XK_braille_dots_2458 = 0x100289a, /* U+289a BRAILLE PATTERN DOTS-2458 */
+ XK_braille_dots_12458 = 0x100289b, /* U+289b BRAILLE PATTERN DOTS-12458 */
+ XK_braille_dots_3458 = 0x100289c, /* U+289c BRAILLE PATTERN DOTS-3458 */
+ XK_braille_dots_13458 = 0x100289d, /* U+289d BRAILLE PATTERN DOTS-13458 */
+ XK_braille_dots_23458 = 0x100289e, /* U+289e BRAILLE PATTERN DOTS-23458 */
+ XK_braille_dots_123458 = 0x100289f, /* U+289f BRAILLE PATTERN DOTS-123458 */
+ XK_braille_dots_68 = 0x10028a0, /* U+28a0 BRAILLE PATTERN DOTS-68 */
+ XK_braille_dots_168 = 0x10028a1, /* U+28a1 BRAILLE PATTERN DOTS-168 */
+ XK_braille_dots_268 = 0x10028a2, /* U+28a2 BRAILLE PATTERN DOTS-268 */
+ XK_braille_dots_1268 = 0x10028a3, /* U+28a3 BRAILLE PATTERN DOTS-1268 */
+ XK_braille_dots_368 = 0x10028a4, /* U+28a4 BRAILLE PATTERN DOTS-368 */
+ XK_braille_dots_1368 = 0x10028a5, /* U+28a5 BRAILLE PATTERN DOTS-1368 */
+ XK_braille_dots_2368 = 0x10028a6, /* U+28a6 BRAILLE PATTERN DOTS-2368 */
+ XK_braille_dots_12368 = 0x10028a7, /* U+28a7 BRAILLE PATTERN DOTS-12368 */
+ XK_braille_dots_468 = 0x10028a8, /* U+28a8 BRAILLE PATTERN DOTS-468 */
+ XK_braille_dots_1468 = 0x10028a9, /* U+28a9 BRAILLE PATTERN DOTS-1468 */
+ XK_braille_dots_2468 = 0x10028aa, /* U+28aa BRAILLE PATTERN DOTS-2468 */
+ XK_braille_dots_12468 = 0x10028ab, /* U+28ab BRAILLE PATTERN DOTS-12468 */
+ XK_braille_dots_3468 = 0x10028ac, /* U+28ac BRAILLE PATTERN DOTS-3468 */
+ XK_braille_dots_13468 = 0x10028ad, /* U+28ad BRAILLE PATTERN DOTS-13468 */
+ XK_braille_dots_23468 = 0x10028ae, /* U+28ae BRAILLE PATTERN DOTS-23468 */
+ XK_braille_dots_123468 = 0x10028af, /* U+28af BRAILLE PATTERN DOTS-123468 */
+ XK_braille_dots_568 = 0x10028b0, /* U+28b0 BRAILLE PATTERN DOTS-568 */
+ XK_braille_dots_1568 = 0x10028b1, /* U+28b1 BRAILLE PATTERN DOTS-1568 */
+ XK_braille_dots_2568 = 0x10028b2, /* U+28b2 BRAILLE PATTERN DOTS-2568 */
+ XK_braille_dots_12568 = 0x10028b3, /* U+28b3 BRAILLE PATTERN DOTS-12568 */
+ XK_braille_dots_3568 = 0x10028b4, /* U+28b4 BRAILLE PATTERN DOTS-3568 */
+ XK_braille_dots_13568 = 0x10028b5, /* U+28b5 BRAILLE PATTERN DOTS-13568 */
+ XK_braille_dots_23568 = 0x10028b6, /* U+28b6 BRAILLE PATTERN DOTS-23568 */
+ XK_braille_dots_123568 = 0x10028b7, /* U+28b7 BRAILLE PATTERN DOTS-123568 */
+ XK_braille_dots_4568 = 0x10028b8, /* U+28b8 BRAILLE PATTERN DOTS-4568 */
+ XK_braille_dots_14568 = 0x10028b9, /* U+28b9 BRAILLE PATTERN DOTS-14568 */
+ XK_braille_dots_24568 = 0x10028ba, /* U+28ba BRAILLE PATTERN DOTS-24568 */
+ XK_braille_dots_124568 = 0x10028bb, /* U+28bb BRAILLE PATTERN DOTS-124568 */
+ XK_braille_dots_34568 = 0x10028bc, /* U+28bc BRAILLE PATTERN DOTS-34568 */
+ XK_braille_dots_134568 = 0x10028bd, /* U+28bd BRAILLE PATTERN DOTS-134568 */
+ XK_braille_dots_234568 = 0x10028be, /* U+28be BRAILLE PATTERN DOTS-234568 */
+ XK_braille_dots_1234568 = 0x10028bf, /* U+28bf BRAILLE PATTERN DOTS-1234568 */
+ XK_braille_dots_78 = 0x10028c0, /* U+28c0 BRAILLE PATTERN DOTS-78 */
+ XK_braille_dots_178 = 0x10028c1, /* U+28c1 BRAILLE PATTERN DOTS-178 */
+ XK_braille_dots_278 = 0x10028c2, /* U+28c2 BRAILLE PATTERN DOTS-278 */
+ XK_braille_dots_1278 = 0x10028c3, /* U+28c3 BRAILLE PATTERN DOTS-1278 */
+ XK_braille_dots_378 = 0x10028c4, /* U+28c4 BRAILLE PATTERN DOTS-378 */
+ XK_braille_dots_1378 = 0x10028c5, /* U+28c5 BRAILLE PATTERN DOTS-1378 */
+ XK_braille_dots_2378 = 0x10028c6, /* U+28c6 BRAILLE PATTERN DOTS-2378 */
+ XK_braille_dots_12378 = 0x10028c7, /* U+28c7 BRAILLE PATTERN DOTS-12378 */
+ XK_braille_dots_478 = 0x10028c8, /* U+28c8 BRAILLE PATTERN DOTS-478 */
+ XK_braille_dots_1478 = 0x10028c9, /* U+28c9 BRAILLE PATTERN DOTS-1478 */
+ XK_braille_dots_2478 = 0x10028ca, /* U+28ca BRAILLE PATTERN DOTS-2478 */
+ XK_braille_dots_12478 = 0x10028cb, /* U+28cb BRAILLE PATTERN DOTS-12478 */
+ XK_braille_dots_3478 = 0x10028cc, /* U+28cc BRAILLE PATTERN DOTS-3478 */
+ XK_braille_dots_13478 = 0x10028cd, /* U+28cd BRAILLE PATTERN DOTS-13478 */
+ XK_braille_dots_23478 = 0x10028ce, /* U+28ce BRAILLE PATTERN DOTS-23478 */
+ XK_braille_dots_123478 = 0x10028cf, /* U+28cf BRAILLE PATTERN DOTS-123478 */
+ XK_braille_dots_578 = 0x10028d0, /* U+28d0 BRAILLE PATTERN DOTS-578 */
+ XK_braille_dots_1578 = 0x10028d1, /* U+28d1 BRAILLE PATTERN DOTS-1578 */
+ XK_braille_dots_2578 = 0x10028d2, /* U+28d2 BRAILLE PATTERN DOTS-2578 */
+ XK_braille_dots_12578 = 0x10028d3, /* U+28d3 BRAILLE PATTERN DOTS-12578 */
+ XK_braille_dots_3578 = 0x10028d4, /* U+28d4 BRAILLE PATTERN DOTS-3578 */
+ XK_braille_dots_13578 = 0x10028d5, /* U+28d5 BRAILLE PATTERN DOTS-13578 */
+ XK_braille_dots_23578 = 0x10028d6, /* U+28d6 BRAILLE PATTERN DOTS-23578 */
+ XK_braille_dots_123578 = 0x10028d7, /* U+28d7 BRAILLE PATTERN DOTS-123578 */
+ XK_braille_dots_4578 = 0x10028d8, /* U+28d8 BRAILLE PATTERN DOTS-4578 */
+ XK_braille_dots_14578 = 0x10028d9, /* U+28d9 BRAILLE PATTERN DOTS-14578 */
+ XK_braille_dots_24578 = 0x10028da, /* U+28da BRAILLE PATTERN DOTS-24578 */
+ XK_braille_dots_124578 = 0x10028db, /* U+28db BRAILLE PATTERN DOTS-124578 */
+ XK_braille_dots_34578 = 0x10028dc, /* U+28dc BRAILLE PATTERN DOTS-34578 */
+ XK_braille_dots_134578 = 0x10028dd, /* U+28dd BRAILLE PATTERN DOTS-134578 */
+ XK_braille_dots_234578 = 0x10028de, /* U+28de BRAILLE PATTERN DOTS-234578 */
+ XK_braille_dots_1234578 = 0x10028df, /* U+28df BRAILLE PATTERN DOTS-1234578 */
+ XK_braille_dots_678 = 0x10028e0, /* U+28e0 BRAILLE PATTERN DOTS-678 */
+ XK_braille_dots_1678 = 0x10028e1, /* U+28e1 BRAILLE PATTERN DOTS-1678 */
+ XK_braille_dots_2678 = 0x10028e2, /* U+28e2 BRAILLE PATTERN DOTS-2678 */
+ XK_braille_dots_12678 = 0x10028e3, /* U+28e3 BRAILLE PATTERN DOTS-12678 */
+ XK_braille_dots_3678 = 0x10028e4, /* U+28e4 BRAILLE PATTERN DOTS-3678 */
+ XK_braille_dots_13678 = 0x10028e5, /* U+28e5 BRAILLE PATTERN DOTS-13678 */
+ XK_braille_dots_23678 = 0x10028e6, /* U+28e6 BRAILLE PATTERN DOTS-23678 */
+ XK_braille_dots_123678 = 0x10028e7, /* U+28e7 BRAILLE PATTERN DOTS-123678 */
+ XK_braille_dots_4678 = 0x10028e8, /* U+28e8 BRAILLE PATTERN DOTS-4678 */
+ XK_braille_dots_14678 = 0x10028e9, /* U+28e9 BRAILLE PATTERN DOTS-14678 */
+ XK_braille_dots_24678 = 0x10028ea, /* U+28ea BRAILLE PATTERN DOTS-24678 */
+ XK_braille_dots_124678 = 0x10028eb, /* U+28eb BRAILLE PATTERN DOTS-124678 */
+ XK_braille_dots_34678 = 0x10028ec, /* U+28ec BRAILLE PATTERN DOTS-34678 */
+ XK_braille_dots_134678 = 0x10028ed, /* U+28ed BRAILLE PATTERN DOTS-134678 */
+ XK_braille_dots_234678 = 0x10028ee, /* U+28ee BRAILLE PATTERN DOTS-234678 */
+ XK_braille_dots_1234678 = 0x10028ef, /* U+28ef BRAILLE PATTERN DOTS-1234678 */
+ XK_braille_dots_5678 = 0x10028f0, /* U+28f0 BRAILLE PATTERN DOTS-5678 */
+ XK_braille_dots_15678 = 0x10028f1, /* U+28f1 BRAILLE PATTERN DOTS-15678 */
+ XK_braille_dots_25678 = 0x10028f2, /* U+28f2 BRAILLE PATTERN DOTS-25678 */
+ XK_braille_dots_125678 = 0x10028f3, /* U+28f3 BRAILLE PATTERN DOTS-125678 */
+ XK_braille_dots_35678 = 0x10028f4, /* U+28f4 BRAILLE PATTERN DOTS-35678 */
+ XK_braille_dots_135678 = 0x10028f5, /* U+28f5 BRAILLE PATTERN DOTS-135678 */
+ XK_braille_dots_235678 = 0x10028f6, /* U+28f6 BRAILLE PATTERN DOTS-235678 */
+ XK_braille_dots_1235678 = 0x10028f7, /* U+28f7 BRAILLE PATTERN DOTS-1235678 */
+ XK_braille_dots_45678 = 0x10028f8, /* U+28f8 BRAILLE PATTERN DOTS-45678 */
+ XK_braille_dots_145678 = 0x10028f9, /* U+28f9 BRAILLE PATTERN DOTS-145678 */
+ XK_braille_dots_245678 = 0x10028fa, /* U+28fa BRAILLE PATTERN DOTS-245678 */
+ XK_braille_dots_1245678 = 0x10028fb, /* U+28fb BRAILLE PATTERN DOTS-1245678 */
+ XK_braille_dots_345678 = 0x10028fc, /* U+28fc BRAILLE PATTERN DOTS-345678 */
+ XK_braille_dots_1345678 = 0x10028fd, /* U+28fd BRAILLE PATTERN DOTS-1345678 */
+ XK_braille_dots_2345678 = 0x10028fe, /* U+28fe BRAILLE PATTERN DOTS-2345678 */
+ XK_braille_dots_12345678 = 0x10028ff, /* U+28ff BRAILLE PATTERN DOTS-12345678 */
+
+ /*
+ * Sinhala (http://unicode.org/charts/PDF/U0D80.pdf)
+ * http://www.nongnu.org/sinhala/doc/transliteration/sinhala-transliteration_6.html
+ */
+
+ // MARK: - XK_SINHALA
+ XK_Sinh_ng = 0x1000d82, /* U+0D82 SINHALA ANUSVARAYA */
+ XK_Sinh_h2 = 0x1000d83, /* U+0D83 SINHALA VISARGAYA */
+ XK_Sinh_a = 0x1000d85, /* U+0D85 SINHALA AYANNA */
+ XK_Sinh_aa = 0x1000d86, /* U+0D86 SINHALA AAYANNA */
+ XK_Sinh_ae = 0x1000d87, /* U+0D87 SINHALA AEYANNA */
+ XK_Sinh_aee = 0x1000d88, /* U+0D88 SINHALA AEEYANNA */
+ XK_Sinh_i = 0x1000d89, /* U+0D89 SINHALA IYANNA */
+ XK_Sinh_ii = 0x1000d8a, /* U+0D8A SINHALA IIYANNA */
+ XK_Sinh_u = 0x1000d8b, /* U+0D8B SINHALA UYANNA */
+ XK_Sinh_uu = 0x1000d8c, /* U+0D8C SINHALA UUYANNA */
+ XK_Sinh_ri = 0x1000d8d, /* U+0D8D SINHALA IRUYANNA */
+ XK_Sinh_rii = 0x1000d8e, /* U+0D8E SINHALA IRUUYANNA */
+ XK_Sinh_lu = 0x1000d8f, /* U+0D8F SINHALA ILUYANNA */
+ XK_Sinh_luu = 0x1000d90, /* U+0D90 SINHALA ILUUYANNA */
+ XK_Sinh_e = 0x1000d91, /* U+0D91 SINHALA EYANNA */
+ XK_Sinh_ee = 0x1000d92, /* U+0D92 SINHALA EEYANNA */
+ XK_Sinh_ai = 0x1000d93, /* U+0D93 SINHALA AIYANNA */
+ XK_Sinh_o = 0x1000d94, /* U+0D94 SINHALA OYANNA */
+ XK_Sinh_oo = 0x1000d95, /* U+0D95 SINHALA OOYANNA */
+ XK_Sinh_au = 0x1000d96, /* U+0D96 SINHALA AUYANNA */
+ XK_Sinh_ka = 0x1000d9a, /* U+0D9A SINHALA KAYANNA */
+ XK_Sinh_kha = 0x1000d9b, /* U+0D9B SINHALA MAHA. KAYANNA */
+ XK_Sinh_ga = 0x1000d9c, /* U+0D9C SINHALA GAYANNA */
+ XK_Sinh_gha = 0x1000d9d, /* U+0D9D SINHALA MAHA. GAYANNA */
+ XK_Sinh_ng2 = 0x1000d9e, /* U+0D9E SINHALA KANTAJA NAASIKYAYA */
+ XK_Sinh_nga = 0x1000d9f, /* U+0D9F SINHALA SANYAKA GAYANNA */
+ XK_Sinh_ca = 0x1000da0, /* U+0DA0 SINHALA CAYANNA */
+ XK_Sinh_cha = 0x1000da1, /* U+0DA1 SINHALA MAHA. CAYANNA */
+ XK_Sinh_ja = 0x1000da2, /* U+0DA2 SINHALA JAYANNA */
+ XK_Sinh_jha = 0x1000da3, /* U+0DA3 SINHALA MAHA. JAYANNA */
+ XK_Sinh_nya = 0x1000da4, /* U+0DA4 SINHALA TAALUJA NAASIKYAYA */
+ XK_Sinh_jnya = 0x1000da5, /* U+0DA5 SINHALA TAALUJA SANYOOGA NAASIKYAYA */
+ XK_Sinh_nja = 0x1000da6, /* U+0DA6 SINHALA SANYAKA JAYANNA */
+ XK_Sinh_tta = 0x1000da7, /* U+0DA7 SINHALA TTAYANNA */
+ XK_Sinh_ttha = 0x1000da8, /* U+0DA8 SINHALA MAHA. TTAYANNA */
+ XK_Sinh_dda = 0x1000da9, /* U+0DA9 SINHALA DDAYANNA */
+ XK_Sinh_ddha = 0x1000daa, /* U+0DAA SINHALA MAHA. DDAYANNA */
+ XK_Sinh_nna = 0x1000dab, /* U+0DAB SINHALA MUURDHAJA NAYANNA */
+ XK_Sinh_ndda = 0x1000dac, /* U+0DAC SINHALA SANYAKA DDAYANNA */
+ XK_Sinh_tha = 0x1000dad, /* U+0DAD SINHALA TAYANNA */
+ XK_Sinh_thha = 0x1000dae, /* U+0DAE SINHALA MAHA. TAYANNA */
+ XK_Sinh_dha = 0x1000daf, /* U+0DAF SINHALA DAYANNA */
+ XK_Sinh_dhha = 0x1000db0, /* U+0DB0 SINHALA MAHA. DAYANNA */
+ XK_Sinh_na = 0x1000db1, /* U+0DB1 SINHALA DANTAJA NAYANNA */
+ XK_Sinh_ndha = 0x1000db3, /* U+0DB3 SINHALA SANYAKA DAYANNA */
+ XK_Sinh_pa = 0x1000db4, /* U+0DB4 SINHALA PAYANNA */
+ XK_Sinh_pha = 0x1000db5, /* U+0DB5 SINHALA MAHA. PAYANNA */
+ XK_Sinh_ba = 0x1000db6, /* U+0DB6 SINHALA BAYANNA */
+ XK_Sinh_bha = 0x1000db7, /* U+0DB7 SINHALA MAHA. BAYANNA */
+ XK_Sinh_ma = 0x1000db8, /* U+0DB8 SINHALA MAYANNA */
+ XK_Sinh_mba = 0x1000db9, /* U+0DB9 SINHALA AMBA BAYANNA */
+ XK_Sinh_ya = 0x1000dba, /* U+0DBA SINHALA YAYANNA */
+ XK_Sinh_ra = 0x1000dbb, /* U+0DBB SINHALA RAYANNA */
+ XK_Sinh_la = 0x1000dbd, /* U+0DBD SINHALA DANTAJA LAYANNA */
+ XK_Sinh_va = 0x1000dc0, /* U+0DC0 SINHALA VAYANNA */
+ XK_Sinh_sha = 0x1000dc1, /* U+0DC1 SINHALA TAALUJA SAYANNA */
+ XK_Sinh_ssha = 0x1000dc2, /* U+0DC2 SINHALA MUURDHAJA SAYANNA */
+ XK_Sinh_sa = 0x1000dc3, /* U+0DC3 SINHALA DANTAJA SAYANNA */
+ XK_Sinh_ha = 0x1000dc4, /* U+0DC4 SINHALA HAYANNA */
+ XK_Sinh_lla = 0x1000dc5, /* U+0DC5 SINHALA MUURDHAJA LAYANNA */
+ XK_Sinh_fa = 0x1000dc6, /* U+0DC6 SINHALA FAYANNA */
+ XK_Sinh_al = 0x1000dca, /* U+0DCA SINHALA AL-LAKUNA */
+ XK_Sinh_aa2 = 0x1000dcf, /* U+0DCF SINHALA AELA-PILLA */
+ XK_Sinh_ae2 = 0x1000dd0, /* U+0DD0 SINHALA AEDA-PILLA */
+ XK_Sinh_aee2 = 0x1000dd1, /* U+0DD1 SINHALA DIGA AEDA-PILLA */
+ XK_Sinh_i2 = 0x1000dd2, /* U+0DD2 SINHALA IS-PILLA */
+ XK_Sinh_ii2 = 0x1000dd3, /* U+0DD3 SINHALA DIGA IS-PILLA */
+ XK_Sinh_u2 = 0x1000dd4, /* U+0DD4 SINHALA PAA-PILLA */
+ XK_Sinh_uu2 = 0x1000dd6, /* U+0DD6 SINHALA DIGA PAA-PILLA */
+ XK_Sinh_ru2 = 0x1000dd8, /* U+0DD8 SINHALA GAETTA-PILLA */
+ XK_Sinh_e2 = 0x1000dd9, /* U+0DD9 SINHALA KOMBUVA */
+ XK_Sinh_ee2 = 0x1000dda, /* U+0DDA SINHALA DIGA KOMBUVA */
+ XK_Sinh_ai2 = 0x1000ddb, /* U+0DDB SINHALA KOMBU DEKA */
+ XK_Sinh_o2 = 0x1000ddc, /* U+0DDC SINHALA KOMBUVA HAA AELA-PILLA*/
+ XK_Sinh_oo2 = 0x1000ddd, /* U+0DDD SINHALA KOMBUVA HAA DIGA AELA-PILLA*/
+ XK_Sinh_au2 = 0x1000dde, /* U+0DDE SINHALA KOMBUVA HAA GAYANUKITTA */
+ XK_Sinh_lu2 = 0x1000ddf, /* U+0DDF SINHALA GAYANUKITTA */
+ XK_Sinh_ruu2 = 0x1000df2, /* U+0DF2 SINHALA DIGA GAETTA-PILLA */
+ XK_Sinh_luu2 = 0x1000df3, /* U+0DF3 SINHALA DIGA GAYANUKITTA */
+ XK_Sinh_kunddaliya = 0x1000df4 /* U+0DF4 SINHALA KUNDDALIYA */
+ // ReSharper restore InconsistentNaming
+}
\ No newline at end of file
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/LogLevel.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/LogLevel.cs
new file mode 100644
index 00000000..92523b60
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/LogLevel.cs
@@ -0,0 +1,10 @@
+namespace RoyalApps.RoyalVNCKit;
+
+// keep in sync with Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
+public enum LogLevel
+{
+ Debug = 0,
+ Info = 1,
+ Warning = 2,
+ Error = 3,
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/MouseButton.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/MouseButton.cs
new file mode 100644
index 00000000..5ee925fe
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/MouseButton.cs
@@ -0,0 +1,9 @@
+namespace RoyalApps.RoyalVNCKit;
+
+// keep in sync with Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
+public enum MouseButton
+{
+ Left = 0,
+ Middle = 1,
+ Right = 2
+}
\ No newline at end of file
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/MouseWheel.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/MouseWheel.cs
new file mode 100644
index 00000000..a2c1a6d6
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/MouseWheel.cs
@@ -0,0 +1,10 @@
+namespace RoyalApps.RoyalVNCKit;
+
+// keep in sync with Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
+public enum MouseWheel
+{
+ Left = 0,
+ Right = 1,
+ Up = 2,
+ Down = 3
+}
\ No newline at end of file
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/NativeExtensions.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/NativeExtensions.cs
new file mode 100644
index 00000000..6271d8cd
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/NativeExtensions.cs
@@ -0,0 +1,12 @@
+using System.Runtime.CompilerServices;
+
+namespace RoyalApps.RoyalVNCKit;
+
+static class NativeExtensions
+{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static byte ToNativeBool(this bool b) => b ? (byte)1 : (byte)0;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool FromNativeBool(this byte b) => b is not 0;
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/README.md b/Bindings/dotnet/RoyalApps.RoyalVNCKit/README.md
new file mode 100644
index 00000000..32523bb8
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/README.md
@@ -0,0 +1,3 @@
+# RoyalApps.RoyalVNCKit
+
+.NET wrapper for RoyalVNCKit with high-level API
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/RoyalApps.RoyalVNCKit.csproj b/Bindings/dotnet/RoyalApps.RoyalVNCKit/RoyalApps.RoyalVNCKit.csproj
new file mode 100644
index 00000000..9676ba23
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/RoyalApps.RoyalVNCKit.csproj
@@ -0,0 +1,27 @@
+
+
+
+ Library
+ net8.0
+ enable
+
+ true
+
+ true
+ true
+ true
+ embedded
+ true
+ strict
+
+ true
+ true
+ false
+ true
+
+
+
+ true
+
+
+
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/RoyalVNCKit.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/RoyalVNCKit.cs
new file mode 100644
index 00000000..0252b312
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/RoyalVNCKit.cs
@@ -0,0 +1,291 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace RoyalApps.RoyalVNCKit;
+
+// NOTE: Manually "imported" from Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
+static unsafe partial class RoyalVNCKit
+{
+ // ReSharper disable once InconsistentNaming
+ const string libRoyalVNCKit = nameof(RoyalVNCKit);
+ const StringMarshalling Utf8Marshalling = StringMarshalling.Utf8;
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void LogDelegate(
+ void* logger,
+ void* context,
+ LogLevel logLevel,
+ string message
+ );
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void* rvnc_logger_create(
+ LogDelegate log,
+ void* context
+ );
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_logger_destroy(void* logger);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial byte rvnc_authentication_type_requires_username(AuthenticationType authenticationType);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial byte rvnc_authentication_type_requires_password(AuthenticationType authenticationType);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial AuthenticationType rvnc_authentication_request_authentication_type_get(void* authenticationRequest);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_authentication_request_cancel(void* authenticationRequest);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_authentication_request_complete_with_username_password(
+ void* authenticationRequest,
+ string username,
+ string password
+ );
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_authentication_request_complete_with_password(
+ void* authenticationRequest,
+ string password
+ );
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void* rvnc_settings_create(
+ byte isDebugLoggingEnabled,
+ string hostname,
+ ushort port,
+ byte isShared,
+ byte isScalingEnabled,
+ byte useDisplayLink,
+ InputMode inputMode,
+ byte isClipboardRedirectionEnabled,
+ ColorDepth colorDepth
+ );
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_settings_destroy(void* settings);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_state_destroy(void* connectionState);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial ConnectionStatus rvnc_connection_state_status_get(void* connectionState);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial string? rvnc_connection_state_error_description_get_copy(void* connectionState);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial byte rvnc_connection_state_error_should_display_to_user_get(void* connectionState);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial byte rvnc_connection_state_error_is_authentication_error_get(void* connectionState);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial ushort rvnc_framebuffer_size_width_get(void* framebuffer);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial ushort rvnc_framebuffer_size_height_get(void* framebuffer);
+
+ // NOTE: This always returns 32-bit BGRA data.
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void* rvnc_framebuffer_pixel_data_get(void* framebuffer);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial ulong rvnc_framebuffer_pixel_data_size_get(void* framebuffer);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial byte rvnc_cursor_is_empty_get(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial ushort rvnc_cursor_size_width_get(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial ushort rvnc_cursor_size_height_get(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial ushort rvnc_cursor_hotspot_x_get(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial ushort rvnc_cursor_hotspot_y_get(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial long rvnc_cursor_bits_per_component_get(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial long rvnc_cursor_bits_per_pixel_get(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial long rvnc_cursor_bytes_per_pixel_get(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial long rvnc_cursor_bytes_per_row_get(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void* rvnc_cursor_pixel_data_get_copy(void* cursor);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_cursor_pixel_data_destroy(void* pixelData);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial ulong rvnc_cursor_pixel_data_size_get(void* cursor);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void ConnectionStateDidChangeDelegate(
+ void* connection,
+ void* context,
+ void* connectionState
+ );
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void AuthenticateDelegate(
+ void* connection,
+ void* context,
+ void* authenticationRequest
+ );
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void DidCreateFramebufferDelegate(
+ void* connection,
+ void* context,
+ void* framebuffer
+ );
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void DidResizeFramebufferDelegate(
+ void* connection,
+ void* context,
+ void* framebuffer
+ );
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void DidUpdateFramebufferDelegate(
+ void* connection,
+ void* context,
+ void* framebuffer,
+ ushort x,
+ ushort y,
+ ushort width,
+ ushort height
+ );
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void DidUpdateCursorDelegate(
+ void* connection,
+ void* context,
+ void* cursor
+ );
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void* rvnc_connection_delegate_create(
+ ConnectionStateDidChangeDelegate connectionStateDidChange,
+ AuthenticateDelegate authenticate,
+ DidCreateFramebufferDelegate didCreateFramebuffer,
+ DidResizeFramebufferDelegate didResizeFramebuffer,
+ DidUpdateFramebufferDelegate didUpdateFramebuffer,
+ DidUpdateCursorDelegate didUpdateCursor
+ );
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_delegate_destroy(void* connectionDelegate);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void* rvnc_connection_create(
+ void* settings,
+ void* logger,
+ void* context
+ );
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_destroy(void* connection);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_connect(void* connection);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_disconnect(void* connection);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_update_color_depth(void* connection, ColorDepth colorDepth);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_delegate_set(void* connection, void* connectionDelegate);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void* rvnc_connection_context_get(void* connection);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void* rvnc_connection_state_get_copy(void* connection);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void* rvnc_connection_settings_get_copy(void* connection);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_mouse_move(void* connection, ushort x, ushort y);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_mouse_down(void* connection, MouseButton button, ushort x, ushort y);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_mouse_up(void* connection, MouseButton button, ushort x, ushort y);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_mouse_wheel(void* connection, MouseWheel wheel, ushort x, ushort y, uint steps);
+
+ // NOTE: key is an X11 keysym (eg. `XK_A` for the latin capital letter "A"). See the `KeySymbol` enum.
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_key_down(void* connection, KeySymbol key);
+
+ [LibraryImport(libRoyalVNCKit, StringMarshalling = Utf8Marshalling)]
+ [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
+ internal static partial void rvnc_connection_key_up(void* connection, KeySymbol key);
+}
\ No newline at end of file
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncConnection.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncConnection.cs
new file mode 100644
index 00000000..712852ac
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncConnection.cs
@@ -0,0 +1,162 @@
+using System;
+
+namespace RoyalApps.RoyalVNCKit;
+
+public sealed unsafe class VncConnection: IDisposable
+{
+ bool _isDisposed;
+ void* _instance;
+
+ VncConnection(void* instance)
+ {
+ ArgumentNullException.ThrowIfNull(instance);
+ _instance = instance;
+ }
+
+ public VncConnection(VncSettings settings) : this(CreateInstance(settings))
+ {
+ Context!.Connection = this;
+ }
+
+ static void* CreateInstance(VncSettings settings)
+ {
+ ArgumentNullException.ThrowIfNull(settings);
+ var context = new VncContext();
+ var logger = new VncLogger(context);
+ context.Logger = logger;
+ return RoyalVNCKit.rvnc_connection_create(settings.Instance, logger.Instance, context.Instance);
+ }
+
+ VncContext? Context
+ {
+ get
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ var contextInstance = RoyalVNCKit.rvnc_connection_context_get(_instance);
+
+ if (contextInstance is null)
+ return null;
+
+ var context = VncContext.FromPointer(contextInstance);
+
+ return context;
+ }
+ }
+
+ public ConnectionStatus Status
+ {
+ get
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ void* nativeState = RoyalVNCKit.rvnc_connection_state_get_copy(_instance);
+ using var holder = new VncConnectionState(nativeState);
+
+ return holder.Status;
+ }
+ }
+
+ public VncConnectionDelegate? Delegate
+ {
+ set
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ var val = value is not null ? value.Instance : null;
+
+ var context = Context;
+
+ if (context is not null)
+ context.ConnectionDelegate = value;
+
+ RoyalVNCKit.rvnc_connection_delegate_set(_instance, val);
+ }
+ }
+
+ public void Connect()
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ RoyalVNCKit.rvnc_connection_connect(_instance);
+ }
+
+ public void Disconnect()
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ RoyalVNCKit.rvnc_connection_disconnect(_instance);
+ }
+
+ public void SendKeyDown(KeySymbol key)
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ RoyalVNCKit.rvnc_connection_key_down(_instance, key);
+ }
+
+ public void SendKeyUp(KeySymbol key)
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ RoyalVNCKit.rvnc_connection_key_up(_instance, key);
+ }
+
+ public void SendMouseButtonDown(ushort x, ushort y, MouseButton button)
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ if (!Enum.IsDefined(button)) {
+ throw new ArgumentOutOfRangeException(nameof(button));
+ }
+
+ RoyalVNCKit.rvnc_connection_mouse_down(_instance, button, x, y);
+ }
+
+ public void SendMouseButtonUp(ushort x, ushort y, MouseButton button)
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ if (!Enum.IsDefined(button)) {
+ throw new ArgumentOutOfRangeException(nameof(button));
+ }
+
+ RoyalVNCKit.rvnc_connection_mouse_up(_instance, button, x, y);
+ }
+
+ public void SendMouseMove(ushort x, ushort y)
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ RoyalVNCKit.rvnc_connection_mouse_move(_instance, x, y);
+ }
+
+ public void SendMouseScroll(ushort x, ushort y, double scrollWheelDeltaX, double scrollWheelDeltaY)
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed || _instance is null, this);
+
+ // TODO
+ MouseWheel direction = MouseWheel.Down;
+ uint steps = 1;
+
+ RoyalVNCKit.rvnc_connection_mouse_wheel(_instance, direction, x, y, steps);
+ }
+
+ public void Dispose()
+ {
+ if (_isDisposed)
+ return;
+
+ var context = Context;
+
+ context?.Dispose();
+
+ _isDisposed = true;
+
+ if (_instance is null)
+ return;
+
+ RoyalVNCKit.rvnc_connection_destroy(_instance);
+ _instance = null;
+ }
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncConnectionDelegate.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncConnectionDelegate.cs
new file mode 100644
index 00000000..5244731d
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncConnectionDelegate.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace RoyalApps.RoyalVNCKit;
+
+public delegate void VncConnectionStateChangedHandler(
+ VncConnection connection,
+ VncConnectionState state
+);
+
+public delegate bool VncAuthenticationRequestedHandler(
+ VncConnection connection,
+ AuthenticationRequest request
+);
+
+public delegate void VncCursorUpdatedHandler(
+ VncConnection connection,
+ VncCursor cursor
+);
+
+public delegate void VncFramebufferCreatedHandler(
+ VncConnection connection,
+ VncFramebuffer framebuffer
+);
+
+public delegate void VncFramebufferResizedHandler(
+ VncConnection connection,
+ VncFramebuffer framebuffer
+);
+
+public delegate void VncFramebufferUpdatedHandler(
+ VncConnection connection,
+ VncFramebuffer framebuffer,
+ VncFramebufferRegion region
+);
+
+public sealed unsafe class VncConnectionDelegate: IDisposable
+{
+ bool _isDisposed;
+ internal void* Instance { get; private set; }
+
+ public VncConnectionStateChangedHandler? ConnectionStateChanged { get; set; }
+ public VncAuthenticationRequestedHandler? AuthenticationRequested { get; set; }
+ public VncCursorUpdatedHandler? CursorUpdated { get; set; }
+ public VncFramebufferCreatedHandler? FramebufferCreated { get; set; }
+ public VncFramebufferResizedHandler? FramebufferResized { get; set; }
+ public VncFramebufferUpdatedHandler? FramebufferUpdated { get; set; }
+
+ VncConnectionDelegate(void* instance)
+ {
+ ArgumentNullException.ThrowIfNull(instance);
+ Instance = instance;
+ }
+
+ public VncConnectionDelegate() : this(
+ RoyalVNCKit.rvnc_connection_delegate_create(
+ connectionStateDidChange: ConnectionStateDidChangeHandler,
+ authenticate: AuthenticateHandler,
+ didCreateFramebuffer: DidCreateFramebufferHandler,
+ didResizeFramebuffer: DidResizeFramebufferHandler,
+ didUpdateFramebuffer: DidUpdateFramebufferHandler,
+ didUpdateCursor: DidUpdateCursorHandler
+ )
+ )
+ { }
+
+ public void Dispose()
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (Instance is null)
+ return;
+
+ RoyalVNCKit.rvnc_connection_delegate_destroy(Instance);
+ Instance = null;
+ }
+
+ static bool TryGetConnectionAndDelegate(
+ void* context,
+ [NotNullWhen(true)] out VncConnection? connection,
+ [NotNullWhen(true)] out VncConnectionDelegate? connectionDelegate
+ )
+ {
+ var vncContext = VncContext.FromPointer(context);
+
+ if (vncContext is null)
+ {
+ connection = null;
+ connectionDelegate = null;
+
+ return false;
+ }
+
+ connection = vncContext.Connection;
+ connectionDelegate = vncContext.ConnectionDelegate;
+
+ return connection is not null && connectionDelegate is not null;
+ }
+
+ static readonly RoyalVNCKit.ConnectionStateDidChangeDelegate ConnectionStateDidChangeHandler = ConnectionStateDidChange;
+ static void ConnectionStateDidChange(
+ void* connection,
+ void* context,
+ void* connectionState
+ )
+ {
+ if (!TryGetConnectionAndDelegate(context, out VncConnection? vncConnection, out VncConnectionDelegate? vncConnectionDelegate)
+ || vncConnectionDelegate is not { ConnectionStateChanged: {} handler })
+ return;
+
+ var state = new VncConnectionState(connectionState);
+ handler.Invoke(vncConnection, state);
+ }
+
+ static readonly RoyalVNCKit.AuthenticateDelegate AuthenticateHandler = Authenticate;
+ static void Authenticate(
+ void* connection,
+ void* context,
+ void* authenticationRequest
+ )
+ {
+ if (!TryGetConnectionAndDelegate(context, out VncConnection? vncConnection, out VncConnectionDelegate? vncConnectionDelegate)
+ || vncConnectionDelegate is not { AuthenticationRequested: { } handler })
+ {
+ RoyalVNCKit.rvnc_authentication_request_cancel(authenticationRequest);
+ return;
+ }
+
+ var authType = RoyalVNCKit.rvnc_authentication_request_authentication_type_get(authenticationRequest);
+ bool requiresUsername = RoyalVNCKit.rvnc_authentication_type_requires_username(authType).FromNativeBool();
+ bool requiresPassword = RoyalVNCKit.rvnc_authentication_type_requires_password(authType).FromNativeBool();
+
+ var request = new AuthenticationRequest(authType, requiresUsername, requiresPassword);
+
+ if (!handler.Invoke(vncConnection, request) || (request.Username is null && request.Password is null))
+ {
+ RoyalVNCKit.rvnc_authentication_request_cancel(authenticationRequest);
+ return;
+ }
+
+ if (request is { Username: string username, Password: string password })
+ RoyalVNCKit.rvnc_authentication_request_complete_with_username_password(authenticationRequest, username, password);
+ else
+ RoyalVNCKit.rvnc_authentication_request_complete_with_password(authenticationRequest, request.Password!);
+ }
+
+ static readonly RoyalVNCKit.DidUpdateCursorDelegate DidUpdateCursorHandler = DidUpdateCursor;
+ static void DidUpdateCursor(
+ void* connection,
+ void* context,
+ void* cursor
+ )
+ {
+ if (!TryGetConnectionAndDelegate(context, out VncConnection? vncConnection, out VncConnectionDelegate? vncConnectionDelegate)
+ || vncConnectionDelegate is not { CursorUpdated: { } handler })
+ return;
+
+ var vncCursor = new VncCursor(cursor);
+ handler.Invoke(vncConnection, vncCursor);
+ }
+
+ static readonly RoyalVNCKit.DidCreateFramebufferDelegate DidCreateFramebufferHandler = DidCreateFramebuffer;
+ static void DidCreateFramebuffer(
+ void* connection,
+ void* context,
+ void* framebuffer
+ )
+ {
+ if (!TryGetConnectionAndDelegate(context, out VncConnection? vncConnection, out VncConnectionDelegate? vncConnectionDelegate)
+ || vncConnectionDelegate is not { FramebufferCreated: { } handler })
+ return;
+
+ var vncFramebuffer = new VncFramebuffer(framebuffer);
+ handler.Invoke(vncConnection, vncFramebuffer);
+ }
+
+ static readonly RoyalVNCKit.DidResizeFramebufferDelegate DidResizeFramebufferHandler = DidResizeFramebuffer;
+ static void DidResizeFramebuffer(
+ void* connection,
+ void* context,
+ void* framebuffer
+ )
+ {
+ if (!TryGetConnectionAndDelegate(context, out VncConnection? vncConnection, out VncConnectionDelegate? vncConnectionDelegate)
+ || vncConnectionDelegate is not { FramebufferResized: { } handler })
+ return;
+
+ var vncFramebuffer = new VncFramebuffer(framebuffer);
+ handler.Invoke(vncConnection, vncFramebuffer);
+ }
+
+ static readonly RoyalVNCKit.DidUpdateFramebufferDelegate DidUpdateFramebufferHandler = DidUpdateFramebuffer;
+ static void DidUpdateFramebuffer(
+ void* connection,
+ void* context,
+ void* framebuffer,
+ ushort x,
+ ushort y,
+ ushort width,
+ ushort height
+ )
+ {
+ if (!TryGetConnectionAndDelegate(context, out VncConnection? vncConnection, out VncConnectionDelegate? vncConnectionDelegate)
+ || vncConnectionDelegate is not { FramebufferUpdated: { } handler })
+ return;
+
+ var vncFramebuffer = new VncFramebuffer(framebuffer);
+ var vncRegion = new VncFramebufferRegion(x, y, width, height);
+ handler.Invoke(vncConnection, vncFramebuffer, vncRegion);
+ }
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncConnectionState.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncConnectionState.cs
new file mode 100644
index 00000000..50a90750
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncConnectionState.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace RoyalApps.RoyalVNCKit;
+
+[StructLayout(LayoutKind.Auto)]
+public readonly unsafe ref struct VncConnectionState
+{
+ readonly void* _instance;
+
+ internal VncConnectionState(void* instance)
+ {
+ ArgumentNullException.ThrowIfNull(instance);
+ _instance = instance;
+ }
+
+ public ConnectionStatus Status => RoyalVNCKit.rvnc_connection_state_status_get(_instance);
+ public string? ErrorDescription => RoyalVNCKit.rvnc_connection_state_error_description_get_copy(_instance);
+ public bool DisplayErrorToUser => RoyalVNCKit.rvnc_connection_state_error_should_display_to_user_get(_instance).FromNativeBool();
+ public bool IsAuthenticationError => RoyalVNCKit.rvnc_connection_state_error_is_authentication_error_get(_instance).FromNativeBool();
+
+ internal void Dispose() => RoyalVNCKit.rvnc_connection_state_destroy(_instance);
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncContext.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncContext.cs
new file mode 100644
index 00000000..96245201
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncContext.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace RoyalApps.RoyalVNCKit;
+
+sealed unsafe class VncContext: IDisposable
+{
+ bool _isDisposed;
+ internal void* Instance { get; private set; }
+
+ internal VncConnection? Connection { get; set; }
+ internal VncConnectionDelegate? ConnectionDelegate { get; set; }
+ internal VncLogger? Logger { get; set; }
+
+ internal VncContext()
+ {
+ var handle = GCHandle.Alloc(this, GCHandleType.Normal);
+ var address = GCHandle.ToIntPtr(handle);
+
+ Instance = (void*)address;
+ }
+
+ internal static VncContext? FromPointer(void* pointer)
+ {
+ if (pointer is null)
+ return null;
+
+ var handle = GCHandle.FromIntPtr((nint)pointer);
+
+ if (!handle.IsAllocated)
+ return null;
+
+ var context = handle.Target as VncContext;
+
+ return context;
+ }
+
+ public void Dispose()
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (Instance is null)
+ return;
+
+ if (Connection is { } connection)
+ {
+ connection.Dispose();
+ Connection = null;
+ }
+
+ if (ConnectionDelegate is { } connectionDelegate)
+ {
+ connectionDelegate.Dispose();
+ ConnectionDelegate = null;
+ }
+
+ if (Logger is { } logger)
+ {
+ logger.Dispose();
+ Logger = null;
+ }
+
+ var handle = GCHandle.FromIntPtr((nint)Instance);
+
+ if (handle.IsAllocated)
+ handle.Free();
+
+ Instance = null;
+ }
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncCursor.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncCursor.cs
new file mode 100644
index 00000000..dc5e5848
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncCursor.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Diagnostics;
+
+namespace RoyalApps.RoyalVNCKit;
+
+public sealed unsafe class VncCursor : IDisposable
+{
+ bool _isDisposed;
+ void* _instance;
+ void* _pixelData;
+
+ internal VncCursor(void* instance)
+ {
+ ArgumentNullException.ThrowIfNull(instance);
+ _instance = instance;
+ }
+
+ public bool IsEmpty => RoyalVNCKit.rvnc_cursor_is_empty_get(_instance).FromNativeBool();
+ public ushort Width => RoyalVNCKit.rvnc_cursor_size_width_get(_instance);
+ public ushort Height => RoyalVNCKit.rvnc_cursor_size_height_get(_instance);
+ public ushort HotspotX => RoyalVNCKit.rvnc_cursor_hotspot_x_get(_instance);
+ public ushort HotspotY => RoyalVNCKit.rvnc_cursor_hotspot_y_get(_instance);
+ public long BitsPerComponent => RoyalVNCKit.rvnc_cursor_bits_per_component_get(_instance);
+ public long BitsPerPixel => RoyalVNCKit.rvnc_cursor_bits_per_pixel_get(_instance);
+ public long BytesPerPixel => RoyalVNCKit.rvnc_cursor_bytes_per_pixel_get(_instance);
+ public long BytesPerRow => RoyalVNCKit.rvnc_cursor_bytes_per_row_get(_instance);
+
+ public ReadOnlySpan PixelData
+ {
+ get
+ {
+ var length = checked((int)RoyalVNCKit.rvnc_cursor_pixel_data_size_get(_instance));
+ if (length is 0)
+ return ReadOnlySpan.Empty;
+
+ if (_pixelData is null)
+ _pixelData = RoyalVNCKit.rvnc_cursor_pixel_data_get_copy(_instance);
+
+ Debug.Assert(_pixelData is not null);
+ return new(_pixelData, length);
+ }
+ }
+
+ public void Dispose()
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (_pixelData is not null)
+ {
+ RoyalVNCKit.rvnc_cursor_pixel_data_destroy(_pixelData);
+ _pixelData = null;
+ }
+
+ _instance = null;
+ }
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncFramebuffer.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncFramebuffer.cs
new file mode 100644
index 00000000..fc65d968
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncFramebuffer.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace RoyalApps.RoyalVNCKit;
+
+[StructLayout(LayoutKind.Auto)]
+public readonly unsafe ref struct VncFramebuffer
+{
+ readonly void* _instance;
+
+ internal VncFramebuffer(void* instance)
+ {
+ ArgumentNullException.ThrowIfNull(instance);
+ _instance = instance;
+ }
+
+ public ushort Width => RoyalVNCKit.rvnc_framebuffer_size_width_get(_instance);
+ public ushort Height => RoyalVNCKit.rvnc_framebuffer_size_height_get(_instance);
+
+ public ReadOnlySpan PixelData
+ {
+ get
+ {
+ var length = checked((int)RoyalVNCKit.rvnc_framebuffer_pixel_data_size_get(_instance));
+ if (length is 0)
+ return ReadOnlySpan.Empty;
+
+ var pixelData = RoyalVNCKit.rvnc_framebuffer_pixel_data_get(_instance);
+
+ Debug.Assert(pixelData is not null);
+ return new(pixelData, length);
+ }
+ }
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncFramebufferRegion.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncFramebufferRegion.cs
new file mode 100644
index 00000000..143bdc31
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncFramebufferRegion.cs
@@ -0,0 +1,23 @@
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace RoyalApps.RoyalVNCKit;
+
+[StructLayout(LayoutKind.Auto)]
+public readonly struct VncFramebufferRegion
+{
+ public ushort X { get; }
+ public ushort Y { get; }
+ public ushort Width { get; }
+ public ushort Height { get; }
+
+ internal VncFramebufferRegion(ushort x, ushort y, ushort width, ushort height)
+ {
+ Debug.Assert(width > 0);
+ Debug.Assert(height > 0);
+ X = x;
+ Y = y;
+ Width = width;
+ Height = height;
+ }
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncLogger.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncLogger.cs
new file mode 100644
index 00000000..23ddf20c
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncLogger.cs
@@ -0,0 +1,54 @@
+using System;
+
+namespace RoyalApps.RoyalVNCKit;
+
+public delegate void VncLogEntryHandler(
+ VncLogger logger,
+ LogLevel logLevel,
+ string message
+);
+
+public sealed unsafe class VncLogger : IDisposable
+{
+ bool _isDisposed;
+ internal void* Instance { get; private set; }
+
+ public VncLogEntryHandler? AddLogEntry { get; set; }
+
+ internal VncLogger(VncContext context)
+ {
+ ArgumentNullException.ThrowIfNull(context);
+ Instance = RoyalVNCKit.rvnc_logger_create(LogEntryHandler, context.Instance);
+ }
+
+ public void Dispose()
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (Instance is null)
+ return;
+
+ RoyalVNCKit.rvnc_logger_destroy(Instance);
+ Instance = null;
+ }
+
+ static readonly RoyalVNCKit.LogDelegate LogEntryHandler = LogEntry;
+
+ static void LogEntry(
+ void* logger,
+ void* context,
+ LogLevel logLevel,
+ string message
+ )
+ {
+ var vncContext = VncContext.FromPointer(context);
+
+ if (vncContext?.Logger is not { } vncLogger)
+ return;
+
+ vncLogger.AddLogEntry?.Invoke(vncLogger, logLevel, message);
+ }
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncSettings.cs b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncSettings.cs
new file mode 100644
index 00000000..678bb793
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/VncSettings.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace RoyalApps.RoyalVNCKit;
+
+public interface IVncSettings
+{
+ public string Hostname { get; }
+ public ushort Port { get; }
+ public InputMode InputMode { get; }
+ public ColorDepth ColorDepth { get; }
+ public bool IsClipboardRedirectionEnabled { get; }
+ public bool IsDebugLoggingEnabled { get; }
+ public bool IsScalingEnabled { get; }
+ public bool IsShared { get; }
+ public bool UseDisplayLink { get; }
+}
+
+public sealed unsafe class VncSettings: IDisposable
+{
+ bool _isDisposed;
+
+ internal void* Instance { get; private set; }
+
+ internal VncSettings(void* instance)
+ {
+ ArgumentNullException.ThrowIfNull(instance);
+ Instance = instance;
+ }
+
+ public VncSettings(IVncSettings settings)
+ {
+ ArgumentNullException.ThrowIfNull(settings);
+ Instance = RoyalVNCKit.rvnc_settings_create(
+ settings.IsDebugLoggingEnabled.ToNativeBool(),
+ settings.Hostname,
+ settings.Port,
+ settings.IsShared.ToNativeBool(),
+ settings.IsScalingEnabled.ToNativeBool(),
+ settings.UseDisplayLink.ToNativeBool(),
+ settings.InputMode,
+ settings.IsClipboardRedirectionEnabled.ToNativeBool(),
+ settings.ColorDepth
+ );
+ }
+
+ public void Dispose()
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (Instance is null)
+ return;
+
+ RoyalVNCKit.rvnc_settings_destroy(Instance);
+ Instance = null;
+ }
+}
diff --git a/Bindings/dotnet/RoyalApps.RoyalVNCKit/nuget/RoyalApps.RoyalVNCKit.nuspec b/Bindings/dotnet/RoyalApps.RoyalVNCKit/nuget/RoyalApps.RoyalVNCKit.nuspec
new file mode 100644
index 00000000..7d65fd6f
--- /dev/null
+++ b/Bindings/dotnet/RoyalApps.RoyalVNCKit/nuget/RoyalApps.RoyalVNCKit.nuspec
@@ -0,0 +1,30 @@
+
+
+
+ RoyalApps.RoyalVNCKit
+ $NUGET_VERSION$
+ RoyalApps
+ MIT
+ https://licenses.nuget.org/MIT
+ RoyalApps_1024.png
+ README.md
+ https://github.com/royalapplications/royalvnc
+ .NET wrapper for RoyalVNC with high-level API
+ RoyalApps RoyalVNCKit VNC .NET
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Bindings/dotnet/RoyalApps_1024.png b/Bindings/dotnet/RoyalApps_1024.png
new file mode 100644
index 00000000..cdf94d9b
Binary files /dev/null and b/Bindings/dotnet/RoyalApps_1024.png differ
diff --git a/Bindings/dotnet/TestAOT/NuGet.config b/Bindings/dotnet/TestAOT/NuGet.config
new file mode 100644
index 00000000..ad60cf47
--- /dev/null
+++ b/Bindings/dotnet/TestAOT/NuGet.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Bindings/dotnet/TestAOT/Program.cs b/Bindings/dotnet/TestAOT/Program.cs
new file mode 100644
index 00000000..cb727abd
--- /dev/null
+++ b/Bindings/dotnet/TestAOT/Program.cs
@@ -0,0 +1,25 @@
+using System;
+using RoyalApps.RoyalVNCKit;
+
+if (args.Length is not 1)
+{
+ Console.Error.WriteLine("""
+ Usage: TestAOT
+
+ Argument:
+ --version Print RoyalVNCKit version and build information.
+ """);
+ return 1;
+}
+
+switch (args[0])
+{
+ case "--version":
+ var version = typeof(VncConnection).Assembly.GetName().Version;
+ Console.WriteLine($"RoyalVNCKit v{version}");
+ return 0;
+
+ default:
+ Console.Error.WriteLine($"Unknown argument found: {args[0]}");
+ return 1;
+}
diff --git a/Bindings/dotnet/TestAOT/TestAOT.csproj b/Bindings/dotnet/TestAOT/TestAOT.csproj
new file mode 100644
index 00000000..49b131f0
--- /dev/null
+++ b/Bindings/dotnet/TestAOT/TestAOT.csproj
@@ -0,0 +1,25 @@
+
+
+
+ Exe
+ net8.0
+ $(NETCoreSdkRuntimeIdentifier)
+ enable
+ true
+ false
+ true
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Bindings/dotnet/nuget-pack-dotnet.ps1 b/Bindings/dotnet/nuget-pack-dotnet.ps1
new file mode 100755
index 00000000..fc0d9040
--- /dev/null
+++ b/Bindings/dotnet/nuget-pack-dotnet.ps1
@@ -0,0 +1,21 @@
+#Requires -PSEdition Core -Version 7.4
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$PSNativeCommandArgumentPassing = 'Standard'
+$PSNativeCommandUseErrorActionPreference = $true
+$PSStyle.OutputRendering = 'ANSI'
+
+. $PSScriptRoot/nuget-utils.ps1
+
+$PROJECT_DIR = Join-Path $REPO_ROOT 'Bindings/dotnet/RoyalApps.RoyalVNCKit' -Resolve
+
+exec { dotnet build --configuration Release "-p:Version=${NUGET_VERSION}" $PROJECT_DIR }
+
+Write-Host 'Creating RoyalApps.RoyalVNCKit NuGet package'
+
+exec {
+ dotnet pack "${PROJECT_DIR}/RoyalApps.RoyalVNCKit.csproj" `
+ "-p:NuspecFile=${PROJECT_DIR}/nuget/RoyalApps.RoyalVNCKit.nuspec" `
+ "-p:NuspecBasePath=${PROJECT_DIR}" `
+ "-p:NuspecProperties=`"NUGET_VERSION=${NUGET_VERSION};NUGET_GIT_COMMIT=${NUGET_GIT_COMMIT}`""
+}
diff --git a/Bindings/dotnet/nuget-pack-native.ps1 b/Bindings/dotnet/nuget-pack-native.ps1
new file mode 100755
index 00000000..481fd642
--- /dev/null
+++ b/Bindings/dotnet/nuget-pack-native.ps1
@@ -0,0 +1,62 @@
+#Requires -PSEdition Core -Version 7.4
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$PSNativeCommandArgumentPassing = 'Standard'
+$PSNativeCommandUseErrorActionPreference = $true
+$PSStyle.OutputRendering = 'ANSI'
+
+. $PSScriptRoot/nuget-utils.ps1
+
+$CONFIGURATION = 'Release'
+if ($NUGET_RID -eq 'win-arm64') {
+ # ref. https://github.com/swiftlang/swift/issues/77220
+ $CONFIGURATION = 'Debug'
+}
+
+$DEMO_DIR = Join-Path $REPO_ROOT 'Bindings/dotnet/RoyalApps.RoyalVNCKit.Demo' -Resolve
+exec { dotnet build --configuration $CONFIGURATION $DEMO_DIR }
+
+$NATIVE_DIR = Join-Path $REPO_ROOT 'Bindings/dotnet/RoyalApps.RoyalVNCKit.native' -Resolve
+$NUSPEC_FILE = Join-Path $NATIVE_DIR 'native.nuspec' -Resolve
+
+if ($HOST_OS -eq 'windows') {
+ $NUSPEC_FILE = Join-Path $NATIVE_DIR 'windows.nuspec' -Resolve
+
+ $SWIFT_CRT_PATH = (Get-Command swiftCRT.dll -ErrorAction Stop).Source
+ $SWIFT_RT_DIR = Split-Path $SWIFT_CRT_PATH -Parent
+ Write-Host "Auto-detected Swift runtime dir: ${SWIFT_RT_DIR}"
+
+ $NUGET_SWIFT_RT_VERSION = $env:NUGET_SWIFT_RT_VERSION
+ if (-not $NUGET_SWIFT_RT_VERSION) {
+ [string]$version = (& swift --version)
+ if ($version -imatch 'Swift version (\d+\.\d+(\.\d+)?)') {
+ $NUGET_SWIFT_RT_VERSION = $Matches.1
+ Write-Host "Auto-detected NUGET_SWIFT_RT_VERSION: ${NUGET_SWIFT_RT_VERSION}"
+ }
+ else {
+ throw "NUGET_SWIFT_RT_VERSION not set and auto-detection failed for: `n${version}"
+ }
+ }
+
+ Write-Host "Creating RoyalApps.native.SwiftRuntime.${NUGET_RID} NuGet package"
+
+ exec {
+ dotnet pack "${NATIVE_DIR}/native.pkgproj" `
+ "-p:NuspecFile=${NATIVE_DIR}/windows.SwiftRuntime.nuspec" `
+ "-p:NuspecBasePath=${NATIVE_DIR}" `
+ "-p:NuspecProperties=`"NUGET_GIT_COMMIT=${NUGET_GIT_COMMIT};NUGET_RID=${NUGET_RID};SWIFT_RT_DIR=${SWIFT_RT_DIR};NUGET_SWIFT_RT_VERSION=${NUGET_SWIFT_RT_VERSION}`""
+ }
+} else {
+ $NUGET_SWIFT_RT_VERSION = ''
+}
+
+Write-Host "Creating RoyalApps.RoyalVNCKit.native.${NUGET_RID} NuGet package"
+
+$NUGET_LIB = Join-Path $DEMO_DIR "bin/${CONFIGURATION}/${NATIVE_LIB}" -Resolve
+
+exec {
+ dotnet pack "${NATIVE_DIR}/native.pkgproj" `
+ "-p:NuspecFile=${NUSPEC_FILE}" `
+ "-p:NuspecBasePath=${NATIVE_DIR}" `
+ "-p:NuspecProperties=`"NUGET_VERSION=${NUGET_VERSION};NUGET_GIT_COMMIT=${NUGET_GIT_COMMIT};NUGET_RID=${NUGET_RID};NUGET_SWIFT_RT_VERSION=${NUGET_SWIFT_RT_VERSION};NUGET_LIB_NAME=${NATIVE_LIB};NUGET_LIB=${NUGET_LIB}`""
+}
diff --git a/Bindings/dotnet/nuget-test-aot.ps1 b/Bindings/dotnet/nuget-test-aot.ps1
new file mode 100755
index 00000000..4a200988
--- /dev/null
+++ b/Bindings/dotnet/nuget-test-aot.ps1
@@ -0,0 +1,31 @@
+#Requires -PSEdition Core -Version 7.4
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$PSNativeCommandArgumentPassing = 'Standard'
+$PSNativeCommandUseErrorActionPreference = $true
+$PSStyle.OutputRendering = 'ANSI'
+
+. $PSScriptRoot/nuget-utils.ps1
+
+$TEST_AOT_DIR = Join-Path $REPO_ROOT 'Bindings/dotnet/TestAOT' -Resolve
+
+$TEST_RID = $NUGET_RID
+if ($HOST_OS -eq "macOS") {
+ $TEST_RID = "${TEST_RID}-${HOST_ARCH}"
+}
+
+Write-Host "Building .NET bindings AOT/package test for ${TEST_RID}"
+exec {
+ dotnet publish --runtime "${TEST_RID}" $TEST_AOT_DIR `
+ "-p:RoyalVNCKit_NativeRID=${NUGET_RID}" `
+ "-p:RoyalVNCKit_NupkgVersion=${NUGET_VERSION}"
+}
+
+$TEST_AOT_PROGRAM = "${TEST_AOT_DIR}/bin/Release/${TEST_RID}/publish/TestAOT"
+if ($HOST_OS -eq 'windows') {
+ $TEST_AOT_PROGRAM += '.exe'
+}
+$TEST_AOT_PROGRAM = Resolve-Path $TEST_AOT_PROGRAM
+
+Write-Host "Testing .NET bindings with AOT for ${TEST_RID}"
+exec { & $TEST_AOT_PROGRAM --version }
diff --git a/Bindings/dotnet/nuget-utils.ps1 b/Bindings/dotnet/nuget-utils.ps1
new file mode 100755
index 00000000..f9d1b991
--- /dev/null
+++ b/Bindings/dotnet/nuget-utils.ps1
@@ -0,0 +1,62 @@
+#Requires -PSEdition Core -Version 7.4
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$PSNativeCommandArgumentPassing = 'Standard'
+$PSNativeCommandUseErrorActionPreference = $true
+$PSStyle.OutputRendering = 'ANSI'
+
+$NUGET_VERSION = $env:NUGET_VERSION
+if (-not $NUGET_VERSION) {
+ throw "NUGET_VERSION was not passed in -- aborting"
+}
+
+$REPO_ROOT = Join-Path $PSScriptRoot '../..' -Resolve
+
+$HOST_OS = if ($IsLinux) { 'linux' }
+ elseif ($IsMacOS) { 'macOS' }
+ elseif ($IsWindows) { 'windows' }
+ else { throw 'Unknown OS -- aborting' }
+
+$HOST_ARCH = 'x64'
+$HOST_ARCH_SWIFT = 'x86_64'
+if ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -ieq 'ARM64') {
+ $HOST_ARCH = 'arm64'
+ $HOST_ARCH_SWIFT = if ($IsMacOS) { 'arm64' } else { 'aarch64' }
+}
+
+$NUGET_GIT_COMMIT = $env:NUGET_GIT_COMMIT
+if (-not $NUGET_GIT_COMMIT) {
+ [string]$NUGET_GIT_COMMIT = (& git rev-parse HEAD)
+ Write-Host "Auto-detected NUGET_GIT_COMMIT: ${NUGET_GIT_COMMIT}"
+}
+
+$NUGET_RID = $env:NUGET_RID
+if (-not $NUGET_RID) {
+ $NUGET_RID = switch ($HOST_OS) {
+ "macOS" { "osx" }
+ "windows" { "win-${HOST_ARCH}" }
+ default { "${HOST_OS}-${HOST_ARCH}" }
+ }
+ Write-Host "Auto-detected NUGET_RID: ${NUGET_RID}"
+}
+
+$NATIVE_LIB = switch ($HOST_OS) {
+ 'linux' { 'libRoyalVNCKit.so' }
+ 'macOS' { 'libRoyalVNCKit.dylib' }
+ 'windows' { 'RoyalVNCKit.dll' }
+}
+
+Write-Host "OS: ${HOST_OS}; NuGet RID: ${NUGET_RID}; arch: ${HOST_ARCH} (.NET), ${HOST_ARCH_SWIFT} (LLVM/Swift); native lib: ${NATIVE_LIB}"
+
+function exec([scriptblock]$command) {
+ $nl_indent = [Environment]::NewLine + ' '
+ $exec_clean_rx = [regex]::new('`\s*$\s+', [System.Text.RegularExpressions.RegexOptions]'Multiline,CultureInvariant,NonBacktracking,ExplicitCapture')
+
+ $clean_command = $exec_clean_rx.Replace($command.ToString().Trim(), $nl_indent)
+ $clean_command = ("@`"`n$clean_command`n`"@" | Invoke-Expression)
+
+ Write-Host $clean_command -ForegroundColor cyan
+ Invoke-Command -ScriptBlock $command
+
+ if ($lastexitcode -ne 0) { throw $lastexitcode }
+}
diff --git a/LICENSE b/LICENSE
index b47d2319..ee80e569 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2022 Royal Apps
+Copyright (c) 2024 Royal Apps
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Package.swift b/Package.swift
index 639c0323..4f44f282 100644
--- a/Package.swift
+++ b/Package.swift
@@ -2,6 +2,69 @@
import PackageDescription
+let swiftLanguageMode = SwiftLanguageMode.v5
+
+let cSettings: [CSetting]
+let libtomCSettings: [CSetting]
+let zTarget: Target
+
+let disableShorten64To32Warning = "-Wno-shorten-64-to-32"
+
+#if os(Windows)
+// Sources\libtommath\bignumshim.c:28:10: warning: 'mp_read_unsigned_bin' is deprecated: replaced by mp_from_ubin [-Wdeprecated-declarations]
+// Sources\libtomcrypt\mac\xcbc\xcbc_file.c:55:9: warning: 'fopen' is deprecated: This function or variable may be unsafe. Consider using fopen_s instead. [-Wdeprecated-declarations]
+let disableDeprecatedDeclarationsWarning = "-Wno-deprecated-declarations"
+
+// Sources\libtomcrypt\include\tomcrypt_cfg.h:27:28: warning: 'malloc' redeclared without 'dllimport' attribute: previous 'dllimport' ignored [-Winconsistent-dllimport]
+// Sources\libtomcrypt\include\tomcrypt_cfg.h:28:28: warning: 'realloc' redeclared without 'dllimport' attribute: previous 'dllimport' ignored [-Winconsistent-dllimport]
+let disableInconsistentDllImportWarning = "-Wno-inconsistent-dllimport"
+
+cSettings = [
+ .unsafeFlags([
+ disableDeprecatedDeclarationsWarning,
+ disableInconsistentDllImportWarning
+ ])
+]
+
+libtomCSettings = [
+ .unsafeFlags([
+ disableShorten64To32Warning,
+ disableDeprecatedDeclarationsWarning,
+ disableInconsistentDllImportWarning
+ ])
+]
+
+zTarget = Target.target(name: "Z", path: "Sources/zlib-1.3.1", cSettings: [
+ .define("STDC"),
+ .define("HAVE_STDARG_H"),
+ .define("HAVE_HIDDEN"),
+
+ .unsafeFlags([
+ disableDeprecatedDeclarationsWarning,
+ ])
+])
+#else
+cSettings = .init()
+
+libtomCSettings = [
+ .unsafeFlags([
+ disableShorten64To32Warning
+ ])
+]
+
+zTarget = Target.target(name: "Z", linkerSettings: [
+ .linkedLibrary("z")
+])
+#endif
+
+let libtommathTarget = Target.target(name: "libtommath",
+ cSettings: libtomCSettings)
+
+let libtomcryptTarget = Target.target(name: "libtomcrypt",
+ cSettings: libtomCSettings)
+
+let d3desTarget = Target.target(name: "d3des")
+
let package = Package(
name: "RoyalVNCKit",
@@ -19,21 +82,49 @@ let package = Package(
type: .dynamic,
targets: [ "RoyalVNCKit" ]
),
+
+ .executable(name: "RoyalVNCKitDemo",
+ targets: [ "RoyalVNCKitDemo" ])
],
-
+
targets: [
+ .target(
+ name: "RoyalVNCKitC",
+ cSettings: cSettings
+ ),
+
.target(
name: "RoyalVNCKit",
+
dependencies: [
- "d3des",
- "libtommath"
+ "RoyalVNCKitC",
+ .byName(name: d3desTarget.name),
+ .byName(name: libtommathTarget.name),
+ .byName(name: libtomcryptTarget.name),
+ .byName(name: zTarget.name)
],
- swiftSettings: [
- .swiftLanguageMode(.v5)
- ]
+
+ cSettings: cSettings,
+ swiftSettings: [ .swiftLanguageMode(swiftLanguageMode) ]
+ ),
+
+ d3desTarget,
+ libtommathTarget,
+ libtomcryptTarget,
+ zTarget,
+
+ .executableTarget(
+ name: "RoyalVNCKitDemo",
+ dependencies: [ "RoyalVNCKit" ],
+
+ cSettings: cSettings
),
- .target(name: "d3des"),
- .target(name: "libtommath")
+ .executableTarget(
+ name: "RoyalVNCKitCDemo",
+ dependencies: [ "RoyalVNCKit" ],
+
+ cSettings: cSettings
+ )
]
)
diff --git a/README.md b/README.md
index 8148a337..198d8445 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,8 @@
![RoyalVNC](Design/Banner_Rendered/Banner.png)
RoyalVNC is a modern, high performance implementation of the [VNC/RFB protocol](https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst) written in Swift.
-The SDK (RoyalVNCKit) is compatible with Swift and Objective-C on macOS, iOS and iPadOS.
-It has no external dependencies but includes some free (public domain) third party code from the libtommath and D3DES libraries (see [Credits](#Credits)).
+The SDK (RoyalVNCKit) is compatible with Swift, Objective-C, and C on macOS, iOS, iPadOS, Linux and Windows.
+It has no external dependencies but includes some free (public domain) third party code from the libtommath, libtomcrypt and D3DES libraries (see [Credits](#Credits)).
## Supported Features
@@ -37,6 +37,7 @@ It has no external dependencies but includes some free (public domain) third par
- Connection state management and rendering is decoupled from each other, so it's possible to build "headless" clients (ie. no rendering of the remote desktop).
- The SDK includes a ready-to-use implementation of a framebuffer view for macOS (subclass of `NSView`), which also handles mouse and keyboard input, local cursor (`NSCursor`), scaling and rendering. The iOS/iPadOS equivalent (`UIView`) is a work-in-progress.
- First-class error handling. The `VNCError` type divides all possible errors into three broad categories: Protocol, Authentication and Connection errors. There are helper functions to retrieve human-readable descriptions for all errors and a convenience functions that allows the SDK consumer to distinguish between errors that should be displayed to the user and ones that shouldn't.
+- Headless CLI demos (one using Swift and another one using the C API) are included in the repository.
- [This repository](https://github.com/royalapplications/royalvnc-demo) contains Demo/Sample clients for macOS (one written in Swift, one in Objective-C) and iOS/iPadOS.
## Usage
@@ -47,4 +48,6 @@ See [Usage](USAGE.md).
## Credits
- [libtommath](https://github.com/libtom/libtommath) ([The LibTom license](https://github.com/libtom/libtommath/blob/develop/LICENSE))
+- [libtomcrypt](https://github.com/libtom/libtomcrypt) ([The LibTom license](https://github.com/libtom/libtomcrypt/blob/develop/LICENSE))
+- [zlib](https://github.com/madler/zlib) ([zlib license](https://github.com/madler/zlib/blob/develop/LICENSE))
- D3DES (Public Domain, Copyright Richard Outerbridge)
diff --git a/Sources/RoyalVNCKit/Clipboard/VNCClipboard.Monitor.swift b/Sources/RoyalVNCKit/Clipboard/VNCClipboard.Monitor.swift
index 13bace95..672ee76e 100644
--- a/Sources/RoyalVNCKit/Clipboard/VNCClipboard.Monitor.swift
+++ b/Sources/RoyalVNCKit/Clipboard/VNCClipboard.Monitor.swift
@@ -1,4 +1,10 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
+
+import Dispatch
#if os(macOS)
import AppKit
@@ -6,7 +12,7 @@ import AppKit
import UIKit
#endif
-class VNCClipboardMonitor {
+final class VNCClipboardMonitor {
let clipboard: VNCClipboard
let monitoringInterval: TimeInterval
let tolerance: TimeInterval
@@ -15,7 +21,10 @@ class VNCClipboardMonitor {
private(set) var isMonitoring = false
+#if !canImport(FoundationEssentials)
private var timer: Timer?
+#endif
+
private var lastChangeCount = 0
init(clipboard: VNCClipboard,
@@ -40,39 +49,39 @@ extension VNCClipboardMonitor {
// -1 to send clipboard to trigger notification immediately if something's on the pasteboard
lastChangeCount = clipboard.changeCount - 1
+#if !canImport(FoundationEssentials)
guard timer == nil else { // Already have a timer
return
}
DispatchQueue.main.async { [weak self] in
guard let self else { return }
-
- let timer = Timer.scheduledTimer(timeInterval: self.monitoringInterval,
- target: self,
- selector: #selector(self.timerDidFire(_:)),
- userInfo: nil,
- repeats: true)
+
+ let timer = Timer.scheduledTimer(withTimeInterval: self.monitoringInterval,
+ repeats: true,
+ block: timerDidFire(_:))
timer.tolerance = self.tolerance
self.timer = timer
self.isMonitoring = true
}
+#endif
}
func stopMonitoring() {
+#if !canImport(FoundationEssentials)
timer?.invalidate()
timer = nil
+#endif
lastChangeCount = 0
isMonitoring = false
}
}
+#if !canImport(FoundationEssentials)
private extension VNCClipboardMonitor {
-#if canImport(ObjectiveC)
- @objc
-#endif
func timerDidFire(_ timer: Timer) {
guard let delegate,
timer == self.timer else {
@@ -99,3 +108,4 @@ private extension VNCClipboardMonitor {
didChangeText: text)
}
}
+#endif
diff --git a/Sources/RoyalVNCKit/Clipboard/VNCClipboard.swift b/Sources/RoyalVNCKit/Clipboard/VNCClipboard.swift
index b4e166a4..7d80c478 100644
--- a/Sources/RoyalVNCKit/Clipboard/VNCClipboard.swift
+++ b/Sources/RoyalVNCKit/Clipboard/VNCClipboard.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
#if os(macOS)
import AppKit
@@ -6,43 +10,51 @@ import AppKit
import UIKit
#endif
-class VNCClipboard {
- #if os(macOS)
+final class VNCClipboard {
+#if os(macOS)
let pasteboard: NSPasteboard
- #elseif os(iOS)
+#elseif os(iOS)
let pasteboard: UIPasteboard
- #endif
+#endif
init() {
+#if os(macOS) || os(iOS)
self.pasteboard = .general
+#endif
}
}
extension VNCClipboard {
var text: String? {
get {
- #if os(macOS)
+#if os(macOS)
let text = pasteboard.string(forType: .string)
- #elseif os(iOS)
+#elseif os(iOS)
let text = pasteboard.string
- #endif
+#else
+ let text: String? = nil
+#endif
return text
}
set {
- #if os(macOS)
+#if os(macOS)
pasteboard.clearContents()
pasteboard.setString(newValue ?? "", forType: .string)
- #elseif os(iOS)
+#elseif os(iOS)
pasteboard.string = newValue
- #endif
+#endif
}
}
}
extension VNCClipboard {
var changeCount: Int {
+#if os(macOS) || os(iOS)
pasteboard.changeCount
+#else
+ 0
+#endif
}
}
diff --git a/Sources/RoyalVNCKit/Clipboard/VNCClipboardMonitorDelegate.swift b/Sources/RoyalVNCKit/Clipboard/VNCClipboardMonitorDelegate.swift
index 5c9b5874..04a6f94a 100644
--- a/Sources/RoyalVNCKit/Clipboard/VNCClipboardMonitorDelegate.swift
+++ b/Sources/RoyalVNCKit/Clipboard/VNCClipboardMonitorDelegate.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
protocol VNCClipboardMonitorDelegate: AnyObject {
func clipboardMonitorShouldMonitor(_ clipboardMonitor: VNCClipboardMonitor) -> Bool
diff --git a/Sources/RoyalVNCKit/Compression/ZlibInflateStream.swift b/Sources/RoyalVNCKit/Compression/ZlibInflateStream.swift
index 8a073264..6055711d 100644
--- a/Sources/RoyalVNCKit/Compression/ZlibInflateStream.swift
+++ b/Sources/RoyalVNCKit/Compression/ZlibInflateStream.swift
@@ -1,5 +1,10 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
-import zlib
+#endif
+
+@_implementationOnly import Z
enum ZlibError: Error {
case unknown(status: Int32, message: String?)
@@ -24,7 +29,7 @@ enum ZlibFlush: Int32 {
case trees = 6 // Z_TREES
}
-class ZlibInflateStream {
+final class ZlibInflateStream {
private let streamPtr: UnsafeMutablePointer
init() throws {
@@ -38,7 +43,7 @@ class ZlibInflateStream {
var status = Z_VERSION_ERROR
withUnsafeMutablePointer(to: &version) { versionPtr in
- status = zlib.inflateInit_(streamPtr, versionPtr, .init(MemoryLayout.size))
+ status = inflateInit_(streamPtr, versionPtr, .init(MemoryLayout.size))
}
guard ZlibError.isSuccess(status) else {
@@ -70,10 +75,10 @@ extension ZlibInflateStream {
/// total number of bytes output so far
var totalOut: UInt {
get {
- streamPtr.pointee.total_out
+ .init(streamPtr.pointee.total_out)
}
set {
- streamPtr.pointee.total_out = newValue
+ streamPtr.pointee.total_out = .init(newValue)
}
}
@@ -90,10 +95,10 @@ extension ZlibInflateStream {
/// total number of input bytes read so far
var totalIn: UInt {
get {
- streamPtr.pointee.total_in
+ .init(streamPtr.pointee.total_in)
}
set {
- streamPtr.pointee.total_in = newValue
+ streamPtr.pointee.total_in = .init(newValue)
}
}
@@ -135,10 +140,10 @@ extension ZlibInflateStream {
/// Adler-32 or CRC-32 value of the uncompressed data
var adler: UInt {
get {
- streamPtr.pointee.adler
+ .init(streamPtr.pointee.adler)
}
set {
- streamPtr.pointee.adler = newValue
+ streamPtr.pointee.adler = .init(newValue)
}
}
}
@@ -150,7 +155,7 @@ extension ZlibInflateStream {
func inflateEnd() throws {
let streamPtr = self.streamPtr
- let status = zlib.inflateEnd(streamPtr)
+ let status = Z.inflateEnd(streamPtr)
guard ZlibError.isSuccess(status) else {
throw Self.error(streamPtr: streamPtr,
@@ -280,7 +285,7 @@ extension ZlibInflateStream {
let flushValue = flush.rawValue
- let status = zlib.inflate(streamPtr, flushValue)
+ let status = Z.inflate(streamPtr, flushValue)
if status == Z_STREAM_END {
return true
diff --git a/Sources/RoyalVNCKit/Compression/ZlibStream.swift b/Sources/RoyalVNCKit/Compression/ZlibStream.swift
index 9b69566b..c3e84b2a 100644
--- a/Sources/RoyalVNCKit/Compression/ZlibStream.swift
+++ b/Sources/RoyalVNCKit/Compression/ZlibStream.swift
@@ -1,7 +1,12 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
-import zlib
+#endif
-class ZlibStream {
+@_implementationOnly import Z
+
+final class ZlibStream {
private let stream: ZlibInflateStream
enum ZlibStreamError: Error {
diff --git a/Sources/RoyalVNCKit/Encryption/AES128ECBEncryption.swift b/Sources/RoyalVNCKit/Encryption/AES128ECBEncryption.swift
index 0f8d98ae..934bacc2 100644
--- a/Sources/RoyalVNCKit/Encryption/AES128ECBEncryption.swift
+++ b/Sources/RoyalVNCKit/Encryption/AES128ECBEncryption.swift
@@ -1,83 +1,112 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
-import CommonCrypto
+#endif
+
+@_implementationOnly import libtomcrypt
struct AES128ECBEncryption {
- static func encrypt(data: Data,
- key: Data) -> Data? {
- let cipherBufferSize = data.count + kCCBlockSizeAES128
- var cipherBuffer = Data(repeating: 0, count: cipherBufferSize)
-
- var cipherData: Data?
-
- cipherBuffer.withUnsafeMutableBytes { cipherBufferBytesPtr in
- guard let cipherBufferPtr = cipherBufferBytesPtr.baseAddress else { return }
-
- data.withUnsafeBytes { dataBytesPtr in
- guard let dataPtr = dataBytesPtr.baseAddress else { return }
-
- key.withUnsafeBytes { keyBytesPtr in
- guard let keyPtr = keyBytesPtr.baseAddress else { return }
-
- var cryptor: CCCryptorRef?
-
- let createStatus = CCCryptorCreateWithMode(.init(kCCEncrypt),
- .init(kCCModeECB),
- .init(kCCAlgorithmAES128),
- .init(ccNoPadding),
- nil,
- keyPtr,
- key.count,
- nil,
- 0,
- 0,
- .zero,
- &cryptor)
-
- defer {
- if let cryptor = cryptor {
- CCCryptorRelease(cryptor)
- }
- }
-
- guard createStatus == kCCSuccess,
- let cryptor = cryptor else {
- return
- }
-
- var actualLength = 0
-
- let updateStatus = CCCryptorUpdate(cryptor,
- dataPtr,
- data.count,
- cipherBufferPtr,
- cipherBufferSize,
- &actualLength)
-
- guard updateStatus == kCCSuccess else {
- return
- }
-
- var finalCipherBuffer = Data(bytes: cipherBufferPtr,
- count: actualLength)
-
- finalCipherBuffer.withUnsafeMutableBytes { finalCipherBufferBytesPtr in
- guard let finalCipherBufferPtr = finalCipherBufferBytesPtr.baseAddress else { return }
-
- let finalStatus = CCCryptorFinal(cryptor,
- finalCipherBufferPtr,
- actualLength,
- &actualLength)
-
- guard finalStatus == kCCSuccess else {
- return
- }
- }
-
- cipherData = finalCipherBuffer
- }
- }
- }
-
- return cipherData
- }
+ static func encrypt(data: Data,
+ key: Data) -> Data? {
+ // Ensure the key is 16 bytes for AES-128
+ guard key.count == 16 else {
+ return nil
+ }
+
+ var aesDesc = aes_desc
+
+ // Register the cipher if necessary
+ guard register_cipher(&aesDesc) == CRYPT_OK else {
+ return nil
+ }
+
+ var ecbKey: symmetric_ECB = symmetric_ECB()
+
+ defer {
+ // Clean up and free the ECB key structure
+ ecb_done(&ecbKey)
+ }
+
+ let blockSizeAES128 = 16
+
+ // Set up the ECB key with AES-128
+ let keySetupResult: Int32 = key.withUnsafeBytes { keyPtr in
+ guard let keyPtrAddr = keyPtr.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
+ return -1
+ }
+
+ let aesCipher = find_cipher("aes")
+
+ // Initialize the ECB structure with the key
+ let result = ecb_start(
+ aesCipher,
+ keyPtrAddr,
+ .init(key.count),
+ 0,
+ &ecbKey
+ )
+
+ return result
+ }
+
+ guard keySetupResult == CRYPT_OK else {
+ return nil
+ }
+
+ // Prepare output buffer for ciphertext (same size as input for ECB mode)
+ var cipherBuffer = Data(repeating: 0,
+ count: ((data.count + blockSizeAES128 - 1) / blockSizeAES128) * blockSizeAES128)
+
+ // Encrypt the data block by block
+ let encryptionResult = cipherBuffer.withUnsafeMutableBytes { cipherBufferPtr in
+ guard let cipherBufferPtrAddr = cipherBufferPtr.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
+ return -1
+ }
+
+ // Encrypt each block of data
+ for blockStart in stride(from: 0,
+ to: data.count,
+ by: blockSizeAES128) {
+ let blockLength = min(blockSizeAES128,
+ data.count - blockStart)
+
+ // Create a block from the data, padding with zeroes if necessary
+ let block = data[blockStart..
private let backingDataPointer: UnsafeMutablePointer?
@@ -99,5 +101,3 @@ extension BigNum {
return data
}
}
-
-// swiftlint:enable identifier_name
diff --git a/Sources/RoyalVNCKit/Encryption/VNCDESEncryption.swift b/Sources/RoyalVNCKit/Encryption/VNCDESEncryption.swift
index 5a564fee..516e6d8b 100644
--- a/Sources/RoyalVNCKit/Encryption/VNCDESEncryption.swift
+++ b/Sources/RoyalVNCKit/Encryption/VNCDESEncryption.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
@_implementationOnly import d3des
diff --git a/Sources/RoyalVNCKit/Extensions/AnyStream.swift b/Sources/RoyalVNCKit/Extensions/AnyStream.swift
index 4db695b9..42b66585 100644
--- a/Sources/RoyalVNCKit/Extensions/AnyStream.swift
+++ b/Sources/RoyalVNCKit/Extensions/AnyStream.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
protocol AnyStream {
func read(length: Int) throws -> Data
@@ -35,10 +39,10 @@ extension AnyStream {
#endif
let bigEndianValue = data.withUnsafeBytes {
- $0.load(as: UInt16.self)
+ $0.loadUnaligned(as: UInt16.self)
}
- let value = CFByteOrderGetCurrent() == .init(CFByteOrderLittleEndian.rawValue)
+ let value = Endianness.current == .little
? UInt16(bigEndian: bigEndianValue)
: bigEndianValue
@@ -56,10 +60,10 @@ extension AnyStream {
#endif
let bigEndianValue = data.withUnsafeBytes {
- $0.load(as: UInt32.self)
+ $0.loadUnaligned(as: UInt32.self)
}
- let value = CFByteOrderGetCurrent() == .init(CFByteOrderLittleEndian.rawValue)
+ let value = Endianness.current == .little
? UInt32(bigEndian: bigEndianValue)
: bigEndianValue
diff --git a/Sources/RoyalVNCKit/Extensions/Array+Extensions.swift b/Sources/RoyalVNCKit/Extensions/Array+Extensions.swift
index 51db7b07..a2ae7969 100644
--- a/Sources/RoyalVNCKit/Extensions/Array+Extensions.swift
+++ b/Sources/RoyalVNCKit/Extensions/Array+Extensions.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension Array where Element: Hashable {
func uniqued() -> Array {
diff --git a/Sources/RoyalVNCKit/Extensions/BinaryInteger+Extensions.swift b/Sources/RoyalVNCKit/Extensions/BinaryInteger+Extensions.swift
new file mode 100644
index 00000000..ba5b218e
--- /dev/null
+++ b/Sources/RoyalVNCKit/Extensions/BinaryInteger+Extensions.swift
@@ -0,0 +1,11 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+extension BinaryInteger {
+ func hexString() -> String {
+ "0x\(String(self, radix: 16, uppercase: true))"
+ }
+}
\ No newline at end of file
diff --git a/Sources/RoyalVNCKit/Extensions/CGRect+Extensions.swift b/Sources/RoyalVNCKit/Extensions/CGRect+Extensions.swift
index 33e856ff..aa84e0e4 100644
--- a/Sources/RoyalVNCKit/Extensions/CGRect+Extensions.swift
+++ b/Sources/RoyalVNCKit/Extensions/CGRect+Extensions.swift
@@ -1,4 +1,6 @@
+#if canImport(CoreGraphics)
import Foundation
+import CoreGraphics
public extension CGRect {
func flipped(bounds: CGRect) -> CGRect {
@@ -8,3 +10,4 @@ public extension CGRect {
height: self.height)
}
}
+#endif
diff --git a/Sources/RoyalVNCKit/Extensions/Character+Extensions.swift b/Sources/RoyalVNCKit/Extensions/Character+Extensions.swift
index 0f58ead9..2ed4fa55 100644
--- a/Sources/RoyalVNCKit/Extensions/Character+Extensions.swift
+++ b/Sources/RoyalVNCKit/Extensions/Character+Extensions.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension Character {
var isPrintable: Bool {
diff --git a/Sources/RoyalVNCKit/Extensions/Data+Extensions.swift b/Sources/RoyalVNCKit/Extensions/Data+Extensions.swift
index 2749304b..0fa7e8ee 100644
--- a/Sources/RoyalVNCKit/Extensions/Data+Extensions.swift
+++ b/Sources/RoyalVNCKit/Extensions/Data+Extensions.swift
@@ -1,5 +1,10 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
-import CryptoKit
+#endif
+
+@_implementationOnly import libtomcrypt
extension Data {
mutating func append(_ uint32: UInt32,
@@ -53,8 +58,49 @@ extension Data {
}
func md5Hash() -> Data {
- let hash = Insecure.MD5.hash(data: self)
- let hashData = Data(hash)
+ var hashState = hash_state()
+
+ // Initialize the MD5 context
+ let initResult = md5_init(&hashState)
+
+ guard initResult == CRYPT_OK else {
+ fatalError("MD5 init failed: \(initResult)")
+ }
+
+ // Process the input data
+ let processResult = self.withUnsafeBytes {
+ guard let ptrAddr = $0.baseAddress else {
+ return CRYPT_ERROR
+ }
+
+ let ret = md5_process(&hashState,
+ ptrAddr,
+ .init(self.count))
+
+ return .init(ret)
+ }
+
+ guard processResult == CRYPT_OK else {
+ fatalError("MD5 process failed: \(processResult)")
+ }
+
+ var hashData = Data(count: 16)
+
+ // Finalize the hash and retrieve the result
+ let doneResult = hashData.withUnsafeMutableBytes {
+ guard let ptrAddr = $0.baseAddress else {
+ return CRYPT_ERROR
+ }
+
+ let ret = md5_done(&hashState,
+ ptrAddr)
+
+ return .init(ret)
+ }
+
+ guard doneResult == CRYPT_OK else {
+ fatalError("MD5 done failed: \(doneResult)")
+ }
return hashData
}
diff --git a/Sources/RoyalVNCKit/Extensions/DataStream.swift b/Sources/RoyalVNCKit/Extensions/DataStream.swift
index 26a5a854..2faa5402 100644
--- a/Sources/RoyalVNCKit/Extensions/DataStream.swift
+++ b/Sources/RoyalVNCKit/Extensions/DataStream.swift
@@ -1,6 +1,10 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
-class DataStream {
+final class DataStream {
let data: Data
private(set) var offset = 0
diff --git a/Sources/RoyalVNCKit/Extensions/Endianness.swift b/Sources/RoyalVNCKit/Extensions/Endianness.swift
new file mode 100644
index 00000000..6b814990
--- /dev/null
+++ b/Sources/RoyalVNCKit/Extensions/Endianness.swift
@@ -0,0 +1,35 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+#if !os(Linux) && !os(Windows)
+import CoreFoundation
+#endif
+
+enum Endianness {
+ case little
+ case big
+}
+
+extension Endianness {
+ static var current: Endianness = {
+ let endianess: Endianness
+
+#if !os(Linux) && !os(Windows)
+ endianess = CFByteOrderGetCurrent() == .init(CFByteOrderLittleEndian.rawValue)
+ ? .little
+ : .big
+#else
+ let number: UInt32 = 0x12345678
+ let converted = number.bigEndian
+
+ endianess = number == converted
+ ? .big
+ : .little
+#endif
+
+ return endianess
+ }()
+}
diff --git a/Sources/RoyalVNCKit/Extensions/Error+Extensions.swift b/Sources/RoyalVNCKit/Extensions/Error+Extensions.swift
new file mode 100644
index 00000000..909ef36d
--- /dev/null
+++ b/Sources/RoyalVNCKit/Extensions/Error+Extensions.swift
@@ -0,0 +1,32 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+extension Error {
+ var humanReadableDescription: String {
+ let errorMessage: String
+
+#if canImport(FoundationEssentials)
+ if let localizedError = self as? LocalizedError,
+ let errorDescription = localizedError.errorDescription {
+ errorMessage = errorDescription
+ } else {
+ errorMessage = String(describing: self)
+ }
+#else
+ errorMessage = self.localizedDescription
+#endif
+
+ return errorMessage
+ }
+
+ var debugDescription: String {
+#if canImport(FoundationEssentials)
+ .init(describing: self)
+#else
+ (self as NSError).debugDescription
+#endif
+ }
+}
diff --git a/Sources/RoyalVNCKit/Extensions/Int16+Extensions.swift b/Sources/RoyalVNCKit/Extensions/Int16+Extensions.swift
index 34f27bfd..c0dafdc5 100644
--- a/Sources/RoyalVNCKit/Extensions/Int16+Extensions.swift
+++ b/Sources/RoyalVNCKit/Extensions/Int16+Extensions.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension Int16 {
func uint8Value(bigEndian: Bool) -> [UInt8] {
diff --git a/Sources/RoyalVNCKit/Extensions/Int32+Extensions.swift b/Sources/RoyalVNCKit/Extensions/Int32+Extensions.swift
index e1905a5f..d4d06716 100644
--- a/Sources/RoyalVNCKit/Extensions/Int32+Extensions.swift
+++ b/Sources/RoyalVNCKit/Extensions/Int32+Extensions.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension Int32 {
func uint8Value(bigEndian: Bool) -> [UInt8] {
diff --git a/Sources/RoyalVNCKit/Extensions/Queue.swift b/Sources/RoyalVNCKit/Extensions/Queue.swift
index 8ef27dd3..d492c29e 100644
--- a/Sources/RoyalVNCKit/Extensions/Queue.swift
+++ b/Sources/RoyalVNCKit/Extensions/Queue.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
struct Queue {
private var list = [T]()
diff --git a/Sources/RoyalVNCKit/Extensions/Task+Extensions.swift b/Sources/RoyalVNCKit/Extensions/Task+Extensions.swift
index 3e7ebc51..a1d83a35 100644
--- a/Sources/RoyalVNCKit/Extensions/Task+Extensions.swift
+++ b/Sources/RoyalVNCKit/Extensions/Task+Extensions.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension Task where Success == Never, Failure == Never {
static func sleep(seconds: Double) async throws {
diff --git a/Sources/RoyalVNCKit/Extensions/UInt16+Extensions.swift b/Sources/RoyalVNCKit/Extensions/UInt16+Extensions.swift
index cf7042d0..51b985a0 100644
--- a/Sources/RoyalVNCKit/Extensions/UInt16+Extensions.swift
+++ b/Sources/RoyalVNCKit/Extensions/UInt16+Extensions.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension UInt16 {
func uint8Value(bigEndian: Bool) -> [UInt8] {
diff --git a/Sources/RoyalVNCKit/Extensions/UInt32+Extensions.swift b/Sources/RoyalVNCKit/Extensions/UInt32+Extensions.swift
index 658ee8d9..5dc73e86 100644
--- a/Sources/RoyalVNCKit/Extensions/UInt32+Extensions.swift
+++ b/Sources/RoyalVNCKit/Extensions/UInt32+Extensions.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension UInt32 {
func uint8Value(bigEndian: Bool) -> [UInt8] {
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.ColorMap.swift b/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.ColorMap.swift
index 102c6554..3fd5714a 100644
--- a/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.ColorMap.swift
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.ColorMap.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCFramebuffer {
struct ColorMap {
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.PixelUtils.swift b/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.PixelUtils.swift
index c4108135..d0978f33 100644
--- a/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.PixelUtils.swift
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.PixelUtils.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCFramebuffer {
enum ColorChannel {
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.Properties.swift b/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.Properties.swift
index e2e2621b..fe277e1e 100644
--- a/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.Properties.swift
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.Properties.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCFramebuffer {
struct Properties: Equatable {
@@ -75,7 +79,7 @@ extension VNCFramebuffer {
let bytesPerPixel = 4
let bytesPerRow = width * bytesPerPixel
- let bits = Int(floor(Double(colorDepth) / 3.0))
+ let bits = Int((Double(colorDepth) / 3.0).rounded(.down))
let colorMax = Int((1 << bits) - 1)
let redMax = colorMax
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.swift b/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.swift
index b0b68c65..0323e74f 100644
--- a/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.swift
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCFramebuffer.swift
@@ -1,6 +1,20 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
+
+#if canImport(CoreGraphics)
+import CoreGraphics
+#endif
+
+#if canImport(CoreImage)
import CoreImage
+#endif
+
+#if canImport(IOSurface)
import IOSurface
+#endif
#if os(macOS)
import AppKit
@@ -9,26 +23,37 @@ import AppKit
#if canImport(ObjectiveC)
@objc(VNCFramebuffer)
#endif
-public class VNCFramebuffer: NSObjectOrAnyObject {
+public final class VNCFramebuffer: NSObjectOrAnyObject {
// MARK: - Public Properties
public let size: VNCSize
+#if canImport(CoreGraphics)
#if canImport(ObjectiveC)
@objc(size)
#endif
public let cgSize: CGSize
+#endif
public let fullRegion: VNCRegion
-
+
+#if canImport(CoreGraphics)
#if canImport(ObjectiveC)
@objc(fullRegion)
#endif
public let cgFullRegion: CGRect
-
+#endif
+
+#if canImport(IOSurface)
#if canImport(ObjectiveC)
@objc
#endif
public let surface: IOSurface
+#else
+ public let buffer: UnsafeMutableRawPointer
+ private let bufferLock = Spinlock()
+#endif
+
+ public let surfaceByteCount: Int
#if canImport(ObjectiveC)
@objc
@@ -58,17 +83,23 @@ public class VNCFramebuffer: NSObjectOrAnyObject {
private(set) var colorMap: ColorMap?
+#if canImport(CoreGraphics)
// MARK: - Private Properties
private static let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
-
+#endif
+
+#if canImport(IOSurface)
private static let surfaceLockOptionsReadOnly: IOSurfaceLockOptions = [ .readOnly ]
private static let surfaceLockOptionsReadWrite: IOSurfaceLockOptions = [ ]
+#endif
private let width: Int
private let height: Int
-
+
+#if canImport(CoreImage)
private let ciContext: CIContext
private let ciImageOptions: [CIImageOption: Any]?
+#endif
private var framebufferHasBeenUpdatedAtLeastOnce = false
@@ -80,10 +111,16 @@ public class VNCFramebuffer: NSObjectOrAnyObject {
let height = Int(size.height)
self.size = size
+
+#if canImport(CoreGraphics)
self.cgSize = size.cgSize
+#endif
self.fullRegion = .init(location: .zero, size: size)
+
+#if canImport(CoreGraphics)
self.cgFullRegion = .init(origin: .zero, size: size.cgSize)
+#endif
self.width = width
self.height = height
@@ -106,6 +143,7 @@ public class VNCFramebuffer: NSObjectOrAnyObject {
self.needsColorConversion = sourceProperties.bytesPerPixel != destinationProperties.bytesPerPixel ||
sourceProperties.bitsPerPixel != destinationProperties.bitsPerPixel
+#if canImport(CoreImage)
self.ciContext = .init(options: [
.allowLowPower: true,
.outputColorSpace: Self.rgbColorSpace,
@@ -115,9 +153,13 @@ public class VNCFramebuffer: NSObjectOrAnyObject {
self.ciImageOptions = [
.colorSpace: Self.rgbColorSpace
]
+#endif
let bufferLength = width * height * destinationProperties.bytesPerPixel
+
+ self.surfaceByteCount = bufferLength
+#if canImport(IOSurface)
let cvPixelFormat = kCVPixelFormatType_32BGRA
guard let surface = IOSurface(properties: [
@@ -132,11 +174,28 @@ public class VNCFramebuffer: NSObjectOrAnyObject {
}
self.surface = surface
+#else
+ let buffer = UnsafeMutableRawPointer.allocate(byteCount: bufferLength,
+ alignment: MemoryLayout.alignment)
+
+ buffer.initializeMemory(as: UInt8.self,
+ repeating: 0,
+ count: bufferLength)
+
+ self.buffer = buffer
+#endif
+ }
+
+ deinit {
+#if !canImport(IOSurface)
+ self.buffer.deallocate()
+#endif
}
}
// MARK: - Public APIs
public extension VNCFramebuffer {
+#if canImport(CoreImage)
#if canImport(ObjectiveC)
@objc
#endif
@@ -153,7 +212,9 @@ public extension VNCFramebuffer {
return image
}
-
+#endif
+
+#if canImport(CoreImage)
#if canImport(ObjectiveC)
@objc
#endif
@@ -174,6 +235,7 @@ public extension VNCFramebuffer {
return finalImage
}
+#endif
#if os(macOS)
@objc
@@ -286,7 +348,7 @@ extension VNCFramebuffer {
let destinationPixel = destinationPixelWith(sourcePixelData: sourcePixelDataPtr,
sourcePixelDataOffset: sourceOffset)
- let maskIdx = row * Int(ceil(Double(cursorWidth) / 8.0)) + Int(floor(Double(column) / 8.0))
+ let maskIdx = row * Int((Double(cursorWidth) / 8.0).rounded(.up)) + Int((Double(column) / 8.0).rounded(.down))
let destinationAlpha: UInt8 = (mask[maskIdx] << (column % 8)) & 0x80 != 0
? destinationMaxAlpha
@@ -399,7 +461,7 @@ private extension VNCFramebuffer {
let sourceColumnLength = regionWidth * sourceBytesPerPixel
let destinationColumnLength = regionWidth * destinationBytesPerPixel
- let targetBase = surface.baseAddress
+ let targetBase = surfaceAddress
data.withUnsafeBytes { sourcePixelDataPtr in
for row in 0.. convert -size {width}x{height} -depth 8 BGRA:{filename} {output}.png
+ func writeSurface() throws {
+ lockSurfaceReadOnly()
+
+ let url = URL(filePath: "/tmp/framebuffer-\(width)x\(height)x\(destinationProperties.bytesPerPixel).\(Int(Date().timeIntervalSince1970)).raw")
+ let data = Data(bytes: buffer, count: width * height * destinationProperties.bytesPerPixel)
+ try data.write(to: url)
+
+ unlockSurfaceReadOnly()
+ }
+}
+*/
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCFramebufferDelegate.swift b/Sources/RoyalVNCKit/Framebuffer/VNCFramebufferDelegate.swift
index f7e2746f..e435f904 100644
--- a/Sources/RoyalVNCKit/Framebuffer/VNCFramebufferDelegate.swift
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCFramebufferDelegate.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
protocol VNCFramebufferDelegate: AnyObject {
func framebuffer(_ framebuffer: VNCFramebuffer,
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCPoint+CG.swift b/Sources/RoyalVNCKit/Framebuffer/VNCPoint+CG.swift
new file mode 100644
index 00000000..cef6a5a4
--- /dev/null
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCPoint+CG.swift
@@ -0,0 +1,22 @@
+#if canImport(CoreGraphics)
+import Foundation
+import CoreGraphics
+
+public extension VNCPoint {
+ init(cgPoint: CGPoint) {
+ self.x = .init(cgPoint.x)
+ self.y = .init(cgPoint.y)
+ }
+
+ var cgPoint: CGPoint {
+ .init(x: CGFloat(x),
+ y: CGFloat(y))
+ }
+}
+
+public extension CGPoint {
+ var vncPoint: VNCPoint {
+ .init(cgPoint: self)
+ }
+}
+#endif
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCPoint.swift b/Sources/RoyalVNCKit/Framebuffer/VNCPoint.swift
index 9fedc51e..b1c96c54 100644
--- a/Sources/RoyalVNCKit/Framebuffer/VNCPoint.swift
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCPoint.swift
@@ -1,6 +1,8 @@
-// swiftlint:disable identifier_name
-
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public struct VNCPoint: Equatable {
public let x: UInt16
@@ -11,11 +13,6 @@ public struct VNCPoint: Equatable {
self.x = x
self.y = y
}
-
- public init(cgPoint: CGPoint) {
- self.x = .init(cgPoint.x)
- self.y = .init(cgPoint.y)
- }
}
extension VNCPoint: Hashable {
@@ -26,25 +23,12 @@ extension VNCPoint: Hashable {
}
public extension VNCPoint {
- var cgPoint: CGPoint {
- .init(x: CGFloat(x),
- y: CGFloat(y))
- }
-
static let zero: Self = .init(x: 0,
y: 0)
}
-public extension CGPoint {
- var vncPoint: VNCPoint {
- .init(cgPoint: self)
- }
-}
-
extension VNCPoint: CustomStringConvertible {
public var description: String {
"x: \(x), y: \(y)"
}
}
-
-// swiftlint:enable identifier_name
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCRegion+CG.swift b/Sources/RoyalVNCKit/Framebuffer/VNCRegion+CG.swift
new file mode 100644
index 00000000..3aeb84f7
--- /dev/null
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCRegion+CG.swift
@@ -0,0 +1,31 @@
+#if canImport(CoreGraphics)
+import Foundation
+import CoreGraphics
+
+public extension VNCRegion {
+ init(cgRect: CGRect) {
+ self.location = .init(cgPoint: cgRect.origin)
+ self.size = .init(cgSize: cgRect.size)
+ }
+
+ var cgRect: CGRect {
+ .init(origin: location.cgPoint,
+ size: size.cgSize)
+ }
+
+ func flipped(bounds: VNCRegion) -> Self {
+ let selfCG = self.cgRect
+
+ return .init(x: .init(selfCG.minX),
+ y: .init(bounds.cgRect.maxY - selfCG.maxY),
+ width: .init(selfCG.width),
+ height: .init(selfCG.height))
+ }
+}
+
+public extension CGRect {
+ var vncRegion: VNCRegion {
+ .init(cgRect: self)
+ }
+}
+#endif
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCRegion.swift b/Sources/RoyalVNCKit/Framebuffer/VNCRegion.swift
index d38aaa42..cd1ce245 100644
--- a/Sources/RoyalVNCKit/Framebuffer/VNCRegion.swift
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCRegion.swift
@@ -1,6 +1,8 @@
-// swiftlint:disable identifier_name
-
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public struct VNCRegion: Equatable {
public let location: VNCPoint
@@ -17,11 +19,6 @@ public struct VNCRegion: Equatable {
self.location = .init(x: x, y: y)
self.size = .init(width: width, height: height)
}
-
- public init(cgRect: CGRect) {
- self.location = .init(cgPoint: cgRect.origin)
- self.size = .init(cgSize: cgRect.size)
- }
}
extension VNCRegion: Hashable {
@@ -32,23 +29,9 @@ extension VNCRegion: Hashable {
}
public extension VNCRegion {
- var cgRect: CGRect {
- .init(origin: location.cgPoint,
- size: size.cgSize)
- }
-
static let zero: Self = .init(location: .zero,
size: .zero)
- func flipped(bounds: VNCRegion) -> Self {
- let selfCG = self.cgRect
-
- return .init(x: .init(selfCG.minX),
- y: .init(bounds.cgRect.maxY - selfCG.maxY),
- width: .init(selfCG.width),
- height: .init(selfCG.height))
- }
-
var x: UInt16 { location.x }
var y: UInt16 { location.y }
@@ -56,16 +39,8 @@ public extension VNCRegion {
var height: UInt16 { size.height }
}
-public extension CGRect {
- var vncRegion: VNCRegion {
- .init(cgRect: self)
- }
-}
-
extension VNCRegion: CustomStringConvertible {
public var description: String {
"\(location); \(size)"
}
}
-
-// swiftlint:enable identifier_name
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCSize+CG.swift b/Sources/RoyalVNCKit/Framebuffer/VNCSize+CG.swift
new file mode 100644
index 00000000..5034d4c3
--- /dev/null
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCSize+CG.swift
@@ -0,0 +1,22 @@
+#if canImport(CoreGraphics)
+import Foundation
+import CoreGraphics
+
+public extension VNCSize {
+ init(cgSize: CGSize) {
+ self.width = .init(cgSize.width)
+ self.height = .init(cgSize.height)
+ }
+
+ var cgSize: CGSize {
+ .init(width: CGFloat(width),
+ height: CGFloat(height))
+ }
+}
+
+public extension CGSize {
+ var vncSize: VNCSize {
+ .init(cgSize: self)
+ }
+}
+#endif
diff --git a/Sources/RoyalVNCKit/Framebuffer/VNCSize.swift b/Sources/RoyalVNCKit/Framebuffer/VNCSize.swift
index a6809889..2c92bbd4 100644
--- a/Sources/RoyalVNCKit/Framebuffer/VNCSize.swift
+++ b/Sources/RoyalVNCKit/Framebuffer/VNCSize.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public struct VNCSize: Equatable {
public let width: UInt16
@@ -9,11 +13,6 @@ public struct VNCSize: Equatable {
self.width = width
self.height = height
}
-
- public init(cgSize: CGSize) {
- self.width = .init(cgSize.width)
- self.height = .init(cgSize.height)
- }
}
extension VNCSize: Hashable {
@@ -24,21 +23,10 @@ extension VNCSize: Hashable {
}
public extension VNCSize {
- var cgSize: CGSize {
- .init(width: CGFloat(width),
- height: CGFloat(height))
- }
-
static let zero: Self = .init(width: 0,
height: 0)
}
-public extension CGSize {
- var vncSize: VNCSize {
- .init(cgSize: self)
- }
-}
-
extension VNCSize: CustomStringConvertible {
public var description: String {
"width: \(width), height: \(height)"
diff --git a/Sources/RoyalVNCKit/Input/MouseButton.swift b/Sources/RoyalVNCKit/Input/MouseButton.swift
deleted file mode 100644
index 6e35a978..00000000
--- a/Sources/RoyalVNCKit/Input/MouseButton.swift
+++ /dev/null
@@ -1,32 +0,0 @@
-import Foundation
-
-extension VNCProtocol {
- struct MouseButton: OptionSet {
- init(rawValue: UInt8) {
- self.rawValue = rawValue
- }
-
- let rawValue: UInt8
-
- /// Left
- static let button1 = MouseButton(rawValue: 1 << 0)
-
- /// Middle
- static let button2 = MouseButton(rawValue: 1 << 1)
-
- /// Right
- static let button3 = MouseButton(rawValue: 1 << 2)
-
- /// Wheel Up
- static let button4 = MouseButton(rawValue: 1 << 3)
-
- /// Wheel Down
- static let button5 = MouseButton(rawValue: 1 << 4)
-
- /// Wheel Left
- static let button6 = MouseButton(rawValue: 1 << 5)
-
- /// Wheel Right
- static let button7 = MouseButton(rawValue: 1 << 6)
- }
-}
diff --git a/Sources/RoyalVNCKit/Input/MousePointerButton.swift b/Sources/RoyalVNCKit/Input/MousePointerButton.swift
new file mode 100644
index 00000000..3bc714c3
--- /dev/null
+++ b/Sources/RoyalVNCKit/Input/MousePointerButton.swift
@@ -0,0 +1,43 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+extension VNCProtocol {
+ struct MousePointerButton: OptionSet {
+ init(rawValue: UInt8) {
+ self.rawValue = rawValue
+ }
+
+ let rawValue: UInt8
+
+ /// Left
+ static let button1 = MousePointerButton(rawValue: 1 << 0)
+ static let left = button1
+
+ /// Middle
+ static let button2 = MousePointerButton(rawValue: 1 << 1)
+ static let middle = button2
+
+ /// Right
+ static let button3 = MousePointerButton(rawValue: 1 << 2)
+ static let right = button3
+
+ /// Wheel Up
+ static let button4 = MousePointerButton(rawValue: 1 << 3)
+ static let wheelUp = button4
+
+ /// Wheel Down
+ static let button5 = MousePointerButton(rawValue: 1 << 4)
+ static let wheelDown = button5
+
+ /// Wheel Left
+ static let button6 = MousePointerButton(rawValue: 1 << 5)
+ static let wheelLeft = button6
+
+ /// Wheel Right
+ static let button7 = MousePointerButton(rawValue: 1 << 6)
+ static let wheelRight = button7
+ }
+}
diff --git a/Sources/RoyalVNCKit/Input/MousePosition.swift b/Sources/RoyalVNCKit/Input/MousePosition.swift
index 2f6d4f81..7d922a7a 100644
--- a/Sources/RoyalVNCKit/Input/MousePosition.swift
+++ b/Sources/RoyalVNCKit/Input/MousePosition.swift
@@ -1,6 +1,8 @@
-// swiftlint:disable identifier_name
-
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct MousePosition {
@@ -8,5 +10,3 @@ extension VNCProtocol {
let y: UInt16
}
}
-
-// swiftlint:enable identifier_name
diff --git a/Sources/RoyalVNCKit/Input/X11KeySymbols.swift b/Sources/RoyalVNCKit/Input/X11KeySymbols.swift
index b440474f..58c85696 100644
--- a/Sources/RoyalVNCKit/Input/X11KeySymbols.swift
+++ b/Sources/RoyalVNCKit/Input/X11KeySymbols.swift
@@ -1,6 +1,10 @@
// swiftlint:disable file_length type_body_length
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
struct X11KeySymbols {
static let XK_VoidSymbol = UInt32(0xffffff) /* Void symbol */
diff --git a/Sources/RoyalVNCKit/Keychain/CredentialsKeychain.swift b/Sources/RoyalVNCKit/Keychain/CredentialsKeychain.swift
index c4398a24..049d6e81 100644
--- a/Sources/RoyalVNCKit/Keychain/CredentialsKeychain.swift
+++ b/Sources/RoyalVNCKit/Keychain/CredentialsKeychain.swift
@@ -1,7 +1,13 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
struct CredentialsKeychain {
+#if canImport(Security)
private let keychain = Keychain()
+#endif
}
extension CredentialsKeychain {
@@ -30,6 +36,7 @@ extension CredentialsKeychain {
private extension CredentialsKeychain {
func string(forKey key: String) -> String {
+#if canImport(Security)
guard let data = keychain.get(key: key) else {
return ""
}
@@ -39,15 +46,22 @@ private extension CredentialsKeychain {
}
return string
+#else
+ fatalError("Not implemented")
+#endif
}
func setString(_ string: String,
forKey key: String) {
+#if canImport(Security)
guard let data = string.data(using: .utf8) else {
return
}
keychain.set(data, forKey: key)
+#else
+ fatalError("Not implemented")
+#endif
}
func usernameKey(forHostname hostname: String,
diff --git a/Sources/RoyalVNCKit/Keychain/Keychain.swift b/Sources/RoyalVNCKit/Keychain/Keychain.swift
index 6d99e53a..20a72a20 100644
--- a/Sources/RoyalVNCKit/Keychain/Keychain.swift
+++ b/Sources/RoyalVNCKit/Keychain/Keychain.swift
@@ -1,3 +1,4 @@
+#if canImport(Security)
import Foundation
import Security
@@ -89,3 +90,4 @@ private extension Keychain {
return success
}
}
+#endif
diff --git a/Sources/RoyalVNCKit/Locks/Spinlock.swift b/Sources/RoyalVNCKit/Locks/Spinlock.swift
new file mode 100644
index 00000000..ac23ec2e
--- /dev/null
+++ b/Sources/RoyalVNCKit/Locks/Spinlock.swift
@@ -0,0 +1,61 @@
+#if canImport(Glibc)
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+import Glibc
+
+final class Spinlock {
+ private var spinlock = pthread_spinlock_t()
+
+ init() {
+ pthread_spin_init(&spinlock, .init(PTHREAD_PROCESS_PRIVATE))
+ }
+
+ deinit {
+ pthread_spin_destroy(&spinlock)
+ }
+
+ func lock() {
+ pthread_spin_lock(&spinlock)
+ }
+
+ func unlock() {
+ pthread_spin_unlock(&spinlock)
+ }
+}
+#endif
+
+#if canImport(WinSDK)
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#endif
+
+import WinSDK
+
+final class Spinlock {
+ private var spinlock = CRITICAL_SECTION()
+
+ init() {
+ // ref. https://learn.microsoft.com/en-us/windows/win32/Sync/using-critical-section-objects
+ let spinCount: DWORD = 0x00000400
+ guard InitializeCriticalSectionAndSpinCount(&spinlock, spinCount) else {
+ fatalError("Could not initialize critical section (Spinlock)")
+ }
+ }
+
+ deinit {
+ DeleteCriticalSection(&spinlock)
+ }
+
+ func lock() {
+ EnterCriticalSection(&spinlock)
+ }
+
+ func unlock() {
+ LeaveCriticalSection(&spinlock)
+ }
+}
+#endif
diff --git a/Sources/RoyalVNCKit/Logging/NSLogLogger.swift b/Sources/RoyalVNCKit/Logging/NSLogLogger.swift
deleted file mode 100644
index 880d6902..00000000
--- a/Sources/RoyalVNCKit/Logging/NSLogLogger.swift
+++ /dev/null
@@ -1,29 +0,0 @@
-import Foundation
-
-class NSLogLogger: VNCLogger {
- var isDebugLoggingEnabled = false
-
- func logDebug(_ message: String) {
- guard isDebugLoggingEnabled else { return }
-
- log(debugMessage(message))
- }
-
- func logInfo(_ message: String) {
- log(infoMessage(message))
- }
-
- func logWarning(_ message: String) {
- log(warningMessage(message))
- }
-
- func logError(_ message: String) {
- log(errorMessage(message))
- }
-}
-
-private extension NSLogLogger {
- func log(_ message: String) {
- NSLog(message)
- }
-}
diff --git a/Sources/RoyalVNCKit/Logging/PrintLogger.swift b/Sources/RoyalVNCKit/Logging/PrintLogger.swift
deleted file mode 100644
index 60d731bf..00000000
--- a/Sources/RoyalVNCKit/Logging/PrintLogger.swift
+++ /dev/null
@@ -1,29 +0,0 @@
-import Foundation
-
-class PrintLogger: VNCLogger {
- var isDebugLoggingEnabled = false
-
- func logDebug(_ message: String) {
- guard isDebugLoggingEnabled else { return }
-
- log(debugMessage(message))
- }
-
- func logInfo(_ message: String) {
- log(infoMessage(message))
- }
-
- func logWarning(_ message: String) {
- log(warningMessage(message))
- }
-
- func logError(_ message: String) {
- log(errorMessage(message))
- }
-}
-
-private extension PrintLogger {
- func log(_ message: String) {
- print(message)
- }
-}
diff --git a/Sources/RoyalVNCKit/Logging/VNCCustomLogger.swift b/Sources/RoyalVNCKit/Logging/VNCCustomLogger.swift
new file mode 100644
index 00000000..32384ca8
--- /dev/null
+++ b/Sources/RoyalVNCKit/Logging/VNCCustomLogger.swift
@@ -0,0 +1,44 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public final class VNCCustomLogger: VNCLogger {
+ public typealias LogHandler = (_ message: String) -> Void
+
+ public let logDebugHandler: LogHandler
+ public let logInfoHandler: LogHandler
+ public let logWarningHandler: LogHandler
+ public let logErrorHandler: LogHandler
+
+ public var isDebugLoggingEnabled = false
+
+ public init(logDebugHandler: @escaping LogHandler,
+ logInfoHandler: @escaping LogHandler,
+ logWarningHandler: @escaping LogHandler,
+ logErrorHandler: @escaping LogHandler) {
+ self.logDebugHandler = logDebugHandler
+ self.logInfoHandler = logInfoHandler
+ self.logWarningHandler = logWarningHandler
+ self.logErrorHandler = logErrorHandler
+ }
+
+ public func logDebug(_ message: String) {
+ guard isDebugLoggingEnabled else { return }
+
+ logDebugHandler(message)
+ }
+
+ public func logInfo(_ message: String) {
+ logInfoHandler(message)
+ }
+
+ public func logWarning(_ message: String) {
+ logWarningHandler(message)
+ }
+
+ public func logError(_ message: String) {
+ logErrorHandler(message)
+ }
+}
diff --git a/Sources/RoyalVNCKit/Logging/VNCNSLogLogger.swift b/Sources/RoyalVNCKit/Logging/VNCNSLogLogger.swift
new file mode 100644
index 00000000..20f5b4bd
--- /dev/null
+++ b/Sources/RoyalVNCKit/Logging/VNCNSLogLogger.swift
@@ -0,0 +1,33 @@
+#if !canImport(FoundationEssentials)
+import Foundation
+
+public final class VNCNSLogLogger: VNCLogger {
+ public var isDebugLoggingEnabled = false
+
+ public init() { }
+
+ public func logDebug(_ message: String) {
+ guard isDebugLoggingEnabled else { return }
+
+ log(debugMessage(message))
+ }
+
+ public func logInfo(_ message: String) {
+ log(infoMessage(message))
+ }
+
+ public func logWarning(_ message: String) {
+ log(warningMessage(message))
+ }
+
+ public func logError(_ message: String) {
+ log(errorMessage(message))
+ }
+}
+
+private extension VNCNSLogLogger {
+ func log(_ message: String) {
+ NSLog(message)
+ }
+}
+#endif
diff --git a/Sources/RoyalVNCKit/Logging/OSLogLogger.swift b/Sources/RoyalVNCKit/Logging/VNCOSLogLogger.swift
similarity index 65%
rename from Sources/RoyalVNCKit/Logging/OSLogLogger.swift
rename to Sources/RoyalVNCKit/Logging/VNCOSLogLogger.swift
index d34d6533..d0541cdd 100644
--- a/Sources/RoyalVNCKit/Logging/OSLogLogger.swift
+++ b/Sources/RoyalVNCKit/Logging/VNCOSLogLogger.swift
@@ -1,26 +1,29 @@
+#if canImport(OSLog)
import Foundation
import OSLog
-class OSLogLogger: VNCLogger {
- var isDebugLoggingEnabled = false
+public final class VNCOSLogLogger: VNCLogger {
+ public var isDebugLoggingEnabled = false
private let logger = Logger.main
+
+ public init() { }
- func logDebug(_ message: String) {
+ public func logDebug(_ message: String) {
guard isDebugLoggingEnabled else { return }
logger.info("\(message)")
}
- func logInfo(_ message: String) {
+ public func logInfo(_ message: String) {
logger.notice("\(message)")
}
- func logWarning(_ message: String) {
+ public func logWarning(_ message: String) {
logger.warning("\(message)")
}
- func logError(_ message: String) {
+ public func logError(_ message: String) {
logger.error("\(message)")
}
}
@@ -35,3 +38,4 @@ fileprivate extension Logger {
static let main = Logger(subsystem: subsystem, category: category)
}
+#endif
diff --git a/Sources/RoyalVNCKit/Logging/VNCPrintLogger.swift b/Sources/RoyalVNCKit/Logging/VNCPrintLogger.swift
new file mode 100644
index 00000000..329f5089
--- /dev/null
+++ b/Sources/RoyalVNCKit/Logging/VNCPrintLogger.swift
@@ -0,0 +1,35 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public final class VNCPrintLogger: VNCLogger {
+ public var isDebugLoggingEnabled = false
+
+ public init() { }
+
+ public func logDebug(_ message: String) {
+ guard isDebugLoggingEnabled else { return }
+
+ log(debugMessage(message))
+ }
+
+ public func logInfo(_ message: String) {
+ log(infoMessage(message))
+ }
+
+ public func logWarning(_ message: String) {
+ log(warningMessage(message))
+ }
+
+ public func logError(_ message: String) {
+ log(errorMessage(message))
+ }
+}
+
+private extension VNCPrintLogger {
+ func log(_ message: String) {
+ print(message)
+ }
+}
diff --git a/Sources/RoyalVNCKit/Network/AddressInfo.swift b/Sources/RoyalVNCKit/Network/AddressInfo.swift
new file mode 100644
index 00000000..a9987e6a
--- /dev/null
+++ b/Sources/RoyalVNCKit/Network/AddressInfo.swift
@@ -0,0 +1,94 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+#if canImport(Glibc)
+import Glibc
+#elseif canImport(WinSDK)
+import WinSDK
+#elseif canImport(Darwin)
+import Darwin
+#endif
+
+final class AddressInfo {
+ private let addrInfo: UnsafeMutablePointer
+
+ init(host: String,
+ port: UInt16) throws(Errors) {
+ let sockstream = SOCK_STREAM
+
+#if canImport(Glibc)
+ let socktype = Int32(sockstream.rawValue)
+#elseif canImport(WinSDK)
+ let socktype = sockstream
+#elseif canImport(Darwin)
+ let socktype = sockstream
+#endif
+
+ var hints = addrinfo()
+ hints.ai_flags = AI_PASSIVE
+ hints.ai_family = AF_INET
+ hints.ai_socktype = socktype
+
+ var addrInfo: UnsafeMutablePointer?
+
+ // Resolve the address
+ let getaddrinfoStatus = getaddrinfo(
+ host,
+ "\(port)",
+ &hints,
+ &addrInfo
+ )
+
+ guard getaddrinfoStatus == 0 else {
+ throw .dnsResolutionFailed
+ }
+
+ guard let addrInfo else {
+ throw .addressInfoEmpty
+ }
+
+ self.addrInfo = addrInfo
+ }
+
+ deinit {
+ freeaddrinfo(addrInfo)
+ }
+}
+
+// MARK: - Property Accessors
+extension AddressInfo {
+#if canImport(Glibc) || canImport(Darwin)
+ typealias Socklen = socklen_t
+#elseif canImport(WinSDK)
+ typealias Socklen = Int
+#endif
+
+ var flags: Int32 { addrInfo.pointee.ai_flags }
+ var family: Int32 { addrInfo.pointee.ai_family }
+ var socktype: Int32 { addrInfo.pointee.ai_socktype }
+ var `protocol`: Int32 { addrInfo.pointee.ai_protocol }
+ var addrlen: Socklen { addrInfo.pointee.ai_addrlen }
+ var canonname: UnsafeMutablePointer? { addrInfo.pointee.ai_canonname }
+ var addr: UnsafeMutablePointer? { addrInfo.pointee.ai_addr }
+ var next: UnsafeMutablePointer? { addrInfo.pointee.ai_next }
+}
+
+// MARK: - Errors
+extension AddressInfo {
+ enum Errors: LocalizedError {
+ case dnsResolutionFailed
+ case addressInfoEmpty
+
+ var errorDescription: String? {
+ switch self {
+ case .dnsResolutionFailed:
+ "DNS resolution failed"
+ case .addressInfoEmpty:
+ "Address info is empty"
+ }
+ }
+ }
+}
diff --git a/Sources/RoyalVNCKit/Network/NetworkConnection.swift b/Sources/RoyalVNCKit/Network/NetworkConnection.swift
index af7aa1be..8f8a14b4 100644
--- a/Sources/RoyalVNCKit/Network/NetworkConnection.swift
+++ b/Sources/RoyalVNCKit/Network/NetworkConnection.swift
@@ -1,4 +1,9 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
+
import Dispatch
enum NetworkConnectionStatus {
@@ -113,10 +118,10 @@ extension NetworkConnectionReading {
}
let bigEndianValue = data.withUnsafeBytes {
- $0.load(as: UInt16.self)
+ $0.loadUnaligned(as: UInt16.self)
}
- let value = CFByteOrderGetCurrent() == .init(CFByteOrderLittleEndian.rawValue)
+ let value = Endianness.current == .little
? UInt16(bigEndian: bigEndianValue)
: bigEndianValue
@@ -132,10 +137,10 @@ extension NetworkConnectionReading {
}
let bigEndianValue = data.withUnsafeBytes {
- $0.load(as: Int16.self)
+ $0.loadUnaligned(as: Int16.self)
}
- let value = CFByteOrderGetCurrent() == .init(CFByteOrderLittleEndian.rawValue)
+ let value = Endianness.current == .little
? Int16(bigEndian: bigEndianValue)
: bigEndianValue
@@ -151,10 +156,10 @@ extension NetworkConnectionReading {
}
let bigEndianValue = data.withUnsafeBytes {
- $0.load(as: UInt32.self)
+ $0.loadUnaligned(as: UInt32.self)
}
- let value = CFByteOrderGetCurrent() == .init(CFByteOrderLittleEndian.rawValue)
+ let value = Endianness.current == .little
? UInt32(bigEndian: bigEndianValue)
: bigEndianValue
@@ -170,10 +175,10 @@ extension NetworkConnectionReading {
}
let bigEndianValue = data.withUnsafeBytes {
- $0.load(as: Int32.self)
+ $0.loadUnaligned(as: Int32.self)
}
- let value = CFByteOrderGetCurrent() == .init(CFByteOrderLittleEndian.rawValue)
+ let value = Endianness.current == .little
? Int32(bigEndian: bigEndianValue)
: bigEndianValue
diff --git a/Sources/RoyalVNCKit/Network/Socket.swift b/Sources/RoyalVNCKit/Network/Socket.swift
new file mode 100644
index 00000000..bb59dfc1
--- /dev/null
+++ b/Sources/RoyalVNCKit/Network/Socket.swift
@@ -0,0 +1,167 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+#if canImport(Glibc)
+import Glibc
+#elseif canImport(WinSDK)
+import WinSDK
+#elseif canImport(Darwin)
+import Darwin
+#endif
+
+final class Socket {
+ let addressInfo: AddressInfo
+
+#if canImport(Glibc) || canImport(Darwin)
+ private typealias NativeSocket = Int32
+#elseif canImport(WinSDK)
+ private typealias NativeSocket = SOCKET
+#endif
+
+ private let nativeSocket: NativeSocket
+
+ init(addressInfo: AddressInfo) throws(Errors) {
+ let nativeSocket = socket(
+ addressInfo.family,
+ addressInfo.socktype,
+ addressInfo.protocol
+ )
+
+#if canImport(Glibc) || canImport(Darwin)
+ guard nativeSocket >= 0 else {
+ throw .socketCreationFailed(underlyingErrorCode: nil)
+ }
+#elseif canImport(WinSDK)
+ guard nativeSocket != INVALID_SOCKET else {
+ let lastError = WSAGetLastError()
+
+ throw .socketCreationFailed(underlyingErrorCode: lastError)
+ }
+#endif
+
+ self.addressInfo = addressInfo
+ self.nativeSocket = nativeSocket
+ }
+
+ func connect() throws(Errors) {
+ let connectResult: Int32
+
+#if canImport(Glibc)
+ connectResult = Glibc.connect(
+ nativeSocket,
+ addressInfo.addr,
+ addressInfo.addrlen
+ )
+#elseif canImport(Darwin)
+ connectResult = Darwin.connect(
+ nativeSocket,
+ addressInfo.addr,
+ addressInfo.addrlen
+ )
+#elseif canImport(WinSDK)
+ connectResult = WinSDK.connect(
+ nativeSocket,
+ addressInfo.addr,
+ .init(addressInfo.addrlen)
+ )
+#endif
+
+ guard connectResult >= 0 else {
+ throw .connectFailed(underlyingErrorCode: connectResult)
+ }
+ }
+
+ func receive(buffer: inout [UInt8]) -> Int {
+ let bufferSize = buffer.count
+
+ let bytesRead: Int = buffer.withUnsafeMutableBytes { bufferPtr in
+ guard let bufferPtrAddr = bufferPtr.baseAddress else {
+ return 0
+ }
+
+ let ret = recv(
+ nativeSocket,
+ bufferPtrAddr,
+ .init(bufferSize),
+ 0
+ )
+
+ return .init(ret)
+ }
+
+ return bytesRead
+ }
+
+ func send(buffer: [UInt8]) -> Int {
+ let bufferCount = buffer.count
+
+ let bytesSent: Int = buffer.withUnsafeBytes { bufferPtr in
+ guard let bufferPtrAddr = bufferPtr.baseAddress else {
+ return -1
+ }
+
+#if canImport(Glibc)
+ let ret = Glibc.send(
+ nativeSocket,
+ bufferPtrAddr,
+ .init(bufferCount),
+ 0
+ )
+#elseif canImport(Darwin)
+ let ret = Darwin.send(
+ nativeSocket,
+ bufferPtrAddr,
+ .init(bufferCount),
+ 0
+ )
+#elseif canImport(WinSDK)
+ let ret = WinSDK.send(
+ nativeSocket,
+ bufferPtrAddr,
+ .init(bufferCount),
+ 0
+ )
+#endif
+
+ return .init(ret)
+ }
+
+ return bytesSent
+ }
+
+ deinit {
+#if canImport(Glibc) || canImport(Darwin)
+ close(nativeSocket)
+#elseif canImport(WinSDK)
+ closesocket(nativeSocket)
+#endif
+ }
+}
+
+// MARK: - Errors
+extension Socket {
+ enum Errors: LocalizedError {
+ case socketCreationFailed(underlyingErrorCode: Int32?)
+ case connectFailed(underlyingErrorCode: Int32)
+
+ var errorDescription: String? {
+ switch self {
+ case .socketCreationFailed(let underlyingErrorCode):
+ let underlyingErrorCodeStr: String
+
+ if let underlyingErrorCode {
+ underlyingErrorCodeStr = "\(underlyingErrorCode)"
+ } else {
+ underlyingErrorCodeStr = "N/A"
+ }
+
+ return "Socket creation failed (\(underlyingErrorCodeStr))"
+ case .connectFailed(let underlyingErrorCode):
+ return "Connect failed (\(underlyingErrorCode))"
+ }
+ }
+ }
+}
diff --git a/Sources/RoyalVNCKit/Network/SocketNetworkConnection.swift b/Sources/RoyalVNCKit/Network/SocketNetworkConnection.swift
new file mode 100644
index 00000000..66497ac0
--- /dev/null
+++ b/Sources/RoyalVNCKit/Network/SocketNetworkConnection.swift
@@ -0,0 +1,173 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+import Dispatch
+
+// TODO: All of this is very hacky and NOT fully fleshed out!
+final class SocketNetworkConnection: NetworkConnection {
+ let settings: NetworkConnectionSettings
+
+ private var socket: Socket?
+
+ // This will be replaced when calling start. Calling any other method before start (which would use this placeholder queue) is a programmer error.
+ private var queue = DispatchQueue(label: "PLACEHOLDER")
+
+ private(set) var statusUpdateHandler: NetworkConnectionStatusUpdateHandler?
+
+ private(set) var status: NetworkConnectionStatus = .unknown("None") {
+ didSet {
+ statusUpdateHandler?(status)
+ }
+ }
+
+ init(settings: NetworkConnectionSettings) {
+#if os(Windows)
+ do {
+ try Winsock.intializeWinsock()
+ } catch {
+ fatalError("Initializing Winsock failed: \(error.humanReadableDescription)")
+ }
+#endif
+
+ self.settings = settings
+ }
+
+ func setStatusUpdateHandler(_ statusUpdateHandler: NetworkConnectionStatusUpdateHandler?) {
+ self.statusUpdateHandler = statusUpdateHandler
+ }
+
+ var isReady: Bool {
+ switch status {
+ case .ready:
+ true
+ default:
+ false
+ }
+ }
+
+ func cancel() {
+ // TODO
+ // fatalError("Not implemented")
+ }
+
+ func start(queue: DispatchQueue) {
+ self.status = .preparing
+ self.queue = queue
+
+ queue.async { [weak self] in
+ guard let self else { return }
+
+ do {
+ let addressInfo = try AddressInfo(host: settings.host,
+ port: settings.port)
+
+ let socket = try Socket(addressInfo: addressInfo)
+
+ try socket.connect()
+
+ self.socket = socket
+ self.status = .ready
+ } catch {
+ self.status = .failed(error)
+ }
+ }
+ }
+}
+
+// MARK: - Reading
+extension SocketNetworkConnection: NetworkConnectionReading {
+ func read(minimumLength: Int,
+ maximumLength: Int) async throws -> Data {
+ let queue = self.queue
+
+ guard let socket else {
+ throw Socket.Errors.socketCreationFailed(underlyingErrorCode: nil)
+ }
+
+ let bufferSize = maximumLength
+
+ return try await withCheckedThrowingContinuation { continuation in
+ queue.async {
+ var buffer = [UInt8](repeating: 0, count: bufferSize)
+ let bytesRead = socket.receive(buffer: &buffer)
+
+ // Handle connection closure
+ if bytesRead == 0 {
+ // TODO
+ continuation.resume(throwing: Errors.connectionClosed)
+
+ return
+ }
+
+ // Handle errors during receiving
+ if bytesRead < 0 {
+ // let errorNumber = errno
+ // print("Error: \(errorNumber.hexString())")
+
+ continuation.resume(throwing: VNCError.protocol(.noData))
+
+ return
+ }
+
+ // Slice the buffer to get only the received data
+ let receivedData = Array(buffer.prefix(.init(bytesRead)))
+ let receivedLength = receivedData.count
+
+ // Validate received data length
+ guard receivedLength >= minimumLength,
+ receivedLength <= maximumLength else {
+ continuation.resume(throwing: VNCError.protocol(.invalidData))
+
+ return
+ }
+
+ continuation.resume(returning: Data(receivedData))
+ }
+ }
+ }
+}
+
+// MARK: - Writing
+extension SocketNetworkConnection: NetworkConnectionWriting {
+ func write(data: Data) async throws {
+ let queue = self.queue
+
+ guard let socket else {
+ throw Socket.Errors.socketCreationFailed(underlyingErrorCode: nil)
+ }
+
+ return try await withCheckedThrowingContinuation { continuation in
+ queue.async {
+ let bytesToSend = [UInt8](data)
+ let bytesSent = socket.send(buffer: bytesToSend)
+
+ if bytesSent < 0 {
+ continuation.resume(throwing: Errors.sendFailed)
+ } else {
+ continuation.resume()
+ }
+ }
+ }
+ }
+}
+
+// MARK: - Errors
+private extension SocketNetworkConnection {
+ // MARK: - Enum for Socket Errors
+ enum Errors: LocalizedError {
+ case sendFailed
+ case connectionClosed
+
+ var errorDescription: String? {
+ switch self {
+ case .sendFailed:
+ "Send failed"
+ case .connectionClosed:
+ "Connection closed"
+ }
+ }
+ }
+}
diff --git a/Sources/RoyalVNCKit/Network/Winsock.swift b/Sources/RoyalVNCKit/Network/Winsock.swift
new file mode 100644
index 00000000..06fa9b49
--- /dev/null
+++ b/Sources/RoyalVNCKit/Network/Winsock.swift
@@ -0,0 +1,44 @@
+#if os(Windows)
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+import WinSDK
+
+struct Winsock {
+ static func intializeWinsock() throws {
+ try intializeWinsock(2, 2)
+ }
+
+ static func intializeWinsock(_ versionA: UInt8, _ versionB: UInt8) throws(Errors) {
+ func makeWord(_ a: UInt8, _ b: UInt8) -> UInt16 {
+ return UInt16(a) | (UInt16(b) << 8)
+ }
+
+ let wVersionRequested = makeWord(versionA, versionB)
+
+ var lpWSAData = WSADATA()
+ let status = WSAStartup(wVersionRequested, &lpWSAData)
+
+ guard status == 0 else {
+ throw Errors.winsockInitError(underlyingErrorCode: status)
+ }
+ }
+}
+
+// MARK: - Errors
+extension Winsock {
+ enum Errors: LocalizedError {
+ case winsockInitError(underlyingErrorCode: Int32)
+
+ var errorDescription: String? {
+ switch self {
+ case .winsockInitError(let underlyingErrorCode):
+ "WSAStartup failed (\(underlyingErrorCode))"
+ }
+ }
+ }
+}
+#endif
diff --git a/Sources/RoyalVNCKit/ObjC/NSObjectOrAnyObject.swift b/Sources/RoyalVNCKit/ObjC/NSObjectOrAnyObject.swift
index 422f4bac..03a7d31f 100644
--- a/Sources/RoyalVNCKit/ObjC/NSObjectOrAnyObject.swift
+++ b/Sources/RoyalVNCKit/ObjC/NSObjectOrAnyObject.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
#if canImport(ObjectiveC)
import ObjectiveC
@@ -7,5 +11,11 @@ import ObjectiveC
#if canImport(ObjectiveC)
public typealias NSObjectOrAnyObject = NSObject
#else
-public typealias NSObjectOrAnyObject = AnyObject
+public typealias NSObjectOrAnyObject = BaseType
+
+public class BaseType {
+ init() {
+
+ }
+}
#endif
diff --git a/Sources/RoyalVNCKit/Protocol/ClientInit.swift b/Sources/RoyalVNCKit/Protocol/ClientInit.swift
index e02ace21..cc733e2f 100644
--- a/Sources/RoyalVNCKit/Protocol/ClientInit.swift
+++ b/Sources/RoyalVNCKit/Protocol/ClientInit.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct ClientInit { }
diff --git a/Sources/RoyalVNCKit/Protocol/EncodingTypes.swift b/Sources/RoyalVNCKit/Protocol/EncodingTypes.swift
index 07a79402..bca9aebd 100644
--- a/Sources/RoyalVNCKit/Protocol/EncodingTypes.swift
+++ b/Sources/RoyalVNCKit/Protocol/EncodingTypes.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
enum EncodingType: Int32 {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Encoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Encoding.swift
index 2575fe16..735762d9 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Encoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Encoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
protocol VNCEncoding {
var encodingType: VNCEncodingType { get }
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Encodings.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Encodings.swift
index 0eb59349..85b330b7 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Encodings.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Encodings.swift
@@ -1,3 +1,7 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
typealias Encodings = [VNCEncodingType: VNCEncoding]
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/CoRREEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/CoRREEncoding.swift
index 2c27f056..ddc2cae4 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/CoRREEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/CoRREEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct CoRREEncoding: VNCFrameEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/CopyRectEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/CopyRectEncoding.swift
index e3e6d456..02ca55fe 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/CopyRectEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/CopyRectEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct CopyRectEncoding: VNCFrameEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/HextileEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/HextileEncoding.swift
index 4552a752..8bf2066c 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/HextileEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/HextileEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct HextileEncoding: VNCFrameEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/RREEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/RREEncoding.swift
index dc7d8e9d..bc8e6368 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/RREEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/RREEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct RREEncoding: VNCFrameEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/RawEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/RawEncoding.swift
index eb3f607b..b12f0c7e 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/RawEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/RawEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct RawEncoding: VNCFrameEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZRLEEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZRLEEncoding.swift
index 9a9bdce2..e9715aa4 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZRLEEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZRLEEncoding.swift
@@ -1,7 +1,11 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
- class ZRLEEncoding: VNCFrameEncoding {
+ final class ZRLEEncoding: VNCFrameEncoding {
let encodingType = VNCFrameEncodingType.zrle.rawValue
static let tileSize: UInt16 = 64
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZRLEEncodingWIP.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZRLEEncodingWIP.swift
index 77abe6c0..4f1ae8db 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZRLEEncodingWIP.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZRLEEncodingWIP.swift
@@ -3,7 +3,7 @@
/* import Foundation
extension VNCProtocol {
- class ZRLEEncoding: VNCFrameEncoding {
+ final class ZRLEEncoding: VNCFrameEncoding {
let encodingType = VNCFrameEncodingType.zrle.rawValue
static let tileSize: UInt16 = 64
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZlibEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZlibEncoding.swift
index 7a30e778..6ce23ae8 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZlibEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Frame/ZlibEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct ZlibEncoding: VNCFrameEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/FrameEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/FrameEncoding.swift
index dd6aea6e..6b475d21 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/FrameEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/FrameEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
protocol VNCFrameEncoding: VNCEncoding {
func decodeRectangle(_ rectangle: VNCProtocol.Rectangle,
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/CompressionLevelEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/CompressionLevelEncoding.swift
index e3a89296..9925fc53 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/CompressionLevelEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/CompressionLevelEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
// TODO: Untested
extension VNCProtocol {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/ContinuousUpdatesEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/ContinuousUpdatesEncoding.swift
index a36d0507..abe0a7ee 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/ContinuousUpdatesEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/ContinuousUpdatesEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct ContinuousUpdatesEncoding: VNCPseudoEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/CursorEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/CursorEncoding.swift
index c84eebfb..05a423ce 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/CursorEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/CursorEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct CursorEncoding: VNCReceivablePseudoEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/DesktopNameEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/DesktopNameEncoding.swift
index ab2e8bbf..0ae1fc1c 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/DesktopNameEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/DesktopNameEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
// TODO: Untested - not sure how?
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/DesktopSizeEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/DesktopSizeEncoding.swift
index 9d607c46..0faea687 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/DesktopSizeEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/DesktopSizeEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct DesktopSizeEncoding: VNCReceivablePseudoEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/ExtendedDesktopSizeEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/ExtendedDesktopSizeEncoding.swift
index ca90b5b5..ff7c5481 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/ExtendedDesktopSizeEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/ExtendedDesktopSizeEncoding.swift
@@ -1,6 +1,10 @@
// swiftlint:disable line_length
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct ExtendedDesktopSizeEncoding: VNCReceivablePseudoEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/LastRectEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/LastRectEncoding.swift
index 3037f52d..c15a5576 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/LastRectEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/Pseudo/LastRectEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct LastRectEncoding: VNCPseudoEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/PseudoEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/PseudoEncoding.swift
index 25f7989b..4bad4412 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/PseudoEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/PseudoEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
protocol VNCPseudoEncoding: VNCEncoding {
diff --git a/Sources/RoyalVNCKit/Protocol/Encodings/ReceivablePseudoEncoding.swift b/Sources/RoyalVNCKit/Protocol/Encodings/ReceivablePseudoEncoding.swift
index 2653dbf6..4be46ddc 100644
--- a/Sources/RoyalVNCKit/Protocol/Encodings/ReceivablePseudoEncoding.swift
+++ b/Sources/RoyalVNCKit/Protocol/Encodings/ReceivablePseudoEncoding.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
protocol VNCReceivablePseudoEncoding: VNCPseudoEncoding {
func receive(_ rectangle: VNCProtocol.Rectangle,
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/ClientCutText.swift b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/ClientCutText.swift
index 3d4d1a4a..1e0b5c9d 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/ClientCutText.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/ClientCutText.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct ClientCutText: VNCSendableMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/EnableContinuousUpdates.swift b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/EnableContinuousUpdates.swift
index 84eaa803..3c6ac70e 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/EnableContinuousUpdates.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/EnableContinuousUpdates.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct EnableContinuousUpdates: VNCSendableMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/FramebufferUpdateRequest.swift b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/FramebufferUpdateRequest.swift
index cefe9d07..8e1dadf0 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/FramebufferUpdateRequest.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/FramebufferUpdateRequest.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct FramebufferUpdateRequest: VNCSendableMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/KeyEvent.swift b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/KeyEvent.swift
index 18070514..3de0055a 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/KeyEvent.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/KeyEvent.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct KeyEvent: VNCSendableMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/PointerEvent.swift b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/PointerEvent.swift
index f6cabc77..cb5952b1 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/PointerEvent.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/PointerEvent.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct PointerEvent: VNCSendableMessage {
@@ -29,7 +33,7 @@ extension VNCProtocol.PointerEvent {
return data
}
- init(buttons: VNCProtocol.MouseButton,
+ init(buttons: VNCProtocol.MousePointerButton,
position: VNCProtocol.MousePosition) {
self.buttonMask = buttons.rawValue
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/SetEncodings.swift b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/SetEncodings.swift
index eb027051..ce2155be 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/SetEncodings.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/SetEncodings.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct SetEncodings: VNCSendableMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/SetPixelFormat.swift b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/SetPixelFormat.swift
index c875891e..d42e2df1 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/SetPixelFormat.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ClientToServer/SetPixelFormat.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct SetPixelFormat: VNCSendableMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/Message.swift b/Sources/RoyalVNCKit/Protocol/Messages/Message.swift
index bab49f62..d7119f96 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/Message.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/Message.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
protocol VNCMessage {
var messageType: UInt8 { get }
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/Bell.swift b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/Bell.swift
index 046c2655..cb03d393 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/Bell.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/Bell.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct Bell: VNCReceivableMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/EndOfContinuousUpdates.swift b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/EndOfContinuousUpdates.swift
index 88fba72a..1c04387d 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/EndOfContinuousUpdates.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/EndOfContinuousUpdates.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct EndOfContinuousUpdates: VNCMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/FramebufferUpdate.swift b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/FramebufferUpdate.swift
index 04a67b9a..27e4d907 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/FramebufferUpdate.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/FramebufferUpdate.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct FramebufferUpdate: VNCReceivableMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/ServerCutText.swift b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/ServerCutText.swift
index 1e2141c8..4c016401 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/ServerCutText.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/ServerCutText.swift
@@ -1,6 +1,10 @@
// swiftlint:disable nesting
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct ServerCutText: VNCReceivableMessage {
@@ -57,8 +61,10 @@ private extension VNCProtocol.ServerCutText {
let bigEndianUnsignedLength = lengthData.withUnsafeBytes {
$0.load(as: UInt32.self)
}
+
+ let endianess = Endianness.current
- var length = CFByteOrderGetCurrent() == .init(CFByteOrderLittleEndian.rawValue)
+ var length = endianess == .little
? Int(UInt32(bigEndian: bigEndianUnsignedLength))
: Int(bigEndianUnsignedLength)
@@ -68,7 +74,7 @@ private extension VNCProtocol.ServerCutText {
$0.load(as: Int32.self)
}
- length = CFByteOrderGetCurrent() == .init(CFByteOrderLittleEndian.rawValue)
+ length = endianess == .little
? Int(Int32(bigEndian: bigEndianSignedLength))
: Int(bigEndianSignedLength)
}
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/ServerToClientMessage.swift b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/ServerToClientMessage.swift
index 275af193..ba52c1e8 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/ServerToClientMessage.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/ServerToClientMessage.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct ServerToClientMessage: VNCMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/SetColourMapEntries.swift b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/SetColourMapEntries.swift
index 3a9fb6a1..e2980579 100644
--- a/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/SetColourMapEntries.swift
+++ b/Sources/RoyalVNCKit/Protocol/Messages/ServerToClient/SetColourMapEntries.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct SetColourMapEntries: VNCReceivableMessage {
diff --git a/Sources/RoyalVNCKit/Protocol/NumberOfSecurityTypes.swift b/Sources/RoyalVNCKit/Protocol/NumberOfSecurityTypes.swift
index ece0a135..8e5bcf18 100644
--- a/Sources/RoyalVNCKit/Protocol/NumberOfSecurityTypes.swift
+++ b/Sources/RoyalVNCKit/Protocol/NumberOfSecurityTypes.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct NumberOfSecurityTypes {
diff --git a/Sources/RoyalVNCKit/Protocol/PixelFormat.swift b/Sources/RoyalVNCKit/Protocol/PixelFormat.swift
index 8447ab7d..41ccba98 100644
--- a/Sources/RoyalVNCKit/Protocol/PixelFormat.swift
+++ b/Sources/RoyalVNCKit/Protocol/PixelFormat.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct PixelFormat {
@@ -56,7 +60,7 @@ extension VNCProtocol {
bpp = 8
}
- let bits = UInt8(floor(Double(depth) / 3.0))
+ let bits = UInt8((Double(depth) / 3.0).rounded(.down))
let colorMax = UInt16((1 << bits) - 1)
self.init(bitsPerPixel: bpp,
diff --git a/Sources/RoyalVNCKit/Protocol/ProtocolVersion.swift b/Sources/RoyalVNCKit/Protocol/ProtocolVersion.swift
index 5546f39e..bd84db54 100644
--- a/Sources/RoyalVNCKit/Protocol/ProtocolVersion.swift
+++ b/Sources/RoyalVNCKit/Protocol/ProtocolVersion.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct ProtocolVersion {
@@ -13,8 +17,15 @@ extension VNCProtocol {
return nil
}
+#if canImport(FoundationEssentials)
+ // TODO: This is not equivalent to the non-FoundationEssentials version as it removes newlines even from within the string, not just the prefix/suffix
+ let trimmedProtocolVersion = protocolVersion
+ .replacing("\r", with: "")
+ .replacing("\n", with: "")
+#else
let trimmedProtocolVersion = protocolVersion
.trimmingCharacters(in: .newlines)
+#endif
guard let parsedProtocolVersion = Self.parseProtocolVersion(trimmedProtocolVersion) else {
return nil
@@ -32,8 +43,33 @@ extension VNCProtocol {
init(majorVersion: UInt32,
minorVersion: UInt32) {
- let protocolVersion = String(format: "RFB %03d.%03d", majorVersion, minorVersion)
-
+ func paddedVersion(_ version: UInt32) -> String {
+ let requiredLength = 3
+ let versionString = String(version)
+
+ if versionString.count == requiredLength {
+ return versionString
+ }
+
+ let paddingCount = requiredLength - versionString.count
+
+ guard paddingCount > 0 else {
+ return versionString
+ }
+
+ let padding = String(repeating: "0",
+ count: requiredLength - versionString.count)
+
+ let padVersion = padding + versionString
+
+ return padVersion
+ }
+
+ let paddedMajorVersion = paddedVersion(majorVersion)
+ let paddedMinorVersion = paddedVersion(minorVersion)
+
+ let protocolVersion = "RFB \(paddedMajorVersion).\(paddedMinorVersion)"
+
self.data = Self.dataWith(protocolVersion: protocolVersion)
self.protocolVersion = protocolVersion
@@ -50,10 +86,29 @@ extension VNCProtocol.ProtocolVersion {
if !protocolVersion.hasSuffix("\n") {
fixedProtocolVersion = "\(protocolVersion)\n"
}
+
+ func paddedVersion(_ version: String) -> String {
+ let requiredLength = 12
+
+ if version.count == requiredLength {
+ return version
+ }
+
+ let paddingCount = requiredLength - version.count
+
+ guard paddingCount > 0 else {
+ return version
+ }
+
+ let padding = String(repeating: "\0",
+ count: requiredLength - version.count)
+
+ let padVersion = version + padding
+
+ return padVersion
+ }
- let paddedProtocolVersion = fixedProtocolVersion.padding(toLength: 12,
- withPad: "\0",
- startingAt: protocolVersion.count)
+ let paddedProtocolVersion = paddedVersion(fixedProtocolVersion)
let data = paddedProtocolVersion.data(using: .utf8)!
@@ -92,9 +147,17 @@ extension VNCProtocol.ProtocolVersion {
private extension VNCProtocol.ProtocolVersion {
static func parseProtocolVersion(_ protocolVersion: String) -> (UInt32, UInt32)? {
+#if canImport(FoundationEssentials)
+ // TODO: This is not equivalent to the non-FoundationEssentials version as it removes newlines even from within the string, not just the prefix/suffix
+ let trimmed = protocolVersion
+ .replacing("\r", with: "")
+ .replacing("\n", with: "")
+ .replacing("RFB ", with: "")
+#else
let trimmed = protocolVersion
.trimmingCharacters(in: .newlines)
.replacingOccurrences(of: "RFB ", with: "")
+#endif
let split = trimmed.split(separator: ".")
diff --git a/Sources/RoyalVNCKit/Protocol/Rectangle.swift b/Sources/RoyalVNCKit/Protocol/Rectangle.swift
index b73e6e43..81222340 100644
--- a/Sources/RoyalVNCKit/Protocol/Rectangle.swift
+++ b/Sources/RoyalVNCKit/Protocol/Rectangle.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct Rectangle {
diff --git a/Sources/RoyalVNCKit/Protocol/Screen.swift b/Sources/RoyalVNCKit/Protocol/Screen.swift
index 69f67c33..9126f00c 100644
--- a/Sources/RoyalVNCKit/Protocol/Screen.swift
+++ b/Sources/RoyalVNCKit/Protocol/Screen.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct Screen {
diff --git a/Sources/RoyalVNCKit/Protocol/SecurityResult.swift b/Sources/RoyalVNCKit/Protocol/SecurityResult.swift
index b2d9ae5c..84e56799 100644
--- a/Sources/RoyalVNCKit/Protocol/SecurityResult.swift
+++ b/Sources/RoyalVNCKit/Protocol/SecurityResult.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct SecurityResult {
diff --git a/Sources/RoyalVNCKit/Protocol/SecurityTypes.swift b/Sources/RoyalVNCKit/Protocol/SecurityTypes.swift
index b8602825..0c686fad 100644
--- a/Sources/RoyalVNCKit/Protocol/SecurityTypes.swift
+++ b/Sources/RoyalVNCKit/Protocol/SecurityTypes.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
enum SecurityType: UInt8 {
diff --git a/Sources/RoyalVNCKit/Protocol/SecurityTypes/AppleRemoteDesktop/ARDAuthentication.swift b/Sources/RoyalVNCKit/Protocol/SecurityTypes/AppleRemoteDesktop/ARDAuthentication.swift
index b529e0a7..692a9ff7 100644
--- a/Sources/RoyalVNCKit/Protocol/SecurityTypes/AppleRemoteDesktop/ARDAuthentication.swift
+++ b/Sources/RoyalVNCKit/Protocol/SecurityTypes/AppleRemoteDesktop/ARDAuthentication.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCProtocol {
struct ARDAuthentication: VNCSecurityType {
diff --git a/Sources/RoyalVNCKit/Protocol/SecurityTypes/AppleRemoteDesktop/ARDAuthenticationImpl.swift b/Sources/RoyalVNCKit/Protocol/SecurityTypes/AppleRemoteDesktop/ARDAuthenticationImpl.swift
index 8c1b5db2..fbc37f59 100644
--- a/Sources/RoyalVNCKit/Protocol/SecurityTypes/AppleRemoteDesktop/ARDAuthenticationImpl.swift
+++ b/Sources/RoyalVNCKit/Protocol/SecurityTypes/AppleRemoteDesktop/ARDAuthenticationImpl.swift
@@ -1,4 +1,12 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
+
+#if canImport(Security)
+import Security
+#endif
extension VNCProtocol.ARDAuthentication {
struct Authentication {
@@ -24,19 +32,24 @@ extension VNCProtocol.ARDAuthentication {
let randomCredsDataSuccess = creds.withUnsafeMutableBytes {
guard let credsBytes = $0.baseAddress else { return false }
- let randomStatus = SecRandomCopyBytes(kSecRandomDefault, credArraySize, credsBytes)
+#if canImport(Security)
+ let randomStatus = SecRandomCopyBytes(kSecRandomDefault, credArraySize, credsBytes)
guard randomStatus == errSecSuccess else { return false }
+#else
+ // TODO: Probably not secure
+ for i in 0.. maxLength
? String(password[password.startIndex.. UnsafeMutablePointer? {
+#if canImport(WinSDK)
+ // avoid: warning: 'strdup' is deprecated: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _strdup
+ return _strdup(self)
+#else
+ return strdup(self)
+#endif
+ }
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_AuthenticationRequest.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_AuthenticationRequest.swift
new file mode 100644
index 00000000..b54d9810
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_AuthenticationRequest.swift
@@ -0,0 +1,112 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+final class VNCAuthenticationRequest_C {
+ typealias CompletionHandler = ((any VNCCredential)?) -> Void
+
+ let authenticationType: VNCAuthenticationType
+ let completionHandler: CompletionHandler
+
+ init(authenticationType: VNCAuthenticationType,
+ completionHandler: @escaping CompletionHandler) {
+ self.authenticationType = authenticationType
+ self.completionHandler = completionHandler
+ }
+
+ func cancel() {
+ completionHandler(nil)
+ }
+
+ func completeWith(credential: any VNCCredential) {
+ completionHandler(credential)
+ }
+
+ func completeWith(username: String,
+ password: String) {
+ let credential = VNCUsernamePasswordCredential(username: username,
+ password: password)
+
+ completeWith(credential: credential)
+ }
+
+ func completeWith(password: String) {
+ let credential = VNCPasswordCredential(password: password)
+
+ completeWith(credential: credential)
+ }
+}
+
+extension VNCAuthenticationRequest_C {
+ func retainedPointer() -> rvnc_authentication_request_t {
+ .retainedPointerFrom(self)
+ }
+
+ func unretainedPointer() -> rvnc_authentication_request_t {
+ .unretainedPointerFrom(self)
+ }
+
+ static func autoreleasePointer(_ pointer: rvnc_authentication_request_t) {
+ pointer.autorelease(VNCFramebuffer.self)
+ }
+
+ static func fromPointer(_ pointer: rvnc_authentication_request_t) -> Self {
+ pointer.unretainedInstance()
+ }
+}
+
+@_cdecl("rvnc_authentication_request_authentication_type_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_authentication_request_authentication_type_get(_ authenticationRequest: rvnc_authentication_request_t) -> RVNC_AUTHENTICATIONTYPE {
+ VNCAuthenticationRequest_C.fromPointer(authenticationRequest)
+ .authenticationType
+ .cVNCAuthenticationType
+}
+
+@_cdecl("rvnc_authentication_request_cancel")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_authentication_request_cancel(_ authenticationRequest: rvnc_authentication_request_t) {
+ let authenticationRequestSwift = VNCAuthenticationRequest_C.fromPointer(authenticationRequest)
+
+ defer {
+ VNCAuthenticationRequest_C.autoreleasePointer(authenticationRequest)
+ }
+
+ authenticationRequestSwift.cancel()
+}
+
+@_cdecl("rvnc_authentication_request_complete_with_username_password")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_authentication_request_complete_with_username_password(_ authenticationRequest: rvnc_authentication_request_t,
+ _ username: UnsafePointer,
+ _ password: UnsafePointer) {
+ let authenticationRequestSwift = VNCAuthenticationRequest_C.fromPointer(authenticationRequest)
+
+ defer {
+ VNCAuthenticationRequest_C.autoreleasePointer(authenticationRequest)
+ }
+
+ authenticationRequestSwift.completeWith(username: .init(cString: username),
+ password: .init(cString: password))
+}
+
+@_cdecl("rvnc_authentication_request_complete_with_password")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_authentication_request_complete_with_password(_ authenticationRequest: rvnc_authentication_request_t,
+ _ password: UnsafePointer) {
+ let authenticationRequestSwift = VNCAuthenticationRequest_C.fromPointer(authenticationRequest)
+
+ defer {
+ VNCAuthenticationRequest_C.autoreleasePointer(authenticationRequest)
+ }
+
+ authenticationRequestSwift.completeWith(password: .init(cString: password))
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_AuthenticationType.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_AuthenticationType.swift
new file mode 100644
index 00000000..37985c33
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_AuthenticationType.swift
@@ -0,0 +1,53 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+extension RVNC_AUTHENTICATIONTYPE {
+ var swiftVNCAuthenticationType: VNCAuthenticationType {
+ switch self {
+ case RVNC_AUTHENTICATIONTYPE_VNC:
+ .vnc
+ case RVNC_AUTHENTICATIONTYPE_APPLEREMOTEDESKTOP:
+ .appleRemoteDesktop
+ case RVNC_AUTHENTICATIONTYPE_ULTRAVNCMSLOGONII:
+ .ultraVNCMSLogonII
+ default:
+ fatalError("Unknown authentication type: \(self)")
+ }
+ }
+}
+
+extension VNCAuthenticationType {
+ var cVNCAuthenticationType: RVNC_AUTHENTICATIONTYPE {
+ switch self {
+ case .vnc:
+ RVNC_AUTHENTICATIONTYPE_VNC
+ case .appleRemoteDesktop:
+ RVNC_AUTHENTICATIONTYPE_APPLEREMOTEDESKTOP
+ case .ultraVNCMSLogonII:
+ RVNC_AUTHENTICATIONTYPE_ULTRAVNCMSLOGONII
+ }
+ }
+}
+
+@_cdecl("rvnc_authentication_type_requires_username")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_authentication_type_requires_username(_ authenticationType: RVNC_AUTHENTICATIONTYPE) -> Bool {
+ let authenticationTypeSwift = authenticationType.swiftVNCAuthenticationType
+
+ return authenticationTypeSwift.requiresUsername
+}
+
+@_cdecl("rvnc_authentication_type_requires_password")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_authentication_type_requires_password(_ authenticationType: RVNC_AUTHENTICATIONTYPE) -> Bool {
+ let authenticationTypeSwift = authenticationType.swiftVNCAuthenticationType
+
+ return authenticationTypeSwift.requiresPassword
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Connection.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Connection.swift
new file mode 100644
index 00000000..8a12354a
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Connection.swift
@@ -0,0 +1,188 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+extension VNCConnection {
+ func retainedPointer() -> rvnc_connection_t {
+ .retainedPointerFrom(self)
+ }
+
+ func unretainedPointer() -> rvnc_connection_t {
+ .unretainedPointerFrom(self)
+ }
+
+ static func autoreleasePointer(_ pointer: rvnc_connection_t) {
+ pointer.autorelease(VNCConnection.self)
+ }
+
+ static func fromPointer(_ pointer: rvnc_connection_t) -> Self {
+ pointer.unretainedInstance()
+ }
+}
+
+@_cdecl("rvnc_connection_create")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_create(_ settings: rvnc_settings_t,
+ _ logger: rvnc_logger_t?,
+ _ context: rvnc_context_t?) -> rvnc_connection_t {
+ let loggerSwift: VNCLogger_C?
+
+ if let logger {
+ loggerSwift = VNCLogger_C.fromPointer(logger)
+ } else {
+ loggerSwift = nil
+ }
+
+ let settingsSwift = VNCConnection.Settings.fromPointer(settings)
+
+ let connection: VNCConnection
+
+ if let loggerSwift {
+ connection = VNCConnection(settings: settingsSwift,
+ logger: loggerSwift,
+ context: context)
+ } else {
+ connection = VNCConnection(settings: settingsSwift,
+ context: context)
+ }
+
+ return connection.retainedPointer()
+}
+
+@_cdecl("rvnc_connection_destroy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_destroy(_ connection: rvnc_connection_t) {
+ VNCConnection.autoreleasePointer(connection)
+}
+
+@_cdecl("rvnc_connection_connect")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_connect(_ connection: rvnc_connection_t) {
+ VNCConnection.fromPointer(connection)
+ .connect()
+}
+
+@_cdecl("rvnc_connection_disconnect")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_disconnect(_ connection: rvnc_connection_t) {
+ VNCConnection.fromPointer(connection)
+ .disconnect()
+}
+
+@_cdecl("rvnc_connection_update_color_depth")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_update_color_depth(_ connection: rvnc_connection_t,
+ _ colorDepth: RVNC_COLORDEPTH) {
+ let colorDepthSwift = colorDepth.swiftColorDepth
+
+ VNCConnection.fromPointer(connection)
+ .updateColorDepth(colorDepthSwift)
+}
+
+@_cdecl("rvnc_connection_delegate_set")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_delegate_set(_ connection: rvnc_connection_t,
+ _ connectionDelegate: rvnc_connection_delegate_t?) {
+ let connectionSwift = VNCConnection.fromPointer(connection)
+ let connectionDelegateSwift: VNCConnectionDelegate?
+
+ if let connectionDelegate {
+ connectionDelegateSwift = VNCConnectionDelegate_C.fromPointer(connectionDelegate)
+ } else {
+ connectionDelegateSwift = nil
+ }
+
+ connectionSwift.delegate = connectionDelegateSwift
+}
+
+@_cdecl("rvnc_connection_context_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_context_get(_ connection: rvnc_connection_t) -> rvnc_context_t? {
+ let connectionSwift = VNCConnection.fromPointer(connection)
+ let context = connectionSwift.context
+
+ return context
+}
+
+@_cdecl("rvnc_connection_state_get_copy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_state_get_copy(_ connection: rvnc_connection_t) -> rvnc_connection_state_t {
+ let connectionSwift = VNCConnection.fromPointer(connection)
+ let connectionState = connectionSwift.connectionState
+ let connectionStateC = connectionState.retainedPointer()
+
+ return connectionStateC
+}
+
+@_cdecl("rvnc_connection_settings_get_copy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_settings_get_copy(_ connection: rvnc_connection_t) -> rvnc_settings_t {
+ let connectionSwift = VNCConnection.fromPointer(connection)
+ let connectionSettings = connectionSwift.settings
+ let connectionSettingsC = connectionSettings.retainedPointer()
+
+ return connectionSettingsC
+}
+
+// MARK: - Mouse Input
+@_cdecl("rvnc_connection_mouse_move")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_mouse_move(_ connection: rvnc_connection_t, _ x: UInt16, _ y: UInt16) {
+ VNCConnection.fromPointer(connection)
+ .mouseMove(x: x, y: y)
+}
+
+@_cdecl("rvnc_connection_mouse_down")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_mouse_down(_ connection: rvnc_connection_t, _ button: RVNC_MOUSEBUTTON, _ x: UInt16, _ y: UInt16) {
+ VNCConnection.fromPointer(connection)
+ .mouseButtonDown(button.swiftVNCMouseButton, x: x, y: y)
+}
+
+@_cdecl("rvnc_connection_mouse_up")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_mouse_up(_ connection: rvnc_connection_t, _ button: RVNC_MOUSEBUTTON, _ x: UInt16, _ y: UInt16) {
+ VNCConnection.fromPointer(connection)
+ .mouseButtonUp(button.swiftVNCMouseButton, x: x, y: y)
+}
+
+@_cdecl("rvnc_connection_mouse_wheel")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_mouse_wheel(_ connection: rvnc_connection_t, _ wheel: RVNC_MOUSEWHEEL, _ x: UInt16, _ y: UInt16, _ steps: UInt32) {
+ VNCConnection.fromPointer(connection)
+ .mouseWheel(wheel.swiftVNCMouseWheel, x: x, y: y, steps: steps)
+}
+
+// MARK: - Keyboard Input
+@_cdecl("rvnc_connection_key_down")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_key_down(_ connection: rvnc_connection_t, _ key: UInt32) {
+ VNCConnection.fromPointer(connection)
+ .keyDown(.init(key))
+}
+
+@_cdecl("rvnc_connection_key_up")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_key_up(_ connection: rvnc_connection_t, _ key: UInt32) {
+ VNCConnection.fromPointer(connection)
+ .keyUp(.init(key))
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_ConnectionDelegate.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_ConnectionDelegate.swift
new file mode 100644
index 00000000..0bc54ca6
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_ConnectionDelegate.swift
@@ -0,0 +1,148 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+extension VNCConnectionDelegate_C {
+ func retainedPointer() -> rvnc_connection_delegate_t {
+ .retainedPointerFrom(self)
+ }
+
+ func unretainedPointer() -> rvnc_connection_delegate_t {
+ .unretainedPointerFrom(self)
+ }
+
+ static func fromPointer(_ pointer: rvnc_connection_delegate_t) -> Self {
+ pointer.unretainedInstance()
+ }
+
+ static func autoreleasePointer(_ pointer: rvnc_connection_delegate_t) {
+ pointer.autorelease(VNCConnectionDelegate_C.self)
+ }
+}
+
+@_cdecl("rvnc_connection_delegate_create")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_delegate_create(
+ _ connectionStateDidChange: rvnc_connection_delegate_connection_state_did_change,
+ _ authenticate: rvnc_connection_delegate_authenticate,
+ _ didCreateFramebuffer: rvnc_connection_delegate_did_create_framebuffer,
+ _ didResizeFramebuffer: rvnc_connection_delegate_did_resize_framebuffer,
+ _ didUpdateFramebuffer: rvnc_connection_delegate_did_update_framebuffer,
+ _ didUpdateCursor: rvnc_connection_delegate_did_update_cursor
+) -> rvnc_connection_delegate_t {
+ let delegate = VNCConnectionDelegate_C(
+ connectionStateDidChange: connectionStateDidChange,
+ authenticate: authenticate,
+ didCreateFramebuffer: didCreateFramebuffer,
+ didResizeFramebuffer: didResizeFramebuffer,
+ didUpdateFramebuffer: didUpdateFramebuffer,
+ didUpdateCursor: didUpdateCursor
+ )
+
+ return delegate.retainedPointer()
+}
+
+@_cdecl("rvnc_connection_delegate_destroy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_delegate_destroy(_ connectionDelegate: rvnc_connection_delegate_t) {
+ VNCConnectionDelegate_C.autoreleasePointer(connectionDelegate)
+}
+
+final class VNCConnectionDelegate_C {
+ let connectionStateDidChange: rvnc_connection_delegate_connection_state_did_change
+ let authenticate: rvnc_connection_delegate_authenticate
+ let didCreateFramebuffer: rvnc_connection_delegate_did_create_framebuffer
+ let didResizeFramebuffer: rvnc_connection_delegate_did_resize_framebuffer
+ let didUpdateFramebuffer: rvnc_connection_delegate_did_update_framebuffer
+ let didUpdateCursor: rvnc_connection_delegate_did_update_cursor
+
+ init(
+ connectionStateDidChange: rvnc_connection_delegate_connection_state_did_change,
+ authenticate: rvnc_connection_delegate_authenticate,
+ didCreateFramebuffer: rvnc_connection_delegate_did_create_framebuffer,
+ didResizeFramebuffer: rvnc_connection_delegate_did_resize_framebuffer,
+ didUpdateFramebuffer: rvnc_connection_delegate_did_update_framebuffer,
+ didUpdateCursor: rvnc_connection_delegate_did_update_cursor
+ ) {
+ self.connectionStateDidChange = connectionStateDidChange
+ self.authenticate = authenticate
+ self.didCreateFramebuffer = didCreateFramebuffer
+ self.didResizeFramebuffer = didResizeFramebuffer
+ self.didUpdateFramebuffer = didUpdateFramebuffer
+ self.didUpdateCursor = didUpdateCursor
+ }
+}
+
+extension VNCConnectionDelegate_C: VNCConnectionDelegate {
+ func connection(_ connection: VNCConnection,
+ stateDidChange connectionState: VNCConnection.ConnectionState) {
+ self.connectionStateDidChange(
+ connection.unretainedPointer(),
+ .init(OpaquePointer(connection.context)),
+ connectionState.unretainedPointer()
+ )
+ }
+
+ func connection(_ connection: VNCConnection,
+ credentialFor authenticationType: VNCAuthenticationType,
+ completion: @escaping ((any VNCCredential)?) -> Void) {
+ let authRequest = VNCAuthenticationRequest_C(authenticationType: authenticationType,
+ completionHandler: completion)
+
+ let authRequestC = authRequest.retainedPointer()
+
+ self.authenticate(
+ connection.unretainedPointer(),
+ .init(OpaquePointer(connection.context)),
+ authRequestC
+ )
+ }
+
+ func connection(_ connection: VNCConnection,
+ didCreateFramebuffer framebuffer: VNCFramebuffer) {
+ self.didCreateFramebuffer(
+ connection.unretainedPointer(),
+ .init(OpaquePointer(connection.context)),
+ framebuffer.unretainedPointer()
+ )
+ }
+
+ func connection(_ connection: VNCConnection,
+ didResizeFramebuffer framebuffer: VNCFramebuffer) {
+ self.didResizeFramebuffer(
+ connection.unretainedPointer(),
+ .init(OpaquePointer(connection.context)),
+ framebuffer.unretainedPointer()
+ )
+ }
+
+ func connection(_ connection: VNCConnection,
+ didUpdateFramebuffer framebuffer: VNCFramebuffer,
+ x: UInt16, y: UInt16,
+ width: UInt16, height: UInt16) {
+ self.didUpdateFramebuffer(
+ connection.unretainedPointer(),
+ .init(OpaquePointer(connection.context)),
+ framebuffer.unretainedPointer(),
+ x,
+ y,
+ width,
+ height
+ )
+ }
+
+ func connection(_ connection: VNCConnection,
+ didUpdateCursor cursor: VNCCursor) {
+ self.didUpdateCursor(
+ connection.unretainedPointer(),
+ .init(OpaquePointer(connection.context)),
+ cursor.unretainedPointer()
+ )
+ }
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_ConnectionState.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_ConnectionState.swift
new file mode 100644
index 00000000..f646f0d2
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_ConnectionState.swift
@@ -0,0 +1,103 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+extension VNCConnection.Status {
+ var cConnectionStatus: RVNC_CONNECTION_STATUS {
+ switch self {
+ case .disconnected:
+ RVNC_CONNECTION_STATUS_DISCONNECTED
+ case .connecting:
+ RVNC_CONNECTION_STATUS_CONNECTING
+ case .connected:
+ RVNC_CONNECTION_STATUS_CONNECTED
+ case .disconnecting:
+ RVNC_CONNECTION_STATUS_DISCONNECTING
+ }
+ }
+}
+
+extension VNCConnection.ConnectionState {
+ func retainedPointer() -> rvnc_connection_state_t {
+ .retainedPointerFrom(self)
+ }
+
+ func unretainedPointer() -> rvnc_connection_state_t {
+ .unretainedPointerFrom(self)
+ }
+
+ static func autoreleasePointer(_ pointer: rvnc_connection_state_t) {
+ pointer.autorelease(VNCConnection.ConnectionState.self)
+ }
+
+ static func fromPointer(_ pointer: rvnc_connection_state_t) -> Self {
+ pointer.unretainedInstance()
+ }
+}
+
+@_cdecl("rvnc_connection_state_destroy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_state_destroy(_ connectionState: rvnc_connection_state_t) {
+ VNCConnection.ConnectionState.autoreleasePointer(connectionState)
+}
+
+@_cdecl("rvnc_connection_state_status_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_state_status_get(_ connectionState: rvnc_connection_state_t) -> RVNC_CONNECTION_STATUS {
+ let connectionStateSwift = VNCConnection.ConnectionState.fromPointer(connectionState)
+ let status = connectionStateSwift.status
+ let cStatus = status.cConnectionStatus
+
+ return cStatus
+}
+
+@_cdecl("rvnc_connection_state_error_description_get_copy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_state_error_description_get_copy(_ connectionState: rvnc_connection_state_t) -> UnsafeMutablePointer? {
+ let connectionStateSwift = VNCConnection.ConnectionState.fromPointer(connectionState)
+ let error = connectionStateSwift.error
+
+ guard let error else {
+ return nil
+ }
+
+ let errorDescription = error.humanReadableDescription
+ let errorDescriptionC = errorDescription.duplicateCString()
+
+ return errorDescriptionC
+}
+
+@_cdecl("rvnc_connection_state_error_should_display_to_user_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_state_error_should_display_to_user_get(_ connectionState: rvnc_connection_state_t) -> Bool {
+ let connectionStateSwift = VNCConnection.ConnectionState.fromPointer(connectionState)
+ let error = connectionStateSwift.error
+
+ guard let vncError = error as? VNCError else {
+ return false
+ }
+
+ return vncError.shouldDisplayToUser
+}
+
+@_cdecl("rvnc_connection_state_error_is_authentication_error_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_connection_state_error_is_authentication_error_get(_ connectionState: rvnc_connection_state_t) -> Bool {
+ let connectionStateSwift = VNCConnection.ConnectionState.fromPointer(connectionState)
+ let error = connectionStateSwift.error
+
+ guard let vncError = error as? VNCError else {
+ return false
+ }
+
+ return vncError.isAuthenticationError
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Cursor.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Cursor.swift
new file mode 100644
index 00000000..5ca50c35
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Cursor.swift
@@ -0,0 +1,131 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+extension VNCCursor {
+ func retainedPointer() -> rvnc_cursor_t {
+ .retainedPointerFrom(self)
+ }
+
+ func unretainedPointer() -> rvnc_cursor_t {
+ .unretainedPointerFrom(self)
+ }
+
+ static func autoreleasePointer(_ pointer: rvnc_cursor_t) {
+ pointer.autorelease(VNCCursor.self)
+ }
+
+ static func fromPointer(_ pointer: rvnc_cursor_t) -> Self {
+ pointer.unretainedInstance()
+ }
+}
+
+@_cdecl("rvnc_cursor_is_empty_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_is_empty_get(_ cursor: rvnc_cursor_t) -> Bool {
+ VNCCursor.fromPointer(cursor)
+ .isEmpty
+}
+
+@_cdecl("rvnc_cursor_size_width_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_size_width_get(_ cursor: rvnc_cursor_t) -> UInt16 {
+ VNCCursor.fromPointer(cursor)
+ .size.width
+}
+
+@_cdecl("rvnc_cursor_size_height_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_size_height_get(_ cursor: rvnc_cursor_t) -> UInt16 {
+ VNCCursor.fromPointer(cursor)
+ .size.height
+}
+
+@_cdecl("rvnc_cursor_hotspot_x_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_hotspot_x_get(_ cursor: rvnc_cursor_t) -> UInt16 {
+ VNCCursor.fromPointer(cursor)
+ .hotspot.x
+}
+
+@_cdecl("rvnc_cursor_hotspot_y_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_hotspot_y_get(_ cursor: rvnc_cursor_t) -> UInt16 {
+ VNCCursor.fromPointer(cursor)
+ .hotspot.y
+}
+
+@_cdecl("rvnc_cursor_bits_per_component_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_bits_per_component_get(_ cursor: rvnc_cursor_t) -> Int64 {
+ .init(VNCCursor.fromPointer(cursor).bitsPerComponent)
+}
+
+@_cdecl("rvnc_cursor_bits_per_pixel_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_bits_per_pixel_get(_ cursor: rvnc_cursor_t) -> Int64 {
+ .init(VNCCursor.fromPointer(cursor).bitsPerPixel)
+}
+
+@_cdecl("rvnc_cursor_bytes_per_pixel_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_bytes_per_pixel_get(_ cursor: rvnc_cursor_t) -> Int64 {
+ .init(VNCCursor.fromPointer(cursor).bytesPerPixel)
+}
+
+@_cdecl("rvnc_cursor_bytes_per_row_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_bytes_per_row_get(_ cursor: rvnc_cursor_t) -> Int64 {
+ .init(VNCCursor.fromPointer(cursor).bytesPerRow)
+}
+
+@_cdecl("rvnc_cursor_pixel_data_get_copy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_pixel_data_get_copy(_ cursor: rvnc_cursor_t) -> UnsafeMutableRawPointer? {
+ let cursorSwift = VNCCursor.fromPointer(cursor)
+ let data = cursorSwift.imageData
+ let size = data.count
+
+ guard size > 0 else {
+ return nil
+ }
+
+ let dataC = UnsafeMutableRawBufferPointer.allocate(byteCount: size,
+ alignment: MemoryLayout.alignment)
+
+ data.copyBytes(to: dataC)
+
+ return dataC.baseAddress
+}
+
+@_cdecl("rvnc_cursor_pixel_data_destroy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_pixel_data_destroy(_ pixelData: UnsafeMutableRawPointer) {
+ pixelData.deallocate()
+}
+
+@_cdecl("rvnc_cursor_pixel_data_size_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_cursor_pixel_data_size_get(_ cursor: rvnc_cursor_t) -> UInt64 {
+ let cursorSwift = VNCCursor.fromPointer(cursor)
+ let data = cursorSwift.imageData
+ let size = data.count
+
+ return .init(size)
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Framebuffer.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Framebuffer.swift
new file mode 100644
index 00000000..9ab119bc
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Framebuffer.swift
@@ -0,0 +1,59 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+extension VNCFramebuffer {
+ func retainedPointer() -> rvnc_framebuffer_t {
+ .retainedPointerFrom(self)
+ }
+
+ func unretainedPointer() -> rvnc_framebuffer_t {
+ .unretainedPointerFrom(self)
+ }
+
+ static func autoreleasePointer(_ pointer: rvnc_framebuffer_t) {
+ pointer.autorelease(VNCFramebuffer.self)
+ }
+
+ static func fromPointer(_ pointer: rvnc_framebuffer_t) -> Self {
+ pointer.unretainedInstance()
+ }
+}
+
+@_cdecl("rvnc_framebuffer_size_width_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_framebuffer_size_width_get(_ framebuffer: rvnc_connection_state_t) -> UInt16 {
+ VNCFramebuffer.fromPointer(framebuffer)
+ .size.width
+}
+
+@_cdecl("rvnc_framebuffer_size_height_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_framebuffer_size_height_get(_ framebuffer: rvnc_connection_state_t) -> UInt16 {
+ VNCFramebuffer.fromPointer(framebuffer)
+ .size.height
+}
+
+@_cdecl("rvnc_framebuffer_pixel_data_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_framebuffer_pixel_data_get(_ framebuffer: rvnc_connection_state_t) -> UnsafeMutableRawPointer {
+ VNCFramebuffer.fromPointer(framebuffer)
+ .surfaceAddress
+}
+
+@_cdecl("rvnc_framebuffer_pixel_data_size_get")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_framebuffer_pixel_data_size_get(_ framebuffer: rvnc_connection_state_t) -> UInt64 {
+ let framebufferSwift = VNCFramebuffer.fromPointer(framebuffer)
+ let surfaceByteCount = framebufferSwift.surfaceByteCount
+
+ return .init(surfaceByteCount)
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Logger.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Logger.swift
new file mode 100644
index 00000000..cc942b56
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Logger.swift
@@ -0,0 +1,86 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+final class VNCLogger_C: VNCLogger {
+ fileprivate let context: rvnc_context_t?
+ fileprivate let logHandler: rvnc_logger_delegate_log
+
+ var isDebugLoggingEnabled: Bool = false
+
+ fileprivate init(context: rvnc_context_t?,
+ logHandler: rvnc_logger_delegate_log) {
+ self.context = context
+ self.logHandler = logHandler
+ }
+
+ func logDebug(_ message: String) {
+ log(message,
+ level: RVNC_LOG_LEVEL_DEBUG)
+ }
+
+ func logInfo(_ message: String) {
+ log(message,
+ level: RVNC_LOG_LEVEL_INFO)
+ }
+
+ func logWarning(_ message: String) {
+ log(message,
+ level: RVNC_LOG_LEVEL_WARNING)
+ }
+
+ func logError(_ message: String) {
+ log(message,
+ level: RVNC_LOG_LEVEL_ERROR)
+ }
+
+ private func log(_ message: String,
+ level: RVNC_LOG_LEVEL) {
+ message.withCString {
+ logHandler(self.unretainedPointer(),
+ self.context,
+ level,
+ $0)
+ }
+ }
+}
+
+extension VNCLogger_C {
+ func retainedPointer() -> rvnc_logger_t {
+ .retainedPointerFrom(self)
+ }
+
+ func unretainedPointer() -> rvnc_logger_t {
+ .unretainedPointerFrom(self)
+ }
+
+ static func autoreleasePointer(_ pointer: rvnc_logger_t) {
+ pointer.autorelease(VNCLogger_C.self)
+ }
+
+ static func fromPointer(_ pointer: rvnc_logger_t) -> Self {
+ pointer.unretainedInstance()
+ }
+}
+
+@_cdecl("rvnc_logger_create")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_logger_create(_ log: rvnc_logger_delegate_log,
+ _ context: rvnc_context_t?) -> rvnc_logger_t {
+ let logger = VNCLogger_C(context: context,
+ logHandler: log)
+
+ return logger.retainedPointer()
+}
+
+@_cdecl("rvnc_logger_destroy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_logger_destroy(_ logger: rvnc_logger_t) {
+ VNCLogger_C.autoreleasePointer(logger)
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_MouseButton.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_MouseButton.swift
new file mode 100644
index 00000000..09a8d6ea
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_MouseButton.swift
@@ -0,0 +1,22 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+extension RVNC_MOUSEBUTTON {
+ var swiftVNCMouseButton: VNCMouseButton {
+ switch self {
+ case RVNC_MOUSEBUTTON_LEFT:
+ .left
+ case RVNC_MOUSEBUTTON_MIDDLE:
+ .middle
+ case RVNC_MOUSEBUTTON_RIGHT:
+ .right
+ default:
+ fatalError("Unknown mouse button: \(self)")
+ }
+ }
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_MouseWheel.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_MouseWheel.swift
new file mode 100644
index 00000000..d0bae254
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_MouseWheel.swift
@@ -0,0 +1,24 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+extension RVNC_MOUSEWHEEL {
+ var swiftVNCMouseWheel: VNCMouseWheel {
+ switch self {
+ case RVNC_MOUSEWHEEL_LEFT:
+ .left
+ case RVNC_MOUSEWHEEL_RIGHT:
+ .right
+ case RVNC_MOUSEWHEEL_UP:
+ .up
+ case RVNC_MOUSEWHEEL_DOWN:
+ .down
+ default:
+ fatalError("Unknown mouse wheel: \(self)")
+ }
+ }
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Settings.swift b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Settings.swift
new file mode 100644
index 00000000..fe8a6900
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/RVNC_Settings.swift
@@ -0,0 +1,95 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@_implementationOnly import RoyalVNCKitC
+
+extension RVNC_INPUTMODE {
+ var swiftInputMode: VNCConnection.Settings.InputMode {
+ switch self {
+ case RVNC_INPUTMODE_NONE:
+ .none
+ case RVNC_INPUTMODE_FORWARDKEYBOARDSHORTCUTSIFNOTINUSELOCALLY:
+ .forwardKeyboardShortcutsIfNotInUseLocally
+ case RVNC_INPUTMODE_FORWARDKEYBOARDSHORTCUTSEVENIFINUSELOCALLY:
+ .forwardKeyboardShortcutsEvenIfInUseLocally
+ case RVNC_INPUTMODE_FORWARDALLKEYBOARDSHORTCUTSANDHOTKEYS:
+ .forwardAllKeyboardShortcutsAndHotKeys
+ default:
+ fatalError("Invalid input mode: \(self)")
+ }
+ }
+}
+
+extension RVNC_COLORDEPTH {
+ var swiftColorDepth: VNCConnection.Settings.ColorDepth {
+ switch self {
+ case RVNC_COLORDEPTH_8BIT:
+ .depth8Bit
+ case RVNC_COLORDEPTH_16BIT:
+ .depth16Bit
+ case RVNC_COLORDEPTH_24BIT:
+ .depth24Bit
+ default:
+ fatalError("Invalid color depth: \(self)")
+ }
+ }
+}
+
+extension VNCConnection.Settings {
+ func retainedPointer() -> rvnc_settings_t {
+ .retainedPointerFrom(self)
+ }
+
+ func unretainedPointer() -> rvnc_settings_t {
+ .unretainedPointerFrom(self)
+ }
+
+ static func autoreleasePointer(_ pointer: rvnc_settings_t) {
+ pointer.autorelease(VNCConnection.Settings.self)
+ }
+
+ static func fromPointer(_ pointer: rvnc_settings_t) -> Self {
+ pointer.unretainedInstance()
+ }
+}
+
+@_cdecl("rvnc_settings_create")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_settings_create(_ isDebugLoggingEnabled: Bool,
+ _ hostname: UnsafePointer,
+ _ port: UInt16,
+ _ isShared: Bool,
+ _ isScalingEnabled: Bool,
+ _ useDisplayLink: Bool,
+ _ inputMode: RVNC_INPUTMODE,
+ _ isClipboardRedirectionEnabled: Bool,
+ _ colorDepth: RVNC_COLORDEPTH) -> rvnc_settings_t {
+ let hostnameStr = String(cString: hostname)
+
+ let inputModeSwift = inputMode.swiftInputMode
+ let colorDepthSwift = colorDepth.swiftColorDepth
+
+ let settings = VNCConnection.Settings(isDebugLoggingEnabled: isDebugLoggingEnabled,
+ hostname: hostnameStr,
+ port: port,
+ isShared: isShared,
+ isScalingEnabled: isScalingEnabled,
+ useDisplayLink: useDisplayLink,
+ inputMode: inputModeSwift,
+ isClipboardRedirectionEnabled: isClipboardRedirectionEnabled,
+ colorDepth: colorDepthSwift,
+ frameEncodings: .default)
+
+ return settings.retainedPointer()
+}
+
+@_cdecl("rvnc_settings_destroy")
+@_spi(RoyalVNCKitC)
+@available(*, unavailable)
+public func rvnc_settings_destroy(_ settings: rvnc_settings_t) {
+ VNCConnection.Settings.autoreleasePointer(settings)
+}
diff --git a/Sources/RoyalVNCKit/SDK/CSDK/UnsafeMutableRawPointer+Extensions.swift b/Sources/RoyalVNCKit/SDK/CSDK/UnsafeMutableRawPointer+Extensions.swift
new file mode 100644
index 00000000..1861d1f8
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/CSDK/UnsafeMutableRawPointer+Extensions.swift
@@ -0,0 +1,60 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+extension UnsafeMutableRawPointer {
+ static func retainedPointerFrom(_ target: T) -> Self {
+ pointerFrom(target,
+ retain: true)
+ }
+
+ static func unretainedPointerFrom(_ target: T) -> Self {
+ pointerFrom(target,
+ retain: false)
+ }
+
+ func autorelease(_ targetType: T.Type) {
+ let _: T = retainedInstance()
+ }
+
+ func retainedInstance() -> T {
+ instance(retain: true)
+ }
+
+ func unretainedInstance() -> T {
+ instance(retain: false)
+ }
+}
+
+private extension UnsafeMutableRawPointer {
+ static func pointerFrom(_ target: T,
+ retain: Bool) -> Self {
+ let targetUnmanaged: Unmanaged
+
+ if retain {
+ targetUnmanaged = .passRetained(target)
+ } else {
+ targetUnmanaged = .passUnretained(target)
+ }
+
+ let targetOpaque = targetUnmanaged.toOpaque()
+
+ return targetOpaque
+ }
+
+ func instance(retain: Bool) -> T {
+ let unmanaged = Unmanaged.fromOpaque(self)
+
+ let inst: T
+
+ if retain {
+ inst = unmanaged.takeRetainedValue()
+ } else {
+ inst = unmanaged.takeUnretainedValue()
+ }
+
+ return inst
+ }
+}
diff --git a/Sources/RoyalVNCKit/SDK/Connection/ConnectionState.swift b/Sources/RoyalVNCKit/SDK/Connection/ConnectionState.swift
index 6296dff3..10ca7e6b 100644
--- a/Sources/RoyalVNCKit/SDK/Connection/ConnectionState.swift
+++ b/Sources/RoyalVNCKit/SDK/Connection/ConnectionState.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public extension VNCConnection {
#if canImport(ObjectiveC)
@@ -14,7 +18,7 @@ public extension VNCConnection {
#if canImport(ObjectiveC)
@objc(VNCConnectionState)
#endif
- class ConnectionState: NSObjectOrAnyObject {
+ final class ConnectionState: NSObjectOrAnyObject {
#if canImport(ObjectiveC)
@objc
#endif
diff --git a/Sources/RoyalVNCKit/SDK/Connection/Settings+UserDefaults.swift b/Sources/RoyalVNCKit/SDK/Connection/Settings+UserDefaults.swift
index 4ea5a447..2de13f99 100644
--- a/Sources/RoyalVNCKit/SDK/Connection/Settings+UserDefaults.swift
+++ b/Sources/RoyalVNCKit/SDK/Connection/Settings+UserDefaults.swift
@@ -1,3 +1,4 @@
+#if !os(Linux) && !os(Windows)
import Foundation
public extension VNCConnection.Settings {
@@ -50,7 +51,7 @@ private extension VNCConnection.Settings {
static var standardUserDefaultsStorage = UserDefaultsStorage(defaults: .standard)
static var credentialsKeychain = CredentialsKeychain()
- class UserDefaultsStorage {
+ final class UserDefaultsStorage {
let defaults: UserDefaults
private let isDebugLoggingEnabledKey = "isDebugLoggingEnabled"
@@ -174,3 +175,4 @@ private extension VNCConnection.Settings {
}
}
}
+#endif
diff --git a/Sources/RoyalVNCKit/SDK/Connection/Settings.swift b/Sources/RoyalVNCKit/SDK/Connection/Settings.swift
index a4c56b80..f8637a1f 100644
--- a/Sources/RoyalVNCKit/SDK/Connection/Settings.swift
+++ b/Sources/RoyalVNCKit/SDK/Connection/Settings.swift
@@ -1,10 +1,14 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public extension VNCConnection {
#if canImport(ObjectiveC)
@objc(VNCConnectionSettings)
#endif
- class Settings: NSObjectOrAnyObject {
+ final class Settings: NSObjectOrAnyObject {
#if canImport(ObjectiveC)
@objc
#endif
@@ -153,7 +157,7 @@ public extension VNCConnection.Settings.InputMode {
@objc(VNCInputModeUtils)
#endif
// swiftlint:disable:next type_name
-public class _ObjC_VNCInputModeUtils: NSObject {
+public final class _ObjC_VNCInputModeUtils: NSObject {
#if canImport(ObjectiveC)
@objc
#endif
diff --git a/Sources/RoyalVNCKit/SDK/Connection/State.swift b/Sources/RoyalVNCKit/SDK/Connection/State.swift
index bbec4cb7..c28dc126 100644
--- a/Sources/RoyalVNCKit/SDK/Connection/State.swift
+++ b/Sources/RoyalVNCKit/SDK/Connection/State.swift
@@ -1,7 +1,11 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
extension VNCConnection {
- class State {
+ final class State {
var disconnectRequested = false
var serverProtocolVersion: VNCProtocol.ProtocolVersion?
diff --git a/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+API.swift b/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+API.swift
index e27cdd4b..ff8c44b4 100644
--- a/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+API.swift
+++ b/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+API.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
// MARK: - Connect/Disconnect
public extension VNCConnection {
@@ -43,74 +47,75 @@ public extension VNCConnection {
#if canImport(ObjectiveC)
@objc
#endif
- func mouseMove(_ mousePosition: CGPoint) {
- enqueueMouseEvent(buttons: [ ],
- nonNormalizedPosition: mousePosition)
- }
-
-#if canImport(ObjectiveC)
- @objc
-#endif
- func mouseDown(_ mousePosition: CGPoint) {
- enqueueMouseEvent(buttons: [ .button1 ],
- nonNormalizedPosition: mousePosition)
- }
-
-#if canImport(ObjectiveC)
- @objc
-#endif
- func rightMouseDown(_ mousePosition: CGPoint) {
- enqueueMouseEvent(buttons: [ .button3 ],
- nonNormalizedPosition: mousePosition)
- }
-
-#if canImport(ObjectiveC)
- @objc
-#endif
- func middleMouseDown(_ mousePosition: CGPoint) {
- enqueueMouseEvent(buttons: [ .button2 ],
- nonNormalizedPosition: mousePosition)
- }
-
-#if canImport(ObjectiveC)
- @objc
-#endif
- func mouseUp(_ mousePosition: CGPoint) {
- enqueueMouseEvent(buttons: [ ],
- nonNormalizedPosition: mousePosition)
- }
-
-#if canImport(ObjectiveC)
- @objc
-#endif
- func mouseWheelUp(_ mousePosition: CGPoint) {
- enqueueMousePressEvent(buttons: [ .button4 ],
- nonNormalizedPosition: mousePosition)
- }
-
+ func mouseMove(x: UInt16, y: UInt16) {
+ enqueueMouseEvent(nonNormalizedX: x,
+ nonNormalizedY: y)
+ }
+
#if canImport(ObjectiveC)
@objc
#endif
- func mouseWheelDown(_ mousePosition: CGPoint) {
- enqueueMousePressEvent(buttons: [ .button5 ],
- nonNormalizedPosition: mousePosition)
- }
-
+ func mouseButtonDown(_ button: VNCMouseButton,
+ x: UInt16, y: UInt16) {
+ updateMouseButtonState(button: button,
+ isDown: true)
+
+ enqueueMouseEvent(nonNormalizedX: x,
+ nonNormalizedY: y)
+ }
+
#if canImport(ObjectiveC)
@objc
#endif
- func mouseWheelLeft(_ mousePosition: CGPoint) {
- enqueueMousePressEvent(buttons: [ .button6 ],
- nonNormalizedPosition: mousePosition)
- }
-
+ func mouseButtonUp(_ button: VNCMouseButton,
+ x: UInt16, y: UInt16) {
+ updateMouseButtonState(button: button,
+ isDown: false)
+
+ enqueueMouseEvent(nonNormalizedX: x,
+ nonNormalizedY: y)
+ }
+
#if canImport(ObjectiveC)
@objc
#endif
- func mouseWheelRight(_ mousePosition: CGPoint) {
- enqueueMousePressEvent(buttons: [ .button7 ],
- nonNormalizedPosition: mousePosition)
- }
+ func mouseWheel(_ wheel: VNCMouseWheel,
+ x: UInt16, y: UInt16,
+ steps: UInt32) {
+ for _ in 0.. VNCProtocol.MousePosition {
- var normalizedX = Int(cgPoint.x)
- var normalizedY = Int(cgPoint.y)
-
- let framebufferWidth = Int(framebuffer?.size.width ?? 0)
- let framebufferHeight = Int(framebuffer?.size.height ?? 0)
-
- if normalizedY < 0 {
- normalizedY = 0
- } else if normalizedY > framebufferHeight {
- normalizedY = framebufferHeight
- }
-
- if normalizedX < 0 {
- normalizedX = 0
- } else if normalizedX > framebufferWidth {
- normalizedX = framebufferWidth
- }
-
- let normalizedPosition = VNCProtocol.MousePosition(x: .init(normalizedX),
- y: .init(normalizedY))
-
- return normalizedPosition
- }
+
+ func normalizedMousePosition(x: UInt16,
+ y: UInt16) -> VNCProtocol.MousePosition {
+ var normalizedX = x
+ var normalizedY = y
+
+ let framebufferWidth = framebuffer?.size.width ?? 0
+ let framebufferHeight = framebuffer?.size.height ?? 0
+
+ if normalizedY > framebufferHeight {
+ normalizedY = framebufferHeight
+ }
+
+ if normalizedX > framebufferWidth {
+ normalizedX = framebufferWidth
+ }
+
+ let normalizedPosition = VNCProtocol.MousePosition(x: normalizedX,
+ y: normalizedY)
+
+ return normalizedPosition
+ }
}
diff --git a/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+Receive.swift b/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+Receive.swift
index bcd28807..f04cc0bb 100644
--- a/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+Receive.swift
+++ b/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+Receive.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
// MARK: - Server to Client Messages
extension VNCConnection {
@@ -70,6 +74,11 @@ private extension VNCConnection {
logger.logDebug("Received Framebuffer Update: \(framebufferUpdate)")
+ /*
+ // Write out the framebuffer for testing purposes
+ try framebuffer.writeSurface()
+ */
+
try await sendFramebufferUpdateRequest()
}
diff --git a/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+Send.swift b/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+Send.swift
index 16814ce0..ac326fe9 100644
--- a/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+Send.swift
+++ b/Sources/RoyalVNCKit/SDK/Connection/VNCConnection+Send.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
// MARK: - Client to Server Messages
extension VNCConnection {
diff --git a/Sources/RoyalVNCKit/SDK/Connection/VNCConnection.swift b/Sources/RoyalVNCKit/SDK/Connection/VNCConnection.swift
index bebfa917..4372a8e0 100644
--- a/Sources/RoyalVNCKit/SDK/Connection/VNCConnection.swift
+++ b/Sources/RoyalVNCKit/SDK/Connection/VNCConnection.swift
@@ -1,4 +1,10 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
+
+import Dispatch
#if canImport(Network)
import Network
@@ -7,12 +13,14 @@ import Network
#if canImport(ObjectiveC)
@objc(VNCConnection)
#endif
-public class VNCConnection: NSObjectOrAnyObject {
+public final class VNCConnection: NSObjectOrAnyObject {
// MARK: - Public Properties
#if canImport(ObjectiveC)
@objc
#endif
public let settings: Settings
+
+ public let context: UnsafeMutableRawPointer?
#if canImport(ObjectiveC)
@objc
@@ -56,16 +64,19 @@ public class VNCConnection: NSObjectOrAnyObject {
let clipboardMonitor: VNCClipboardMonitor
var clientToServerMessageQueue = Queue()
+
+ var mouseButtonState: VNCProtocol.MousePointerButton = [ ]
lazy var connection: some NetworkConnection = {
let connectionSettings = NetworkConnectionSettings(connectionTimeout: 15,
host: settings.hostname,
port: settings.port)
+ // NOTE: To test SocketNetworkConnection on Darwin (macOS, iOS, etc.), comment out the the #if
#if canImport(Network)
let connection = NWConnection(settings: connectionSettings)
#else
- fatalError("TODO: Implement NetworkConnection for Linux/Windows/etc.")
+ let connection = SocketNetworkConnection(settings: connectionSettings)
#endif
connection.setStatusUpdateHandler(connectionStatusDidChange)
@@ -107,7 +118,7 @@ public class VNCConnection: NSObjectOrAnyObject {
try encodingTypes.validate()
} catch {
// If the sanity check fails here, it's a programming error
- fatalError((error as NSError).debugDescription)
+ fatalError(error.debugDescription)
}
return encs
@@ -157,43 +168,64 @@ public class VNCConnection: NSObjectOrAnyObject {
}
// MARK: - Public Initializers
+ public init(settings: Settings,
+ logger: VNCLogger,
+ context: UnsafeMutableRawPointer?) {
+ self.settings = settings
+
+ logger.isDebugLoggingEnabled = settings.isDebugLoggingEnabled
+
+ self.logger = logger
+
+ self.context = context
+
+ self.sharedZStream = .init()
+
+ let clipboard = VNCClipboard()
+
+ let clipboardMonitor = VNCClipboardMonitor(clipboard: clipboard,
+ monitoringInterval: 0.5,
+ tolerance: 0.15)
+
+ self.clipboard = clipboard
+
+ self.clipboardMonitor = clipboardMonitor
+
+ super.init()
+
+ self.clipboardMonitor.delegate = self
+ }
+
#if canImport(ObjectiveC)
@objc
#endif
- public init(settings: Settings,
- logger: VNCLogger) {
- self.settings = settings
-
- logger.isDebugLoggingEnabled = settings.isDebugLoggingEnabled
-
- self.logger = logger
-
- self.sharedZStream = .init()
-
- let clipboard = VNCClipboard()
-
- let clipboardMonitor = VNCClipboardMonitor(clipboard: clipboard,
- monitoringInterval: 0.5,
- tolerance: 0.15)
-
- self.clipboard = clipboard
-
- self.clipboardMonitor = clipboardMonitor
-
- super.init()
-
- self.clipboardMonitor.delegate = self
+ public convenience init(settings: Settings,
+ logger: VNCLogger) {
+ self.init(settings: settings,
+ logger: logger,
+ context: nil)
}
#if canImport(ObjectiveC)
@objc
#endif
public convenience init(settings: Settings) {
- let logger = OSLogLogger()
-
- self.init(settings: settings,
- logger: logger)
+ self.init(settings: settings,
+ context: nil)
}
+
+ public convenience init(settings: Settings,
+ context: UnsafeMutableRawPointer?) {
+#if canImport(OSLog)
+ let logger = VNCOSLogLogger()
+#else
+ let logger = VNCPrintLogger()
+#endif
+
+ self.init(settings: settings,
+ logger: logger,
+ context: context)
+ }
deinit {
let _self = self
@@ -295,6 +327,8 @@ private extension VNCConnection {
try await sendFramebufferUpdateRequest()
} catch {
handleBreakingError(error)
+
+ return
}
updateConnectionState(.connected)
diff --git a/Sources/RoyalVNCKit/SDK/Connection/VNCConnectionDelegate.swift b/Sources/RoyalVNCKit/SDK/Connection/VNCConnectionDelegate.swift
index 93e8f14d..9d112536 100644
--- a/Sources/RoyalVNCKit/SDK/Connection/VNCConnectionDelegate.swift
+++ b/Sources/RoyalVNCKit/SDK/Connection/VNCConnectionDelegate.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
#if canImport(ObjectiveC)
@objc(VNCConnectionDelegate)
@@ -28,14 +32,15 @@ public protocol VNCConnectionDelegate: AnyObject {
#endif
func connection(_ connection: VNCConnection,
didResizeFramebuffer framebuffer: VNCFramebuffer)
-
+
#if canImport(ObjectiveC)
@objc
#endif
- func connection(_ connection: VNCConnection,
- framebuffer: VNCFramebuffer,
- didUpdateRegion updatedRegion: CGRect)
-
+ func connection(_ connection: VNCConnection,
+ didUpdateFramebuffer framebuffer: VNCFramebuffer,
+ x: UInt16, y: UInt16,
+ width: UInt16, height: UInt16)
+
#if canImport(ObjectiveC)
@objc
#endif
diff --git a/Sources/RoyalVNCKit/SDK/Cursor/VNCCursor.swift b/Sources/RoyalVNCKit/SDK/Cursor/VNCCursor.swift
index 5764845f..eda68a05 100644
--- a/Sources/RoyalVNCKit/SDK/Cursor/VNCCursor.swift
+++ b/Sources/RoyalVNCKit/SDK/Cursor/VNCCursor.swift
@@ -1,10 +1,17 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
+
+#if canImport(CoreGraphics)
import CoreGraphics
+#endif
#if canImport(ObjectiveC)
@objc(VNCCursor)
#endif
-public class VNCCursor: NSObjectOrAnyObject {
+public final class VNCCursor: NSObjectOrAnyObject {
#if canImport(ObjectiveC)
@objc
#endif
@@ -42,8 +49,10 @@ public class VNCCursor: NSObjectOrAnyObject {
@objc
#endif
public let bytesPerRow: Int
-
+
+#if canImport(CoreGraphics)
private static let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
+#endif
override init() {
self.isEmpty = true
@@ -78,6 +87,7 @@ public class VNCCursor: NSObjectOrAnyObject {
}
}
+#if canImport(CoreGraphics)
public extension VNCCursor {
#if canImport(ObjectiveC)
@objc
@@ -92,7 +102,7 @@ public extension VNCCursor {
var cgHotspot: CGPoint {
hotspot.cgPoint
}
-
+
#if canImport(ObjectiveC)
@objc
#endif
@@ -122,3 +132,4 @@ public extension VNCCursor {
return image
}
}
+#endif
diff --git a/Sources/RoyalVNCKit/SDK/Error/AuthenticationError.swift b/Sources/RoyalVNCKit/SDK/Error/AuthenticationError.swift
index 9056595c..93b3df1b 100644
--- a/Sources/RoyalVNCKit/SDK/Error/AuthenticationError.swift
+++ b/Sources/RoyalVNCKit/SDK/Error/AuthenticationError.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public extension VNCError {
enum AuthenticationError: Error, LocalizedError {
diff --git a/Sources/RoyalVNCKit/SDK/Error/ConnectionError.swift b/Sources/RoyalVNCKit/SDK/Error/ConnectionError.swift
index d46838ad..9b20af33 100644
--- a/Sources/RoyalVNCKit/SDK/Error/ConnectionError.swift
+++ b/Sources/RoyalVNCKit/SDK/Error/ConnectionError.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public extension VNCError {
enum ConnectionError: Error, LocalizedError {
diff --git a/Sources/RoyalVNCKit/SDK/Error/ProtocolError.swift b/Sources/RoyalVNCKit/SDK/Error/ProtocolError.swift
index 13990506..aafdc83e 100644
--- a/Sources/RoyalVNCKit/SDK/Error/ProtocolError.swift
+++ b/Sources/RoyalVNCKit/SDK/Error/ProtocolError.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public extension VNCError {
enum ProtocolError: Error, LocalizedError {
diff --git a/Sources/RoyalVNCKit/SDK/Error/VNCError.swift b/Sources/RoyalVNCKit/SDK/Error/VNCError.swift
index 6969a939..76582163 100644
--- a/Sources/RoyalVNCKit/SDK/Error/VNCError.swift
+++ b/Sources/RoyalVNCKit/SDK/Error/VNCError.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public enum VNCError: Error, LocalizedError {
case `protocol`(_ underlyingError: ProtocolError)
@@ -56,7 +60,7 @@ public enum VNCError: Error, LocalizedError {
extension VNCError {
static func combinedErrorDescription(_ baseErrorDescription: String,
underlyingError: Error?) -> String {
- let underlyingErrorDescription = underlyingError?.localizedDescription ?? ""
+ let underlyingErrorDescription = underlyingError?.humanReadableDescription ?? ""
guard underlyingErrorDescription != baseErrorDescription else {
return baseErrorDescription
@@ -71,7 +75,7 @@ extension VNCError {
#if canImport(ObjectiveC)
@objc(VNCErrorUtils)
// swiftlint:disable:next type_name
-public class _ObjC_VNCErrorUtils: NSObject {
+public final class _ObjC_VNCErrorUtils: NSObject {
@objc
public static func shouldDisplayErrorToUser(_ error: Error) -> Bool {
guard let vncError = error as? VNCError else {
diff --git a/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode+ObjC.swift b/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode+ObjC.swift
index 7acf6a41..f33a69de 100644
--- a/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode+ObjC.swift
+++ b/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode+ObjC.swift
@@ -1,11 +1,11 @@
// This is hacky, but I currently don't have a better idea on how to handle this for ObjC
+#if canImport(ObjectiveC)
import Foundation
-#if canImport(ObjectiveC)
@objc(VNCKeyCode)
// swiftlint:disable:next type_name
-public class _ObjC_VNCKeyCode: NSObject {
+public final class _ObjC_VNCKeyCode: NSObject {
// Must be kept in Sync with VNCKeyCode!
@objc
diff --git a/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode+String.swift b/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode+String.swift
index 053e44c4..5c86586f 100644
--- a/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode+String.swift
+++ b/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode+String.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public extension VNCKeyCode {
static func keyCodesFrom(characters: String) -> [VNCKeyCode] {
diff --git a/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode.swift b/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode.swift
index 8f4aa5c1..7139ab59 100644
--- a/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode.swift
+++ b/Sources/RoyalVNCKit/SDK/Input/VNCKeyCode.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public struct VNCKeyCode: Equatable {
public let rawValue: UInt32
@@ -190,7 +194,7 @@ public extension VNCKeyCode {
}
var hexDescription: String {
- let keyHex = String(format: "0x%04X", rawValue)
+ let keyHex = rawValue.hexString()
return keyHex
}
diff --git a/Sources/RoyalVNCKit/SDK/Logging/VNCLogger.swift b/Sources/RoyalVNCKit/SDK/Logging/VNCLogger.swift
index ad06b6cf..7fe98afc 100644
--- a/Sources/RoyalVNCKit/SDK/Logging/VNCLogger.swift
+++ b/Sources/RoyalVNCKit/SDK/Logging/VNCLogger.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
#if canImport(ObjectiveC)
@objc(VNCLogger)
diff --git a/Sources/RoyalVNCKit/SDK/UI/DisplayLink/macOS/DisplayLink.swift b/Sources/RoyalVNCKit/SDK/UI/DisplayLink/macOS/DisplayLink.swift
index be8dfe5e..f13052dd 100644
--- a/Sources/RoyalVNCKit/SDK/UI/DisplayLink/macOS/DisplayLink.swift
+++ b/Sources/RoyalVNCKit/SDK/UI/DisplayLink/macOS/DisplayLink.swift
@@ -6,7 +6,7 @@ protocol DisplayLinkDelegate: AnyObject {
func displayLinkDidUpdate(_ displayLink: DisplayLink)
}
-class DisplayLink {
+final class DisplayLink {
private let displayLink: CVDisplayLink
weak var delegate: DisplayLinkDelegate?
diff --git a/Sources/RoyalVNCKit/SDK/UI/FramebufferView/VNCFramebufferView+Extensions.swift b/Sources/RoyalVNCKit/SDK/UI/FramebufferView/VNCFramebufferView+Extensions.swift
index ade68754..b4adc1aa 100644
--- a/Sources/RoyalVNCKit/SDK/UI/FramebufferView/VNCFramebufferView+Extensions.swift
+++ b/Sources/RoyalVNCKit/SDK/UI/FramebufferView/VNCFramebufferView+Extensions.swift
@@ -1,3 +1,4 @@
+#if os(macOS) || os(iOS)
import Foundation
extension VNCFramebufferView {
@@ -8,36 +9,43 @@ extension VNCFramebufferView {
func handleScrollWheel(scrollDelta: CGPoint,
hasPreciseScrollingDeltas: Bool,
- mousePosition: CGPoint) {
+ mousePositionX: UInt16,
+ mousePositionY: UInt16) {
if hasPreciseScrollingDeltas {
handlePreciseScrollingDelta(scrollDelta,
- mousePosition: mousePosition)
+ mousePositionX: mousePositionX,
+ mousePositionY: mousePositionY)
} else {
handleImpreciseScrollingDelta(scrollDelta,
- mousePosition: mousePosition)
+ mousePositionX: mousePositionX,
+ mousePositionY: mousePositionY)
}
}
func handleImpreciseScrollingDelta(_ scrollDelta: CGPoint,
- mousePosition: CGPoint) {
- guard let connection = self.connection else { return }
-
+ mousePositionX: UInt16,
+ mousePositionY: UInt16) {
+ guard let connection = self.connection else {
+ return
+ }
+
if scrollDelta.x < 0 {
- connection.mouseWheelRight(mousePosition)
+ connection.mouseWheel(.right, x: mousePositionX, y: mousePositionY, steps: 1)
} else if scrollDelta.x > 0 {
- connection.mouseWheelLeft(mousePosition)
+ connection.mouseWheel(.left, x: mousePositionX, y: mousePositionY, steps: 1)
}
if scrollDelta.y < 0 {
- connection.mouseWheelDown(mousePosition)
+ connection.mouseWheel(.down, x: mousePositionX, y: mousePositionY, steps: 1)
} else if scrollDelta.y > 0 {
- connection.mouseWheelUp(mousePosition)
+ connection.mouseWheel(.up, x: mousePositionX, y: mousePositionY, steps: 1)
}
}
func handlePreciseScrollingDelta(_ scrollDelta: CGPoint,
- mousePosition: CGPoint) {
- accumulatedScrollDeltaX += scrollDelta.x
+ mousePositionX: UInt16,
+ mousePositionY: UInt16) {
+ accumulatedScrollDeltaX += scrollDelta.x
accumulatedScrollDeltaY += scrollDelta.y
// #if DEBUG
@@ -47,11 +55,11 @@ extension VNCFramebufferView {
if abs(accumulatedScrollDeltaX) >= scrollStep {
while abs(accumulatedScrollDeltaX) >= scrollStep {
if accumulatedScrollDeltaX < 0 {
- connection?.mouseWheelRight(mousePosition)
+ connection?.mouseWheel(.right, x: mousePositionX, y: mousePositionY, steps: 1)
accumulatedScrollDeltaX += scrollStep
} else if accumulatedScrollDeltaX > 0 {
- connection?.mouseWheelLeft(mousePosition)
+ connection?.mouseWheel(.left, x: mousePositionX, y: mousePositionY, steps: 1)
accumulatedScrollDeltaX -= scrollStep
}
@@ -63,11 +71,11 @@ extension VNCFramebufferView {
if abs(accumulatedScrollDeltaY) >= scrollStep {
while abs(accumulatedScrollDeltaY) >= scrollStep {
if accumulatedScrollDeltaY < 0 {
- connection?.mouseWheelDown(mousePosition)
+ connection?.mouseWheel(.down, x: mousePositionX, y: mousePositionY, steps: 1)
accumulatedScrollDeltaY += scrollStep
} else if accumulatedScrollDeltaY > 0 {
- connection?.mouseWheelUp(mousePosition)
+ connection?.mouseWheel(.up, x: mousePositionX, y: mousePositionY, steps: 1)
accumulatedScrollDeltaY -= scrollStep
}
@@ -77,3 +85,4 @@ extension VNCFramebufferView {
}
}
}
+#endif
diff --git a/Sources/RoyalVNCKit/SDK/UI/FramebufferView/VNCFramebufferView.swift b/Sources/RoyalVNCKit/SDK/UI/FramebufferView/VNCFramebufferView.swift
index 50ccfe97..e659a3a7 100644
--- a/Sources/RoyalVNCKit/SDK/UI/FramebufferView/VNCFramebufferView.swift
+++ b/Sources/RoyalVNCKit/SDK/UI/FramebufferView/VNCFramebufferView.swift
@@ -1,3 +1,4 @@
+#if os(macOS) || os(iOS)
import Foundation
#if canImport(ObjectiveC)
@@ -47,9 +48,10 @@ public protocol VNCFramebufferView: AnyObject {
#if canImport(ObjectiveC)
@objc
#endif
- func connection(_ connection: VNCConnection,
- framebuffer: VNCFramebuffer,
- didUpdateRegion updatedRegion: CGRect)
+ func connection(_ connection: VNCConnection,
+ didUpdateFramebuffer framebuffer: VNCFramebuffer,
+ x: UInt16, y: UInt16,
+ width: UInt16, height: UInt16)
#if canImport(ObjectiveC)
@objc
@@ -57,3 +59,4 @@ public protocol VNCFramebufferView: AnyObject {
func connection(_ connection: VNCConnection,
didUpdateCursor cursor: VNCCursor)
}
+#endif
diff --git a/Sources/RoyalVNCKit/SDK/UI/FramebufferView/macOS/VNCCAFramebufferView.swift b/Sources/RoyalVNCKit/SDK/UI/FramebufferView/macOS/VNCCAFramebufferView.swift
index 4cb4a17f..7bbe1b32 100644
--- a/Sources/RoyalVNCKit/SDK/UI/FramebufferView/macOS/VNCCAFramebufferView.swift
+++ b/Sources/RoyalVNCKit/SDK/UI/FramebufferView/macOS/VNCCAFramebufferView.swift
@@ -4,7 +4,7 @@ import AppKit
import Carbon
@objc(VNCCAFramebufferView)
-public class VNCCAFramebufferView: NSView, VNCFramebufferView {
+public final class VNCCAFramebufferView: NSView, VNCFramebufferView {
@objc
public private(set) weak var connection: VNCConnection?
@@ -156,7 +156,7 @@ public class VNCCAFramebufferView: NSView, VNCFramebufferView {
removeDisplayLink()
- guard let window = window,
+ guard let window,
let screen = window.screen ?? NSScreen.main else {
return
}
@@ -173,7 +173,7 @@ public class VNCCAFramebufferView: NSView, VNCFramebufferView {
}
public override func updateTrackingAreas() {
- if let trackingArea = trackingArea {
+ if let trackingArea {
removeTrackingArea(trackingArea)
}
@@ -242,8 +242,9 @@ public class VNCCAFramebufferView: NSView, VNCFramebufferView {
extension VNCCAFramebufferView {
public func connection(_ connection: VNCConnection,
- framebuffer: VNCFramebuffer,
- didUpdateRegion updatedRegion: CGRect) {
+ didUpdateFramebuffer framebuffer: VNCFramebuffer,
+ x: UInt16, y: UInt16,
+ width: UInt16, height: UInt16) {
// NOTE: If we ever take the updatedRegion into consideration, we will likely need to flip the coordinates on macOS
guard !settings.useDisplayLink,
@@ -264,17 +265,36 @@ extension VNCCAFramebufferView {
// MARK: - Positions
private extension VNCCAFramebufferView {
- func scaledContentRelativePosition(of event: NSEvent) -> CGPoint? {
+ struct UInt16Point {
+ let x: UInt16
+ let y: UInt16
+
+ init(x: UInt16, y: UInt16) {
+ self.x = x
+ self.y = y
+ }
+
+ init(_ point: CGPoint) {
+ self.x = .init(point.x)
+ self.y = .init(point.y)
+ }
+ }
+
+ func scaledContentRelativePosition(of event: NSEvent) -> UInt16Point? {
let viewRelativePosition = viewRelativePosition(of: event)
let contentRect = contentRect
- guard contentRect.contains(viewRelativePosition) else { return nil }
+ guard contentRect.contains(viewRelativePosition) else {
+ return nil
+ }
let scaledPosition = CGPoint(x: (viewRelativePosition.x - contentRect.origin.x) / scaleRatio,
y: (viewRelativePosition.y - contentRect.origin.y) / scaleRatio)
+
+ let scaledPositionUInt16 = UInt16Point(scaledPosition)
- return scaledPosition
+ return scaledPositionUInt16
}
func viewRelativePosition(of event: NSEvent) -> CGPoint {
@@ -288,72 +308,109 @@ private extension VNCCAFramebufferView {
// MARK: - Mouse Input
extension VNCCAFramebufferView {
func handleMouseMoved(with event: NSEvent) {
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.mouseMove(position)
+ connection.mouseMove(x: position.x, y: position.y)
}
func handleMouseDown(with event: NSEvent) {
window?.makeFirstResponder(self)
becomeFirstResponder()
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.mouseDown(position)
+ connection.mouseButtonDown(.left,
+ x: position.x, y: position.y)
}
func handleMouseDragged(with event: NSEvent) {
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.mouseDown(position)
+ connection.mouseButtonDown(.left,
+ x: position.x, y: position.y)
}
func handleMouseUp(with event: NSEvent) {
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.mouseUp(position)
+ connection.mouseButtonUp(.left,
+ x: position.x, y: position.y)
}
func handleRightMouseDown(with event: NSEvent) {
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.rightMouseDown(position)
+ connection.mouseButtonDown(.right,
+ x: position.x, y: position.y)
}
func handleRightMouseDragged(with event: NSEvent) {
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.rightMouseDown(position)
+ connection.mouseButtonDown(.right,
+ x: position.x, y: position.y)
}
func handleRightMouseUp(with event: NSEvent) {
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.mouseUp(position)
+ connection.mouseButtonUp(.right,
+ x: position.x, y: position.y)
}
func handleOtherMouseDown(with event: NSEvent) {
guard isMiddleButton(event: event) else { return }
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.middleMouseDown(position)
+ connection.mouseButtonDown(.middle,
+ x: position.x, y: position.y)
}
func handleOtherMouseDragged(with event: NSEvent) {
- guard isMiddleButton(event: event) else { return }
-
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ isMiddleButton(event: event),
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.middleMouseDown(position)
+ connection.mouseButtonDown(.middle,
+ x: position.x, y: position.y)
}
func handleOtherMouseUp(with event: NSEvent) {
- guard isMiddleButton(event: event) else { return }
-
- guard let position = scaledContentRelativePosition(of: event) else { return }
+ guard let connection,
+ isMiddleButton(event: event),
+ let position = scaledContentRelativePosition(of: event) else {
+ return
+ }
- connection?.mouseUp(position)
+ connection.mouseButtonUp(.middle,
+ x: position.x, y: position.y)
}
func handleScrollWheel(with event: NSEvent) {
@@ -364,7 +421,8 @@ extension VNCCAFramebufferView {
handleScrollWheel(scrollDelta: scrollDelta,
hasPreciseScrollingDeltas: event.hasPreciseScrollingDeltas,
- mousePosition: position)
+ mousePositionX: position.x,
+ mousePositionY: position.y)
}
func isMiddleButton(event: NSEvent) -> Bool {
@@ -377,7 +435,7 @@ extension VNCCAFramebufferView {
// MARK: - Keyboard Input
extension VNCCAFramebufferView {
func handleKey(event: NSEvent?) {
- guard let event = event else { return }
+ guard let event else { return }
if event.type == .keyDown {
handleKeyDown(with: event)
@@ -387,8 +445,8 @@ extension VNCCAFramebufferView {
}
func handleKeyDown(with event: NSEvent?) {
- guard let event = event,
- let connection = self.connection else {
+ guard let event,
+ let connection else {
return
}
@@ -400,8 +458,8 @@ extension VNCCAFramebufferView {
}
func handleKeyUp(with event: NSEvent?) {
- guard let event = event,
- let connection = self.connection else {
+ guard let event,
+ let connection else {
return
}
@@ -431,19 +489,19 @@ extension VNCCAFramebufferView {
func handlePerformKeyEquivalent(with event: NSEvent) -> Bool {
// swiftlint:disable:next control_statement
guard (settings.inputMode == .forwardKeyboardShortcutsEvenIfInUseLocally || settings.inputMode == .forwardAllKeyboardShortcutsAndHotKeys),
- let window = window,
+ let window,
(window.firstResponder == window || window.firstResponder == self) else {
return false
}
let flags = event.modifierFlags
-
- guard flags.contains(.shift) ||
- flags.contains(.control) ||
- flags.contains(.option) ||
- flags.contains(.command) else {
- return false
- }
+
+ guard flags.contains(.shift) ||
+ flags.contains(.control) ||
+ flags.contains(.option) ||
+ flags.contains(.command) else {
+ return false
+ }
handleKeyDown(with: event)
handleKeyUp(with: event)
@@ -470,7 +528,7 @@ private extension VNCCAFramebufferView {
func updateImage(_ image: CGImage?) {
DispatchQueue.main.async { [weak self] in
guard let self,
- let layer = self.layer else {
+ let layer else {
return
}
diff --git a/Sources/RoyalVNCKit/SDK/UI/ScrollView/macOS/VNCCenteringClipView.swift b/Sources/RoyalVNCKit/SDK/UI/ScrollView/macOS/VNCCenteringClipView.swift
index 40353967..7109a6cb 100644
--- a/Sources/RoyalVNCKit/SDK/UI/ScrollView/macOS/VNCCenteringClipView.swift
+++ b/Sources/RoyalVNCKit/SDK/UI/ScrollView/macOS/VNCCenteringClipView.swift
@@ -5,7 +5,7 @@ import AppKit
#if canImport(ObjectiveC)
@objc(VNCCenteringClipView)
#endif
-public class VNCCenteringClipView: NSClipView {
+public final class VNCCenteringClipView: NSClipView {
public override func constrainBoundsRect(_ proposedBounds: NSRect) -> NSRect {
var rect = super.constrainBoundsRect(proposedBounds)
diff --git a/Sources/RoyalVNCKit/SDK/UI/ScrollView/macOS/VNCScrollView.swift b/Sources/RoyalVNCKit/SDK/UI/ScrollView/macOS/VNCScrollView.swift
index 55d7b7ac..6b356868 100644
--- a/Sources/RoyalVNCKit/SDK/UI/ScrollView/macOS/VNCScrollView.swift
+++ b/Sources/RoyalVNCKit/SDK/UI/ScrollView/macOS/VNCScrollView.swift
@@ -5,7 +5,7 @@ import AppKit
#if canImport(ObjectiveC)
@objc(VNCScrollView)
#endif
-public class VNCScrollView: NSScrollView {
+public final class VNCScrollView: NSScrollView {
public override func scrollWheel(with event: NSEvent) {
nextResponder?
.nextResponder?
diff --git a/Sources/RoyalVNCKit/SDK/VNCAccessibilityUtils.swift b/Sources/RoyalVNCKit/SDK/VNCAccessibilityUtils.swift
index f372cd44..32b7a2e6 100644
--- a/Sources/RoyalVNCKit/SDK/VNCAccessibilityUtils.swift
+++ b/Sources/RoyalVNCKit/SDK/VNCAccessibilityUtils.swift
@@ -4,7 +4,7 @@ import AppKit
import ApplicationServices
@objc(VNCAccessibilityUtils)
-public class VNCAccessibilityUtils: NSObject {
+public final class VNCAccessibilityUtils: NSObject {
private static let accessibilityPreferencePaneURL = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility")!
@objc
diff --git a/Sources/RoyalVNCKit/SDK/VNCAuthenticationType.swift b/Sources/RoyalVNCKit/SDK/VNCAuthenticationType.swift
index 4e81a3fb..bad6ee23 100644
--- a/Sources/RoyalVNCKit/SDK/VNCAuthenticationType.swift
+++ b/Sources/RoyalVNCKit/SDK/VNCAuthenticationType.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
#if canImport(ObjectiveC)
@objc(VNCAuthenticationType)
@@ -36,7 +40,7 @@ public extension VNCAuthenticationType {
#if canImport(ObjectiveC)
@objc(VNCAuthenticationTypeUtils)
// swiftlint:disable:next type_name
-public class _ObjC_VNCAuthenticationTypeUtils: NSObject {
+public final class _ObjC_VNCAuthenticationTypeUtils: NSObject {
@objc
public static func authenticationTypeRequiresUsername(_ authenticationType: VNCAuthenticationType) -> Bool {
authenticationType.requiresUsername
diff --git a/Sources/RoyalVNCKit/SDK/VNCCredential.swift b/Sources/RoyalVNCKit/SDK/VNCCredential.swift
index 3ab87b62..c2ae1e78 100644
--- a/Sources/RoyalVNCKit/SDK/VNCCredential.swift
+++ b/Sources/RoyalVNCKit/SDK/VNCCredential.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
#if canImport(ObjectiveC)
@objc(VNCCredential)
@@ -8,7 +12,7 @@ public protocol VNCCredential: AnyObject { }
#if canImport(ObjectiveC)
@objc(VNCPasswordCredential)
#endif
-public class VNCPasswordCredential: NSObjectOrAnyObject, VNCCredential {
+public final class VNCPasswordCredential: NSObjectOrAnyObject, VNCCredential {
#if canImport(ObjectiveC)
@objc
#endif
@@ -25,7 +29,7 @@ public class VNCPasswordCredential: NSObjectOrAnyObject, VNCCredential {
#if canImport(ObjectiveC)
@objc(VNCUsernamePasswordCredential)
#endif
-public class VNCUsernamePasswordCredential: NSObjectOrAnyObject, VNCCredential {
+public final class VNCUsernamePasswordCredential: NSObjectOrAnyObject, VNCCredential {
#if canImport(ObjectiveC)
@objc
#endif
diff --git a/Sources/RoyalVNCKit/SDK/VNCEncodingType.swift b/Sources/RoyalVNCKit/SDK/VNCEncodingType.swift
index e9540d37..338e306f 100644
--- a/Sources/RoyalVNCKit/SDK/VNCEncodingType.swift
+++ b/Sources/RoyalVNCKit/SDK/VNCEncodingType.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
/// VNC Encodings can either be specified as Int32 or UInt32 which have the same byte size. You MUST NOT actually use a Int64 value!
public struct VNCEncodingType: RawRepresentable, ExpressibleByIntegerLiteral, Equatable, Hashable {
diff --git a/Sources/RoyalVNCKit/SDK/VNCFrameEncodingType.swift b/Sources/RoyalVNCKit/SDK/VNCFrameEncodingType.swift
index 82df43cf..951b01b0 100644
--- a/Sources/RoyalVNCKit/SDK/VNCFrameEncodingType.swift
+++ b/Sources/RoyalVNCKit/SDK/VNCFrameEncodingType.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
#if canImport(ObjectiveC)
@objc(VNCFrameEncodingType)
@@ -58,7 +62,7 @@ public extension VNCFrameEncodingType {
#if canImport(ObjectiveC)
@objc(VNCFrameEncodingTypeUtils)
// swiftlint:disable:next type_name
-public class _ObjC_VNCFrameEncodingTypeUtils: NSObject {
+public final class _ObjC_VNCFrameEncodingTypeUtils: NSObject {
@objc
public static var defaultFrameEncodings: [Int64] {
VNCFrameEncodingType.defaultFrameEncodings.map({ $0.rawValue.rawValue })
diff --git a/Sources/RoyalVNCKit/SDK/VNCMouseButton.swift b/Sources/RoyalVNCKit/SDK/VNCMouseButton.swift
new file mode 100644
index 00000000..67defcba
--- /dev/null
+++ b/Sources/RoyalVNCKit/SDK/VNCMouseButton.swift
@@ -0,0 +1,52 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+#if canImport(ObjectiveC)
+@objc(VNCMouseButton)
+#endif
+public enum VNCMouseButton: Int {
+ case left
+ case middle
+ case right
+}
+
+#if canImport(ObjectiveC)
+@objc(VNCMouseWheel)
+#endif
+public enum VNCMouseWheel: Int {
+ case left
+ case right
+ case up
+ case down
+}
+
+extension VNCMouseButton {
+ var mousePointerButton: VNCProtocol.MousePointerButton {
+ switch self {
+ case .left:
+ .left
+ case .middle:
+ .middle
+ case .right:
+ .right
+ }
+ }
+}
+
+extension VNCMouseWheel {
+ var mousePointerButton: VNCProtocol.MousePointerButton {
+ switch self {
+ case .left:
+ .wheelLeft
+ case .right:
+ .wheelRight
+ case .up:
+ .wheelUp
+ case .down:
+ .wheelDown
+ }
+ }
+}
diff --git a/Sources/RoyalVNCKit/SDK/VNCPseudoEncodingType.swift b/Sources/RoyalVNCKit/SDK/VNCPseudoEncodingType.swift
index 814b583f..7f963f8f 100644
--- a/Sources/RoyalVNCKit/SDK/VNCPseudoEncodingType.swift
+++ b/Sources/RoyalVNCKit/SDK/VNCPseudoEncodingType.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
public enum VNCPseudoEncodingType: VNCEncodingType {
case lastRect = -224
diff --git a/Sources/RoyalVNCKit/SDK/VNCScreen.swift b/Sources/RoyalVNCKit/SDK/VNCScreen.swift
index 5cffa051..75311d14 100644
--- a/Sources/RoyalVNCKit/SDK/VNCScreen.swift
+++ b/Sources/RoyalVNCKit/SDK/VNCScreen.swift
@@ -1,10 +1,17 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
+
+#if canImport(CoreGraphics)
import CoreGraphics
+#endif
#if canImport(ObjectiveC)
@objc(VNCScreen)
#endif
-public class VNCScreen: NSObjectOrAnyObject {
+public final class VNCScreen: NSObjectOrAnyObject {
#if canImport(ObjectiveC)
@objc
#endif
@@ -19,6 +26,7 @@ public class VNCScreen: NSObjectOrAnyObject {
}
}
+#if canImport(CoreGraphics)
public extension VNCScreen {
#if canImport(ObjectiveC)
@objc
@@ -27,7 +35,9 @@ public extension VNCScreen {
frame.cgRect
}
}
+#endif
+#if canImport(ObjectiveC)
// MARK: - Equatable overrides for NSObject
extension VNCScreen {
public override func isEqual(_ object: Any?) -> Bool {
@@ -49,6 +59,16 @@ extension VNCScreen {
return hasher.finalize()
}
}
+#else
+extension VNCScreen: Equatable {
+ public static func ==(lhs: VNCScreen, rhs: VNCScreen) -> Bool {
+ let equal = lhs.id == rhs.id &&
+ lhs.frame == rhs.frame
+
+ return equal
+ }
+}
+#endif
extension VNCScreen {
convenience init(screen: VNCProtocol.Screen) {
diff --git a/Sources/RoyalVNCKit/Sound/VNCSystemSound.swift b/Sources/RoyalVNCKit/Sound/VNCSystemSound.swift
index 7e47b63b..d5311be2 100644
--- a/Sources/RoyalVNCKit/Sound/VNCSystemSound.swift
+++ b/Sources/RoyalVNCKit/Sound/VNCSystemSound.swift
@@ -1,4 +1,8 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
import Foundation
+#endif
#if os(iOS)
import AVFoundation
diff --git a/Sources/RoyalVNCKitC/RoyalVNCKitC.c b/Sources/RoyalVNCKitC/RoyalVNCKitC.c
new file mode 100644
index 00000000..5ac359ac
--- /dev/null
+++ b/Sources/RoyalVNCKitC/RoyalVNCKitC.c
@@ -0,0 +1,6 @@
+#ifndef RoyalVNCKitC_h
+#define RoyalVNCKitC_h
+
+#include "RoyalVNCKitC.h"
+
+#endif /* RoyalVNCKitC_h */
diff --git a/Sources/RoyalVNCKitC/include/RoyalVNCKitC.h b/Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
new file mode 100644
index 00000000..46ae006d
--- /dev/null
+++ b/Sources/RoyalVNCKitC/include/RoyalVNCKitC.h
@@ -0,0 +1,222 @@
+#include
+#include
+#include
+#include
+
+// NOTE: Memory management roughly follows Apple's CoreFoundation Ownership Policy: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-CJBEJBHH
+// If you create an object (by calling a method suffixed with either `_create` or `_copy`), you own it and must relinquish ownership when you have finished using it (by calling a matching method suffixed with `_destroy` or `free` in case of C strings).
+// If you get an object from somewhere else, you do not own it. You must not store a reference to such objects since they might be destroyed right after the function call that they're passed into finishes.
+
+
+#pragma mark - Enums
+
+typedef enum {
+ RVNC_LOG_LEVEL_DEBUG = 0,
+ RVNC_LOG_LEVEL_INFO = 1,
+ RVNC_LOG_LEVEL_WARNING = 2,
+ RVNC_LOG_LEVEL_ERROR = 3
+} RVNC_LOG_LEVEL;
+
+typedef enum {
+ RVNC_CONNECTION_STATUS_DISCONNECTED = 0,
+ RVNC_CONNECTION_STATUS_CONNECTING = 1,
+ RVNC_CONNECTION_STATUS_CONNECTED = 2,
+ RVNC_CONNECTION_STATUS_DISCONNECTING = 3
+} RVNC_CONNECTION_STATUS;
+
+typedef enum {
+ RVNC_INPUTMODE_NONE = 0,
+ RVNC_INPUTMODE_FORWARDKEYBOARDSHORTCUTSIFNOTINUSELOCALLY = 1,
+ RVNC_INPUTMODE_FORWARDKEYBOARDSHORTCUTSEVENIFINUSELOCALLY = 2,
+ RVNC_INPUTMODE_FORWARDALLKEYBOARDSHORTCUTSANDHOTKEYS = 3
+} RVNC_INPUTMODE;
+
+typedef enum {
+ RVNC_COLORDEPTH_8BIT = 8, // 256 Colors
+ RVNC_COLORDEPTH_16BIT = 16,
+ RVNC_COLORDEPTH_24BIT = 24
+} RVNC_COLORDEPTH;
+
+typedef enum {
+ RVNC_AUTHENTICATIONTYPE_VNC = 0,
+ RVNC_AUTHENTICATIONTYPE_APPLEREMOTEDESKTOP = 1,
+ RVNC_AUTHENTICATIONTYPE_ULTRAVNCMSLOGONII = 2
+} RVNC_AUTHENTICATIONTYPE;
+
+typedef enum {
+ RVNC_MOUSEBUTTON_LEFT = 0,
+ RVNC_MOUSEBUTTON_MIDDLE = 1,
+ RVNC_MOUSEBUTTON_RIGHT = 2
+} RVNC_MOUSEBUTTON;
+
+typedef enum {
+ RVNC_MOUSEWHEEL_LEFT = 0,
+ RVNC_MOUSEWHEEL_RIGHT = 1,
+ RVNC_MOUSEWHEEL_UP = 2,
+ RVNC_MOUSEWHEEL_DOWN = 3
+} RVNC_MOUSEWHEEL;
+
+
+#pragma mark - Types
+
+typedef void* rvnc_context_t;
+typedef void* rvnc_logger_t;
+typedef void* rvnc_logger_delegate_t;
+typedef void* rvnc_authentication_request_t;
+typedef void* rvnc_settings_t;
+typedef void* rvnc_connection_state_t;
+typedef void* rvnc_framebuffer_t;
+typedef void* rvnc_connection_t;
+typedef void* rvnc_connection_delegate_t;
+typedef void* rvnc_cursor_t;
+
+
+#pragma mark - Logger
+
+typedef void (*rvnc_logger_delegate_log)(rvnc_logger_t _Nonnull /* logger */,
+ const rvnc_context_t _Nullable /* context */,
+ RVNC_LOG_LEVEL /* logLevel */,
+ const char* _Nonnull /* message */);
+
+extern rvnc_logger_t _Nonnull rvnc_logger_create(rvnc_logger_delegate_log _Nonnull log,
+ rvnc_context_t _Nullable context);
+extern void rvnc_logger_destroy(rvnc_logger_t _Nonnull logger);
+
+
+#pragma mark - Authentication Type
+
+extern bool rvnc_authentication_type_requires_username(RVNC_AUTHENTICATIONTYPE authenticationType);
+extern bool rvnc_authentication_type_requires_password(RVNC_AUTHENTICATIONTYPE authenticationType);
+
+
+#pragma mark - Authentication Request
+
+extern RVNC_AUTHENTICATIONTYPE rvnc_authentication_request_authentication_type_get(rvnc_authentication_request_t _Nonnull authenticationRequest);
+
+extern void rvnc_authentication_request_cancel(rvnc_authentication_request_t _Nonnull authenticationRequest);
+
+extern void rvnc_authentication_request_complete_with_username_password(rvnc_authentication_request_t _Nonnull authenticationRequest,
+ const char* _Nonnull username,
+ const char* _Nonnull password);
+
+extern void rvnc_authentication_request_complete_with_password(rvnc_authentication_request_t _Nonnull authenticationRequest,
+ const char* _Nonnull password);
+
+
+#pragma mark - Settings
+
+extern rvnc_settings_t _Nonnull rvnc_settings_create(bool isDebugLoggingEnabled,
+ const char* _Nonnull hostname,
+ uint16_t port,
+ bool isShared,
+ bool isScalingEnabled,
+ bool useDisplayLink,
+ RVNC_INPUTMODE inputMode,
+ bool isClipboardRedirectionEnabled,
+ RVNC_COLORDEPTH colorDepth);
+
+extern void rvnc_settings_destroy(rvnc_settings_t _Nonnull settings);
+
+
+#pragma mark - Connection State
+
+extern void rvnc_connection_state_destroy(rvnc_connection_state_t _Nonnull connectionState);
+
+extern RVNC_CONNECTION_STATUS rvnc_connection_state_status_get(rvnc_connection_state_t _Nonnull connectionState);
+extern char* _Nullable rvnc_connection_state_error_description_get_copy(rvnc_connection_state_t _Nonnull connectionState);
+extern bool rvnc_connection_state_error_should_display_to_user_get(rvnc_connection_state_t _Nonnull connectionState);
+extern bool rvnc_connection_state_error_is_authentication_error_get(rvnc_connection_state_t _Nonnull connectionState);
+
+
+#pragma mark - Framebuffer
+
+extern uint16_t rvnc_framebuffer_size_width_get(rvnc_framebuffer_t _Nonnull framebuffer);
+extern uint16_t rvnc_framebuffer_size_height_get(rvnc_framebuffer_t _Nonnull framebuffer);
+
+// NOTE: This always returns 32-bit BGRA data.
+extern void* _Nonnull rvnc_framebuffer_pixel_data_get(rvnc_framebuffer_t _Nonnull framebuffer);
+extern uint64_t rvnc_framebuffer_pixel_data_size_get(rvnc_framebuffer_t _Nonnull framebuffer);
+
+
+#pragma mark - Cursor
+
+extern bool rvnc_cursor_is_empty_get(rvnc_cursor_t _Nonnull cursor);
+extern uint16_t rvnc_cursor_size_width_get(rvnc_cursor_t _Nonnull cursor);
+extern uint16_t rvnc_cursor_size_height_get(rvnc_cursor_t _Nonnull cursor);
+extern uint16_t rvnc_cursor_hotspot_x_get(rvnc_cursor_t _Nonnull cursor);
+extern uint16_t rvnc_cursor_hotspot_y_get(rvnc_cursor_t _Nonnull cursor);
+extern int64_t rvnc_cursor_bits_per_component_get(rvnc_cursor_t _Nonnull cursor);
+extern int64_t rvnc_cursor_bits_per_pixel_get(rvnc_cursor_t _Nonnull cursor);
+extern int64_t rvnc_cursor_bytes_per_pixel_get(rvnc_cursor_t _Nonnull cursor);
+extern int64_t rvnc_cursor_bytes_per_row_get(rvnc_cursor_t _Nonnull cursor);
+extern void* _Nullable rvnc_cursor_pixel_data_get_copy(rvnc_cursor_t _Nonnull cursor);
+extern void rvnc_cursor_pixel_data_destroy(void* _Nonnull pixelData);
+extern uint64_t rvnc_cursor_pixel_data_size_get(rvnc_cursor_t _Nonnull cursor);
+
+
+#pragma mark - Connection Delegate
+
+typedef void (*rvnc_connection_delegate_connection_state_did_change)(rvnc_connection_t _Nonnull /* connection */,
+ const rvnc_context_t _Nullable /* context */,
+ _Nonnull rvnc_connection_state_t /* connectionState */);
+
+typedef void (*rvnc_connection_delegate_authenticate)(rvnc_connection_t _Nonnull /* connection */,
+ const rvnc_context_t _Nullable /* context */,
+ _Nonnull rvnc_authentication_request_t /* authenticationRequest */);
+
+typedef void (*rvnc_connection_delegate_did_create_framebuffer)(rvnc_connection_t _Nonnull /* connection */,
+ const rvnc_context_t _Nullable /* context */,
+ _Nonnull rvnc_framebuffer_t /* framebuffer */);
+
+typedef void (*rvnc_connection_delegate_did_resize_framebuffer)(rvnc_connection_t _Nonnull /* connection */,
+ const rvnc_context_t _Nullable /* context */,
+ _Nonnull rvnc_framebuffer_t /* framebuffer */);
+
+typedef void (*rvnc_connection_delegate_did_update_framebuffer)(rvnc_connection_t _Nonnull /* connection */,
+ const rvnc_context_t _Nullable /* context */,
+ _Nonnull rvnc_framebuffer_t /* framebuffer */,
+ uint16_t /* x */,
+ uint16_t /* y */,
+ uint16_t /* width */,
+ uint16_t /* height */);
+
+typedef void (*rvnc_connection_delegate_did_update_cursor)(rvnc_connection_t _Nonnull /* connection */,
+ const rvnc_context_t _Nullable /* context */,
+ rvnc_cursor_t _Nonnull /* cursor */);
+
+extern rvnc_connection_delegate_t _Nonnull rvnc_connection_delegate_create(rvnc_connection_delegate_connection_state_did_change _Nonnull connectionStateDidChange,
+ rvnc_connection_delegate_authenticate _Nonnull authenticate,
+ rvnc_connection_delegate_did_create_framebuffer _Nonnull didCreateFramebuffer,
+ rvnc_connection_delegate_did_resize_framebuffer _Nonnull didResizeFramebuffer,
+ rvnc_connection_delegate_did_update_framebuffer _Nonnull didUpdateFramebuffer,
+ rvnc_connection_delegate_did_update_cursor _Nonnull didUpdateCursor);
+
+extern void rvnc_connection_delegate_destroy(rvnc_connection_delegate_t _Nonnull connectionDelegate);
+
+
+#pragma mark - Connection
+
+extern rvnc_connection_t _Nonnull rvnc_connection_create(rvnc_settings_t _Nonnull settings,
+ rvnc_logger_t _Nullable logger,
+ rvnc_context_t _Nullable context);
+
+extern void rvnc_connection_destroy(rvnc_connection_t _Nonnull connection);
+
+extern void rvnc_connection_connect(rvnc_connection_t _Nonnull connection);
+extern void rvnc_connection_disconnect(rvnc_connection_t _Nonnull connection);
+
+extern void rvnc_connection_update_color_depth(rvnc_connection_t _Nonnull connection, RVNC_COLORDEPTH colorDepth);
+extern void rvnc_connection_delegate_set(rvnc_connection_t _Nonnull connection, rvnc_connection_delegate_t _Nullable connectionDelegate);
+
+extern rvnc_context_t _Nullable rvnc_connection_context_get(rvnc_connection_t _Nonnull connection);
+extern rvnc_connection_state_t _Nonnull rvnc_connection_state_get_copy(rvnc_connection_t _Nonnull connection);
+extern rvnc_settings_t _Nonnull rvnc_connection_settings_get_copy(rvnc_connection_t _Nonnull connection);
+
+extern void rvnc_connection_mouse_move(rvnc_connection_t _Nonnull connection, uint16_t x, uint16_t y);
+extern void rvnc_connection_mouse_down(rvnc_connection_t _Nonnull connection, RVNC_MOUSEBUTTON button, uint16_t x, uint16_t y);
+extern void rvnc_connection_mouse_up(rvnc_connection_t _Nonnull connection, RVNC_MOUSEBUTTON button, uint16_t x, uint16_t y);
+extern void rvnc_connection_mouse_wheel(rvnc_connection_t _Nonnull connection, RVNC_MOUSEWHEEL wheel, uint16_t x, uint16_t y, uint32_t steps);
+
+// NOTE: key is an X11 keysym (eg. `XK_A` for the latin capital letter "A"). See the `X11KeySymbols` struct.
+extern void rvnc_connection_key_down(rvnc_connection_t _Nonnull connection, uint32_t key);
+extern void rvnc_connection_key_up(rvnc_connection_t _Nonnull connection, uint32_t key);
diff --git a/Sources/RoyalVNCKitCDemo/main.c b/Sources/RoyalVNCKitCDemo/main.c
new file mode 100644
index 00000000..4bb03005
--- /dev/null
+++ b/Sources/RoyalVNCKitCDemo/main.c
@@ -0,0 +1,408 @@
+#include
+#include
+#include
+
+#ifndef _WIN32
+#include
+#else // _WIN32
+#include
+
+// resolve:
+// Sources\RoyalVNCKitCDemo\main.c:301:9: error: call to undeclared function 'usleep'; ISO C99 and later do not support implicit function declarations
+// Sources\RoyalVNCKitCDemo\main.c:301:9: note: did you mean '_sleep'?
+// note: convert from microseconds to milliseconds and call the builtin `_sleep` function
+#define usleep(us) _sleep((us)/1000)
+#endif // _WIN32
+
+#include
+
+#pragma mark - Context
+
+typedef struct Context {
+ rvnc_connection_t connection;
+} Context;
+
+
+#pragma mark - Helpers
+
+char* readLine(void) {
+ int maxLength = sizeof(char) * 4096;
+ char* str = malloc(maxLength);
+
+ if (fgets(str, maxLength, stdin)) {
+ size_t len = strlen(str);
+
+ if (len > 0 &&
+ str[len - 1] == '\n') {
+ str[--len] = '\0';
+ }
+ }
+
+ return str;
+}
+
+char* readPassword(const char* prompt) {
+#ifndef _WIN32
+ char* password = getpass(prompt);
+
+ if (!password) {
+ return NULL;
+ }
+
+ size_t len = strlen(password);
+ char* result = malloc(len + 1);
+
+ if (!result) {
+ return NULL;
+ }
+
+ strcpy(result, password);
+
+ return result;
+#else
+ int len = 4096;
+ char* buf = malloc(sizeof(char) * len);
+
+ /* Resources that will be cleaned up */
+ int pwlen = 0;
+ DWORD orig = 0;
+ WCHAR *wbuf = 0;
+ SIZE_T wbuf_len = 0;
+ HANDLE hi, ho = INVALID_HANDLE_VALUE;
+
+ /* Set up input console handle */
+ DWORD access = GENERIC_READ | GENERIC_WRITE;
+ hi = CreateFileA("CONIN$", access, 0, 0, OPEN_EXISTING, 0, 0);
+ if (!GetConsoleMode(hi, &orig)) goto done;
+ DWORD mode = orig;
+ mode |= ENABLE_PROCESSED_INPUT;
+ mode |= ENABLE_LINE_INPUT;
+ mode &= ~ENABLE_ECHO_INPUT;
+ if (!SetConsoleMode(hi, mode)) goto done;
+
+ /* Set up output console handle */
+ ho = CreateFileA("CONOUT$", GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
+ if (!WriteConsoleA(ho, prompt, strlen(prompt), 0, 0)) goto done;
+
+ /* Allocate a wide character buffer the size of the output */
+ wbuf_len = (len - 1 + 2) * sizeof(WCHAR);
+ wbuf = HeapAlloc(GetProcessHeap(), 0, wbuf_len);
+ if (!wbuf) goto done;
+
+ /* Read and convert to UTF-8 */
+ DWORD nread;
+ if (!ReadConsoleW(hi, wbuf, len - 1 + 2, &nread, 0)) goto done;
+ if (nread < 2) goto done;
+ if (wbuf[nread-2] != '\r' || wbuf[nread-1] != '\n') goto done;
+ wbuf[nread-2] = 0; // truncate "\r\n"
+ pwlen = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, len, 0, 0);
+
+done:
+ if (wbuf) {
+ SecureZeroMemory(wbuf, wbuf_len);
+ HeapFree(GetProcessHeap(), 0, wbuf);
+ }
+ /* Exploit that operations on INVALID_HANDLE_VALUE are no-ops */
+ WriteConsoleA(ho, "\n", 1, 0, 0);
+ SetConsoleMode(hi, orig);
+ CloseHandle(ho);
+ CloseHandle(hi);
+
+ return buf;
+#endif
+}
+
+char* connectionStatusToString(RVNC_CONNECTION_STATUS connectionStatus) {
+ switch (connectionStatus) {
+ case RVNC_CONNECTION_STATUS_DISCONNECTED:
+ return "Disconnected";
+ case RVNC_CONNECTION_STATUS_CONNECTING:
+ return "Connecting";
+ case RVNC_CONNECTION_STATUS_CONNECTED:
+ return "Connected";
+ case RVNC_CONNECTION_STATUS_DISCONNECTING:
+ return "Disconnecting";
+ }
+}
+
+char* authenticationTypeToString(RVNC_AUTHENTICATIONTYPE authenticationType) {
+ switch (authenticationType) {
+ case RVNC_AUTHENTICATIONTYPE_VNC:
+ return "VNC";
+ case RVNC_AUTHENTICATIONTYPE_APPLEREMOTEDESKTOP:
+ return "Apple Remote Desktop";
+ case RVNC_AUTHENTICATIONTYPE_ULTRAVNCMSLOGONII:
+ return "Ultra VNC MS Logon II";
+ }
+}
+
+char* logLevelToString(RVNC_LOG_LEVEL logLevel) {
+ switch (logLevel) {
+ case RVNC_LOG_LEVEL_DEBUG:
+ return "Debug";
+ case RVNC_LOG_LEVEL_INFO:
+ return "Info";
+ case RVNC_LOG_LEVEL_WARNING:
+ return "Warning";
+ case RVNC_LOG_LEVEL_ERROR:
+ return "Error";
+ }
+}
+
+
+#pragma mark - Logger Delegate implementation
+
+void loggerDelegate_log(rvnc_logger_t logger,
+ const rvnc_context_t context,
+ RVNC_LOG_LEVEL logLevel,
+ const char* message) {
+ char* logLevelStr = logLevelToString(logLevel);
+
+ printf("[%s] %s\n",
+ logLevelStr,
+ message);
+}
+
+
+#pragma mark - Connection Delegate implementation
+
+void delegate_connectionStateDidChange(rvnc_connection_t connection,
+ const rvnc_context_t context,
+ rvnc_connection_state_t connectionState) {
+ RVNC_CONNECTION_STATUS status = rvnc_connection_state_status_get(connectionState);
+ const char* statusStr = connectionStatusToString(status);
+
+ char* errorDescription = rvnc_connection_state_error_description_get_copy(connectionState);
+ char* errorDescriptionForLog;
+
+ if (errorDescription) {
+ errorDescriptionForLog = errorDescription;
+ } else {
+ errorDescriptionForLog = "N/A";
+ }
+
+ bool shouldDisplayErrorToUser = rvnc_connection_state_error_should_display_to_user_get(connectionState);
+ bool isAuthenticationError = rvnc_connection_state_error_is_authentication_error_get(connectionState);
+
+ if (shouldDisplayErrorToUser) {
+ printf("delegate_connectionStateDidChange - Status: %s; Error Description: %s; Is Authentication Error: %s\n",
+ statusStr,
+ errorDescriptionForLog,
+ isAuthenticationError ? "Yes" : "No");
+ } else {
+ printf("delegate_connectionStateDidChange - Status: %s\n",
+ statusStr);
+ }
+
+ if (errorDescription) {
+ free(errorDescription);
+ }
+}
+
+void delegate_authenticate(rvnc_connection_t connection,
+ const rvnc_context_t context,
+ rvnc_authentication_request_t authenticationRequest) {
+ RVNC_AUTHENTICATIONTYPE authenticationType = rvnc_authentication_request_authentication_type_get(authenticationRequest);
+ char* authenticationTypeStr = authenticationTypeToString(authenticationType);
+
+ printf("delegate_authenticate - Authentication type: %s\n",
+ authenticationTypeStr);
+
+ bool requiresUsername = rvnc_authentication_type_requires_username(authenticationType);
+ bool requiresPassword = rvnc_authentication_type_requires_password(authenticationType);
+
+ if (requiresUsername) {
+ printf("Enter username: ");
+ char* username = readLine();
+ char* password = readPassword("Enter password: ");
+
+ if (username &&
+ password) {
+ rvnc_authentication_request_complete_with_username_password(authenticationRequest,
+ username,
+ password);
+ } else {
+ rvnc_authentication_request_cancel(authenticationRequest);
+ }
+
+ if (username) {
+ free(username);
+ }
+
+ if (password) {
+ free(password);
+ }
+ } else if (requiresPassword) {
+ char* password = readPassword("Enter password: ");
+
+ if (password) {
+ rvnc_authentication_request_complete_with_password(authenticationRequest,
+ password);
+
+ free(password);
+ } else {
+ rvnc_authentication_request_cancel(authenticationRequest);
+ }
+ } else { // Should never happen because authenticate is only called if a credential is actually required. So either requiresUsername or requiresPassword or both must be true.
+ rvnc_authentication_request_cancel(authenticationRequest);
+ }
+}
+
+void delegate_didCreateFramebuffer(rvnc_connection_t connection,
+ const rvnc_context_t context,
+ rvnc_framebuffer_t framebuffer) {
+ printf("delegate_didCreateFramebuffer - Framebuffer Size: %ix%i; Pixel Data Size %" PRIu64 "; Pixel Data Pointer: %p\n",
+ rvnc_framebuffer_size_width_get(framebuffer),
+ rvnc_framebuffer_size_height_get(framebuffer),
+ rvnc_framebuffer_pixel_data_size_get(framebuffer),
+ rvnc_framebuffer_pixel_data_get(framebuffer));
+}
+
+void delegate_didResizeFramebuffer(rvnc_connection_t connection,
+ const rvnc_context_t context,
+ rvnc_framebuffer_t framebuffer) {
+ printf("delegate_didResizeFramebuffer - Framebuffer Size: %ix%i; Pixel Data Size %" PRIu64 "; Pixel Data Pointer: %p\n",
+ rvnc_framebuffer_size_width_get(framebuffer),
+ rvnc_framebuffer_size_height_get(framebuffer),
+ rvnc_framebuffer_pixel_data_size_get(framebuffer),
+ rvnc_framebuffer_pixel_data_get(framebuffer));
+}
+
+void delegate_didUpdateFramebuffer(rvnc_connection_t connection,
+ const rvnc_context_t context,
+ rvnc_framebuffer_t framebuffer,
+ uint16_t x,
+ uint16_t y,
+ uint16_t width,
+ uint16_t height) {
+ printf("delegate_didUpdateFramebuffer - x: %i; y: %i; width: %i; height: %i\n",
+ x,
+ y,
+ width,
+ height);
+}
+
+void delegate_didUpdateCursor(rvnc_connection_t connection,
+ const rvnc_context_t context,
+ rvnc_cursor_t cursor) {
+ bool isEmpty = rvnc_cursor_is_empty_get(cursor);
+ uint16_t width = rvnc_cursor_size_width_get(cursor);
+ uint16_t height = rvnc_cursor_size_height_get(cursor);
+ uint16_t hotspotX = rvnc_cursor_hotspot_x_get(cursor);
+ uint16_t hotspotY = rvnc_cursor_hotspot_y_get(cursor);
+ int64_t bitsPerComponent = rvnc_cursor_bits_per_component_get(cursor);
+ int64_t bitsPerPixel = rvnc_cursor_bits_per_pixel_get(cursor);
+ int64_t bytesPerPixel = rvnc_cursor_bytes_per_pixel_get(cursor);
+ int64_t bytesPerRow = rvnc_cursor_bytes_per_row_get(cursor);
+ void* pixelData = rvnc_cursor_pixel_data_get_copy(cursor);
+ uint64_t pixelDataSize = rvnc_cursor_pixel_data_size_get(cursor);
+
+ printf("delegate_didUpdateCursor - isEmpty: %s; width: %i; height: %i; hotspotX: %i; hotspotY: %i; bitsPerComponent: %" PRId64 "; bitsPerPixel: %" PRId64 "; bytesPerPixel: %" PRId64 "; bytesPerRow: %" PRId64 "; pixelData: %p; pixelDataSize: %" PRIu64 "\n",
+ isEmpty ? "Yes" : "No",
+ width,
+ height,
+ hotspotX,
+ hotspotY,
+ bitsPerComponent,
+ bitsPerPixel,
+ bytesPerPixel,
+ bytesPerRow,
+ pixelData,
+ pixelDataSize);
+
+ if (pixelData) {
+ rvnc_cursor_pixel_data_destroy(pixelData);
+ }
+}
+
+
+#pragma mark - Main
+
+int main(int argc, char *argv[]) {
+ // Get hostname either from args or stdin
+ const char* hostname;
+
+ if (argc >= 2) {
+ hostname = argv[1];
+ } else {
+ printf("Enter hostname: ");
+
+ hostname = readLine();
+ }
+
+ if (strlen(hostname) <= 0) {
+ printf("No hostname given\n");
+
+ exit(1);
+ }
+
+ // Declare settings
+ const uint16_t port = 5900;
+ const bool isShared = true;
+ const bool isScalingEnabled = false;
+ const bool useDisplayLink = false;
+ const RVNC_INPUTMODE inputMode = RVNC_INPUTMODE_NONE;
+ const bool isClipboardRedirectionEnabled = false;
+ const RVNC_COLORDEPTH colorDepth = RVNC_COLORDEPTH_24BIT;
+ const bool enableDebugLogging = true;
+
+ // Create context
+ Context* context = malloc(sizeof(Context));
+
+ // Create logger
+ rvnc_logger_t logger = rvnc_logger_create(loggerDelegate_log,
+ context);
+
+ // Create settings
+ rvnc_settings_t settings = rvnc_settings_create(enableDebugLogging,
+ hostname,
+ port,
+ isShared,
+ isScalingEnabled,
+ useDisplayLink,
+ inputMode,
+ isClipboardRedirectionEnabled,
+ colorDepth);
+
+ // Create connection
+ rvnc_connection_t connection = rvnc_connection_create(settings,
+ logger,
+ context);
+
+ // Create connection delegate
+ rvnc_connection_delegate_t connectionDelegate = rvnc_connection_delegate_create(delegate_connectionStateDidChange,
+ delegate_authenticate,
+ delegate_didCreateFramebuffer,
+ delegate_didResizeFramebuffer,
+ delegate_didUpdateFramebuffer,
+ delegate_didUpdateCursor);
+
+ // Set connection delegate in connection
+ rvnc_connection_delegate_set(connection, connectionDelegate);
+
+ // Connect
+ rvnc_connection_connect(connection);
+
+ // Run loop until connection is disconnected
+ while (true) {
+ rvnc_connection_state_t connectionState = rvnc_connection_state_get_copy(connection);
+ RVNC_CONNECTION_STATUS connectionStatus = rvnc_connection_state_status_get(connectionState);
+
+ rvnc_connection_state_destroy(connectionState);
+
+ if (connectionStatus == RVNC_CONNECTION_STATUS_DISCONNECTED) {
+ break;
+ }
+
+ usleep(0.5 * 1000000.0);
+ }
+
+ // Clean up
+ rvnc_connection_destroy(connection);
+ rvnc_connection_delegate_destroy(connectionDelegate);
+ rvnc_settings_destroy(settings);
+ rvnc_logger_destroy(logger);
+ free(context);
+
+ return EXIT_SUCCESS;
+}
diff --git a/Sources/RoyalVNCKitDemo/ConnectionDelegate.swift b/Sources/RoyalVNCKitDemo/ConnectionDelegate.swift
new file mode 100644
index 00000000..81838523
--- /dev/null
+++ b/Sources/RoyalVNCKitDemo/ConnectionDelegate.swift
@@ -0,0 +1,107 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+import RoyalVNCKit
+
+final class ConnectionDelegate: VNCConnectionDelegate {
+ func connection(_ connection: VNCConnection,
+ stateDidChange connectionState: VNCConnection.ConnectionState) {
+ let connectionStateString: String
+
+ switch connectionState.status {
+ case .connecting:
+ connectionStateString = "Connecting"
+ case .connected:
+ connectionStateString = "Connected"
+ case .disconnecting:
+ connectionStateString = "Disconnecting"
+ case .disconnected:
+ connectionStateString = "Disconnected"
+ }
+
+ connection.logger.logDebug("connection stateDidChange: \(connectionStateString)")
+ }
+
+ func connection(_ connection: VNCConnection,
+ credentialFor authenticationType: VNCAuthenticationType,
+ completion: @escaping ((any VNCCredential)?) -> Void) {
+ let authenticationTypeString: String
+
+ switch authenticationType {
+ case .vnc:
+ authenticationTypeString = "VNC"
+ case .appleRemoteDesktop:
+ authenticationTypeString = "Apple Remote Desktop"
+ case .ultraVNCMSLogonII:
+ authenticationTypeString = "UltraVNC MS Logon II"
+ }
+
+ connection.logger.logDebug("connection credentialFor: \(authenticationTypeString)")
+
+ func readUser() -> String? {
+ print("Enter username: ", terminator: "")
+ let username = readLine(strippingNewline: true)
+
+ return username
+ }
+
+ func readPW() -> String? {
+ let password = readPassword(prompt: "Enter password: ")
+
+ return password
+ }
+
+ if authenticationType.requiresUsername,
+ authenticationType.requiresPassword {
+ guard let username = readUser() else {
+ completion(nil)
+
+ return
+ }
+
+ guard let password = readPW() else {
+ completion(nil)
+
+ return
+ }
+
+ completion(VNCUsernamePasswordCredential(username: username,
+ password: password))
+ } else if authenticationType.requiresPassword {
+ guard let password = readPW() else {
+ completion(nil)
+
+ return
+ }
+
+ completion(VNCPasswordCredential(password: password))
+ } else {
+ completion(nil)
+ }
+ }
+
+ func connection(_ connection: VNCConnection,
+ didCreateFramebuffer framebuffer: VNCFramebuffer) {
+ connection.logger.logDebug("connection didCreateFramebuffer")
+ }
+
+ func connection(_ connection: VNCConnection,
+ didResizeFramebuffer framebuffer: VNCFramebuffer) {
+ connection.logger.logDebug("connection didResizeFramebuffer")
+ }
+
+ func connection(_ connection: VNCConnection,
+ didUpdateFramebuffer framebuffer: VNCFramebuffer,
+ x: UInt16, y: UInt16,
+ width: UInt16, height: UInt16) {
+ connection.logger.logDebug("connection didUpdateFramebuffer")
+ }
+
+ func connection(_ connection: VNCConnection,
+ didUpdateCursor cursor: VNCCursor) {
+ connection.logger.logDebug("connection didUpdateCursor")
+ }
+}
diff --git a/Sources/RoyalVNCKitDemo/PlatformUtils.swift b/Sources/RoyalVNCKitDemo/PlatformUtils.swift
new file mode 100644
index 00000000..51fa7d30
--- /dev/null
+++ b/Sources/RoyalVNCKitDemo/PlatformUtils.swift
@@ -0,0 +1,143 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+#if canImport(Darwin)
+import Darwin
+#elseif canImport(Glibc)
+import Glibc
+#elseif canImport(WinSDK)
+import WinSDK
+#endif
+
+func platformSleep(forTimeInterval timeInterval: TimeInterval) {
+#if canImport(WinSDK)
+ let timeIntervalMS = UInt32(timeInterval * 1000.0)
+
+ Sleep(timeIntervalMS)
+#elseif canImport(Glibc)
+ let timeIntervalMicroseconds = UInt32(timeInterval * 1000000.0)
+
+ usleep(timeIntervalMicroseconds)
+#else
+ Thread.sleep(forTimeInterval: timeInterval)
+#endif
+}
+
+func readPassword(prompt: String) -> String? {
+#if canImport(Darwin)
+ var buffer = [CChar](repeating: 0,
+ count: 4096)
+
+ guard let passwordC = readpassphrase(prompt,
+ &buffer,
+ buffer.count,
+ 0) else {
+ return nil
+ }
+
+ let password = String(cString: passwordC)
+
+ return password
+#elseif canImport(Glibc)
+ guard let passwordC = getpass(prompt) else {
+ return nil
+ }
+
+ let password = String(cString: passwordC)
+
+ return password
+#else
+ let len = 4096
+
+ /* Resources that will be cleaned up */
+ var orig: DWORD = 0
+ var wbuf: UnsafeMutableRawPointer?
+ var wbuf_len: SIZE_T = 0
+ var hi = INVALID_HANDLE_VALUE
+ var ho = INVALID_HANDLE_VALUE
+
+ defer {
+ if let wbuf {
+ RtlSecureZeroMemory(wbuf, .init(wbuf_len))
+ HeapFree(GetProcessHeap(), 0, wbuf)
+ }
+
+ /* Exploit that operations on INVALID_HANDLE_VALUE are no-ops */
+ WriteConsoleA(ho, "\n", 1, nil, nil)
+ SetConsoleMode(hi, orig)
+ CloseHandle(ho)
+ CloseHandle(hi)
+ }
+
+ /* Set up input console handle */
+ let access = DWORD(GENERIC_READ) | DWORD(GENERIC_WRITE)
+ hi = CreateFileA("CONIN$", access, 0, nil, .init(OPEN_EXISTING), 0, nil)
+
+ guard GetConsoleMode(hi, &orig) else {
+ return nil
+ }
+
+ var mode = orig
+ mode |= .init(ENABLE_PROCESSED_INPUT)
+ mode |= .init(ENABLE_LINE_INPUT)
+ mode &= ~(.init(ENABLE_ECHO_INPUT))
+
+ guard SetConsoleMode(hi, mode) else {
+ return nil
+ }
+
+ /* Set up output console handle */
+ ho = CreateFileA("CONOUT$", .init(GENERIC_WRITE), 0, nil, .init(OPEN_EXISTING), 0, nil)
+
+ guard WriteConsoleA(ho, prompt, .init(strlen(prompt)), nil, nil) else {
+ return nil
+ }
+
+ /* Allocate a wide character buffer the size of the output */
+ wbuf_len = (SIZE_T(len) - 1 + 2) * SIZE_T(MemoryLayout.stride)
+ wbuf = HeapAlloc(GetProcessHeap(), 0, wbuf_len)
+
+ guard let wbuf else {
+ return nil
+ }
+
+ /* Read and convert to UTF-8 */
+ var nread: DWORD = 0
+
+ guard ReadConsoleW(hi, wbuf, DWORD(len) - 1 + 2, &nread, nil) else {
+ return nil
+ }
+
+ guard nread >= 2 else {
+ return nil
+ }
+
+ // TODO: Do this to the passwordBuf string
+ let wbufAsWchar = UnsafeMutablePointer(OpaquePointer(wbuf))
+
+ if wbufAsWchar[Int(nread)-2] != UInt16("\r".utf16.first!) ||
+ wbufAsWchar[Int(nread)-1] != UInt16("\n".utf16.first!) {
+ return nil
+ }
+
+ wbufAsWchar[Int(nread)-2] = 0 // truncate "\r\n"
+
+ guard let buf = malloc(MemoryLayout.stride * len) else {
+ return nil
+ }
+
+ defer {
+ free(buf)
+ }
+
+ WideCharToMultiByte(.init(CP_UTF8), 0, .init(OpaquePointer(wbuf)), -1, buf, .init(len), nil, nil);
+
+ let bufAsCCharPtr = UnsafeMutablePointer(OpaquePointer(buf))
+ let passwordBuf = String(cString: bufAsCCharPtr)
+
+ return passwordBuf
+#endif
+}
diff --git a/Sources/RoyalVNCKitDemo/main.swift b/Sources/RoyalVNCKitDemo/main.swift
new file mode 100644
index 00000000..bf507cdb
--- /dev/null
+++ b/Sources/RoyalVNCKitDemo/main.swift
@@ -0,0 +1,71 @@
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+#if canImport(Darwin)
+import Darwin
+#elseif canImport(Glibc)
+import Glibc
+#elseif canImport(WinSDK)
+import WinSDK
+#endif
+
+import RoyalVNCKit
+
+// Get hostname either from args or stdin
+let args = CommandLine.arguments
+let hostname: String
+
+if args.count >= 2 {
+ hostname = args[1]
+} else {
+ print("Enter hostname: ", terminator: "")
+ hostname = readLine(strippingNewline: true) ?? ""
+}
+
+guard !hostname.isEmpty else {
+ print("No hostname given")
+
+ exit(1)
+}
+
+// Create logger
+let logger = VNCPrintLogger()
+
+// Create settings
+let settings = VNCConnection.Settings(isDebugLoggingEnabled: true,
+ hostname: hostname,
+ port: 5900,
+ isShared: true,
+ isScalingEnabled: true,
+ useDisplayLink: false,
+ inputMode: .none,
+ isClipboardRedirectionEnabled: false,
+ colorDepth: .depth24Bit,
+ frameEncodings: .default)
+
+// Create connection
+let connection = VNCConnection(settings: settings,
+ logger: logger)
+
+// Create connection delegate
+let connectionDelegate = ConnectionDelegate()
+
+// Set connection delegate in connection
+connection.delegate = connectionDelegate
+
+// Connect
+connection.connect()
+
+// Run loop until connection is disconnected
+while true {
+ let connectionStatus = connection.connectionState.status
+
+ if connectionStatus == .disconnected {
+ break
+ }
+
+ platformSleep(forTimeInterval: 0.5)
+}
diff --git a/Sources/Z/ZDummy.c b/Sources/Z/ZDummy.c
new file mode 100644
index 00000000..9f4943b9
--- /dev/null
+++ b/Sources/Z/ZDummy.c
@@ -0,0 +1 @@
+#include "ZIncludes.h"
diff --git a/Sources/Z/include/ZIncludes.h b/Sources/Z/include/ZIncludes.h
new file mode 100644
index 00000000..4470a1fd
--- /dev/null
+++ b/Sources/Z/include/ZIncludes.h
@@ -0,0 +1 @@
+#include
diff --git a/Sources/libtomcrypt/ciphers/aes/aes.c b/Sources/libtomcrypt/ciphers/aes/aes.c
new file mode 100644
index 00000000..3a5d0dbb
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/aes/aes.c
@@ -0,0 +1,730 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* AES implementation by Tom St Denis
+ *
+ * Derived from the Public Domain source code by
+
+---
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen
+ * @author Antoon Bosselaers
+ * @author Paulo Barreto
+---
+ */
+/**
+ @file aes.c
+ Implementation of AES
+*/
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RIJNDAEL
+
+#ifndef ENCRYPT_ONLY
+
+#define SETUP rijndael_setup
+#define ECB_ENC rijndael_ecb_encrypt
+#define ECB_DEC rijndael_ecb_decrypt
+#define ECB_DONE rijndael_done
+#define ECB_TEST rijndael_test
+#define ECB_KS rijndael_keysize
+
+const struct ltc_cipher_descriptor rijndael_desc =
+{
+ "rijndael",
+ 6,
+ 16, 32, 16, 10,
+ SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#else
+
+#define SETUP rijndael_enc_setup
+#define ECB_ENC rijndael_enc_ecb_encrypt
+#define ECB_KS rijndael_enc_keysize
+#define ECB_DONE rijndael_enc_done
+
+const struct ltc_cipher_descriptor rijndael_enc_desc =
+{
+ "rijndael",
+ 6,
+ 16, 32, 16, 10,
+ SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#endif
+
+#define LTC_AES_TAB_C
+#include "aes_tab.c"
+
+static ulong32 setup_mix(ulong32 temp)
+{
+ return (Te4_3[LTC_BYTE(temp, 2)]) ^
+ (Te4_2[LTC_BYTE(temp, 1)]) ^
+ (Te4_1[LTC_BYTE(temp, 0)]) ^
+ (Te4_0[LTC_BYTE(temp, 3)]);
+}
+
+#ifndef ENCRYPT_ONLY
+#ifdef LTC_SMALL_CODE
+static ulong32 setup_mix2(ulong32 temp)
+{
+ return Td0(255 & Te4[LTC_BYTE(temp, 3)]) ^
+ Td1(255 & Te4[LTC_BYTE(temp, 2)]) ^
+ Td2(255 & Te4[LTC_BYTE(temp, 1)]) ^
+ Td3(255 & Te4[LTC_BYTE(temp, 0)]);
+}
+#endif
+#endif
+
+ /**
+ Initialize the AES (Rijndael) block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int i;
+ ulong32 temp, *rk, *K;
+#ifndef ENCRYPT_ONLY
+ ulong32 *rrk;
+#endif
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (keylen != 16 && keylen != 24 && keylen != 32) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
+ K = LTC_ALIGN_BUF(skey->rijndael.K, 16);
+ skey->rijndael.eK = K;
+ K += 60;
+ skey->rijndael.dK = K;
+
+ /* setup the forward key */
+ i = 0;
+ rk = skey->rijndael.eK;
+ LOAD32H(rk[0], key );
+ LOAD32H(rk[1], key + 4);
+ LOAD32H(rk[2], key + 8);
+ LOAD32H(rk[3], key + 12);
+ if (keylen == 16) {
+ for (;;) {
+ temp = rk[3];
+ rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10) {
+ break;
+ }
+ rk += 4;
+ }
+ } else if (keylen == 24) {
+ LOAD32H(rk[4], key + 16);
+ LOAD32H(rk[5], key + 20);
+ for (;;) {
+ #ifdef _MSC_VER
+ temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5];
+ #else
+ temp = rk[5];
+ #endif
+ rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8) {
+ break;
+ }
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ } else if (keylen == 32) {
+ LOAD32H(rk[4], key + 16);
+ LOAD32H(rk[5], key + 20);
+ LOAD32H(rk[6], key + 24);
+ LOAD32H(rk[7], key + 28);
+ for (;;) {
+ #ifdef _MSC_VER
+ temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7];
+ #else
+ temp = rk[7];
+ #endif
+ rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7) {
+ break;
+ }
+ temp = rk[11];
+ rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8));
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+ rk += 8;
+ }
+ } else {
+ /* this can't happen */
+ /* coverity[dead_error_line] */
+ return CRYPT_ERROR;
+ }
+
+#ifndef ENCRYPT_ONLY
+ /* setup the inverse key now */
+ rk = skey->rijndael.dK;
+ rrk = skey->rijndael.eK + (28 + keylen) - 4;
+
+ /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+ /* copy first */
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk = *rrk;
+ rk -= 3; rrk -= 3;
+
+ for (i = 1; i < skey->rijndael.Nr; i++) {
+ rrk -= 4;
+ rk += 4;
+ #ifdef LTC_SMALL_CODE
+ temp = rrk[0];
+ rk[0] = setup_mix2(temp);
+ temp = rrk[1];
+ rk[1] = setup_mix2(temp);
+ temp = rrk[2];
+ rk[2] = setup_mix2(temp);
+ temp = rrk[3];
+ rk[3] = setup_mix2(temp);
+ #else
+ temp = rrk[0];
+ rk[0] =
+ Tks0[LTC_BYTE(temp, 3)] ^
+ Tks1[LTC_BYTE(temp, 2)] ^
+ Tks2[LTC_BYTE(temp, 1)] ^
+ Tks3[LTC_BYTE(temp, 0)];
+ temp = rrk[1];
+ rk[1] =
+ Tks0[LTC_BYTE(temp, 3)] ^
+ Tks1[LTC_BYTE(temp, 2)] ^
+ Tks2[LTC_BYTE(temp, 1)] ^
+ Tks3[LTC_BYTE(temp, 0)];
+ temp = rrk[2];
+ rk[2] =
+ Tks0[LTC_BYTE(temp, 3)] ^
+ Tks1[LTC_BYTE(temp, 2)] ^
+ Tks2[LTC_BYTE(temp, 1)] ^
+ Tks3[LTC_BYTE(temp, 0)];
+ temp = rrk[3];
+ rk[3] =
+ Tks0[LTC_BYTE(temp, 3)] ^
+ Tks1[LTC_BYTE(temp, 2)] ^
+ Tks2[LTC_BYTE(temp, 1)] ^
+ Tks3[LTC_BYTE(temp, 0)];
+ #endif
+
+ }
+
+ /* copy last */
+ rrk -= 4;
+ rk += 4;
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk = *rrk;
+#endif /* ENCRYPT_ONLY */
+
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with AES
+ @param pt The input plaintext (16 bytes)
+ @param ct The output ciphertext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int ECB_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+ ulong32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const ulong32 *rk;
+ int Nr, r;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ Nr = skey->rijndael.Nr;
+
+ if (Nr < 2 || Nr > 16)
+ return CRYPT_INVALID_ROUNDS;
+
+ rk = skey->rijndael.eK;
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ LOAD32H(s0, pt ); s0 ^= rk[0];
+ LOAD32H(s1, pt + 4); s1 ^= rk[1];
+ LOAD32H(s2, pt + 8); s2 ^= rk[2];
+ LOAD32H(s3, pt + 12); s3 ^= rk[3];
+
+#ifdef LTC_SMALL_CODE
+
+ for (r = 0; ; r++) {
+ rk += 4;
+ t0 =
+ Te0(LTC_BYTE(s0, 3)) ^
+ Te1(LTC_BYTE(s1, 2)) ^
+ Te2(LTC_BYTE(s2, 1)) ^
+ Te3(LTC_BYTE(s3, 0)) ^
+ rk[0];
+ t1 =
+ Te0(LTC_BYTE(s1, 3)) ^
+ Te1(LTC_BYTE(s2, 2)) ^
+ Te2(LTC_BYTE(s3, 1)) ^
+ Te3(LTC_BYTE(s0, 0)) ^
+ rk[1];
+ t2 =
+ Te0(LTC_BYTE(s2, 3)) ^
+ Te1(LTC_BYTE(s3, 2)) ^
+ Te2(LTC_BYTE(s0, 1)) ^
+ Te3(LTC_BYTE(s1, 0)) ^
+ rk[2];
+ t3 =
+ Te0(LTC_BYTE(s3, 3)) ^
+ Te1(LTC_BYTE(s0, 2)) ^
+ Te2(LTC_BYTE(s1, 1)) ^
+ Te3(LTC_BYTE(s2, 0)) ^
+ rk[3];
+ if (r == Nr-2) {
+ break;
+ }
+ s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+ }
+ rk += 4;
+
+#else
+
+ /*
+ * Nr - 1 full rounds:
+ */
+ r = Nr >> 1;
+ for (;;) {
+ t0 =
+ Te0(LTC_BYTE(s0, 3)) ^
+ Te1(LTC_BYTE(s1, 2)) ^
+ Te2(LTC_BYTE(s2, 1)) ^
+ Te3(LTC_BYTE(s3, 0)) ^
+ rk[4];
+ t1 =
+ Te0(LTC_BYTE(s1, 3)) ^
+ Te1(LTC_BYTE(s2, 2)) ^
+ Te2(LTC_BYTE(s3, 1)) ^
+ Te3(LTC_BYTE(s0, 0)) ^
+ rk[5];
+ t2 =
+ Te0(LTC_BYTE(s2, 3)) ^
+ Te1(LTC_BYTE(s3, 2)) ^
+ Te2(LTC_BYTE(s0, 1)) ^
+ Te3(LTC_BYTE(s1, 0)) ^
+ rk[6];
+ t3 =
+ Te0(LTC_BYTE(s3, 3)) ^
+ Te1(LTC_BYTE(s0, 2)) ^
+ Te2(LTC_BYTE(s1, 1)) ^
+ Te3(LTC_BYTE(s2, 0)) ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Te0(LTC_BYTE(t0, 3)) ^
+ Te1(LTC_BYTE(t1, 2)) ^
+ Te2(LTC_BYTE(t2, 1)) ^
+ Te3(LTC_BYTE(t3, 0)) ^
+ rk[0];
+ s1 =
+ Te0(LTC_BYTE(t1, 3)) ^
+ Te1(LTC_BYTE(t2, 2)) ^
+ Te2(LTC_BYTE(t3, 1)) ^
+ Te3(LTC_BYTE(t0, 0)) ^
+ rk[1];
+ s2 =
+ Te0(LTC_BYTE(t2, 3)) ^
+ Te1(LTC_BYTE(t3, 2)) ^
+ Te2(LTC_BYTE(t0, 1)) ^
+ Te3(LTC_BYTE(t1, 0)) ^
+ rk[2];
+ s3 =
+ Te0(LTC_BYTE(t3, 3)) ^
+ Te1(LTC_BYTE(t0, 2)) ^
+ Te2(LTC_BYTE(t1, 1)) ^
+ Te3(LTC_BYTE(t2, 0)) ^
+ rk[3];
+ }
+
+#endif
+
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Te4_3[LTC_BYTE(t0, 3)]) ^
+ (Te4_2[LTC_BYTE(t1, 2)]) ^
+ (Te4_1[LTC_BYTE(t2, 1)]) ^
+ (Te4_0[LTC_BYTE(t3, 0)]) ^
+ rk[0];
+ STORE32H(s0, ct);
+ s1 =
+ (Te4_3[LTC_BYTE(t1, 3)]) ^
+ (Te4_2[LTC_BYTE(t2, 2)]) ^
+ (Te4_1[LTC_BYTE(t3, 1)]) ^
+ (Te4_0[LTC_BYTE(t0, 0)]) ^
+ rk[1];
+ STORE32H(s1, ct+4);
+ s2 =
+ (Te4_3[LTC_BYTE(t2, 3)]) ^
+ (Te4_2[LTC_BYTE(t3, 2)]) ^
+ (Te4_1[LTC_BYTE(t0, 1)]) ^
+ (Te4_0[LTC_BYTE(t1, 0)]) ^
+ rk[2];
+ STORE32H(s2, ct+8);
+ s3 =
+ (Te4_3[LTC_BYTE(t3, 3)]) ^
+ (Te4_2[LTC_BYTE(t0, 2)]) ^
+ (Te4_1[LTC_BYTE(t1, 1)]) ^
+ (Te4_0[LTC_BYTE(t2, 0)]) ^
+ rk[3];
+ STORE32H(s3, ct+12);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int ECB_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_rijndael_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+ return err;
+}
+#endif
+
+#ifndef ENCRYPT_ONLY
+
+/**
+ Decrypts a block of text with AES
+ @param ct The input ciphertext (16 bytes)
+ @param pt The output plaintext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int ECB_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+ ulong32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const ulong32 *rk;
+ int Nr, r;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ Nr = skey->rijndael.Nr;
+
+ if (Nr < 2 || Nr > 16)
+ return CRYPT_INVALID_ROUNDS;
+
+ rk = skey->rijndael.dK;
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ LOAD32H(s0, ct ); s0 ^= rk[0];
+ LOAD32H(s1, ct + 4); s1 ^= rk[1];
+ LOAD32H(s2, ct + 8); s2 ^= rk[2];
+ LOAD32H(s3, ct + 12); s3 ^= rk[3];
+
+#ifdef LTC_SMALL_CODE
+ for (r = 0; ; r++) {
+ rk += 4;
+ t0 =
+ Td0(LTC_BYTE(s0, 3)) ^
+ Td1(LTC_BYTE(s3, 2)) ^
+ Td2(LTC_BYTE(s2, 1)) ^
+ Td3(LTC_BYTE(s1, 0)) ^
+ rk[0];
+ t1 =
+ Td0(LTC_BYTE(s1, 3)) ^
+ Td1(LTC_BYTE(s0, 2)) ^
+ Td2(LTC_BYTE(s3, 1)) ^
+ Td3(LTC_BYTE(s2, 0)) ^
+ rk[1];
+ t2 =
+ Td0(LTC_BYTE(s2, 3)) ^
+ Td1(LTC_BYTE(s1, 2)) ^
+ Td2(LTC_BYTE(s0, 1)) ^
+ Td3(LTC_BYTE(s3, 0)) ^
+ rk[2];
+ t3 =
+ Td0(LTC_BYTE(s3, 3)) ^
+ Td1(LTC_BYTE(s2, 2)) ^
+ Td2(LTC_BYTE(s1, 1)) ^
+ Td3(LTC_BYTE(s0, 0)) ^
+ rk[3];
+ if (r == Nr-2) {
+ break;
+ }
+ s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+ }
+ rk += 4;
+
+#else
+
+ /*
+ * Nr - 1 full rounds:
+ */
+ r = Nr >> 1;
+ for (;;) {
+
+ t0 =
+ Td0(LTC_BYTE(s0, 3)) ^
+ Td1(LTC_BYTE(s3, 2)) ^
+ Td2(LTC_BYTE(s2, 1)) ^
+ Td3(LTC_BYTE(s1, 0)) ^
+ rk[4];
+ t1 =
+ Td0(LTC_BYTE(s1, 3)) ^
+ Td1(LTC_BYTE(s0, 2)) ^
+ Td2(LTC_BYTE(s3, 1)) ^
+ Td3(LTC_BYTE(s2, 0)) ^
+ rk[5];
+ t2 =
+ Td0(LTC_BYTE(s2, 3)) ^
+ Td1(LTC_BYTE(s1, 2)) ^
+ Td2(LTC_BYTE(s0, 1)) ^
+ Td3(LTC_BYTE(s3, 0)) ^
+ rk[6];
+ t3 =
+ Td0(LTC_BYTE(s3, 3)) ^
+ Td1(LTC_BYTE(s2, 2)) ^
+ Td2(LTC_BYTE(s1, 1)) ^
+ Td3(LTC_BYTE(s0, 0)) ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+
+ s0 =
+ Td0(LTC_BYTE(t0, 3)) ^
+ Td1(LTC_BYTE(t3, 2)) ^
+ Td2(LTC_BYTE(t2, 1)) ^
+ Td3(LTC_BYTE(t1, 0)) ^
+ rk[0];
+ s1 =
+ Td0(LTC_BYTE(t1, 3)) ^
+ Td1(LTC_BYTE(t0, 2)) ^
+ Td2(LTC_BYTE(t3, 1)) ^
+ Td3(LTC_BYTE(t2, 0)) ^
+ rk[1];
+ s2 =
+ Td0(LTC_BYTE(t2, 3)) ^
+ Td1(LTC_BYTE(t1, 2)) ^
+ Td2(LTC_BYTE(t0, 1)) ^
+ Td3(LTC_BYTE(t3, 0)) ^
+ rk[2];
+ s3 =
+ Td0(LTC_BYTE(t3, 3)) ^
+ Td1(LTC_BYTE(t2, 2)) ^
+ Td2(LTC_BYTE(t1, 1)) ^
+ Td3(LTC_BYTE(t0, 0)) ^
+ rk[3];
+ }
+#endif
+
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Td4[LTC_BYTE(t0, 3)] & 0xff000000) ^
+ (Td4[LTC_BYTE(t3, 2)] & 0x00ff0000) ^
+ (Td4[LTC_BYTE(t2, 1)] & 0x0000ff00) ^
+ (Td4[LTC_BYTE(t1, 0)] & 0x000000ff) ^
+ rk[0];
+ STORE32H(s0, pt);
+ s1 =
+ (Td4[LTC_BYTE(t1, 3)] & 0xff000000) ^
+ (Td4[LTC_BYTE(t0, 2)] & 0x00ff0000) ^
+ (Td4[LTC_BYTE(t3, 1)] & 0x0000ff00) ^
+ (Td4[LTC_BYTE(t2, 0)] & 0x000000ff) ^
+ rk[1];
+ STORE32H(s1, pt+4);
+ s2 =
+ (Td4[LTC_BYTE(t2, 3)] & 0xff000000) ^
+ (Td4[LTC_BYTE(t1, 2)] & 0x00ff0000) ^
+ (Td4[LTC_BYTE(t0, 1)] & 0x0000ff00) ^
+ (Td4[LTC_BYTE(t3, 0)] & 0x000000ff) ^
+ rk[2];
+ STORE32H(s2, pt+8);
+ s3 =
+ (Td4[LTC_BYTE(t3, 3)] & 0xff000000) ^
+ (Td4[LTC_BYTE(t2, 2)] & 0x00ff0000) ^
+ (Td4[LTC_BYTE(t1, 1)] & 0x0000ff00) ^
+ (Td4[LTC_BYTE(t0, 0)] & 0x000000ff) ^
+ rk[3];
+ STORE32H(s3, pt+12);
+
+ return CRYPT_OK;
+}
+
+
+#ifdef LTC_CLEAN_STACK
+int ECB_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_rijndael_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+ return err;
+}
+#endif
+
+/**
+ Performs a self-test of the AES block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int ECB_TEST(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ int err;
+ static const struct {
+ int keylen;
+ unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+ { 16,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+ 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
+ }, {
+ 24,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+ 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
+ }, {
+ 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 },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+ 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
+ }
+ };
+
+ symmetric_key key;
+ unsigned char tmp[2][16];
+ int i, y;
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ zeromem(&key, sizeof(key));
+ if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+
+ rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key);
+ rijndael_ecb_decrypt(tmp[0], tmp[1], &key);
+ if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i) ||
+ compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 16; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) rijndael_ecb_encrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 1000; y++) rijndael_ecb_decrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif /* ENCRYPT_ONLY */
+
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void ECB_DONE(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int ECB_KS(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize < 24) {
+ *keysize = 16;
+ return CRYPT_OK;
+ }
+ if (*keysize < 32) {
+ *keysize = 24;
+ return CRYPT_OK;
+ }
+ *keysize = 32;
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/ciphers/aes/aes_desc.c b/Sources/libtomcrypt/ciphers/aes/aes_desc.c
new file mode 100644
index 00000000..7c537df7
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/aes/aes_desc.c
@@ -0,0 +1,254 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* Auto-detection of AES implementation by Steffen Jaeckel */
+/**
+ @file aes_desc.c
+ Run-time detection of correct AES implementation
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_RIJNDAEL)
+
+#ifndef ENCRYPT_ONLY
+
+#define AES_SETUP aes_setup
+#define AES_ENC aes_ecb_encrypt
+#define AES_DEC aes_ecb_decrypt
+#define AES_DONE aes_done
+#define AES_TEST aes_test
+#define AES_KS aes_keysize
+
+const struct ltc_cipher_descriptor aes_desc =
+{
+ "aes",
+ 6,
+ 16, 32, 16, 10,
+ AES_SETUP, AES_ENC, AES_DEC, AES_TEST, AES_DONE, AES_KS,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#else
+
+#define AES_SETUP aes_enc_setup
+#define AES_ENC aes_enc_ecb_encrypt
+#define AES_DONE aes_enc_done
+#define AES_TEST aes_enc_test
+#define AES_KS aes_enc_keysize
+
+const struct ltc_cipher_descriptor aes_enc_desc =
+{
+ "aes",
+ 6,
+ 16, 32, 16, 10,
+ AES_SETUP, AES_ENC, NULL, NULL, AES_DONE, AES_KS,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#endif
+
+/* Code partially borrowed from https://software.intel.com/content/www/us/en/develop/articles/intel-sha-extensions.html */
+#if defined(LTC_AES_NI)
+static LTC_INLINE int s_aesni_is_supported(void)
+{
+ static int initialized = 0, is_supported = 0;
+
+ if (initialized == 0) {
+ int a, b, c, d;
+
+ /* Look for CPUID.1.0.ECX[19] (SSE4.1) and CPUID.1.0.ECX[25] (AES-NI)
+ * EAX = 1, ECX = 0
+ */
+ a = 1;
+ c = 0;
+
+ __asm__ volatile ("cpuid"
+ :"=a"(a), "=b"(b), "=c"(c), "=d"(d)
+ :"a"(a), "c"(c)
+ );
+
+ is_supported = ((c >> 19) & 1) && ((c >> 25) & 1);
+ initialized = 1;
+ }
+
+ return is_supported;
+}
+
+#ifndef ENCRYPT_ONLY
+int aesni_is_supported(void)
+{
+ return s_aesni_is_supported();
+}
+#endif
+#endif
+
+ /**
+ Initialize the AES (Rijndael) block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int AES_SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+#ifdef LTC_AES_NI
+ if (s_aesni_is_supported()) {
+ return aesni_setup(key, keylen, num_rounds, skey);
+ }
+#endif
+ /* Last resort, software AES */
+ return rijndael_setup(key, keylen, num_rounds, skey);
+}
+
+/**
+ Encrypts a block of text with AES
+ @param pt The input plaintext (16 bytes)
+ @param ct The output ciphertext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int AES_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+#ifdef LTC_AES_NI
+ if (s_aesni_is_supported()) {
+ return aesni_ecb_encrypt(pt, ct, skey);
+ }
+#endif
+ return rijndael_ecb_encrypt(pt, ct, skey);
+}
+
+
+#ifndef ENCRYPT_ONLY
+/**
+ Decrypts a block of text with AES
+ @param ct The input ciphertext (16 bytes)
+ @param pt The output plaintext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int AES_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+#ifdef LTC_AES_NI
+ if (s_aesni_is_supported()) {
+ return aesni_ecb_decrypt(ct, pt, skey);
+ }
+#endif
+ return rijndael_ecb_decrypt(ct, pt, skey);
+}
+#endif /* ENCRYPT_ONLY */
+
+/**
+ Performs a self-test of the AES block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int AES_TEST(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ int err;
+ static const struct {
+ int keylen;
+ unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+ { 16,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+ 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
+ }, {
+ 24,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+ 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
+ }, {
+ 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 },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+ 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
+ }
+ };
+
+ symmetric_key key;
+ unsigned char tmp[2][16];
+ int i;
+#ifndef ENCRYPT_ONLY
+ int y;
+#endif
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ zeromem(&key, sizeof(key));
+ if ((err = AES_SETUP(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+
+ AES_ENC(tests[i].pt, tmp[0], &key);
+ if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+#ifndef ENCRYPT_ONLY
+ AES_DEC(tmp[0], tmp[1], &key);
+ if (compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 16; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) AES_ENC(tmp[0], tmp[0], &key);
+ for (y = 0; y < 1000; y++) AES_DEC(tmp[0], tmp[0], &key);
+ for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+#endif
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void AES_DONE(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int AES_KS(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize < 24) {
+ *keysize = 16;
+ return CRYPT_OK;
+ }
+ if (*keysize < 32) {
+ *keysize = 24;
+ return CRYPT_OK;
+ }
+ *keysize = 32;
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/ciphers/aes/aes_tab.c b/Sources/libtomcrypt/ciphers/aes/aes_tab.c
new file mode 100644
index 00000000..5e590041
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/aes/aes_tab.c
@@ -0,0 +1,1022 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/* The precomputed tables for AES */
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+#ifdef LTC_AES_TAB_C
+
+/**
+ @file aes_tab.c
+ AES tables
+*/
+static const ulong32 TE0[256] = {
+ 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
+ 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
+ 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
+ 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
+ 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
+ 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
+ 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
+ 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
+ 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
+ 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
+ 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
+ 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
+ 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
+ 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
+ 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
+ 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
+ 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
+ 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
+ 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
+ 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
+ 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
+ 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
+ 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
+ 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
+ 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
+ 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
+ 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
+ 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
+ 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
+ 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
+ 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
+ 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
+ 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
+ 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
+ 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
+ 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
+ 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
+ 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
+ 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
+ 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
+ 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
+ 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
+ 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
+ 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
+ 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
+ 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
+ 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
+ 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
+ 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
+ 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
+ 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
+ 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
+ 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
+ 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
+ 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
+ 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
+ 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
+ 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
+ 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
+ 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
+ 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
+ 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
+ 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
+ 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL,
+};
+
+#if !defined(PELI_TAB) && defined(LTC_SMALL_CODE)
+static const ulong32 Te4[256] = {
+ 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL,
+ 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL,
+ 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL,
+ 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL,
+ 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL,
+ 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL,
+ 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL,
+ 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL,
+ 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL,
+ 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL,
+ 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL,
+ 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL,
+ 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL,
+ 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL,
+ 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL,
+ 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL,
+ 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL,
+ 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL,
+ 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL,
+ 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL,
+ 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL,
+ 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL,
+ 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL,
+ 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL,
+ 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL,
+ 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL,
+ 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL,
+ 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL,
+ 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL,
+ 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL,
+ 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL,
+ 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL,
+ 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL,
+ 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL,
+ 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL,
+ 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL,
+ 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL,
+ 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL,
+ 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL,
+ 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL,
+ 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL,
+ 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL,
+ 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL,
+ 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL,
+ 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL,
+ 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL,
+ 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL,
+ 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL,
+ 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL,
+ 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL,
+ 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL,
+ 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL,
+ 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL,
+ 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL,
+ 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL,
+ 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL,
+ 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL,
+ 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL,
+ 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL,
+ 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL,
+ 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL,
+ 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL,
+ 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL,
+ 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,
+};
+#endif
+
+#ifndef ENCRYPT_ONLY
+
+static const ulong32 TD0[256] = {
+ 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
+ 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
+ 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
+ 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
+ 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
+ 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
+ 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
+ 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
+ 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
+ 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
+ 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
+ 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
+ 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
+ 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
+ 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
+ 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
+ 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
+ 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
+ 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
+ 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
+ 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
+ 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
+ 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
+ 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
+ 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
+ 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
+ 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
+ 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
+ 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
+ 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
+ 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
+ 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
+ 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
+ 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
+ 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
+ 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
+ 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
+ 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
+ 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
+ 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
+ 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
+ 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
+ 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
+ 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
+ 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
+ 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
+ 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
+ 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
+ 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
+ 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
+ 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
+ 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
+ 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
+ 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
+ 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
+ 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
+ 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
+ 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
+ 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
+ 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
+ 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
+ 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
+ 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
+ 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL,
+};
+
+static const ulong32 Td4[256] = {
+ 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL,
+ 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL,
+ 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL,
+ 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL,
+ 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL,
+ 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL,
+ 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL,
+ 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL,
+ 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL,
+ 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL,
+ 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL,
+ 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL,
+ 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL,
+ 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL,
+ 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL,
+ 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL,
+ 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL,
+ 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL,
+ 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL,
+ 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL,
+ 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL,
+ 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL,
+ 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL,
+ 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL,
+ 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL,
+ 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL,
+ 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL,
+ 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL,
+ 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL,
+ 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL,
+ 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL,
+ 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL,
+ 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL,
+ 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL,
+ 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL,
+ 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL,
+ 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL,
+ 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL,
+ 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL,
+ 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL,
+ 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL,
+ 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL,
+ 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL,
+ 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL,
+ 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL,
+ 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL,
+ 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL,
+ 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL,
+ 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL,
+ 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL,
+ 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL,
+ 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL,
+ 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL,
+ 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL,
+ 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL,
+ 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL,
+ 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL,
+ 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL,
+ 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL,
+ 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL,
+ 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL,
+ 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL,
+ 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL,
+ 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,
+};
+
+#endif /* ENCRYPT_ONLY */
+
+#ifdef LTC_SMALL_CODE
+
+#define Te0(x) TE0[x]
+#define Te1(x) RORc(TE0[x], 8)
+#define Te2(x) RORc(TE0[x], 16)
+#define Te3(x) RORc(TE0[x], 24)
+
+#define Td0(x) TD0[x]
+#define Td1(x) RORc(TD0[x], 8)
+#define Td2(x) RORc(TD0[x], 16)
+#define Td3(x) RORc(TD0[x], 24)
+
+#define Te4_0 0x000000FF & Te4
+#define Te4_1 0x0000FF00 & Te4
+#define Te4_2 0x00FF0000 & Te4
+#define Te4_3 0xFF000000 & Te4
+
+#else
+
+#define Te0(x) TE0[x]
+#define Te1(x) TE1[x]
+#define Te2(x) TE2[x]
+#define Te3(x) TE3[x]
+
+#define Td0(x) TD0[x]
+#define Td1(x) TD1[x]
+#define Td2(x) TD2[x]
+#define Td3(x) TD3[x]
+
+static const ulong32 TE1[256] = {
+ 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,
+ 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,
+ 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,
+ 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,
+ 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,
+ 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,
+ 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,
+ 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,
+ 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,
+ 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,
+ 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,
+ 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,
+ 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,
+ 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,
+ 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,
+ 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,
+ 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,
+ 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,
+ 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,
+ 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,
+ 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,
+ 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,
+ 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,
+ 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,
+ 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,
+ 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,
+ 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,
+ 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,
+ 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,
+ 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,
+ 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,
+ 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,
+ 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,
+ 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,
+ 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,
+ 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,
+ 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,
+ 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,
+ 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,
+ 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,
+ 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,
+ 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,
+ 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,
+ 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,
+ 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,
+ 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,
+ 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,
+ 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,
+ 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,
+ 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,
+ 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,
+ 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,
+ 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,
+ 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,
+ 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,
+ 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,
+ 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,
+ 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,
+ 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,
+ 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,
+ 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,
+ 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,
+ 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,
+ 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL,
+};
+static const ulong32 TE2[256] = {
+ 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,
+ 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,
+ 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,
+ 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,
+ 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,
+ 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,
+ 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,
+ 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,
+ 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,
+ 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,
+ 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,
+ 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,
+ 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,
+ 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,
+ 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,
+ 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,
+ 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,
+ 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,
+ 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,
+ 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,
+ 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,
+ 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,
+ 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,
+ 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,
+ 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,
+ 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,
+ 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,
+ 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,
+ 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,
+ 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,
+ 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,
+ 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,
+ 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,
+ 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,
+ 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,
+ 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,
+ 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,
+ 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,
+ 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,
+ 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,
+ 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,
+ 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,
+ 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,
+ 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,
+ 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,
+ 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,
+ 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,
+ 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,
+ 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,
+ 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,
+ 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,
+ 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,
+ 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,
+ 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,
+ 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,
+ 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,
+ 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,
+ 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,
+ 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,
+ 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,
+ 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,
+ 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,
+ 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,
+ 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL,
+};
+static const ulong32 TE3[256] = {
+
+ 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,
+ 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,
+ 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,
+ 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,
+ 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,
+ 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,
+ 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,
+ 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,
+ 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,
+ 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,
+ 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,
+ 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,
+ 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,
+ 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,
+ 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,
+ 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,
+ 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,
+ 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,
+ 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,
+ 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,
+ 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,
+ 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,
+ 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,
+ 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,
+ 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,
+ 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,
+ 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,
+ 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,
+ 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,
+ 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,
+ 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,
+ 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,
+ 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,
+ 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,
+ 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,
+ 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,
+ 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,
+ 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,
+ 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,
+ 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,
+ 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,
+ 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,
+ 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,
+ 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,
+ 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,
+ 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,
+ 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,
+ 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,
+ 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,
+ 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,
+ 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,
+ 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,
+ 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,
+ 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,
+ 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,
+ 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,
+ 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,
+ 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,
+ 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,
+ 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,
+ 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,
+ 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,
+ 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,
+ 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL,
+};
+
+#ifndef PELI_TAB
+static const ulong32 Te4_0[] = {
+0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL,
+0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL,
+0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL,
+0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL,
+0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL,
+0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL,
+0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL,
+0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL,
+0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL,
+0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL,
+0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL,
+0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL,
+0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL,
+0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL,
+0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL,
+0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL,
+0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL,
+0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL,
+0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL,
+0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL,
+0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL,
+0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL,
+0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL,
+0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL,
+0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL,
+0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL,
+0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL,
+0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL,
+0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL,
+0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL,
+0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL,
+0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL
+};
+
+static const ulong32 Te4_1[] = {
+0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL,
+0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL,
+0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL,
+0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL,
+0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL,
+0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL,
+0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL,
+0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL,
+0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL,
+0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL,
+0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL,
+0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL,
+0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL,
+0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL,
+0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL,
+0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL,
+0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL,
+0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL,
+0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL,
+0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL,
+0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL,
+0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL,
+0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL,
+0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL,
+0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL,
+0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL,
+0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL,
+0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL,
+0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL,
+0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL,
+0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL,
+0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL
+};
+
+static const ulong32 Te4_2[] = {
+0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL,
+0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL,
+0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL,
+0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL,
+0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL,
+0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL,
+0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL,
+0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL,
+0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL,
+0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL,
+0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL,
+0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL,
+0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL,
+0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL,
+0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL,
+0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL,
+0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL,
+0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL,
+0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL,
+0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL,
+0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL,
+0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL,
+0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL,
+0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL,
+0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL,
+0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL,
+0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL,
+0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL,
+0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL,
+0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL,
+0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL,
+0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL
+};
+
+static const ulong32 Te4_3[] = {
+0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL,
+0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL,
+0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL,
+0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL,
+0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL,
+0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL,
+0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL,
+0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL,
+0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL,
+0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL,
+0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL,
+0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL,
+0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL,
+0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL,
+0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL,
+0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL,
+0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL,
+0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL,
+0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL,
+0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL,
+0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL,
+0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL,
+0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL,
+0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL,
+0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL,
+0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL,
+0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL,
+0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL,
+0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL,
+0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL,
+0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL,
+0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL
+};
+#endif /* pelimac */
+
+#ifndef ENCRYPT_ONLY
+
+static const ulong32 TD1[256] = {
+ 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
+ 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
+ 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,
+ 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,
+ 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,
+ 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,
+ 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,
+ 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,
+ 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,
+ 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,
+ 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,
+ 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,
+ 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,
+ 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,
+ 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,
+ 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,
+ 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,
+ 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,
+ 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,
+ 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,
+ 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,
+ 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,
+ 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,
+ 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,
+ 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,
+ 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,
+ 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,
+ 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,
+ 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,
+ 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,
+ 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,
+ 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,
+ 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,
+ 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,
+ 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,
+ 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,
+ 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,
+ 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,
+ 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,
+ 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,
+ 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,
+ 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,
+ 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,
+ 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,
+ 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,
+ 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,
+ 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,
+ 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,
+ 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,
+ 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,
+ 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,
+ 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,
+ 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,
+ 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,
+ 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,
+ 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,
+ 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,
+ 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,
+ 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,
+ 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,
+ 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,
+ 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,
+ 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,
+ 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL,
+};
+static const ulong32 TD2[256] = {
+ 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,
+ 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,
+ 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,
+ 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,
+ 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,
+ 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,
+ 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,
+ 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,
+ 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,
+ 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,
+ 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,
+ 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,
+ 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,
+ 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,
+ 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,
+ 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,
+ 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,
+ 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,
+ 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,
+ 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,
+ 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,
+ 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,
+ 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,
+ 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,
+ 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,
+ 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,
+ 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,
+ 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,
+ 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,
+ 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,
+ 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,
+ 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,
+ 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,
+ 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,
+ 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,
+ 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,
+ 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,
+ 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,
+ 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,
+ 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,
+ 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,
+ 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,
+ 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,
+ 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,
+ 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,
+ 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,
+ 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,
+ 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,
+ 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,
+ 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,
+ 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,
+ 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,
+ 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,
+ 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,
+ 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,
+ 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,
+ 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,
+ 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,
+ 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,
+ 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,
+ 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,
+ 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,
+ 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,
+ 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL,
+};
+static const ulong32 TD3[256] = {
+ 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,
+ 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,
+ 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,
+ 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,
+ 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,
+ 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,
+ 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,
+ 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,
+ 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,
+ 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,
+ 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,
+ 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,
+ 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,
+ 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,
+ 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,
+ 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,
+ 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,
+ 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,
+ 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,
+ 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,
+ 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,
+ 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,
+ 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,
+ 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,
+ 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,
+ 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,
+ 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,
+ 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,
+ 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,
+ 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,
+ 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,
+ 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,
+ 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,
+ 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,
+ 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,
+ 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,
+ 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,
+ 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,
+ 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,
+ 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,
+ 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,
+ 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,
+ 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,
+ 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,
+ 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,
+ 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,
+ 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,
+ 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,
+ 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,
+ 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,
+ 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,
+ 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,
+ 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,
+ 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,
+ 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,
+ 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,
+ 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,
+ 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,
+ 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,
+ 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,
+ 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,
+ 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,
+ 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,
+ 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL,
+};
+
+static const ulong32 Tks0[] = {
+0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL,
+0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL,
+0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL,
+0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL,
+0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL,
+0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL,
+0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL,
+0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL,
+0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL,
+0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL,
+0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL,
+0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL,
+0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL,
+0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL,
+0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL,
+0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL,
+0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL,
+0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL,
+0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL,
+0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL,
+0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL,
+0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL,
+0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL,
+0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL,
+0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL,
+0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL,
+0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL,
+0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL,
+0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL,
+0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL,
+0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL,
+0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL
+};
+
+static const ulong32 Tks1[] = {
+0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL,
+0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL,
+0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL,
+0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL,
+0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL,
+0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL,
+0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL,
+0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL,
+0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL,
+0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL,
+0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL,
+0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL,
+0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL,
+0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL,
+0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL,
+0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL,
+0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL,
+0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL,
+0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL,
+0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL,
+0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL,
+0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL,
+0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL,
+0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL,
+0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL,
+0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL,
+0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL,
+0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL,
+0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL,
+0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL,
+0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL,
+0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL
+};
+
+static const ulong32 Tks2[] = {
+0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL,
+0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL,
+0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL,
+0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL,
+0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL,
+0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL,
+0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL,
+0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL,
+0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL,
+0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL,
+0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL,
+0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL,
+0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL,
+0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL,
+0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL,
+0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL,
+0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL,
+0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL,
+0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL,
+0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL,
+0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL,
+0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL,
+0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL,
+0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL,
+0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL,
+0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL,
+0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL,
+0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL,
+0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL,
+0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL,
+0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL,
+0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL
+};
+
+static const ulong32 Tks3[] = {
+0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL,
+0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL,
+0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL,
+0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL,
+0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL,
+0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL,
+0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL,
+0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL,
+0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL,
+0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL,
+0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL,
+0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL,
+0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL,
+0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL,
+0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL,
+0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL,
+0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL,
+0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL,
+0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL,
+0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL,
+0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL,
+0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL,
+0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL,
+0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL,
+0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL,
+0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL,
+0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL,
+0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL,
+0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL,
+0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL,
+0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL,
+0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL
+};
+
+#endif /* ENCRYPT_ONLY */
+
+#endif /* SMALL CODE */
+
+#ifndef PELI_TAB
+static const ulong32 rcon[] = {
+ 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
+ 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
+ 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#endif
+
+#endif /* LTC_AES_TAB_C */
diff --git a/Sources/libtomcrypt/ciphers/aes/aesni.c b/Sources/libtomcrypt/ciphers/aes/aesni.c
new file mode 100644
index 00000000..ecfc008e
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/aes/aesni.c
@@ -0,0 +1,374 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* AES-NI implementation by Steffen Jaeckel */
+/**
+ @file aesni.c
+ Implementation of AES via the AES-NI instruction on x86_64
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_AES_NI)
+
+const struct ltc_cipher_descriptor aesni_desc =
+{
+ "aes",
+ 6,
+ 16, 32, 16, 10,
+ aesni_setup, aesni_ecb_encrypt, aesni_ecb_decrypt, aesni_test, aesni_done, aesni_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#include
+#include
+#include
+
+#define setup_mix(t, c) _mm_extract_epi32(_mm_aeskeygenassist_si128(t, 0), c)
+#define temp_load(k) _mm_loadu_si128((__m128i*)(k))
+#define temp_update(t, k) _mm_insert_epi32(t, k, 3)
+#define temp_invert(k) _mm_aesimc_si128(*((__m128i*)(k)))
+
+
+static const ulong32 rcon[] = {
+ 0x01UL, 0x02UL, 0x04UL, 0x08UL, 0x10UL, 0x20UL, 0x40UL, 0x80UL, 0x1BUL, 0x36UL
+};
+
+ /**
+ Initialize the AES (Rijndael) block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+LTC_ATTRIBUTE((__target__("aes,sse4.1")))
+int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int i;
+ __m128i temp;
+ ulong32 *rk, *K;
+ ulong32 *rrk;
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (keylen != 16 && keylen != 24 && keylen != 32) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if (num_rounds != 0 && num_rounds != (keylen / 4 + 6)) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ skey->rijndael.Nr = keylen / 4 + 6;
+ K = LTC_ALIGN_BUF(skey->rijndael.K, 16);
+ skey->rijndael.eK = K;
+ K += 60;
+ skey->rijndael.dK = K;
+
+ /* setup the forward key */
+ i = 0;
+ rk = skey->rijndael.eK;
+ LOAD32L(rk[0], key);
+ LOAD32L(rk[1], key + 4);
+ LOAD32L(rk[2], key + 8);
+ LOAD32L(rk[3], key + 12);
+ if (keylen == 16) {
+ temp = temp_load(key);
+ for (;;) {
+ rk[4] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10) {
+ break;
+ }
+ temp = temp_update(temp, rk[7]);
+ rk += 4;
+ }
+ } else if (keylen == 24) {
+ LOAD32L(rk[4], key + 16);
+ LOAD32L(rk[5], key + 20);
+ temp = temp_load(key + 8);
+ for (;;) {
+ rk[6] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i];
+ rk[7] = rk[1] ^ rk[6];
+ rk[8] = rk[2] ^ rk[7];
+ rk[9] = rk[3] ^ rk[8];
+ if (++i == 8) {
+ break;
+ }
+ rk[10] = rk[4] ^ rk[9];
+ rk[11] = rk[5] ^ rk[10];
+ temp = temp_update(temp, rk[11]);
+ rk += 6;
+ }
+ } else if (keylen == 32) {
+ LOAD32L(rk[4], key + 16);
+ LOAD32L(rk[5], key + 20);
+ LOAD32L(rk[6], key + 24);
+ LOAD32L(rk[7], key + 28);
+ temp = temp_load(key + 16);
+ for (;;) {
+ rk[8] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i];
+ rk[9] = rk[1] ^ rk[8];
+ rk[10] = rk[2] ^ rk[9];
+ rk[11] = rk[3] ^ rk[10];
+ if (++i == 7) {
+ break;
+ }
+ temp = temp_update(temp, rk[11]);
+ rk[12] = rk[4] ^ setup_mix(temp, 2);
+ rk[13] = rk[5] ^ rk[12];
+ rk[14] = rk[6] ^ rk[13];
+ rk[15] = rk[7] ^ rk[14];
+ temp = temp_update(temp, rk[15]);
+ rk += 8;
+ }
+ } else {
+ /* this can't happen */
+ /* coverity[dead_error_line] */
+ return CRYPT_ERROR;
+ }
+
+ /* setup the inverse key now */
+ rk = skey->rijndael.dK;
+ rrk = skey->rijndael.eK + skey->rijndael.Nr * 4;
+
+ /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+ /* copy first */
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk = *rrk;
+ rk -= 3;
+ rrk -= 3;
+
+ for (i = 1; i < skey->rijndael.Nr; i++) {
+ rrk -= 4;
+ rk += 4;
+ temp = temp_invert(rk);
+ *((__m128i*) rk) = temp_invert(rrk);
+ }
+
+ /* copy last */
+ rrk -= 4;
+ rk += 4;
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk = *rrk;
+
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with AES
+ @param pt The input plaintext (16 bytes)
+ @param ct The output ciphertext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+LTC_ATTRIBUTE((__target__("aes")))
+#ifdef LTC_CLEAN_STACK
+static int s_aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+ int Nr, r;
+ const __m128i *skeys;
+ __m128i block;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ Nr = skey->rijndael.Nr;
+
+ if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS;
+
+ skeys = (__m128i*) skey->rijndael.eK;
+ block = _mm_loadu_si128((const __m128i*) (pt));
+
+ block = _mm_xor_si128(block, skeys[0]);
+ for (r = 1; r < Nr - 1; r += 2) {
+ block = _mm_aesenc_si128(block, skeys[r]);
+ block = _mm_aesenc_si128(block, skeys[r + 1]);
+ }
+ block = _mm_aesenc_si128(block, skeys[Nr - 1]);
+ block = _mm_aesenclast_si128(block, skeys[Nr]);
+
+ _mm_storeu_si128((__m128i*) ct, block);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_aesni_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+ return err;
+}
+#endif
+
+
+/**
+ Decrypts a block of text with AES
+ @param ct The input ciphertext (16 bytes)
+ @param pt The output plaintext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+LTC_ATTRIBUTE((__target__("aes")))
+#ifdef LTC_CLEAN_STACK
+static int s_aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+ int Nr, r;
+ const __m128i *skeys;
+ __m128i block;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ Nr = skey->rijndael.Nr;
+
+ if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS;
+
+ skeys = (__m128i*) skey->rijndael.dK;
+ block = _mm_loadu_si128((const __m128i*) (ct));
+
+ block = _mm_xor_si128(block, skeys[0]);
+ for (r = 1; r < Nr - 1; r += 2) {
+ block = _mm_aesdec_si128(block, skeys[r]);
+ block = _mm_aesdec_si128(block, skeys[r + 1]);
+ }
+ block = _mm_aesdec_si128(block, skeys[Nr - 1]);
+ block = _mm_aesdeclast_si128(block, skeys[Nr]);
+
+ _mm_storeu_si128((__m128i*) pt, block);
+
+ return CRYPT_OK;
+}
+
+
+#ifdef LTC_CLEAN_STACK
+int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_aesni_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+ return err;
+}
+#endif
+
+/**
+ Performs a self-test of the AES block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int aesni_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ int err;
+ static const struct {
+ int keylen;
+ unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+ { 16,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+ 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
+ }, {
+ 24,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+ 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
+ }, {
+ 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 },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+ 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
+ }
+ };
+
+ symmetric_key key;
+ unsigned char tmp[2][16];
+ int i, y;
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ zeromem(&key, sizeof(key));
+ if ((err = aesni_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+
+ aesni_ecb_encrypt(tests[i].pt, tmp[0], &key);
+ aesni_ecb_decrypt(tmp[0], tmp[1], &key);
+ if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES-NI Encrypt", i) ||
+ compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES-NI Decrypt", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 16; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) aesni_ecb_encrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 1000; y++) aesni_ecb_decrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void aesni_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int aesni_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize < 24) {
+ *keysize = 16;
+ return CRYPT_OK;
+ }
+ if (*keysize < 32) {
+ *keysize = 24;
+ return CRYPT_OK;
+ }
+ *keysize = 32;
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/ciphers/anubis.c b/Sources/libtomcrypt/ciphers/anubis.c
new file mode 100644
index 00000000..f6a1c58d
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/anubis.c
@@ -0,0 +1,1550 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file anubis.c
+ Anubis implementation derived from public domain source
+ Authors: Paulo S.L.M. Barreto and Vincent Rijmen.
+*/
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_ANUBIS
+
+const struct ltc_cipher_descriptor anubis_desc = {
+ "anubis",
+ 19,
+ 16, 40, 16, 12,
+ &anubis_setup,
+ &anubis_ecb_encrypt,
+ &anubis_ecb_decrypt,
+ &anubis_test,
+ &anubis_done,
+ &anubis_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#define MAX_N 10
+
+/*
+ * Though Anubis is endianness-neutral, the encryption tables are listed
+ * in BIG-ENDIAN format, which is adopted throughout this implementation
+ * (but little-endian notation would be equally suitable if consistently
+ * employed).
+ */
+#if defined(LTC_ANUBIS_TWEAK)
+
+static const ulong32 T0[256] = {
+ 0xba69d2bbU, 0x54a84de5U, 0x2f5ebce2U, 0x74e8cd25U,
+ 0x53a651f7U, 0xd3bb6bd0U, 0xd2b96fd6U, 0x4d9a29b3U,
+ 0x50a05dfdU, 0xac458acfU, 0x8d070e09U, 0xbf63c6a5U,
+ 0x70e0dd3dU, 0x52a455f1U, 0x9a29527bU, 0x4c982db5U,
+ 0xeac98f46U, 0xd5b773c4U, 0x97336655U, 0xd1bf63dcU,
+ 0x3366ccaaU, 0x51a259fbU, 0x5bb671c7U, 0xa651a2f3U,
+ 0xdea15ffeU, 0x48903dadU, 0xa84d9ad7U, 0x992f5e71U,
+ 0xdbab4be0U, 0x3264c8acU, 0xb773e695U, 0xfce5d732U,
+ 0xe3dbab70U, 0x9e214263U, 0x913f7e41U, 0x9b2b567dU,
+ 0xe2d9af76U, 0xbb6bd6bdU, 0x4182199bU, 0x6edca579U,
+ 0xa557aef9U, 0xcb8b0b80U, 0x6bd6b167U, 0x95376e59U,
+ 0xa15fbee1U, 0xf3fbeb10U, 0xb17ffe81U, 0x0204080cU,
+ 0xcc851792U, 0xc49537a2U, 0x1d3a744eU, 0x14285078U,
+ 0xc39b2bb0U, 0x63c69157U, 0xdaa94fe6U, 0x5dba69d3U,
+ 0x5fbe61dfU, 0xdca557f2U, 0x7dfae913U, 0xcd871394U,
+ 0x7ffee11fU, 0x5ab475c1U, 0x6cd8ad75U, 0x5cb86dd5U,
+ 0xf7f3fb08U, 0x264c98d4U, 0xffe3db38U, 0xedc79354U,
+ 0xe8cd874aU, 0x9d274e69U, 0x6fdea17fU, 0x8e010203U,
+ 0x19326456U, 0xa05dbae7U, 0xf0fde71aU, 0x890f1e11U,
+ 0x0f1e3c22U, 0x070e1c12U, 0xaf4386c5U, 0xfbebcb20U,
+ 0x08102030U, 0x152a547eU, 0x0d1a342eU, 0x04081018U,
+ 0x01020406U, 0x64c88d45U, 0xdfa35bf8U, 0x76ecc529U,
+ 0x79f2f90bU, 0xdda753f4U, 0x3d7af48eU, 0x162c5874U,
+ 0x3f7efc82U, 0x376edcb2U, 0x6ddaa973U, 0x3870e090U,
+ 0xb96fdeb1U, 0x73e6d137U, 0xe9cf834cU, 0x356ad4beU,
+ 0x55aa49e3U, 0x71e2d93bU, 0x7bf6f107U, 0x8c050a0fU,
+ 0x72e4d531U, 0x880d1a17U, 0xf6f1ff0eU, 0x2a54a8fcU,
+ 0x3e7cf884U, 0x5ebc65d9U, 0x274e9cd2U, 0x468c0589U,
+ 0x0c183028U, 0x65ca8943U, 0x68d0bd6dU, 0x61c2995bU,
+ 0x03060c0aU, 0xc19f23bcU, 0x57ae41efU, 0xd6b17fceU,
+ 0xd9af43ecU, 0x58b07dcdU, 0xd8ad47eaU, 0x66cc8549U,
+ 0xd7b37bc8U, 0x3a74e89cU, 0xc88d078aU, 0x3c78f088U,
+ 0xfae9cf26U, 0x96316253U, 0xa753a6f5U, 0x982d5a77U,
+ 0xecc59752U, 0xb86ddab7U, 0xc7933ba8U, 0xae4182c3U,
+ 0x69d2b96bU, 0x4b9631a7U, 0xab4b96ddU, 0xa94f9ed1U,
+ 0x67ce814fU, 0x0a14283cU, 0x478e018fU, 0xf2f9ef16U,
+ 0xb577ee99U, 0x224488ccU, 0xe5d7b364U, 0xeec19f5eU,
+ 0xbe61c2a3U, 0x2b56acfaU, 0x811f3e21U, 0x1224486cU,
+ 0x831b362dU, 0x1b366c5aU, 0x0e1c3824U, 0x23468ccaU,
+ 0xf5f7f304U, 0x458a0983U, 0x214284c6U, 0xce811f9eU,
+ 0x499239abU, 0x2c58b0e8U, 0xf9efc32cU, 0xe6d1bf6eU,
+ 0xb671e293U, 0x2850a0f0U, 0x172e5c72U, 0x8219322bU,
+ 0x1a34685cU, 0x8b0b161dU, 0xfee1df3eU, 0x8a09121bU,
+ 0x09122436U, 0xc98f038cU, 0x87132635U, 0x4e9c25b9U,
+ 0xe1dfa37cU, 0x2e5cb8e4U, 0xe4d5b762U, 0xe0dda77aU,
+ 0xebcb8b40U, 0x903d7a47U, 0xa455aaffU, 0x1e3c7844U,
+ 0x85172e39U, 0x60c09d5dU, 0x00000000U, 0x254a94deU,
+ 0xf4f5f702U, 0xf1ffe31cU, 0x94356a5fU, 0x0b162c3aU,
+ 0xe7d3bb68U, 0x75eac923U, 0xefc39b58U, 0x3468d0b8U,
+ 0x3162c4a6U, 0xd4b577c2U, 0xd0bd67daU, 0x86112233U,
+ 0x7efce519U, 0xad478ec9U, 0xfde7d334U, 0x2952a4f6U,
+ 0x3060c0a0U, 0x3b76ec9aU, 0x9f234665U, 0xf8edc72aU,
+ 0xc6913faeU, 0x13264c6aU, 0x060c1814U, 0x050a141eU,
+ 0xc59733a4U, 0x11224466U, 0x77eec12fU, 0x7cf8ed15U,
+ 0x7af4f501U, 0x78f0fd0dU, 0x366cd8b4U, 0x1c387048U,
+ 0x3972e496U, 0x59b279cbU, 0x18306050U, 0x56ac45e9U,
+ 0xb37bf68dU, 0xb07dfa87U, 0x244890d8U, 0x204080c0U,
+ 0xb279f28bU, 0x9239724bU, 0xa35bb6edU, 0xc09d27baU,
+ 0x44880d85U, 0x62c49551U, 0x10204060U, 0xb475ea9fU,
+ 0x84152a3fU, 0x43861197U, 0x933b764dU, 0xc2992fb6U,
+ 0x4a9435a1U, 0xbd67cea9U, 0x8f030605U, 0x2d5ab4eeU,
+ 0xbc65caafU, 0x9c254a6fU, 0x6ad4b561U, 0x40801d9dU,
+ 0xcf831b98U, 0xa259b2ebU, 0x801d3a27U, 0x4f9e21bfU,
+ 0x1f3e7c42U, 0xca890f86U, 0xaa4992dbU, 0x42841591U,
+};
+
+static const ulong32 T1[256] = {
+ 0x69babbd2U, 0xa854e54dU, 0x5e2fe2bcU, 0xe87425cdU,
+ 0xa653f751U, 0xbbd3d06bU, 0xb9d2d66fU, 0x9a4db329U,
+ 0xa050fd5dU, 0x45accf8aU, 0x078d090eU, 0x63bfa5c6U,
+ 0xe0703dddU, 0xa452f155U, 0x299a7b52U, 0x984cb52dU,
+ 0xc9ea468fU, 0xb7d5c473U, 0x33975566U, 0xbfd1dc63U,
+ 0x6633aaccU, 0xa251fb59U, 0xb65bc771U, 0x51a6f3a2U,
+ 0xa1defe5fU, 0x9048ad3dU, 0x4da8d79aU, 0x2f99715eU,
+ 0xabdbe04bU, 0x6432acc8U, 0x73b795e6U, 0xe5fc32d7U,
+ 0xdbe370abU, 0x219e6342U, 0x3f91417eU, 0x2b9b7d56U,
+ 0xd9e276afU, 0x6bbbbdd6U, 0x82419b19U, 0xdc6e79a5U,
+ 0x57a5f9aeU, 0x8bcb800bU, 0xd66b67b1U, 0x3795596eU,
+ 0x5fa1e1beU, 0xfbf310ebU, 0x7fb181feU, 0x04020c08U,
+ 0x85cc9217U, 0x95c4a237U, 0x3a1d4e74U, 0x28147850U,
+ 0x9bc3b02bU, 0xc6635791U, 0xa9dae64fU, 0xba5dd369U,
+ 0xbe5fdf61U, 0xa5dcf257U, 0xfa7d13e9U, 0x87cd9413U,
+ 0xfe7f1fe1U, 0xb45ac175U, 0xd86c75adU, 0xb85cd56dU,
+ 0xf3f708fbU, 0x4c26d498U, 0xe3ff38dbU, 0xc7ed5493U,
+ 0xcde84a87U, 0x279d694eU, 0xde6f7fa1U, 0x018e0302U,
+ 0x32195664U, 0x5da0e7baU, 0xfdf01ae7U, 0x0f89111eU,
+ 0x1e0f223cU, 0x0e07121cU, 0x43afc586U, 0xebfb20cbU,
+ 0x10083020U, 0x2a157e54U, 0x1a0d2e34U, 0x08041810U,
+ 0x02010604U, 0xc864458dU, 0xa3dff85bU, 0xec7629c5U,
+ 0xf2790bf9U, 0xa7ddf453U, 0x7a3d8ef4U, 0x2c167458U,
+ 0x7e3f82fcU, 0x6e37b2dcU, 0xda6d73a9U, 0x703890e0U,
+ 0x6fb9b1deU, 0xe67337d1U, 0xcfe94c83U, 0x6a35bed4U,
+ 0xaa55e349U, 0xe2713bd9U, 0xf67b07f1U, 0x058c0f0aU,
+ 0xe47231d5U, 0x0d88171aU, 0xf1f60effU, 0x542afca8U,
+ 0x7c3e84f8U, 0xbc5ed965U, 0x4e27d29cU, 0x8c468905U,
+ 0x180c2830U, 0xca654389U, 0xd0686dbdU, 0xc2615b99U,
+ 0x06030a0cU, 0x9fc1bc23U, 0xae57ef41U, 0xb1d6ce7fU,
+ 0xafd9ec43U, 0xb058cd7dU, 0xadd8ea47U, 0xcc664985U,
+ 0xb3d7c87bU, 0x743a9ce8U, 0x8dc88a07U, 0x783c88f0U,
+ 0xe9fa26cfU, 0x31965362U, 0x53a7f5a6U, 0x2d98775aU,
+ 0xc5ec5297U, 0x6db8b7daU, 0x93c7a83bU, 0x41aec382U,
+ 0xd2696bb9U, 0x964ba731U, 0x4babdd96U, 0x4fa9d19eU,
+ 0xce674f81U, 0x140a3c28U, 0x8e478f01U, 0xf9f216efU,
+ 0x77b599eeU, 0x4422cc88U, 0xd7e564b3U, 0xc1ee5e9fU,
+ 0x61bea3c2U, 0x562bfaacU, 0x1f81213eU, 0x24126c48U,
+ 0x1b832d36U, 0x361b5a6cU, 0x1c0e2438U, 0x4623ca8cU,
+ 0xf7f504f3U, 0x8a458309U, 0x4221c684U, 0x81ce9e1fU,
+ 0x9249ab39U, 0x582ce8b0U, 0xeff92cc3U, 0xd1e66ebfU,
+ 0x71b693e2U, 0x5028f0a0U, 0x2e17725cU, 0x19822b32U,
+ 0x341a5c68U, 0x0b8b1d16U, 0xe1fe3edfU, 0x098a1b12U,
+ 0x12093624U, 0x8fc98c03U, 0x13873526U, 0x9c4eb925U,
+ 0xdfe17ca3U, 0x5c2ee4b8U, 0xd5e462b7U, 0xdde07aa7U,
+ 0xcbeb408bU, 0x3d90477aU, 0x55a4ffaaU, 0x3c1e4478U,
+ 0x1785392eU, 0xc0605d9dU, 0x00000000U, 0x4a25de94U,
+ 0xf5f402f7U, 0xfff11ce3U, 0x35945f6aU, 0x160b3a2cU,
+ 0xd3e768bbU, 0xea7523c9U, 0xc3ef589bU, 0x6834b8d0U,
+ 0x6231a6c4U, 0xb5d4c277U, 0xbdd0da67U, 0x11863322U,
+ 0xfc7e19e5U, 0x47adc98eU, 0xe7fd34d3U, 0x5229f6a4U,
+ 0x6030a0c0U, 0x763b9aecU, 0x239f6546U, 0xedf82ac7U,
+ 0x91c6ae3fU, 0x26136a4cU, 0x0c061418U, 0x0a051e14U,
+ 0x97c5a433U, 0x22116644U, 0xee772fc1U, 0xf87c15edU,
+ 0xf47a01f5U, 0xf0780dfdU, 0x6c36b4d8U, 0x381c4870U,
+ 0x723996e4U, 0xb259cb79U, 0x30185060U, 0xac56e945U,
+ 0x7bb38df6U, 0x7db087faU, 0x4824d890U, 0x4020c080U,
+ 0x79b28bf2U, 0x39924b72U, 0x5ba3edb6U, 0x9dc0ba27U,
+ 0x8844850dU, 0xc4625195U, 0x20106040U, 0x75b49feaU,
+ 0x15843f2aU, 0x86439711U, 0x3b934d76U, 0x99c2b62fU,
+ 0x944aa135U, 0x67bda9ceU, 0x038f0506U, 0x5a2deeb4U,
+ 0x65bcafcaU, 0x259c6f4aU, 0xd46a61b5U, 0x80409d1dU,
+ 0x83cf981bU, 0x59a2ebb2U, 0x1d80273aU, 0x9e4fbf21U,
+ 0x3e1f427cU, 0x89ca860fU, 0x49aadb92U, 0x84429115U,
+};
+
+static const ulong32 T2[256] = {
+ 0xd2bbba69U, 0x4de554a8U, 0xbce22f5eU, 0xcd2574e8U,
+ 0x51f753a6U, 0x6bd0d3bbU, 0x6fd6d2b9U, 0x29b34d9aU,
+ 0x5dfd50a0U, 0x8acfac45U, 0x0e098d07U, 0xc6a5bf63U,
+ 0xdd3d70e0U, 0x55f152a4U, 0x527b9a29U, 0x2db54c98U,
+ 0x8f46eac9U, 0x73c4d5b7U, 0x66559733U, 0x63dcd1bfU,
+ 0xccaa3366U, 0x59fb51a2U, 0x71c75bb6U, 0xa2f3a651U,
+ 0x5ffedea1U, 0x3dad4890U, 0x9ad7a84dU, 0x5e71992fU,
+ 0x4be0dbabU, 0xc8ac3264U, 0xe695b773U, 0xd732fce5U,
+ 0xab70e3dbU, 0x42639e21U, 0x7e41913fU, 0x567d9b2bU,
+ 0xaf76e2d9U, 0xd6bdbb6bU, 0x199b4182U, 0xa5796edcU,
+ 0xaef9a557U, 0x0b80cb8bU, 0xb1676bd6U, 0x6e599537U,
+ 0xbee1a15fU, 0xeb10f3fbU, 0xfe81b17fU, 0x080c0204U,
+ 0x1792cc85U, 0x37a2c495U, 0x744e1d3aU, 0x50781428U,
+ 0x2bb0c39bU, 0x915763c6U, 0x4fe6daa9U, 0x69d35dbaU,
+ 0x61df5fbeU, 0x57f2dca5U, 0xe9137dfaU, 0x1394cd87U,
+ 0xe11f7ffeU, 0x75c15ab4U, 0xad756cd8U, 0x6dd55cb8U,
+ 0xfb08f7f3U, 0x98d4264cU, 0xdb38ffe3U, 0x9354edc7U,
+ 0x874ae8cdU, 0x4e699d27U, 0xa17f6fdeU, 0x02038e01U,
+ 0x64561932U, 0xbae7a05dU, 0xe71af0fdU, 0x1e11890fU,
+ 0x3c220f1eU, 0x1c12070eU, 0x86c5af43U, 0xcb20fbebU,
+ 0x20300810U, 0x547e152aU, 0x342e0d1aU, 0x10180408U,
+ 0x04060102U, 0x8d4564c8U, 0x5bf8dfa3U, 0xc52976ecU,
+ 0xf90b79f2U, 0x53f4dda7U, 0xf48e3d7aU, 0x5874162cU,
+ 0xfc823f7eU, 0xdcb2376eU, 0xa9736ddaU, 0xe0903870U,
+ 0xdeb1b96fU, 0xd13773e6U, 0x834ce9cfU, 0xd4be356aU,
+ 0x49e355aaU, 0xd93b71e2U, 0xf1077bf6U, 0x0a0f8c05U,
+ 0xd53172e4U, 0x1a17880dU, 0xff0ef6f1U, 0xa8fc2a54U,
+ 0xf8843e7cU, 0x65d95ebcU, 0x9cd2274eU, 0x0589468cU,
+ 0x30280c18U, 0x894365caU, 0xbd6d68d0U, 0x995b61c2U,
+ 0x0c0a0306U, 0x23bcc19fU, 0x41ef57aeU, 0x7fced6b1U,
+ 0x43ecd9afU, 0x7dcd58b0U, 0x47ead8adU, 0x854966ccU,
+ 0x7bc8d7b3U, 0xe89c3a74U, 0x078ac88dU, 0xf0883c78U,
+ 0xcf26fae9U, 0x62539631U, 0xa6f5a753U, 0x5a77982dU,
+ 0x9752ecc5U, 0xdab7b86dU, 0x3ba8c793U, 0x82c3ae41U,
+ 0xb96b69d2U, 0x31a74b96U, 0x96ddab4bU, 0x9ed1a94fU,
+ 0x814f67ceU, 0x283c0a14U, 0x018f478eU, 0xef16f2f9U,
+ 0xee99b577U, 0x88cc2244U, 0xb364e5d7U, 0x9f5eeec1U,
+ 0xc2a3be61U, 0xacfa2b56U, 0x3e21811fU, 0x486c1224U,
+ 0x362d831bU, 0x6c5a1b36U, 0x38240e1cU, 0x8cca2346U,
+ 0xf304f5f7U, 0x0983458aU, 0x84c62142U, 0x1f9ece81U,
+ 0x39ab4992U, 0xb0e82c58U, 0xc32cf9efU, 0xbf6ee6d1U,
+ 0xe293b671U, 0xa0f02850U, 0x5c72172eU, 0x322b8219U,
+ 0x685c1a34U, 0x161d8b0bU, 0xdf3efee1U, 0x121b8a09U,
+ 0x24360912U, 0x038cc98fU, 0x26358713U, 0x25b94e9cU,
+ 0xa37ce1dfU, 0xb8e42e5cU, 0xb762e4d5U, 0xa77ae0ddU,
+ 0x8b40ebcbU, 0x7a47903dU, 0xaaffa455U, 0x78441e3cU,
+ 0x2e398517U, 0x9d5d60c0U, 0x00000000U, 0x94de254aU,
+ 0xf702f4f5U, 0xe31cf1ffU, 0x6a5f9435U, 0x2c3a0b16U,
+ 0xbb68e7d3U, 0xc92375eaU, 0x9b58efc3U, 0xd0b83468U,
+ 0xc4a63162U, 0x77c2d4b5U, 0x67dad0bdU, 0x22338611U,
+ 0xe5197efcU, 0x8ec9ad47U, 0xd334fde7U, 0xa4f62952U,
+ 0xc0a03060U, 0xec9a3b76U, 0x46659f23U, 0xc72af8edU,
+ 0x3faec691U, 0x4c6a1326U, 0x1814060cU, 0x141e050aU,
+ 0x33a4c597U, 0x44661122U, 0xc12f77eeU, 0xed157cf8U,
+ 0xf5017af4U, 0xfd0d78f0U, 0xd8b4366cU, 0x70481c38U,
+ 0xe4963972U, 0x79cb59b2U, 0x60501830U, 0x45e956acU,
+ 0xf68db37bU, 0xfa87b07dU, 0x90d82448U, 0x80c02040U,
+ 0xf28bb279U, 0x724b9239U, 0xb6eda35bU, 0x27bac09dU,
+ 0x0d854488U, 0x955162c4U, 0x40601020U, 0xea9fb475U,
+ 0x2a3f8415U, 0x11974386U, 0x764d933bU, 0x2fb6c299U,
+ 0x35a14a94U, 0xcea9bd67U, 0x06058f03U, 0xb4ee2d5aU,
+ 0xcaafbc65U, 0x4a6f9c25U, 0xb5616ad4U, 0x1d9d4080U,
+ 0x1b98cf83U, 0xb2eba259U, 0x3a27801dU, 0x21bf4f9eU,
+ 0x7c421f3eU, 0x0f86ca89U, 0x92dbaa49U, 0x15914284U,
+};
+
+static const ulong32 T3[256] = {
+ 0xbbd269baU, 0xe54da854U, 0xe2bc5e2fU, 0x25cde874U,
+ 0xf751a653U, 0xd06bbbd3U, 0xd66fb9d2U, 0xb3299a4dU,
+ 0xfd5da050U, 0xcf8a45acU, 0x090e078dU, 0xa5c663bfU,
+ 0x3ddde070U, 0xf155a452U, 0x7b52299aU, 0xb52d984cU,
+ 0x468fc9eaU, 0xc473b7d5U, 0x55663397U, 0xdc63bfd1U,
+ 0xaacc6633U, 0xfb59a251U, 0xc771b65bU, 0xf3a251a6U,
+ 0xfe5fa1deU, 0xad3d9048U, 0xd79a4da8U, 0x715e2f99U,
+ 0xe04babdbU, 0xacc86432U, 0x95e673b7U, 0x32d7e5fcU,
+ 0x70abdbe3U, 0x6342219eU, 0x417e3f91U, 0x7d562b9bU,
+ 0x76afd9e2U, 0xbdd66bbbU, 0x9b198241U, 0x79a5dc6eU,
+ 0xf9ae57a5U, 0x800b8bcbU, 0x67b1d66bU, 0x596e3795U,
+ 0xe1be5fa1U, 0x10ebfbf3U, 0x81fe7fb1U, 0x0c080402U,
+ 0x921785ccU, 0xa23795c4U, 0x4e743a1dU, 0x78502814U,
+ 0xb02b9bc3U, 0x5791c663U, 0xe64fa9daU, 0xd369ba5dU,
+ 0xdf61be5fU, 0xf257a5dcU, 0x13e9fa7dU, 0x941387cdU,
+ 0x1fe1fe7fU, 0xc175b45aU, 0x75add86cU, 0xd56db85cU,
+ 0x08fbf3f7U, 0xd4984c26U, 0x38dbe3ffU, 0x5493c7edU,
+ 0x4a87cde8U, 0x694e279dU, 0x7fa1de6fU, 0x0302018eU,
+ 0x56643219U, 0xe7ba5da0U, 0x1ae7fdf0U, 0x111e0f89U,
+ 0x223c1e0fU, 0x121c0e07U, 0xc58643afU, 0x20cbebfbU,
+ 0x30201008U, 0x7e542a15U, 0x2e341a0dU, 0x18100804U,
+ 0x06040201U, 0x458dc864U, 0xf85ba3dfU, 0x29c5ec76U,
+ 0x0bf9f279U, 0xf453a7ddU, 0x8ef47a3dU, 0x74582c16U,
+ 0x82fc7e3fU, 0xb2dc6e37U, 0x73a9da6dU, 0x90e07038U,
+ 0xb1de6fb9U, 0x37d1e673U, 0x4c83cfe9U, 0xbed46a35U,
+ 0xe349aa55U, 0x3bd9e271U, 0x07f1f67bU, 0x0f0a058cU,
+ 0x31d5e472U, 0x171a0d88U, 0x0efff1f6U, 0xfca8542aU,
+ 0x84f87c3eU, 0xd965bc5eU, 0xd29c4e27U, 0x89058c46U,
+ 0x2830180cU, 0x4389ca65U, 0x6dbdd068U, 0x5b99c261U,
+ 0x0a0c0603U, 0xbc239fc1U, 0xef41ae57U, 0xce7fb1d6U,
+ 0xec43afd9U, 0xcd7db058U, 0xea47add8U, 0x4985cc66U,
+ 0xc87bb3d7U, 0x9ce8743aU, 0x8a078dc8U, 0x88f0783cU,
+ 0x26cfe9faU, 0x53623196U, 0xf5a653a7U, 0x775a2d98U,
+ 0x5297c5ecU, 0xb7da6db8U, 0xa83b93c7U, 0xc38241aeU,
+ 0x6bb9d269U, 0xa731964bU, 0xdd964babU, 0xd19e4fa9U,
+ 0x4f81ce67U, 0x3c28140aU, 0x8f018e47U, 0x16eff9f2U,
+ 0x99ee77b5U, 0xcc884422U, 0x64b3d7e5U, 0x5e9fc1eeU,
+ 0xa3c261beU, 0xfaac562bU, 0x213e1f81U, 0x6c482412U,
+ 0x2d361b83U, 0x5a6c361bU, 0x24381c0eU, 0xca8c4623U,
+ 0x04f3f7f5U, 0x83098a45U, 0xc6844221U, 0x9e1f81ceU,
+ 0xab399249U, 0xe8b0582cU, 0x2cc3eff9U, 0x6ebfd1e6U,
+ 0x93e271b6U, 0xf0a05028U, 0x725c2e17U, 0x2b321982U,
+ 0x5c68341aU, 0x1d160b8bU, 0x3edfe1feU, 0x1b12098aU,
+ 0x36241209U, 0x8c038fc9U, 0x35261387U, 0xb9259c4eU,
+ 0x7ca3dfe1U, 0xe4b85c2eU, 0x62b7d5e4U, 0x7aa7dde0U,
+ 0x408bcbebU, 0x477a3d90U, 0xffaa55a4U, 0x44783c1eU,
+ 0x392e1785U, 0x5d9dc060U, 0x00000000U, 0xde944a25U,
+ 0x02f7f5f4U, 0x1ce3fff1U, 0x5f6a3594U, 0x3a2c160bU,
+ 0x68bbd3e7U, 0x23c9ea75U, 0x589bc3efU, 0xb8d06834U,
+ 0xa6c46231U, 0xc277b5d4U, 0xda67bdd0U, 0x33221186U,
+ 0x19e5fc7eU, 0xc98e47adU, 0x34d3e7fdU, 0xf6a45229U,
+ 0xa0c06030U, 0x9aec763bU, 0x6546239fU, 0x2ac7edf8U,
+ 0xae3f91c6U, 0x6a4c2613U, 0x14180c06U, 0x1e140a05U,
+ 0xa43397c5U, 0x66442211U, 0x2fc1ee77U, 0x15edf87cU,
+ 0x01f5f47aU, 0x0dfdf078U, 0xb4d86c36U, 0x4870381cU,
+ 0x96e47239U, 0xcb79b259U, 0x50603018U, 0xe945ac56U,
+ 0x8df67bb3U, 0x87fa7db0U, 0xd8904824U, 0xc0804020U,
+ 0x8bf279b2U, 0x4b723992U, 0xedb65ba3U, 0xba279dc0U,
+ 0x850d8844U, 0x5195c462U, 0x60402010U, 0x9fea75b4U,
+ 0x3f2a1584U, 0x97118643U, 0x4d763b93U, 0xb62f99c2U,
+ 0xa135944aU, 0xa9ce67bdU, 0x0506038fU, 0xeeb45a2dU,
+ 0xafca65bcU, 0x6f4a259cU, 0x61b5d46aU, 0x9d1d8040U,
+ 0x981b83cfU, 0xebb259a2U, 0x273a1d80U, 0xbf219e4fU,
+ 0x427c3e1fU, 0x860f89caU, 0xdb9249aaU, 0x91158442U,
+};
+
+static const ulong32 T4[256] = {
+ 0xbabababaU, 0x54545454U, 0x2f2f2f2fU, 0x74747474U,
+ 0x53535353U, 0xd3d3d3d3U, 0xd2d2d2d2U, 0x4d4d4d4dU,
+ 0x50505050U, 0xacacacacU, 0x8d8d8d8dU, 0xbfbfbfbfU,
+ 0x70707070U, 0x52525252U, 0x9a9a9a9aU, 0x4c4c4c4cU,
+ 0xeaeaeaeaU, 0xd5d5d5d5U, 0x97979797U, 0xd1d1d1d1U,
+ 0x33333333U, 0x51515151U, 0x5b5b5b5bU, 0xa6a6a6a6U,
+ 0xdedededeU, 0x48484848U, 0xa8a8a8a8U, 0x99999999U,
+ 0xdbdbdbdbU, 0x32323232U, 0xb7b7b7b7U, 0xfcfcfcfcU,
+ 0xe3e3e3e3U, 0x9e9e9e9eU, 0x91919191U, 0x9b9b9b9bU,
+ 0xe2e2e2e2U, 0xbbbbbbbbU, 0x41414141U, 0x6e6e6e6eU,
+ 0xa5a5a5a5U, 0xcbcbcbcbU, 0x6b6b6b6bU, 0x95959595U,
+ 0xa1a1a1a1U, 0xf3f3f3f3U, 0xb1b1b1b1U, 0x02020202U,
+ 0xccccccccU, 0xc4c4c4c4U, 0x1d1d1d1dU, 0x14141414U,
+ 0xc3c3c3c3U, 0x63636363U, 0xdadadadaU, 0x5d5d5d5dU,
+ 0x5f5f5f5fU, 0xdcdcdcdcU, 0x7d7d7d7dU, 0xcdcdcdcdU,
+ 0x7f7f7f7fU, 0x5a5a5a5aU, 0x6c6c6c6cU, 0x5c5c5c5cU,
+ 0xf7f7f7f7U, 0x26262626U, 0xffffffffU, 0xededededU,
+ 0xe8e8e8e8U, 0x9d9d9d9dU, 0x6f6f6f6fU, 0x8e8e8e8eU,
+ 0x19191919U, 0xa0a0a0a0U, 0xf0f0f0f0U, 0x89898989U,
+ 0x0f0f0f0fU, 0x07070707U, 0xafafafafU, 0xfbfbfbfbU,
+ 0x08080808U, 0x15151515U, 0x0d0d0d0dU, 0x04040404U,
+ 0x01010101U, 0x64646464U, 0xdfdfdfdfU, 0x76767676U,
+ 0x79797979U, 0xddddddddU, 0x3d3d3d3dU, 0x16161616U,
+ 0x3f3f3f3fU, 0x37373737U, 0x6d6d6d6dU, 0x38383838U,
+ 0xb9b9b9b9U, 0x73737373U, 0xe9e9e9e9U, 0x35353535U,
+ 0x55555555U, 0x71717171U, 0x7b7b7b7bU, 0x8c8c8c8cU,
+ 0x72727272U, 0x88888888U, 0xf6f6f6f6U, 0x2a2a2a2aU,
+ 0x3e3e3e3eU, 0x5e5e5e5eU, 0x27272727U, 0x46464646U,
+ 0x0c0c0c0cU, 0x65656565U, 0x68686868U, 0x61616161U,
+ 0x03030303U, 0xc1c1c1c1U, 0x57575757U, 0xd6d6d6d6U,
+ 0xd9d9d9d9U, 0x58585858U, 0xd8d8d8d8U, 0x66666666U,
+ 0xd7d7d7d7U, 0x3a3a3a3aU, 0xc8c8c8c8U, 0x3c3c3c3cU,
+ 0xfafafafaU, 0x96969696U, 0xa7a7a7a7U, 0x98989898U,
+ 0xececececU, 0xb8b8b8b8U, 0xc7c7c7c7U, 0xaeaeaeaeU,
+ 0x69696969U, 0x4b4b4b4bU, 0xababababU, 0xa9a9a9a9U,
+ 0x67676767U, 0x0a0a0a0aU, 0x47474747U, 0xf2f2f2f2U,
+ 0xb5b5b5b5U, 0x22222222U, 0xe5e5e5e5U, 0xeeeeeeeeU,
+ 0xbebebebeU, 0x2b2b2b2bU, 0x81818181U, 0x12121212U,
+ 0x83838383U, 0x1b1b1b1bU, 0x0e0e0e0eU, 0x23232323U,
+ 0xf5f5f5f5U, 0x45454545U, 0x21212121U, 0xcecececeU,
+ 0x49494949U, 0x2c2c2c2cU, 0xf9f9f9f9U, 0xe6e6e6e6U,
+ 0xb6b6b6b6U, 0x28282828U, 0x17171717U, 0x82828282U,
+ 0x1a1a1a1aU, 0x8b8b8b8bU, 0xfefefefeU, 0x8a8a8a8aU,
+ 0x09090909U, 0xc9c9c9c9U, 0x87878787U, 0x4e4e4e4eU,
+ 0xe1e1e1e1U, 0x2e2e2e2eU, 0xe4e4e4e4U, 0xe0e0e0e0U,
+ 0xebebebebU, 0x90909090U, 0xa4a4a4a4U, 0x1e1e1e1eU,
+ 0x85858585U, 0x60606060U, 0x00000000U, 0x25252525U,
+ 0xf4f4f4f4U, 0xf1f1f1f1U, 0x94949494U, 0x0b0b0b0bU,
+ 0xe7e7e7e7U, 0x75757575U, 0xefefefefU, 0x34343434U,
+ 0x31313131U, 0xd4d4d4d4U, 0xd0d0d0d0U, 0x86868686U,
+ 0x7e7e7e7eU, 0xadadadadU, 0xfdfdfdfdU, 0x29292929U,
+ 0x30303030U, 0x3b3b3b3bU, 0x9f9f9f9fU, 0xf8f8f8f8U,
+ 0xc6c6c6c6U, 0x13131313U, 0x06060606U, 0x05050505U,
+ 0xc5c5c5c5U, 0x11111111U, 0x77777777U, 0x7c7c7c7cU,
+ 0x7a7a7a7aU, 0x78787878U, 0x36363636U, 0x1c1c1c1cU,
+ 0x39393939U, 0x59595959U, 0x18181818U, 0x56565656U,
+ 0xb3b3b3b3U, 0xb0b0b0b0U, 0x24242424U, 0x20202020U,
+ 0xb2b2b2b2U, 0x92929292U, 0xa3a3a3a3U, 0xc0c0c0c0U,
+ 0x44444444U, 0x62626262U, 0x10101010U, 0xb4b4b4b4U,
+ 0x84848484U, 0x43434343U, 0x93939393U, 0xc2c2c2c2U,
+ 0x4a4a4a4aU, 0xbdbdbdbdU, 0x8f8f8f8fU, 0x2d2d2d2dU,
+ 0xbcbcbcbcU, 0x9c9c9c9cU, 0x6a6a6a6aU, 0x40404040U,
+ 0xcfcfcfcfU, 0xa2a2a2a2U, 0x80808080U, 0x4f4f4f4fU,
+ 0x1f1f1f1fU, 0xcacacacaU, 0xaaaaaaaaU, 0x42424242U,
+};
+
+static const ulong32 T5[256] = {
+ 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U,
+ 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U,
+ 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U,
+ 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U,
+ 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U,
+ 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U,
+ 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U,
+ 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U,
+ 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U,
+ 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U,
+ 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U,
+ 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U,
+ 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U,
+ 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U,
+ 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U,
+ 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U,
+ 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U,
+ 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U,
+ 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U,
+ 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U,
+ 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U,
+ 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U,
+ 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U,
+ 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U,
+ 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU,
+ 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU,
+ 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU,
+ 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU,
+ 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU,
+ 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU,
+ 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU,
+ 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU,
+ 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU,
+ 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU,
+ 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU,
+ 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU,
+ 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU,
+ 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU,
+ 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU,
+ 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU,
+ 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U,
+ 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U,
+ 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U,
+ 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U,
+ 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U,
+ 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U,
+ 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U,
+ 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U,
+ 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U,
+ 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U,
+ 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U,
+ 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U,
+ 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U,
+ 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U,
+ 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U,
+ 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U,
+ 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU,
+ 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU,
+ 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU,
+ 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU,
+ 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU,
+ 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU,
+ 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU,
+ 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU,
+};
+
+/**
+ * The round constants.
+ */
+static const ulong32 rc[] = {
+ 0xba542f74U, 0x53d3d24dU, 0x50ac8dbfU, 0x70529a4cU,
+ 0xead597d1U, 0x33515ba6U, 0xde48a899U, 0xdb32b7fcU,
+ 0xe39e919bU, 0xe2bb416eU, 0xa5cb6b95U, 0xa1f3b102U,
+ 0xccc41d14U, 0xc363da5dU, 0x5fdc7dcdU, 0x7f5a6c5cU,
+ 0xf726ffedU, 0xe89d6f8eU, 0x19a0f089U,
+};
+
+
+
+#else
+
+
+static const ulong32 T0[256] = {
+ 0xa753a6f5U, 0xd3bb6bd0U, 0xe6d1bf6eU, 0x71e2d93bU,
+ 0xd0bd67daU, 0xac458acfU, 0x4d9a29b3U, 0x79f2f90bU,
+ 0x3a74e89cU, 0xc98f038cU, 0x913f7e41U, 0xfce5d732U,
+ 0x1e3c7844U, 0x478e018fU, 0x54a84de5U, 0xbd67cea9U,
+ 0x8c050a0fU, 0xa557aef9U, 0x7af4f501U, 0xfbebcb20U,
+ 0x63c69157U, 0xb86ddab7U, 0xdda753f4U, 0xd4b577c2U,
+ 0xe5d7b364U, 0xb37bf68dU, 0xc59733a4U, 0xbe61c2a3U,
+ 0xa94f9ed1U, 0x880d1a17U, 0x0c183028U, 0xa259b2ebU,
+ 0x3972e496U, 0xdfa35bf8U, 0x2952a4f6U, 0xdaa94fe6U,
+ 0x2b56acfaU, 0xa84d9ad7U, 0xcb8b0b80U, 0x4c982db5U,
+ 0x4b9631a7U, 0x224488ccU, 0xaa4992dbU, 0x244890d8U,
+ 0x4182199bU, 0x70e0dd3dU, 0xa651a2f3U, 0xf9efc32cU,
+ 0x5ab475c1U, 0xe2d9af76U, 0xb07dfa87U, 0x366cd8b4U,
+ 0x7dfae913U, 0xe4d5b762U, 0x3366ccaaU, 0xffe3db38U,
+ 0x60c09d5dU, 0x204080c0U, 0x08102030U, 0x8b0b161dU,
+ 0x5ebc65d9U, 0xab4b96ddU, 0x7ffee11fU, 0x78f0fd0dU,
+ 0x7cf8ed15U, 0x2c58b0e8U, 0x57ae41efU, 0xd2b96fd6U,
+ 0xdca557f2U, 0x6ddaa973U, 0x7efce519U, 0x0d1a342eU,
+ 0x53a651f7U, 0x94356a5fU, 0xc39b2bb0U, 0x2850a0f0U,
+ 0x274e9cd2U, 0x060c1814U, 0x5fbe61dfU, 0xad478ec9U,
+ 0x67ce814fU, 0x5cb86dd5U, 0x55aa49e3U, 0x48903dadU,
+ 0x0e1c3824U, 0x52a455f1U, 0xeac98f46U, 0x42841591U,
+ 0x5bb671c7U, 0x5dba69d3U, 0x3060c0a0U, 0x58b07dcdU,
+ 0x51a259fbU, 0x59b279cbU, 0x3c78f088U, 0x4e9c25b9U,
+ 0x3870e090U, 0x8a09121bU, 0x72e4d531U, 0x14285078U,
+ 0xe7d3bb68U, 0xc6913faeU, 0xdea15ffeU, 0x50a05dfdU,
+ 0x8e010203U, 0x9239724bU, 0xd1bf63dcU, 0x77eec12fU,
+ 0x933b764dU, 0x458a0983U, 0x9a29527bU, 0xce811f9eU,
+ 0x2d5ab4eeU, 0x03060c0aU, 0x62c49551U, 0xb671e293U,
+ 0xb96fdeb1U, 0xbf63c6a5U, 0x96316253U, 0x6bd6b167U,
+ 0x3f7efc82U, 0x070e1c12U, 0x1224486cU, 0xae4182c3U,
+ 0x40801d9dU, 0x3468d0b8U, 0x468c0589U, 0x3e7cf884U,
+ 0xdbab4be0U, 0xcf831b98U, 0xecc59752U, 0xcc851792U,
+ 0xc19f23bcU, 0xa15fbee1U, 0xc09d27baU, 0xd6b17fceU,
+ 0x1d3a744eU, 0xf4f5f702U, 0x61c2995bU, 0x3b76ec9aU,
+ 0x10204060U, 0xd8ad47eaU, 0x68d0bd6dU, 0xa05dbae7U,
+ 0xb17ffe81U, 0x0a14283cU, 0x69d2b96bU, 0x6cd8ad75U,
+ 0x499239abU, 0xfae9cf26U, 0x76ecc529U, 0xc49537a2U,
+ 0x9e214263U, 0x9b2b567dU, 0x6edca579U, 0x992f5e71U,
+ 0xc2992fb6U, 0xb773e695U, 0x982d5a77U, 0xbc65caafU,
+ 0x8f030605U, 0x85172e39U, 0x1f3e7c42U, 0xb475ea9fU,
+ 0xf8edc72aU, 0x11224466U, 0x2e5cb8e4U, 0x00000000U,
+ 0x254a94deU, 0x1c387048U, 0x2a54a8fcU, 0x3d7af48eU,
+ 0x050a141eU, 0x4f9e21bfU, 0x7bf6f107U, 0xb279f28bU,
+ 0x3264c8acU, 0x903d7a47U, 0xaf4386c5U, 0x19326456U,
+ 0xa35bb6edU, 0xf7f3fb08U, 0x73e6d137U, 0x9d274e69U,
+ 0x152a547eU, 0x74e8cd25U, 0xeec19f5eU, 0xca890f86U,
+ 0x9f234665U, 0x0f1e3c22U, 0x1b366c5aU, 0x75eac923U,
+ 0x86112233U, 0x84152a3fU, 0x9c254a6fU, 0x4a9435a1U,
+ 0x97336655U, 0x1a34685cU, 0x65ca8943U, 0xf6f1ff0eU,
+ 0xedc79354U, 0x09122436U, 0xbb6bd6bdU, 0x264c98d4U,
+ 0x831b362dU, 0xebcb8b40U, 0x6fdea17fU, 0x811f3e21U,
+ 0x04081018U, 0x6ad4b561U, 0x43861197U, 0x01020406U,
+ 0x172e5c72U, 0xe1dfa37cU, 0x87132635U, 0xf5f7f304U,
+ 0x8d070e09U, 0xe3dbab70U, 0x23468ccaU, 0x801d3a27U,
+ 0x44880d85U, 0x162c5874U, 0x66cc8549U, 0x214284c6U,
+ 0xfee1df3eU, 0xd5b773c4U, 0x3162c4a6U, 0xd9af43ecU,
+ 0x356ad4beU, 0x18306050U, 0x0204080cU, 0x64c88d45U,
+ 0xf2f9ef16U, 0xf1ffe31cU, 0x56ac45e9U, 0xcd871394U,
+ 0x8219322bU, 0xc88d078aU, 0xba69d2bbU, 0xf0fde71aU,
+ 0xefc39b58U, 0xe9cf834cU, 0xe8cd874aU, 0xfde7d334U,
+ 0x890f1e11U, 0xd7b37bc8U, 0xc7933ba8U, 0xb577ee99U,
+ 0xa455aaffU, 0x2f5ebce2U, 0x95376e59U, 0x13264c6aU,
+ 0x0b162c3aU, 0xf3fbeb10U, 0xe0dda77aU, 0x376edcb2U,
+};
+
+static const ulong32 T1[256] = {
+ 0x53a7f5a6U, 0xbbd3d06bU, 0xd1e66ebfU, 0xe2713bd9U,
+ 0xbdd0da67U, 0x45accf8aU, 0x9a4db329U, 0xf2790bf9U,
+ 0x743a9ce8U, 0x8fc98c03U, 0x3f91417eU, 0xe5fc32d7U,
+ 0x3c1e4478U, 0x8e478f01U, 0xa854e54dU, 0x67bda9ceU,
+ 0x058c0f0aU, 0x57a5f9aeU, 0xf47a01f5U, 0xebfb20cbU,
+ 0xc6635791U, 0x6db8b7daU, 0xa7ddf453U, 0xb5d4c277U,
+ 0xd7e564b3U, 0x7bb38df6U, 0x97c5a433U, 0x61bea3c2U,
+ 0x4fa9d19eU, 0x0d88171aU, 0x180c2830U, 0x59a2ebb2U,
+ 0x723996e4U, 0xa3dff85bU, 0x5229f6a4U, 0xa9dae64fU,
+ 0x562bfaacU, 0x4da8d79aU, 0x8bcb800bU, 0x984cb52dU,
+ 0x964ba731U, 0x4422cc88U, 0x49aadb92U, 0x4824d890U,
+ 0x82419b19U, 0xe0703dddU, 0x51a6f3a2U, 0xeff92cc3U,
+ 0xb45ac175U, 0xd9e276afU, 0x7db087faU, 0x6c36b4d8U,
+ 0xfa7d13e9U, 0xd5e462b7U, 0x6633aaccU, 0xe3ff38dbU,
+ 0xc0605d9dU, 0x4020c080U, 0x10083020U, 0x0b8b1d16U,
+ 0xbc5ed965U, 0x4babdd96U, 0xfe7f1fe1U, 0xf0780dfdU,
+ 0xf87c15edU, 0x582ce8b0U, 0xae57ef41U, 0xb9d2d66fU,
+ 0xa5dcf257U, 0xda6d73a9U, 0xfc7e19e5U, 0x1a0d2e34U,
+ 0xa653f751U, 0x35945f6aU, 0x9bc3b02bU, 0x5028f0a0U,
+ 0x4e27d29cU, 0x0c061418U, 0xbe5fdf61U, 0x47adc98eU,
+ 0xce674f81U, 0xb85cd56dU, 0xaa55e349U, 0x9048ad3dU,
+ 0x1c0e2438U, 0xa452f155U, 0xc9ea468fU, 0x84429115U,
+ 0xb65bc771U, 0xba5dd369U, 0x6030a0c0U, 0xb058cd7dU,
+ 0xa251fb59U, 0xb259cb79U, 0x783c88f0U, 0x9c4eb925U,
+ 0x703890e0U, 0x098a1b12U, 0xe47231d5U, 0x28147850U,
+ 0xd3e768bbU, 0x91c6ae3fU, 0xa1defe5fU, 0xa050fd5dU,
+ 0x018e0302U, 0x39924b72U, 0xbfd1dc63U, 0xee772fc1U,
+ 0x3b934d76U, 0x8a458309U, 0x299a7b52U, 0x81ce9e1fU,
+ 0x5a2deeb4U, 0x06030a0cU, 0xc4625195U, 0x71b693e2U,
+ 0x6fb9b1deU, 0x63bfa5c6U, 0x31965362U, 0xd66b67b1U,
+ 0x7e3f82fcU, 0x0e07121cU, 0x24126c48U, 0x41aec382U,
+ 0x80409d1dU, 0x6834b8d0U, 0x8c468905U, 0x7c3e84f8U,
+ 0xabdbe04bU, 0x83cf981bU, 0xc5ec5297U, 0x85cc9217U,
+ 0x9fc1bc23U, 0x5fa1e1beU, 0x9dc0ba27U, 0xb1d6ce7fU,
+ 0x3a1d4e74U, 0xf5f402f7U, 0xc2615b99U, 0x763b9aecU,
+ 0x20106040U, 0xadd8ea47U, 0xd0686dbdU, 0x5da0e7baU,
+ 0x7fb181feU, 0x140a3c28U, 0xd2696bb9U, 0xd86c75adU,
+ 0x9249ab39U, 0xe9fa26cfU, 0xec7629c5U, 0x95c4a237U,
+ 0x219e6342U, 0x2b9b7d56U, 0xdc6e79a5U, 0x2f99715eU,
+ 0x99c2b62fU, 0x73b795e6U, 0x2d98775aU, 0x65bcafcaU,
+ 0x038f0506U, 0x1785392eU, 0x3e1f427cU, 0x75b49feaU,
+ 0xedf82ac7U, 0x22116644U, 0x5c2ee4b8U, 0x00000000U,
+ 0x4a25de94U, 0x381c4870U, 0x542afca8U, 0x7a3d8ef4U,
+ 0x0a051e14U, 0x9e4fbf21U, 0xf67b07f1U, 0x79b28bf2U,
+ 0x6432acc8U, 0x3d90477aU, 0x43afc586U, 0x32195664U,
+ 0x5ba3edb6U, 0xf3f708fbU, 0xe67337d1U, 0x279d694eU,
+ 0x2a157e54U, 0xe87425cdU, 0xc1ee5e9fU, 0x89ca860fU,
+ 0x239f6546U, 0x1e0f223cU, 0x361b5a6cU, 0xea7523c9U,
+ 0x11863322U, 0x15843f2aU, 0x259c6f4aU, 0x944aa135U,
+ 0x33975566U, 0x341a5c68U, 0xca654389U, 0xf1f60effU,
+ 0xc7ed5493U, 0x12093624U, 0x6bbbbdd6U, 0x4c26d498U,
+ 0x1b832d36U, 0xcbeb408bU, 0xde6f7fa1U, 0x1f81213eU,
+ 0x08041810U, 0xd46a61b5U, 0x86439711U, 0x02010604U,
+ 0x2e17725cU, 0xdfe17ca3U, 0x13873526U, 0xf7f504f3U,
+ 0x078d090eU, 0xdbe370abU, 0x4623ca8cU, 0x1d80273aU,
+ 0x8844850dU, 0x2c167458U, 0xcc664985U, 0x4221c684U,
+ 0xe1fe3edfU, 0xb7d5c473U, 0x6231a6c4U, 0xafd9ec43U,
+ 0x6a35bed4U, 0x30185060U, 0x04020c08U, 0xc864458dU,
+ 0xf9f216efU, 0xfff11ce3U, 0xac56e945U, 0x87cd9413U,
+ 0x19822b32U, 0x8dc88a07U, 0x69babbd2U, 0xfdf01ae7U,
+ 0xc3ef589bU, 0xcfe94c83U, 0xcde84a87U, 0xe7fd34d3U,
+ 0x0f89111eU, 0xb3d7c87bU, 0x93c7a83bU, 0x77b599eeU,
+ 0x55a4ffaaU, 0x5e2fe2bcU, 0x3795596eU, 0x26136a4cU,
+ 0x160b3a2cU, 0xfbf310ebU, 0xdde07aa7U, 0x6e37b2dcU,
+};
+
+static const ulong32 T2[256] = {
+ 0xa6f5a753U, 0x6bd0d3bbU, 0xbf6ee6d1U, 0xd93b71e2U,
+ 0x67dad0bdU, 0x8acfac45U, 0x29b34d9aU, 0xf90b79f2U,
+ 0xe89c3a74U, 0x038cc98fU, 0x7e41913fU, 0xd732fce5U,
+ 0x78441e3cU, 0x018f478eU, 0x4de554a8U, 0xcea9bd67U,
+ 0x0a0f8c05U, 0xaef9a557U, 0xf5017af4U, 0xcb20fbebU,
+ 0x915763c6U, 0xdab7b86dU, 0x53f4dda7U, 0x77c2d4b5U,
+ 0xb364e5d7U, 0xf68db37bU, 0x33a4c597U, 0xc2a3be61U,
+ 0x9ed1a94fU, 0x1a17880dU, 0x30280c18U, 0xb2eba259U,
+ 0xe4963972U, 0x5bf8dfa3U, 0xa4f62952U, 0x4fe6daa9U,
+ 0xacfa2b56U, 0x9ad7a84dU, 0x0b80cb8bU, 0x2db54c98U,
+ 0x31a74b96U, 0x88cc2244U, 0x92dbaa49U, 0x90d82448U,
+ 0x199b4182U, 0xdd3d70e0U, 0xa2f3a651U, 0xc32cf9efU,
+ 0x75c15ab4U, 0xaf76e2d9U, 0xfa87b07dU, 0xd8b4366cU,
+ 0xe9137dfaU, 0xb762e4d5U, 0xccaa3366U, 0xdb38ffe3U,
+ 0x9d5d60c0U, 0x80c02040U, 0x20300810U, 0x161d8b0bU,
+ 0x65d95ebcU, 0x96ddab4bU, 0xe11f7ffeU, 0xfd0d78f0U,
+ 0xed157cf8U, 0xb0e82c58U, 0x41ef57aeU, 0x6fd6d2b9U,
+ 0x57f2dca5U, 0xa9736ddaU, 0xe5197efcU, 0x342e0d1aU,
+ 0x51f753a6U, 0x6a5f9435U, 0x2bb0c39bU, 0xa0f02850U,
+ 0x9cd2274eU, 0x1814060cU, 0x61df5fbeU, 0x8ec9ad47U,
+ 0x814f67ceU, 0x6dd55cb8U, 0x49e355aaU, 0x3dad4890U,
+ 0x38240e1cU, 0x55f152a4U, 0x8f46eac9U, 0x15914284U,
+ 0x71c75bb6U, 0x69d35dbaU, 0xc0a03060U, 0x7dcd58b0U,
+ 0x59fb51a2U, 0x79cb59b2U, 0xf0883c78U, 0x25b94e9cU,
+ 0xe0903870U, 0x121b8a09U, 0xd53172e4U, 0x50781428U,
+ 0xbb68e7d3U, 0x3faec691U, 0x5ffedea1U, 0x5dfd50a0U,
+ 0x02038e01U, 0x724b9239U, 0x63dcd1bfU, 0xc12f77eeU,
+ 0x764d933bU, 0x0983458aU, 0x527b9a29U, 0x1f9ece81U,
+ 0xb4ee2d5aU, 0x0c0a0306U, 0x955162c4U, 0xe293b671U,
+ 0xdeb1b96fU, 0xc6a5bf63U, 0x62539631U, 0xb1676bd6U,
+ 0xfc823f7eU, 0x1c12070eU, 0x486c1224U, 0x82c3ae41U,
+ 0x1d9d4080U, 0xd0b83468U, 0x0589468cU, 0xf8843e7cU,
+ 0x4be0dbabU, 0x1b98cf83U, 0x9752ecc5U, 0x1792cc85U,
+ 0x23bcc19fU, 0xbee1a15fU, 0x27bac09dU, 0x7fced6b1U,
+ 0x744e1d3aU, 0xf702f4f5U, 0x995b61c2U, 0xec9a3b76U,
+ 0x40601020U, 0x47ead8adU, 0xbd6d68d0U, 0xbae7a05dU,
+ 0xfe81b17fU, 0x283c0a14U, 0xb96b69d2U, 0xad756cd8U,
+ 0x39ab4992U, 0xcf26fae9U, 0xc52976ecU, 0x37a2c495U,
+ 0x42639e21U, 0x567d9b2bU, 0xa5796edcU, 0x5e71992fU,
+ 0x2fb6c299U, 0xe695b773U, 0x5a77982dU, 0xcaafbc65U,
+ 0x06058f03U, 0x2e398517U, 0x7c421f3eU, 0xea9fb475U,
+ 0xc72af8edU, 0x44661122U, 0xb8e42e5cU, 0x00000000U,
+ 0x94de254aU, 0x70481c38U, 0xa8fc2a54U, 0xf48e3d7aU,
+ 0x141e050aU, 0x21bf4f9eU, 0xf1077bf6U, 0xf28bb279U,
+ 0xc8ac3264U, 0x7a47903dU, 0x86c5af43U, 0x64561932U,
+ 0xb6eda35bU, 0xfb08f7f3U, 0xd13773e6U, 0x4e699d27U,
+ 0x547e152aU, 0xcd2574e8U, 0x9f5eeec1U, 0x0f86ca89U,
+ 0x46659f23U, 0x3c220f1eU, 0x6c5a1b36U, 0xc92375eaU,
+ 0x22338611U, 0x2a3f8415U, 0x4a6f9c25U, 0x35a14a94U,
+ 0x66559733U, 0x685c1a34U, 0x894365caU, 0xff0ef6f1U,
+ 0x9354edc7U, 0x24360912U, 0xd6bdbb6bU, 0x98d4264cU,
+ 0x362d831bU, 0x8b40ebcbU, 0xa17f6fdeU, 0x3e21811fU,
+ 0x10180408U, 0xb5616ad4U, 0x11974386U, 0x04060102U,
+ 0x5c72172eU, 0xa37ce1dfU, 0x26358713U, 0xf304f5f7U,
+ 0x0e098d07U, 0xab70e3dbU, 0x8cca2346U, 0x3a27801dU,
+ 0x0d854488U, 0x5874162cU, 0x854966ccU, 0x84c62142U,
+ 0xdf3efee1U, 0x73c4d5b7U, 0xc4a63162U, 0x43ecd9afU,
+ 0xd4be356aU, 0x60501830U, 0x080c0204U, 0x8d4564c8U,
+ 0xef16f2f9U, 0xe31cf1ffU, 0x45e956acU, 0x1394cd87U,
+ 0x322b8219U, 0x078ac88dU, 0xd2bbba69U, 0xe71af0fdU,
+ 0x9b58efc3U, 0x834ce9cfU, 0x874ae8cdU, 0xd334fde7U,
+ 0x1e11890fU, 0x7bc8d7b3U, 0x3ba8c793U, 0xee99b577U,
+ 0xaaffa455U, 0xbce22f5eU, 0x6e599537U, 0x4c6a1326U,
+ 0x2c3a0b16U, 0xeb10f3fbU, 0xa77ae0ddU, 0xdcb2376eU,
+};
+
+static const ulong32 T3[256] = {
+ 0xf5a653a7U, 0xd06bbbd3U, 0x6ebfd1e6U, 0x3bd9e271U,
+ 0xda67bdd0U, 0xcf8a45acU, 0xb3299a4dU, 0x0bf9f279U,
+ 0x9ce8743aU, 0x8c038fc9U, 0x417e3f91U, 0x32d7e5fcU,
+ 0x44783c1eU, 0x8f018e47U, 0xe54da854U, 0xa9ce67bdU,
+ 0x0f0a058cU, 0xf9ae57a5U, 0x01f5f47aU, 0x20cbebfbU,
+ 0x5791c663U, 0xb7da6db8U, 0xf453a7ddU, 0xc277b5d4U,
+ 0x64b3d7e5U, 0x8df67bb3U, 0xa43397c5U, 0xa3c261beU,
+ 0xd19e4fa9U, 0x171a0d88U, 0x2830180cU, 0xebb259a2U,
+ 0x96e47239U, 0xf85ba3dfU, 0xf6a45229U, 0xe64fa9daU,
+ 0xfaac562bU, 0xd79a4da8U, 0x800b8bcbU, 0xb52d984cU,
+ 0xa731964bU, 0xcc884422U, 0xdb9249aaU, 0xd8904824U,
+ 0x9b198241U, 0x3ddde070U, 0xf3a251a6U, 0x2cc3eff9U,
+ 0xc175b45aU, 0x76afd9e2U, 0x87fa7db0U, 0xb4d86c36U,
+ 0x13e9fa7dU, 0x62b7d5e4U, 0xaacc6633U, 0x38dbe3ffU,
+ 0x5d9dc060U, 0xc0804020U, 0x30201008U, 0x1d160b8bU,
+ 0xd965bc5eU, 0xdd964babU, 0x1fe1fe7fU, 0x0dfdf078U,
+ 0x15edf87cU, 0xe8b0582cU, 0xef41ae57U, 0xd66fb9d2U,
+ 0xf257a5dcU, 0x73a9da6dU, 0x19e5fc7eU, 0x2e341a0dU,
+ 0xf751a653U, 0x5f6a3594U, 0xb02b9bc3U, 0xf0a05028U,
+ 0xd29c4e27U, 0x14180c06U, 0xdf61be5fU, 0xc98e47adU,
+ 0x4f81ce67U, 0xd56db85cU, 0xe349aa55U, 0xad3d9048U,
+ 0x24381c0eU, 0xf155a452U, 0x468fc9eaU, 0x91158442U,
+ 0xc771b65bU, 0xd369ba5dU, 0xa0c06030U, 0xcd7db058U,
+ 0xfb59a251U, 0xcb79b259U, 0x88f0783cU, 0xb9259c4eU,
+ 0x90e07038U, 0x1b12098aU, 0x31d5e472U, 0x78502814U,
+ 0x68bbd3e7U, 0xae3f91c6U, 0xfe5fa1deU, 0xfd5da050U,
+ 0x0302018eU, 0x4b723992U, 0xdc63bfd1U, 0x2fc1ee77U,
+ 0x4d763b93U, 0x83098a45U, 0x7b52299aU, 0x9e1f81ceU,
+ 0xeeb45a2dU, 0x0a0c0603U, 0x5195c462U, 0x93e271b6U,
+ 0xb1de6fb9U, 0xa5c663bfU, 0x53623196U, 0x67b1d66bU,
+ 0x82fc7e3fU, 0x121c0e07U, 0x6c482412U, 0xc38241aeU,
+ 0x9d1d8040U, 0xb8d06834U, 0x89058c46U, 0x84f87c3eU,
+ 0xe04babdbU, 0x981b83cfU, 0x5297c5ecU, 0x921785ccU,
+ 0xbc239fc1U, 0xe1be5fa1U, 0xba279dc0U, 0xce7fb1d6U,
+ 0x4e743a1dU, 0x02f7f5f4U, 0x5b99c261U, 0x9aec763bU,
+ 0x60402010U, 0xea47add8U, 0x6dbdd068U, 0xe7ba5da0U,
+ 0x81fe7fb1U, 0x3c28140aU, 0x6bb9d269U, 0x75add86cU,
+ 0xab399249U, 0x26cfe9faU, 0x29c5ec76U, 0xa23795c4U,
+ 0x6342219eU, 0x7d562b9bU, 0x79a5dc6eU, 0x715e2f99U,
+ 0xb62f99c2U, 0x95e673b7U, 0x775a2d98U, 0xafca65bcU,
+ 0x0506038fU, 0x392e1785U, 0x427c3e1fU, 0x9fea75b4U,
+ 0x2ac7edf8U, 0x66442211U, 0xe4b85c2eU, 0x00000000U,
+ 0xde944a25U, 0x4870381cU, 0xfca8542aU, 0x8ef47a3dU,
+ 0x1e140a05U, 0xbf219e4fU, 0x07f1f67bU, 0x8bf279b2U,
+ 0xacc86432U, 0x477a3d90U, 0xc58643afU, 0x56643219U,
+ 0xedb65ba3U, 0x08fbf3f7U, 0x37d1e673U, 0x694e279dU,
+ 0x7e542a15U, 0x25cde874U, 0x5e9fc1eeU, 0x860f89caU,
+ 0x6546239fU, 0x223c1e0fU, 0x5a6c361bU, 0x23c9ea75U,
+ 0x33221186U, 0x3f2a1584U, 0x6f4a259cU, 0xa135944aU,
+ 0x55663397U, 0x5c68341aU, 0x4389ca65U, 0x0efff1f6U,
+ 0x5493c7edU, 0x36241209U, 0xbdd66bbbU, 0xd4984c26U,
+ 0x2d361b83U, 0x408bcbebU, 0x7fa1de6fU, 0x213e1f81U,
+ 0x18100804U, 0x61b5d46aU, 0x97118643U, 0x06040201U,
+ 0x725c2e17U, 0x7ca3dfe1U, 0x35261387U, 0x04f3f7f5U,
+ 0x090e078dU, 0x70abdbe3U, 0xca8c4623U, 0x273a1d80U,
+ 0x850d8844U, 0x74582c16U, 0x4985cc66U, 0xc6844221U,
+ 0x3edfe1feU, 0xc473b7d5U, 0xa6c46231U, 0xec43afd9U,
+ 0xbed46a35U, 0x50603018U, 0x0c080402U, 0x458dc864U,
+ 0x16eff9f2U, 0x1ce3fff1U, 0xe945ac56U, 0x941387cdU,
+ 0x2b321982U, 0x8a078dc8U, 0xbbd269baU, 0x1ae7fdf0U,
+ 0x589bc3efU, 0x4c83cfe9U, 0x4a87cde8U, 0x34d3e7fdU,
+ 0x111e0f89U, 0xc87bb3d7U, 0xa83b93c7U, 0x99ee77b5U,
+ 0xffaa55a4U, 0xe2bc5e2fU, 0x596e3795U, 0x6a4c2613U,
+ 0x3a2c160bU, 0x10ebfbf3U, 0x7aa7dde0U, 0xb2dc6e37U,
+};
+
+static const ulong32 T4[256] = {
+ 0xa7a7a7a7U, 0xd3d3d3d3U, 0xe6e6e6e6U, 0x71717171U,
+ 0xd0d0d0d0U, 0xacacacacU, 0x4d4d4d4dU, 0x79797979U,
+ 0x3a3a3a3aU, 0xc9c9c9c9U, 0x91919191U, 0xfcfcfcfcU,
+ 0x1e1e1e1eU, 0x47474747U, 0x54545454U, 0xbdbdbdbdU,
+ 0x8c8c8c8cU, 0xa5a5a5a5U, 0x7a7a7a7aU, 0xfbfbfbfbU,
+ 0x63636363U, 0xb8b8b8b8U, 0xddddddddU, 0xd4d4d4d4U,
+ 0xe5e5e5e5U, 0xb3b3b3b3U, 0xc5c5c5c5U, 0xbebebebeU,
+ 0xa9a9a9a9U, 0x88888888U, 0x0c0c0c0cU, 0xa2a2a2a2U,
+ 0x39393939U, 0xdfdfdfdfU, 0x29292929U, 0xdadadadaU,
+ 0x2b2b2b2bU, 0xa8a8a8a8U, 0xcbcbcbcbU, 0x4c4c4c4cU,
+ 0x4b4b4b4bU, 0x22222222U, 0xaaaaaaaaU, 0x24242424U,
+ 0x41414141U, 0x70707070U, 0xa6a6a6a6U, 0xf9f9f9f9U,
+ 0x5a5a5a5aU, 0xe2e2e2e2U, 0xb0b0b0b0U, 0x36363636U,
+ 0x7d7d7d7dU, 0xe4e4e4e4U, 0x33333333U, 0xffffffffU,
+ 0x60606060U, 0x20202020U, 0x08080808U, 0x8b8b8b8bU,
+ 0x5e5e5e5eU, 0xababababU, 0x7f7f7f7fU, 0x78787878U,
+ 0x7c7c7c7cU, 0x2c2c2c2cU, 0x57575757U, 0xd2d2d2d2U,
+ 0xdcdcdcdcU, 0x6d6d6d6dU, 0x7e7e7e7eU, 0x0d0d0d0dU,
+ 0x53535353U, 0x94949494U, 0xc3c3c3c3U, 0x28282828U,
+ 0x27272727U, 0x06060606U, 0x5f5f5f5fU, 0xadadadadU,
+ 0x67676767U, 0x5c5c5c5cU, 0x55555555U, 0x48484848U,
+ 0x0e0e0e0eU, 0x52525252U, 0xeaeaeaeaU, 0x42424242U,
+ 0x5b5b5b5bU, 0x5d5d5d5dU, 0x30303030U, 0x58585858U,
+ 0x51515151U, 0x59595959U, 0x3c3c3c3cU, 0x4e4e4e4eU,
+ 0x38383838U, 0x8a8a8a8aU, 0x72727272U, 0x14141414U,
+ 0xe7e7e7e7U, 0xc6c6c6c6U, 0xdedededeU, 0x50505050U,
+ 0x8e8e8e8eU, 0x92929292U, 0xd1d1d1d1U, 0x77777777U,
+ 0x93939393U, 0x45454545U, 0x9a9a9a9aU, 0xcecececeU,
+ 0x2d2d2d2dU, 0x03030303U, 0x62626262U, 0xb6b6b6b6U,
+ 0xb9b9b9b9U, 0xbfbfbfbfU, 0x96969696U, 0x6b6b6b6bU,
+ 0x3f3f3f3fU, 0x07070707U, 0x12121212U, 0xaeaeaeaeU,
+ 0x40404040U, 0x34343434U, 0x46464646U, 0x3e3e3e3eU,
+ 0xdbdbdbdbU, 0xcfcfcfcfU, 0xececececU, 0xccccccccU,
+ 0xc1c1c1c1U, 0xa1a1a1a1U, 0xc0c0c0c0U, 0xd6d6d6d6U,
+ 0x1d1d1d1dU, 0xf4f4f4f4U, 0x61616161U, 0x3b3b3b3bU,
+ 0x10101010U, 0xd8d8d8d8U, 0x68686868U, 0xa0a0a0a0U,
+ 0xb1b1b1b1U, 0x0a0a0a0aU, 0x69696969U, 0x6c6c6c6cU,
+ 0x49494949U, 0xfafafafaU, 0x76767676U, 0xc4c4c4c4U,
+ 0x9e9e9e9eU, 0x9b9b9b9bU, 0x6e6e6e6eU, 0x99999999U,
+ 0xc2c2c2c2U, 0xb7b7b7b7U, 0x98989898U, 0xbcbcbcbcU,
+ 0x8f8f8f8fU, 0x85858585U, 0x1f1f1f1fU, 0xb4b4b4b4U,
+ 0xf8f8f8f8U, 0x11111111U, 0x2e2e2e2eU, 0x00000000U,
+ 0x25252525U, 0x1c1c1c1cU, 0x2a2a2a2aU, 0x3d3d3d3dU,
+ 0x05050505U, 0x4f4f4f4fU, 0x7b7b7b7bU, 0xb2b2b2b2U,
+ 0x32323232U, 0x90909090U, 0xafafafafU, 0x19191919U,
+ 0xa3a3a3a3U, 0xf7f7f7f7U, 0x73737373U, 0x9d9d9d9dU,
+ 0x15151515U, 0x74747474U, 0xeeeeeeeeU, 0xcacacacaU,
+ 0x9f9f9f9fU, 0x0f0f0f0fU, 0x1b1b1b1bU, 0x75757575U,
+ 0x86868686U, 0x84848484U, 0x9c9c9c9cU, 0x4a4a4a4aU,
+ 0x97979797U, 0x1a1a1a1aU, 0x65656565U, 0xf6f6f6f6U,
+ 0xededededU, 0x09090909U, 0xbbbbbbbbU, 0x26262626U,
+ 0x83838383U, 0xebebebebU, 0x6f6f6f6fU, 0x81818181U,
+ 0x04040404U, 0x6a6a6a6aU, 0x43434343U, 0x01010101U,
+ 0x17171717U, 0xe1e1e1e1U, 0x87878787U, 0xf5f5f5f5U,
+ 0x8d8d8d8dU, 0xe3e3e3e3U, 0x23232323U, 0x80808080U,
+ 0x44444444U, 0x16161616U, 0x66666666U, 0x21212121U,
+ 0xfefefefeU, 0xd5d5d5d5U, 0x31313131U, 0xd9d9d9d9U,
+ 0x35353535U, 0x18181818U, 0x02020202U, 0x64646464U,
+ 0xf2f2f2f2U, 0xf1f1f1f1U, 0x56565656U, 0xcdcdcdcdU,
+ 0x82828282U, 0xc8c8c8c8U, 0xbabababaU, 0xf0f0f0f0U,
+ 0xefefefefU, 0xe9e9e9e9U, 0xe8e8e8e8U, 0xfdfdfdfdU,
+ 0x89898989U, 0xd7d7d7d7U, 0xc7c7c7c7U, 0xb5b5b5b5U,
+ 0xa4a4a4a4U, 0x2f2f2f2fU, 0x95959595U, 0x13131313U,
+ 0x0b0b0b0bU, 0xf3f3f3f3U, 0xe0e0e0e0U, 0x37373737U,
+};
+
+static const ulong32 T5[256] = {
+ 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U,
+ 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U,
+ 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U,
+ 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U,
+ 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U,
+ 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U,
+ 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U,
+ 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U,
+ 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U,
+ 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U,
+ 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U,
+ 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U,
+ 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U,
+ 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U,
+ 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U,
+ 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U,
+ 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U,
+ 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U,
+ 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U,
+ 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U,
+ 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U,
+ 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U,
+ 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U,
+ 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U,
+ 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU,
+ 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU,
+ 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU,
+ 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU,
+ 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU,
+ 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU,
+ 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU,
+ 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU,
+ 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU,
+ 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU,
+ 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU,
+ 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU,
+ 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU,
+ 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU,
+ 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU,
+ 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU,
+ 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U,
+ 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U,
+ 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U,
+ 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U,
+ 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U,
+ 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U,
+ 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U,
+ 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U,
+ 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U,
+ 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U,
+ 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U,
+ 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U,
+ 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U,
+ 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U,
+ 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U,
+ 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U,
+ 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU,
+ 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU,
+ 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU,
+ 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU,
+ 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU,
+ 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU,
+ 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU,
+ 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU,
+};
+
+/**
+ * The round constants.
+ */
+static const ulong32 rc[] = {
+ 0xa7d3e671U, 0xd0ac4d79U, 0x3ac991fcU, 0x1e4754bdU,
+ 0x8ca57afbU, 0x63b8ddd4U, 0xe5b3c5beU, 0xa9880ca2U,
+ 0x39df29daU, 0x2ba8cb4cU, 0x4b22aa24U, 0x4170a6f9U,
+ 0x5ae2b036U, 0x7de433ffU, 0x6020088bU, 0x5eab7f78U,
+ 0x7c2c57d2U, 0xdc6d7e0dU, 0x5394c328U,
+};
+
+#endif
+
+ /**
+ Initialize the Anubis block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+#ifdef LTC_CLEAN_STACK
+static int s_anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+ int N, R, i, pos, r;
+ ulong32 kappa[MAX_N];
+ ulong32 inter[MAX_N] = { 0 }; /* initialize as all zeroes */
+ ulong32 v, K0, K1, K2, K3;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* Valid sizes (in bytes) are 16, 20, 24, 28, 32, 36, and 40. */
+ if ((keylen & 3) || (keylen < 16) || (keylen > 40)) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ skey->anubis.keyBits = keylen*8;
+
+ /*
+ * determine the N length parameter:
+ * (N.B. it is assumed that the key length is valid!)
+ */
+ N = skey->anubis.keyBits >> 5;
+
+ /*
+ * determine number of rounds from key size:
+ */
+ skey->anubis.R = R = 8 + N;
+
+ if (num_rounds != 0 && num_rounds != skey->anubis.R) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /*
+ * map cipher key to initial key state (mu):
+ */
+ for (i = 0, pos = 0; i < N; i++, pos += 4) {
+ kappa[i] =
+ (((ulong32)key[pos ]) << 24) ^
+ (((ulong32)key[pos + 1]) << 16) ^
+ (((ulong32)key[pos + 2]) << 8) ^
+ (((ulong32)key[pos + 3]) );
+ }
+
+ /*
+ * generate R + 1 round keys:
+ */
+ for (r = 0; r <= R; r++) {
+ /*
+ * generate r-th round key K^r:
+ */
+ K0 = T4[(kappa[N - 1] >> 24) & 0xff];
+ K1 = T4[(kappa[N - 1] >> 16) & 0xff];
+ K2 = T4[(kappa[N - 1] >> 8) & 0xff];
+ K3 = T4[(kappa[N - 1] ) & 0xff];
+ for (i = N - 2; i >= 0; i--) {
+ K0 = T4[(kappa[i] >> 24) & 0xff] ^
+ (T5[(K0 >> 24) & 0xff] & 0xff000000U) ^
+ (T5[(K0 >> 16) & 0xff] & 0x00ff0000U) ^
+ (T5[(K0 >> 8) & 0xff] & 0x0000ff00U) ^
+ (T5[(K0 ) & 0xff] & 0x000000ffU);
+ K1 = T4[(kappa[i] >> 16) & 0xff] ^
+ (T5[(K1 >> 24) & 0xff] & 0xff000000U) ^
+ (T5[(K1 >> 16) & 0xff] & 0x00ff0000U) ^
+ (T5[(K1 >> 8) & 0xff] & 0x0000ff00U) ^
+ (T5[(K1 ) & 0xff] & 0x000000ffU);
+ K2 = T4[(kappa[i] >> 8) & 0xff] ^
+ (T5[(K2 >> 24) & 0xff] & 0xff000000U) ^
+ (T5[(K2 >> 16) & 0xff] & 0x00ff0000U) ^
+ (T5[(K2 >> 8) & 0xff] & 0x0000ff00U) ^
+ (T5[(K2 ) & 0xff] & 0x000000ffU);
+ K3 = T4[(kappa[i] ) & 0xff] ^
+ (T5[(K3 >> 24) & 0xff] & 0xff000000U) ^
+ (T5[(K3 >> 16) & 0xff] & 0x00ff0000U) ^
+ (T5[(K3 >> 8) & 0xff] & 0x0000ff00U) ^
+ (T5[(K3 ) & 0xff] & 0x000000ffU);
+ }
+ /*
+ -- this is the code to use with the large U tables:
+ K0 = K1 = K2 = K3 = 0;
+ for (i = 0; i < N; i++) {
+ K0 ^= U[i][(kappa[i] >> 24) & 0xff];
+ K1 ^= U[i][(kappa[i] >> 16) & 0xff];
+ K2 ^= U[i][(kappa[i] >> 8) & 0xff];
+ K3 ^= U[i][(kappa[i] ) & 0xff];
+ }
+ */
+ skey->anubis.roundKeyEnc[r][0] = K0;
+ skey->anubis.roundKeyEnc[r][1] = K1;
+ skey->anubis.roundKeyEnc[r][2] = K2;
+ skey->anubis.roundKeyEnc[r][3] = K3;
+
+ /*
+ * compute kappa^{r+1} from kappa^r:
+ */
+ if (r == R) {
+ break;
+ }
+ for (i = 0; i < N; i++) {
+ int j = i;
+ inter[i] = T0[(kappa[j--] >> 24) & 0xff]; if (j < 0) j = N - 1;
+ inter[i] ^= T1[(kappa[j--] >> 16) & 0xff]; if (j < 0) j = N - 1;
+ inter[i] ^= T2[(kappa[j--] >> 8) & 0xff]; if (j < 0) j = N - 1;
+ inter[i] ^= T3[(kappa[j ] ) & 0xff];
+ }
+ kappa[0] = inter[0] ^ rc[r];
+ for (i = 1; i < N; i++) {
+ kappa[i] = inter[i];
+ }
+ }
+
+ /*
+ * generate inverse key schedule: K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}):
+ */
+ for (i = 0; i < 4; i++) {
+ skey->anubis.roundKeyDec[0][i] = skey->anubis.roundKeyEnc[R][i];
+ skey->anubis.roundKeyDec[R][i] = skey->anubis.roundKeyEnc[0][i];
+ }
+ for (r = 1; r < R; r++) {
+ for (i = 0; i < 4; i++) {
+ v = skey->anubis.roundKeyEnc[R - r][i];
+ skey->anubis.roundKeyDec[r][i] =
+ T0[T4[(v >> 24) & 0xff] & 0xff] ^
+ T1[T4[(v >> 16) & 0xff] & 0xff] ^
+ T2[T4[(v >> 8) & 0xff] & 0xff] ^
+ T3[T4[(v ) & 0xff] & 0xff];
+ }
+ }
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int err;
+ err = s_anubis_setup(key, keylen, num_rounds, skey);
+ burn_stack(sizeof(int) * 5 + sizeof(ulong32) * (MAX_N + MAX_N + 5));
+ return err;
+}
+#endif
+
+
+static void anubis_crypt(const unsigned char *plaintext, unsigned char *ciphertext,
+ const ulong32 roundKey[18 + 1][4], int R) {
+ int i, pos, r;
+ ulong32 state[4];
+ ulong32 inter[4];
+
+ /*
+ * map plaintext block to cipher state (mu)
+ * and add initial round key (sigma[K^0]):
+ */
+ for (i = 0, pos = 0; i < 4; i++, pos += 4) {
+ state[i] =
+ (((ulong32)plaintext[pos ]) << 24) ^
+ (((ulong32)plaintext[pos + 1]) << 16) ^
+ (((ulong32)plaintext[pos + 2]) << 8) ^
+ (((ulong32)plaintext[pos + 3]) ) ^
+ roundKey[0][i];
+ }
+
+ /*
+ * R - 1 full rounds:
+ */
+ for (r = 1; r < R; r++) {
+ inter[0] =
+ T0[(state[0] >> 24) & 0xff] ^
+ T1[(state[1] >> 24) & 0xff] ^
+ T2[(state[2] >> 24) & 0xff] ^
+ T3[(state[3] >> 24) & 0xff] ^
+ roundKey[r][0];
+ inter[1] =
+ T0[(state[0] >> 16) & 0xff] ^
+ T1[(state[1] >> 16) & 0xff] ^
+ T2[(state[2] >> 16) & 0xff] ^
+ T3[(state[3] >> 16) & 0xff] ^
+ roundKey[r][1];
+ inter[2] =
+ T0[(state[0] >> 8) & 0xff] ^
+ T1[(state[1] >> 8) & 0xff] ^
+ T2[(state[2] >> 8) & 0xff] ^
+ T3[(state[3] >> 8) & 0xff] ^
+ roundKey[r][2];
+ inter[3] =
+ T0[(state[0] ) & 0xff] ^
+ T1[(state[1] ) & 0xff] ^
+ T2[(state[2] ) & 0xff] ^
+ T3[(state[3] ) & 0xff] ^
+ roundKey[r][3];
+ state[0] = inter[0];
+ state[1] = inter[1];
+ state[2] = inter[2];
+ state[3] = inter[3];
+ }
+
+ /*
+ * last round:
+ */
+ inter[0] =
+ (T0[(state[0] >> 24) & 0xff] & 0xff000000U) ^
+ (T1[(state[1] >> 24) & 0xff] & 0x00ff0000U) ^
+ (T2[(state[2] >> 24) & 0xff] & 0x0000ff00U) ^
+ (T3[(state[3] >> 24) & 0xff] & 0x000000ffU) ^
+ roundKey[R][0];
+ inter[1] =
+ (T0[(state[0] >> 16) & 0xff] & 0xff000000U) ^
+ (T1[(state[1] >> 16) & 0xff] & 0x00ff0000U) ^
+ (T2[(state[2] >> 16) & 0xff] & 0x0000ff00U) ^
+ (T3[(state[3] >> 16) & 0xff] & 0x000000ffU) ^
+ roundKey[R][1];
+ inter[2] =
+ (T0[(state[0] >> 8) & 0xff] & 0xff000000U) ^
+ (T1[(state[1] >> 8) & 0xff] & 0x00ff0000U) ^
+ (T2[(state[2] >> 8) & 0xff] & 0x0000ff00U) ^
+ (T3[(state[3] >> 8) & 0xff] & 0x000000ffU) ^
+ roundKey[R][2];
+ inter[3] =
+ (T0[(state[0] ) & 0xff] & 0xff000000U) ^
+ (T1[(state[1] ) & 0xff] & 0x00ff0000U) ^
+ (T2[(state[2] ) & 0xff] & 0x0000ff00U) ^
+ (T3[(state[3] ) & 0xff] & 0x000000ffU) ^
+ roundKey[R][3];
+
+ /*
+ * map cipher state to ciphertext block (mu^{-1}):
+ */
+ for (i = 0, pos = 0; i < 4; i++, pos += 4) {
+ ulong32 w = inter[i];
+ ciphertext[pos ] = (unsigned char)(w >> 24);
+ ciphertext[pos + 1] = (unsigned char)(w >> 16);
+ ciphertext[pos + 2] = (unsigned char)(w >> 8);
+ ciphertext[pos + 3] = (unsigned char)(w );
+ }
+}
+
+/**
+ Encrypts a block of text with Anubis
+ @param pt The input plaintext (16 bytes)
+ @param ct The output ciphertext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (skey->anubis.R < 12 || skey->anubis.R > 18) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ anubis_crypt(pt, ct, skey->anubis.roundKeyEnc, skey->anubis.R);
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with Anubis
+ @param ct The input ciphertext (16 bytes)
+ @param pt The output plaintext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (skey->anubis.R < 12 || skey->anubis.R > 18) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ anubis_crypt(ct, pt, skey->anubis.roundKeyDec, skey->anubis.R);
+ return CRYPT_OK;
+}
+
+/**
+ Performs a self-test of the Anubis block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int anubis_test(void)
+{
+#if !defined(LTC_TEST)
+ return CRYPT_NOP;
+#else
+ static const struct test {
+ int keylen;
+ unsigned char pt[16], ct[16], key[40];
+ } tests[] = {
+#ifndef LTC_ANUBIS_TWEAK
+ /**** ORIGINAL LTC_ANUBIS ****/
+ /* 128 bit keys */
+{
+ 16,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xF0, 0x68, 0x60, 0xFC, 0x67, 0x30, 0xE8, 0x18,
+ 0xF1, 0x32, 0xC7, 0x8A, 0xF4, 0x13, 0x2A, 0xFE },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 16,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xA8, 0x66, 0x84, 0x80, 0x07, 0x74, 0x5C, 0x89,
+ 0xFC, 0x5E, 0xB5, 0xBA, 0xD4, 0xFE, 0x32, 0x6D },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 160-bit keys */
+{
+ 20,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xBD, 0x5E, 0x32, 0xBE, 0x51, 0x67, 0xA8, 0xE2,
+ 0x72, 0xD7, 0x95, 0x0F, 0x83, 0xC6, 0x8C, 0x31 },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 20,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4C, 0x1F, 0x86, 0x2E, 0x11, 0xEB, 0xCE, 0xEB,
+ 0xFE, 0xB9, 0x73, 0xC9, 0xDF, 0xEF, 0x7A, 0xDB },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 192-bit keys */
+{
+ 24,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x17, 0xAC, 0x57, 0x44, 0x9D, 0x59, 0x61, 0x66,
+ 0xD0, 0xC7, 0x9E, 0x04, 0x7C, 0xC7, 0x58, 0xF0 },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 24,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x71, 0x52, 0xB4, 0xEB, 0x1D, 0xAA, 0x36, 0xFD,
+ 0x57, 0x14, 0x5F, 0x57, 0x04, 0x9F, 0x70, 0x74 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 224-bit keys */
+{
+ 28,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xA2, 0xF0, 0xA6, 0xB9, 0x17, 0x93, 0x2A, 0x3B,
+ 0xEF, 0x08, 0xE8, 0x7A, 0x58, 0xD6, 0xF8, 0x53 },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 28,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xF0, 0xCA, 0xFC, 0x78, 0x8B, 0x4B, 0x4E, 0x53,
+ 0x8B, 0xC4, 0x32, 0x6A, 0xF5, 0xB9, 0x1B, 0x5F },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 256-bit keys */
+{
+ 32,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xE0, 0x86, 0xAC, 0x45, 0x6B, 0x3C, 0xE5, 0x13,
+ 0xED, 0xF5, 0xDF, 0xDD, 0xD6, 0x3B, 0x71, 0x93 },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 32,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x50, 0x01, 0xB9, 0xF5, 0x21, 0xC1, 0xC1, 0x29,
+ 0x00, 0xD5, 0xEC, 0x98, 0x2B, 0x9E, 0xE8, 0x21 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 288-bit keys */
+{
+ 36,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xE8, 0xF4, 0xAF, 0x2B, 0x21, 0xA0, 0x87, 0x9B,
+ 0x41, 0x95, 0xB9, 0x71, 0x75, 0x79, 0x04, 0x7C },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 36,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xE6, 0xA6, 0xA5, 0xBC, 0x8B, 0x63, 0x6F, 0xE2,
+ 0xBD, 0xA7, 0xA7, 0x53, 0xAB, 0x40, 0x22, 0xE0 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 320-bit keys */
+{
+ 40,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x17, 0x04, 0xD7, 0x2C, 0xC6, 0x85, 0x76, 0x02,
+ 0x4B, 0xCC, 0x39, 0x80, 0xD8, 0x22, 0xEA, 0xA4 },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 40,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7A, 0x41, 0xE6, 0x7D, 0x4F, 0xD8, 0x64, 0xF0,
+ 0x44, 0xA8, 0x3C, 0x73, 0x81, 0x7E, 0x53, 0xD8 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+}
+#else
+ /**** Tweaked LTC_ANUBIS ****/
+ /* 128 bit keys */
+{
+ 16,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xB8, 0x35, 0xBD, 0xC3, 0x34, 0x82, 0x9D, 0x83,
+ 0x71, 0xBF, 0xA3, 0x71, 0xE4, 0xB3, 0xC4, 0xFD },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 16,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xE6, 0x14, 0x1E, 0xAF, 0xEB, 0xE0, 0x59, 0x3C,
+ 0x48, 0xE1, 0xCD, 0xF2, 0x1B, 0xBA, 0xA1, 0x89 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 160-bit keys */
+{
+ 20,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x97, 0x59, 0x79, 0x4B, 0x5C, 0xA0, 0x70, 0x73,
+ 0x24, 0xEF, 0xB3, 0x58, 0x67, 0xCA, 0xD4, 0xB3 },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 20,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xB8, 0x0D, 0xFB, 0x9B, 0xE4, 0xA1, 0x58, 0x87,
+ 0xB3, 0x76, 0xD5, 0x02, 0x18, 0x95, 0xC1, 0x2E },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 192-bit keys */
+{
+ 24,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7D, 0x62, 0x3B, 0x52, 0xC7, 0x4C, 0x64, 0xD8,
+ 0xEB, 0xC7, 0x2D, 0x57, 0x97, 0x85, 0x43, 0x8F },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 24,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xB1, 0x0A, 0x59, 0xDD, 0x5D, 0x5D, 0x8D, 0x67,
+ 0xEC, 0xEE, 0x4A, 0xC4, 0xBE, 0x4F, 0xA8, 0x4F },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 224-bit keys */
+{
+ 28,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x68, 0x9E, 0x05, 0x94, 0x6A, 0x94, 0x43, 0x8F,
+ 0xE7, 0x8E, 0x37, 0x3D, 0x24, 0x97, 0x92, 0xF5 },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 28,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xDD, 0xB7, 0xB0, 0xB4, 0xE9, 0xB4, 0x9B, 0x9C,
+ 0x38, 0x20, 0x25, 0x0B, 0x47, 0xC2, 0x1F, 0x89 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 256-bit keys */
+{
+ 32,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x96, 0x00, 0xF0, 0x76, 0x91, 0x69, 0x29, 0x87,
+ 0xF5, 0xE5, 0x97, 0xDB, 0xDB, 0xAF, 0x1B, 0x0A },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 32,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x69, 0x9C, 0xAF, 0xDD, 0x94, 0xC7, 0xBC, 0x60,
+ 0x44, 0xFE, 0x02, 0x05, 0x8A, 0x6E, 0xEF, 0xBD },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 288-bit keys */
+{
+ 36,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0F, 0xC7, 0xA2, 0xC0, 0x11, 0x17, 0xAC, 0x43,
+ 0x52, 0x5E, 0xDF, 0x6C, 0xF3, 0x96, 0x33, 0x6C },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 36,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xAD, 0x08, 0x4F, 0xED, 0x55, 0xA6, 0x94, 0x3E,
+ 0x7E, 0x5E, 0xED, 0x05, 0xA1, 0x9D, 0x41, 0xB4 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 }
+},
+
+ /* 320-bit keys */
+{
+ 40,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xFE, 0xE2, 0x0E, 0x2A, 0x9D, 0xC5, 0x83, 0xBA,
+ 0xA3, 0xA6, 0xD6, 0xA6, 0xF2, 0xE8, 0x06, 0xA5 },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ 40,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x86, 0x3D, 0xCC, 0x4A, 0x60, 0x34, 0x9C, 0x28,
+ 0xA7, 0xDA, 0xA4, 0x3B, 0x0A, 0xD7, 0xFD, 0xC7 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+}
+#endif
+};
+ int x, y;
+ unsigned char buf[2][16];
+ symmetric_key skey;
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ anubis_setup(tests[x].key, tests[x].keylen, 0, &skey);
+ anubis_ecb_encrypt(tests[x].pt, buf[0], &skey);
+ anubis_ecb_decrypt(buf[0], buf[1], &skey);
+ if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis Encrypt", x) ||
+ compare_testvector(buf[1], 16, tests[x].pt, 16, "Anubis Decrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ for (y = 0; y < 1000; y++) anubis_ecb_encrypt(buf[0], buf[0], &skey);
+ for (y = 0; y < 1000; y++) anubis_ecb_decrypt(buf[0], buf[0], &skey);
+ if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis 1000", 1000)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void anubis_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int anubis_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize >= 40) {
+ *keysize = 40;
+ } else if (*keysize >= 36) {
+ *keysize = 36;
+ } else if (*keysize >= 32) {
+ *keysize = 32;
+ } else if (*keysize >= 28) {
+ *keysize = 28;
+ } else if (*keysize >= 24) {
+ *keysize = 24;
+ } else if (*keysize >= 20) {
+ *keysize = 20;
+ } else if (*keysize >= 16) {
+ *keysize = 16;
+ } else {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/ciphers/blowfish.c b/Sources/libtomcrypt/ciphers/blowfish.c
new file mode 100644
index 00000000..4187701d
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/blowfish.c
@@ -0,0 +1,658 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**
+ @file blowfish.c
+ Implementation of the Blowfish block cipher, Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLOWFISH
+
+const struct ltc_cipher_descriptor blowfish_desc =
+{
+ "blowfish",
+ 0,
+ 8, 72, 8, 16,
+ &blowfish_setup,
+ &blowfish_ecb_encrypt,
+ &blowfish_ecb_decrypt,
+ &blowfish_test,
+ &blowfish_done,
+ &blowfish_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ulong32 ORIG_P[16 + 2] = {
+ 0x243F6A88UL, 0x85A308D3UL, 0x13198A2EUL, 0x03707344UL,
+ 0xA4093822UL, 0x299F31D0UL, 0x082EFA98UL, 0xEC4E6C89UL,
+ 0x452821E6UL, 0x38D01377UL, 0xBE5466CFUL, 0x34E90C6CUL,
+ 0xC0AC29B7UL, 0xC97C50DDUL, 0x3F84D5B5UL, 0xB5470917UL,
+ 0x9216D5D9UL, 0x8979FB1BUL
+};
+
+static const ulong32 ORIG_S[4][256] = {
+ { 0xD1310BA6UL, 0x98DFB5ACUL, 0x2FFD72DBUL, 0xD01ADFB7UL,
+ 0xB8E1AFEDUL, 0x6A267E96UL, 0xBA7C9045UL, 0xF12C7F99UL,
+ 0x24A19947UL, 0xB3916CF7UL, 0x0801F2E2UL, 0x858EFC16UL,
+ 0x636920D8UL, 0x71574E69UL, 0xA458FEA3UL, 0xF4933D7EUL,
+ 0x0D95748FUL, 0x728EB658UL, 0x718BCD58UL, 0x82154AEEUL,
+ 0x7B54A41DUL, 0xC25A59B5UL, 0x9C30D539UL, 0x2AF26013UL,
+ 0xC5D1B023UL, 0x286085F0UL, 0xCA417918UL, 0xB8DB38EFUL,
+ 0x8E79DCB0UL, 0x603A180EUL, 0x6C9E0E8BUL, 0xB01E8A3EUL,
+ 0xD71577C1UL, 0xBD314B27UL, 0x78AF2FDAUL, 0x55605C60UL,
+ 0xE65525F3UL, 0xAA55AB94UL, 0x57489862UL, 0x63E81440UL,
+ 0x55CA396AUL, 0x2AAB10B6UL, 0xB4CC5C34UL, 0x1141E8CEUL,
+ 0xA15486AFUL, 0x7C72E993UL, 0xB3EE1411UL, 0x636FBC2AUL,
+ 0x2BA9C55DUL, 0x741831F6UL, 0xCE5C3E16UL, 0x9B87931EUL,
+ 0xAFD6BA33UL, 0x6C24CF5CUL, 0x7A325381UL, 0x28958677UL,
+ 0x3B8F4898UL, 0x6B4BB9AFUL, 0xC4BFE81BUL, 0x66282193UL,
+ 0x61D809CCUL, 0xFB21A991UL, 0x487CAC60UL, 0x5DEC8032UL,
+ 0xEF845D5DUL, 0xE98575B1UL, 0xDC262302UL, 0xEB651B88UL,
+ 0x23893E81UL, 0xD396ACC5UL, 0x0F6D6FF3UL, 0x83F44239UL,
+ 0x2E0B4482UL, 0xA4842004UL, 0x69C8F04AUL, 0x9E1F9B5EUL,
+ 0x21C66842UL, 0xF6E96C9AUL, 0x670C9C61UL, 0xABD388F0UL,
+ 0x6A51A0D2UL, 0xD8542F68UL, 0x960FA728UL, 0xAB5133A3UL,
+ 0x6EEF0B6CUL, 0x137A3BE4UL, 0xBA3BF050UL, 0x7EFB2A98UL,
+ 0xA1F1651DUL, 0x39AF0176UL, 0x66CA593EUL, 0x82430E88UL,
+ 0x8CEE8619UL, 0x456F9FB4UL, 0x7D84A5C3UL, 0x3B8B5EBEUL,
+ 0xE06F75D8UL, 0x85C12073UL, 0x401A449FUL, 0x56C16AA6UL,
+ 0x4ED3AA62UL, 0x363F7706UL, 0x1BFEDF72UL, 0x429B023DUL,
+ 0x37D0D724UL, 0xD00A1248UL, 0xDB0FEAD3UL, 0x49F1C09BUL,
+ 0x075372C9UL, 0x80991B7BUL, 0x25D479D8UL, 0xF6E8DEF7UL,
+ 0xE3FE501AUL, 0xB6794C3BUL, 0x976CE0BDUL, 0x04C006BAUL,
+ 0xC1A94FB6UL, 0x409F60C4UL, 0x5E5C9EC2UL, 0x196A2463UL,
+ 0x68FB6FAFUL, 0x3E6C53B5UL, 0x1339B2EBUL, 0x3B52EC6FUL,
+ 0x6DFC511FUL, 0x9B30952CUL, 0xCC814544UL, 0xAF5EBD09UL,
+ 0xBEE3D004UL, 0xDE334AFDUL, 0x660F2807UL, 0x192E4BB3UL,
+ 0xC0CBA857UL, 0x45C8740FUL, 0xD20B5F39UL, 0xB9D3FBDBUL,
+ 0x5579C0BDUL, 0x1A60320AUL, 0xD6A100C6UL, 0x402C7279UL,
+ 0x679F25FEUL, 0xFB1FA3CCUL, 0x8EA5E9F8UL, 0xDB3222F8UL,
+ 0x3C7516DFUL, 0xFD616B15UL, 0x2F501EC8UL, 0xAD0552ABUL,
+ 0x323DB5FAUL, 0xFD238760UL, 0x53317B48UL, 0x3E00DF82UL,
+ 0x9E5C57BBUL, 0xCA6F8CA0UL, 0x1A87562EUL, 0xDF1769DBUL,
+ 0xD542A8F6UL, 0x287EFFC3UL, 0xAC6732C6UL, 0x8C4F5573UL,
+ 0x695B27B0UL, 0xBBCA58C8UL, 0xE1FFA35DUL, 0xB8F011A0UL,
+ 0x10FA3D98UL, 0xFD2183B8UL, 0x4AFCB56CUL, 0x2DD1D35BUL,
+ 0x9A53E479UL, 0xB6F84565UL, 0xD28E49BCUL, 0x4BFB9790UL,
+ 0xE1DDF2DAUL, 0xA4CB7E33UL, 0x62FB1341UL, 0xCEE4C6E8UL,
+ 0xEF20CADAUL, 0x36774C01UL, 0xD07E9EFEUL, 0x2BF11FB4UL,
+ 0x95DBDA4DUL, 0xAE909198UL, 0xEAAD8E71UL, 0x6B93D5A0UL,
+ 0xD08ED1D0UL, 0xAFC725E0UL, 0x8E3C5B2FUL, 0x8E7594B7UL,
+ 0x8FF6E2FBUL, 0xF2122B64UL, 0x8888B812UL, 0x900DF01CUL,
+ 0x4FAD5EA0UL, 0x688FC31CUL, 0xD1CFF191UL, 0xB3A8C1ADUL,
+ 0x2F2F2218UL, 0xBE0E1777UL, 0xEA752DFEUL, 0x8B021FA1UL,
+ 0xE5A0CC0FUL, 0xB56F74E8UL, 0x18ACF3D6UL, 0xCE89E299UL,
+ 0xB4A84FE0UL, 0xFD13E0B7UL, 0x7CC43B81UL, 0xD2ADA8D9UL,
+ 0x165FA266UL, 0x80957705UL, 0x93CC7314UL, 0x211A1477UL,
+ 0xE6AD2065UL, 0x77B5FA86UL, 0xC75442F5UL, 0xFB9D35CFUL,
+ 0xEBCDAF0CUL, 0x7B3E89A0UL, 0xD6411BD3UL, 0xAE1E7E49UL,
+ 0x00250E2DUL, 0x2071B35EUL, 0x226800BBUL, 0x57B8E0AFUL,
+ 0x2464369BUL, 0xF009B91EUL, 0x5563911DUL, 0x59DFA6AAUL,
+ 0x78C14389UL, 0xD95A537FUL, 0x207D5BA2UL, 0x02E5B9C5UL,
+ 0x83260376UL, 0x6295CFA9UL, 0x11C81968UL, 0x4E734A41UL,
+ 0xB3472DCAUL, 0x7B14A94AUL, 0x1B510052UL, 0x9A532915UL,
+ 0xD60F573FUL, 0xBC9BC6E4UL, 0x2B60A476UL, 0x81E67400UL,
+ 0x08BA6FB5UL, 0x571BE91FUL, 0xF296EC6BUL, 0x2A0DD915UL,
+ 0xB6636521UL, 0xE7B9F9B6UL, 0xFF34052EUL, 0xC5855664UL,
+ 0x53B02D5DUL, 0xA99F8FA1UL, 0x08BA4799UL, 0x6E85076AUL },
+ { 0x4B7A70E9UL, 0xB5B32944UL, 0xDB75092EUL, 0xC4192623UL,
+ 0xAD6EA6B0UL, 0x49A7DF7DUL, 0x9CEE60B8UL, 0x8FEDB266UL,
+ 0xECAA8C71UL, 0x699A17FFUL, 0x5664526CUL, 0xC2B19EE1UL,
+ 0x193602A5UL, 0x75094C29UL, 0xA0591340UL, 0xE4183A3EUL,
+ 0x3F54989AUL, 0x5B429D65UL, 0x6B8FE4D6UL, 0x99F73FD6UL,
+ 0xA1D29C07UL, 0xEFE830F5UL, 0x4D2D38E6UL, 0xF0255DC1UL,
+ 0x4CDD2086UL, 0x8470EB26UL, 0x6382E9C6UL, 0x021ECC5EUL,
+ 0x09686B3FUL, 0x3EBAEFC9UL, 0x3C971814UL, 0x6B6A70A1UL,
+ 0x687F3584UL, 0x52A0E286UL, 0xB79C5305UL, 0xAA500737UL,
+ 0x3E07841CUL, 0x7FDEAE5CUL, 0x8E7D44ECUL, 0x5716F2B8UL,
+ 0xB03ADA37UL, 0xF0500C0DUL, 0xF01C1F04UL, 0x0200B3FFUL,
+ 0xAE0CF51AUL, 0x3CB574B2UL, 0x25837A58UL, 0xDC0921BDUL,
+ 0xD19113F9UL, 0x7CA92FF6UL, 0x94324773UL, 0x22F54701UL,
+ 0x3AE5E581UL, 0x37C2DADCUL, 0xC8B57634UL, 0x9AF3DDA7UL,
+ 0xA9446146UL, 0x0FD0030EUL, 0xECC8C73EUL, 0xA4751E41UL,
+ 0xE238CD99UL, 0x3BEA0E2FUL, 0x3280BBA1UL, 0x183EB331UL,
+ 0x4E548B38UL, 0x4F6DB908UL, 0x6F420D03UL, 0xF60A04BFUL,
+ 0x2CB81290UL, 0x24977C79UL, 0x5679B072UL, 0xBCAF89AFUL,
+ 0xDE9A771FUL, 0xD9930810UL, 0xB38BAE12UL, 0xDCCF3F2EUL,
+ 0x5512721FUL, 0x2E6B7124UL, 0x501ADDE6UL, 0x9F84CD87UL,
+ 0x7A584718UL, 0x7408DA17UL, 0xBC9F9ABCUL, 0xE94B7D8CUL,
+ 0xEC7AEC3AUL, 0xDB851DFAUL, 0x63094366UL, 0xC464C3D2UL,
+ 0xEF1C1847UL, 0x3215D908UL, 0xDD433B37UL, 0x24C2BA16UL,
+ 0x12A14D43UL, 0x2A65C451UL, 0x50940002UL, 0x133AE4DDUL,
+ 0x71DFF89EUL, 0x10314E55UL, 0x81AC77D6UL, 0x5F11199BUL,
+ 0x043556F1UL, 0xD7A3C76BUL, 0x3C11183BUL, 0x5924A509UL,
+ 0xF28FE6EDUL, 0x97F1FBFAUL, 0x9EBABF2CUL, 0x1E153C6EUL,
+ 0x86E34570UL, 0xEAE96FB1UL, 0x860E5E0AUL, 0x5A3E2AB3UL,
+ 0x771FE71CUL, 0x4E3D06FAUL, 0x2965DCB9UL, 0x99E71D0FUL,
+ 0x803E89D6UL, 0x5266C825UL, 0x2E4CC978UL, 0x9C10B36AUL,
+ 0xC6150EBAUL, 0x94E2EA78UL, 0xA5FC3C53UL, 0x1E0A2DF4UL,
+ 0xF2F74EA7UL, 0x361D2B3DUL, 0x1939260FUL, 0x19C27960UL,
+ 0x5223A708UL, 0xF71312B6UL, 0xEBADFE6EUL, 0xEAC31F66UL,
+ 0xE3BC4595UL, 0xA67BC883UL, 0xB17F37D1UL, 0x018CFF28UL,
+ 0xC332DDEFUL, 0xBE6C5AA5UL, 0x65582185UL, 0x68AB9802UL,
+ 0xEECEA50FUL, 0xDB2F953BUL, 0x2AEF7DADUL, 0x5B6E2F84UL,
+ 0x1521B628UL, 0x29076170UL, 0xECDD4775UL, 0x619F1510UL,
+ 0x13CCA830UL, 0xEB61BD96UL, 0x0334FE1EUL, 0xAA0363CFUL,
+ 0xB5735C90UL, 0x4C70A239UL, 0xD59E9E0BUL, 0xCBAADE14UL,
+ 0xEECC86BCUL, 0x60622CA7UL, 0x9CAB5CABUL, 0xB2F3846EUL,
+ 0x648B1EAFUL, 0x19BDF0CAUL, 0xA02369B9UL, 0x655ABB50UL,
+ 0x40685A32UL, 0x3C2AB4B3UL, 0x319EE9D5UL, 0xC021B8F7UL,
+ 0x9B540B19UL, 0x875FA099UL, 0x95F7997EUL, 0x623D7DA8UL,
+ 0xF837889AUL, 0x97E32D77UL, 0x11ED935FUL, 0x16681281UL,
+ 0x0E358829UL, 0xC7E61FD6UL, 0x96DEDFA1UL, 0x7858BA99UL,
+ 0x57F584A5UL, 0x1B227263UL, 0x9B83C3FFUL, 0x1AC24696UL,
+ 0xCDB30AEBUL, 0x532E3054UL, 0x8FD948E4UL, 0x6DBC3128UL,
+ 0x58EBF2EFUL, 0x34C6FFEAUL, 0xFE28ED61UL, 0xEE7C3C73UL,
+ 0x5D4A14D9UL, 0xE864B7E3UL, 0x42105D14UL, 0x203E13E0UL,
+ 0x45EEE2B6UL, 0xA3AAABEAUL, 0xDB6C4F15UL, 0xFACB4FD0UL,
+ 0xC742F442UL, 0xEF6ABBB5UL, 0x654F3B1DUL, 0x41CD2105UL,
+ 0xD81E799EUL, 0x86854DC7UL, 0xE44B476AUL, 0x3D816250UL,
+ 0xCF62A1F2UL, 0x5B8D2646UL, 0xFC8883A0UL, 0xC1C7B6A3UL,
+ 0x7F1524C3UL, 0x69CB7492UL, 0x47848A0BUL, 0x5692B285UL,
+ 0x095BBF00UL, 0xAD19489DUL, 0x1462B174UL, 0x23820E00UL,
+ 0x58428D2AUL, 0x0C55F5EAUL, 0x1DADF43EUL, 0x233F7061UL,
+ 0x3372F092UL, 0x8D937E41UL, 0xD65FECF1UL, 0x6C223BDBUL,
+ 0x7CDE3759UL, 0xCBEE7460UL, 0x4085F2A7UL, 0xCE77326EUL,
+ 0xA6078084UL, 0x19F8509EUL, 0xE8EFD855UL, 0x61D99735UL,
+ 0xA969A7AAUL, 0xC50C06C2UL, 0x5A04ABFCUL, 0x800BCADCUL,
+ 0x9E447A2EUL, 0xC3453484UL, 0xFDD56705UL, 0x0E1E9EC9UL,
+ 0xDB73DBD3UL, 0x105588CDUL, 0x675FDA79UL, 0xE3674340UL,
+ 0xC5C43465UL, 0x713E38D8UL, 0x3D28F89EUL, 0xF16DFF20UL,
+ 0x153E21E7UL, 0x8FB03D4AUL, 0xE6E39F2BUL, 0xDB83ADF7UL },
+ { 0xE93D5A68UL, 0x948140F7UL, 0xF64C261CUL, 0x94692934UL,
+ 0x411520F7UL, 0x7602D4F7UL, 0xBCF46B2EUL, 0xD4A20068UL,
+ 0xD4082471UL, 0x3320F46AUL, 0x43B7D4B7UL, 0x500061AFUL,
+ 0x1E39F62EUL, 0x97244546UL, 0x14214F74UL, 0xBF8B8840UL,
+ 0x4D95FC1DUL, 0x96B591AFUL, 0x70F4DDD3UL, 0x66A02F45UL,
+ 0xBFBC09ECUL, 0x03BD9785UL, 0x7FAC6DD0UL, 0x31CB8504UL,
+ 0x96EB27B3UL, 0x55FD3941UL, 0xDA2547E6UL, 0xABCA0A9AUL,
+ 0x28507825UL, 0x530429F4UL, 0x0A2C86DAUL, 0xE9B66DFBUL,
+ 0x68DC1462UL, 0xD7486900UL, 0x680EC0A4UL, 0x27A18DEEUL,
+ 0x4F3FFEA2UL, 0xE887AD8CUL, 0xB58CE006UL, 0x7AF4D6B6UL,
+ 0xAACE1E7CUL, 0xD3375FECUL, 0xCE78A399UL, 0x406B2A42UL,
+ 0x20FE9E35UL, 0xD9F385B9UL, 0xEE39D7ABUL, 0x3B124E8BUL,
+ 0x1DC9FAF7UL, 0x4B6D1856UL, 0x26A36631UL, 0xEAE397B2UL,
+ 0x3A6EFA74UL, 0xDD5B4332UL, 0x6841E7F7UL, 0xCA7820FBUL,
+ 0xFB0AF54EUL, 0xD8FEB397UL, 0x454056ACUL, 0xBA489527UL,
+ 0x55533A3AUL, 0x20838D87UL, 0xFE6BA9B7UL, 0xD096954BUL,
+ 0x55A867BCUL, 0xA1159A58UL, 0xCCA92963UL, 0x99E1DB33UL,
+ 0xA62A4A56UL, 0x3F3125F9UL, 0x5EF47E1CUL, 0x9029317CUL,
+ 0xFDF8E802UL, 0x04272F70UL, 0x80BB155CUL, 0x05282CE3UL,
+ 0x95C11548UL, 0xE4C66D22UL, 0x48C1133FUL, 0xC70F86DCUL,
+ 0x07F9C9EEUL, 0x41041F0FUL, 0x404779A4UL, 0x5D886E17UL,
+ 0x325F51EBUL, 0xD59BC0D1UL, 0xF2BCC18FUL, 0x41113564UL,
+ 0x257B7834UL, 0x602A9C60UL, 0xDFF8E8A3UL, 0x1F636C1BUL,
+ 0x0E12B4C2UL, 0x02E1329EUL, 0xAF664FD1UL, 0xCAD18115UL,
+ 0x6B2395E0UL, 0x333E92E1UL, 0x3B240B62UL, 0xEEBEB922UL,
+ 0x85B2A20EUL, 0xE6BA0D99UL, 0xDE720C8CUL, 0x2DA2F728UL,
+ 0xD0127845UL, 0x95B794FDUL, 0x647D0862UL, 0xE7CCF5F0UL,
+ 0x5449A36FUL, 0x877D48FAUL, 0xC39DFD27UL, 0xF33E8D1EUL,
+ 0x0A476341UL, 0x992EFF74UL, 0x3A6F6EABUL, 0xF4F8FD37UL,
+ 0xA812DC60UL, 0xA1EBDDF8UL, 0x991BE14CUL, 0xDB6E6B0DUL,
+ 0xC67B5510UL, 0x6D672C37UL, 0x2765D43BUL, 0xDCD0E804UL,
+ 0xF1290DC7UL, 0xCC00FFA3UL, 0xB5390F92UL, 0x690FED0BUL,
+ 0x667B9FFBUL, 0xCEDB7D9CUL, 0xA091CF0BUL, 0xD9155EA3UL,
+ 0xBB132F88UL, 0x515BAD24UL, 0x7B9479BFUL, 0x763BD6EBUL,
+ 0x37392EB3UL, 0xCC115979UL, 0x8026E297UL, 0xF42E312DUL,
+ 0x6842ADA7UL, 0xC66A2B3BUL, 0x12754CCCUL, 0x782EF11CUL,
+ 0x6A124237UL, 0xB79251E7UL, 0x06A1BBE6UL, 0x4BFB6350UL,
+ 0x1A6B1018UL, 0x11CAEDFAUL, 0x3D25BDD8UL, 0xE2E1C3C9UL,
+ 0x44421659UL, 0x0A121386UL, 0xD90CEC6EUL, 0xD5ABEA2AUL,
+ 0x64AF674EUL, 0xDA86A85FUL, 0xBEBFE988UL, 0x64E4C3FEUL,
+ 0x9DBC8057UL, 0xF0F7C086UL, 0x60787BF8UL, 0x6003604DUL,
+ 0xD1FD8346UL, 0xF6381FB0UL, 0x7745AE04UL, 0xD736FCCCUL,
+ 0x83426B33UL, 0xF01EAB71UL, 0xB0804187UL, 0x3C005E5FUL,
+ 0x77A057BEUL, 0xBDE8AE24UL, 0x55464299UL, 0xBF582E61UL,
+ 0x4E58F48FUL, 0xF2DDFDA2UL, 0xF474EF38UL, 0x8789BDC2UL,
+ 0x5366F9C3UL, 0xC8B38E74UL, 0xB475F255UL, 0x46FCD9B9UL,
+ 0x7AEB2661UL, 0x8B1DDF84UL, 0x846A0E79UL, 0x915F95E2UL,
+ 0x466E598EUL, 0x20B45770UL, 0x8CD55591UL, 0xC902DE4CUL,
+ 0xB90BACE1UL, 0xBB8205D0UL, 0x11A86248UL, 0x7574A99EUL,
+ 0xB77F19B6UL, 0xE0A9DC09UL, 0x662D09A1UL, 0xC4324633UL,
+ 0xE85A1F02UL, 0x09F0BE8CUL, 0x4A99A025UL, 0x1D6EFE10UL,
+ 0x1AB93D1DUL, 0x0BA5A4DFUL, 0xA186F20FUL, 0x2868F169UL,
+ 0xDCB7DA83UL, 0x573906FEUL, 0xA1E2CE9BUL, 0x4FCD7F52UL,
+ 0x50115E01UL, 0xA70683FAUL, 0xA002B5C4UL, 0x0DE6D027UL,
+ 0x9AF88C27UL, 0x773F8641UL, 0xC3604C06UL, 0x61A806B5UL,
+ 0xF0177A28UL, 0xC0F586E0UL, 0x006058AAUL, 0x30DC7D62UL,
+ 0x11E69ED7UL, 0x2338EA63UL, 0x53C2DD94UL, 0xC2C21634UL,
+ 0xBBCBEE56UL, 0x90BCB6DEUL, 0xEBFC7DA1UL, 0xCE591D76UL,
+ 0x6F05E409UL, 0x4B7C0188UL, 0x39720A3DUL, 0x7C927C24UL,
+ 0x86E3725FUL, 0x724D9DB9UL, 0x1AC15BB4UL, 0xD39EB8FCUL,
+ 0xED545578UL, 0x08FCA5B5UL, 0xD83D7CD3UL, 0x4DAD0FC4UL,
+ 0x1E50EF5EUL, 0xB161E6F8UL, 0xA28514D9UL, 0x6C51133CUL,
+ 0x6FD5C7E7UL, 0x56E14EC4UL, 0x362ABFCEUL, 0xDDC6C837UL,
+ 0xD79A3234UL, 0x92638212UL, 0x670EFA8EUL, 0x406000E0UL },
+ { 0x3A39CE37UL, 0xD3FAF5CFUL, 0xABC27737UL, 0x5AC52D1BUL,
+ 0x5CB0679EUL, 0x4FA33742UL, 0xD3822740UL, 0x99BC9BBEUL,
+ 0xD5118E9DUL, 0xBF0F7315UL, 0xD62D1C7EUL, 0xC700C47BUL,
+ 0xB78C1B6BUL, 0x21A19045UL, 0xB26EB1BEUL, 0x6A366EB4UL,
+ 0x5748AB2FUL, 0xBC946E79UL, 0xC6A376D2UL, 0x6549C2C8UL,
+ 0x530FF8EEUL, 0x468DDE7DUL, 0xD5730A1DUL, 0x4CD04DC6UL,
+ 0x2939BBDBUL, 0xA9BA4650UL, 0xAC9526E8UL, 0xBE5EE304UL,
+ 0xA1FAD5F0UL, 0x6A2D519AUL, 0x63EF8CE2UL, 0x9A86EE22UL,
+ 0xC089C2B8UL, 0x43242EF6UL, 0xA51E03AAUL, 0x9CF2D0A4UL,
+ 0x83C061BAUL, 0x9BE96A4DUL, 0x8FE51550UL, 0xBA645BD6UL,
+ 0x2826A2F9UL, 0xA73A3AE1UL, 0x4BA99586UL, 0xEF5562E9UL,
+ 0xC72FEFD3UL, 0xF752F7DAUL, 0x3F046F69UL, 0x77FA0A59UL,
+ 0x80E4A915UL, 0x87B08601UL, 0x9B09E6ADUL, 0x3B3EE593UL,
+ 0xE990FD5AUL, 0x9E34D797UL, 0x2CF0B7D9UL, 0x022B8B51UL,
+ 0x96D5AC3AUL, 0x017DA67DUL, 0xD1CF3ED6UL, 0x7C7D2D28UL,
+ 0x1F9F25CFUL, 0xADF2B89BUL, 0x5AD6B472UL, 0x5A88F54CUL,
+ 0xE029AC71UL, 0xE019A5E6UL, 0x47B0ACFDUL, 0xED93FA9BUL,
+ 0xE8D3C48DUL, 0x283B57CCUL, 0xF8D56629UL, 0x79132E28UL,
+ 0x785F0191UL, 0xED756055UL, 0xF7960E44UL, 0xE3D35E8CUL,
+ 0x15056DD4UL, 0x88F46DBAUL, 0x03A16125UL, 0x0564F0BDUL,
+ 0xC3EB9E15UL, 0x3C9057A2UL, 0x97271AECUL, 0xA93A072AUL,
+ 0x1B3F6D9BUL, 0x1E6321F5UL, 0xF59C66FBUL, 0x26DCF319UL,
+ 0x7533D928UL, 0xB155FDF5UL, 0x03563482UL, 0x8ABA3CBBUL,
+ 0x28517711UL, 0xC20AD9F8UL, 0xABCC5167UL, 0xCCAD925FUL,
+ 0x4DE81751UL, 0x3830DC8EUL, 0x379D5862UL, 0x9320F991UL,
+ 0xEA7A90C2UL, 0xFB3E7BCEUL, 0x5121CE64UL, 0x774FBE32UL,
+ 0xA8B6E37EUL, 0xC3293D46UL, 0x48DE5369UL, 0x6413E680UL,
+ 0xA2AE0810UL, 0xDD6DB224UL, 0x69852DFDUL, 0x09072166UL,
+ 0xB39A460AUL, 0x6445C0DDUL, 0x586CDECFUL, 0x1C20C8AEUL,
+ 0x5BBEF7DDUL, 0x1B588D40UL, 0xCCD2017FUL, 0x6BB4E3BBUL,
+ 0xDDA26A7EUL, 0x3A59FF45UL, 0x3E350A44UL, 0xBCB4CDD5UL,
+ 0x72EACEA8UL, 0xFA6484BBUL, 0x8D6612AEUL, 0xBF3C6F47UL,
+ 0xD29BE463UL, 0x542F5D9EUL, 0xAEC2771BUL, 0xF64E6370UL,
+ 0x740E0D8DUL, 0xE75B1357UL, 0xF8721671UL, 0xAF537D5DUL,
+ 0x4040CB08UL, 0x4EB4E2CCUL, 0x34D2466AUL, 0x0115AF84UL,
+ 0xE1B00428UL, 0x95983A1DUL, 0x06B89FB4UL, 0xCE6EA048UL,
+ 0x6F3F3B82UL, 0x3520AB82UL, 0x011A1D4BUL, 0x277227F8UL,
+ 0x611560B1UL, 0xE7933FDCUL, 0xBB3A792BUL, 0x344525BDUL,
+ 0xA08839E1UL, 0x51CE794BUL, 0x2F32C9B7UL, 0xA01FBAC9UL,
+ 0xE01CC87EUL, 0xBCC7D1F6UL, 0xCF0111C3UL, 0xA1E8AAC7UL,
+ 0x1A908749UL, 0xD44FBD9AUL, 0xD0DADECBUL, 0xD50ADA38UL,
+ 0x0339C32AUL, 0xC6913667UL, 0x8DF9317CUL, 0xE0B12B4FUL,
+ 0xF79E59B7UL, 0x43F5BB3AUL, 0xF2D519FFUL, 0x27D9459CUL,
+ 0xBF97222CUL, 0x15E6FC2AUL, 0x0F91FC71UL, 0x9B941525UL,
+ 0xFAE59361UL, 0xCEB69CEBUL, 0xC2A86459UL, 0x12BAA8D1UL,
+ 0xB6C1075EUL, 0xE3056A0CUL, 0x10D25065UL, 0xCB03A442UL,
+ 0xE0EC6E0EUL, 0x1698DB3BUL, 0x4C98A0BEUL, 0x3278E964UL,
+ 0x9F1F9532UL, 0xE0D392DFUL, 0xD3A0342BUL, 0x8971F21EUL,
+ 0x1B0A7441UL, 0x4BA3348CUL, 0xC5BE7120UL, 0xC37632D8UL,
+ 0xDF359F8DUL, 0x9B992F2EUL, 0xE60B6F47UL, 0x0FE3F11DUL,
+ 0xE54CDA54UL, 0x1EDAD891UL, 0xCE6279CFUL, 0xCD3E7E6FUL,
+ 0x1618B166UL, 0xFD2C1D05UL, 0x848FD2C5UL, 0xF6FB2299UL,
+ 0xF523F357UL, 0xA6327623UL, 0x93A83531UL, 0x56CCCD02UL,
+ 0xACF08162UL, 0x5A75EBB5UL, 0x6E163697UL, 0x88D273CCUL,
+ 0xDE966292UL, 0x81B949D0UL, 0x4C50901BUL, 0x71C65614UL,
+ 0xE6C6C7BDUL, 0x327A140AUL, 0x45E1D006UL, 0xC3F27B9AUL,
+ 0xC9AA53FDUL, 0x62A80F00UL, 0xBB25BFE2UL, 0x35BDD2F6UL,
+ 0x71126905UL, 0xB2040222UL, 0xB6CBCF7CUL, 0xCD769C2BUL,
+ 0x53113EC0UL, 0x1640E3D3UL, 0x38ABBD60UL, 0x2547ADF0UL,
+ 0xBA38209CUL, 0xF746CE76UL, 0x77AFA1C5UL, 0x20756060UL,
+ 0x85CBFE4EUL, 0x8AE88DD8UL, 0x7AAAF9B0UL, 0x4CF9AA7EUL,
+ 0x1948C25CUL, 0x02FB8A8CUL, 0x01C36AE4UL, 0xD6EBE1F9UL,
+ 0x90D4F869UL, 0xA65CDEA0UL, 0x3F09252DUL, 0xC208E69FUL,
+ 0xB74E6132UL, 0xCE77E25BUL, 0x578FDFE3UL, 0x3AC372E6UL }
+};
+
+#ifndef __GNUC__
+#define F(x) ((S1[LTC_BYTE(x,3)] + S2[LTC_BYTE(x,2)]) ^ S3[LTC_BYTE(x,1)]) + S4[LTC_BYTE(x,0)]
+#else
+#define F(x) ((skey->blowfish.S[0][LTC_BYTE(x,3)] + skey->blowfish.S[1][LTC_BYTE(x,2)]) ^ skey->blowfish.S[2][LTC_BYTE(x,1)]) + skey->blowfish.S[3][LTC_BYTE(x,0)]
+#endif
+
+static void s_blowfish_encipher(ulong32 *L, ulong32 *R, const symmetric_key *skey)
+{
+ int rounds;
+
+ ulong32 l, r;
+#ifndef __GNUC__
+ const ulong32 *S1, *S2, *S3, *S4;
+
+ S1 = skey->blowfish.S[0];
+ S2 = skey->blowfish.S[1];
+ S3 = skey->blowfish.S[2];
+ S4 = skey->blowfish.S[3];
+#endif
+
+ l = *L;
+ r = *R;
+
+ /* do 16 rounds */
+ for (rounds = 0; rounds < 16; ) {
+ l ^= skey->blowfish.K[rounds++]; r ^= F(l);
+ r ^= skey->blowfish.K[rounds++]; l ^= F(r);
+ l ^= skey->blowfish.K[rounds++]; r ^= F(l);
+ r ^= skey->blowfish.K[rounds++]; l ^= F(r);
+ }
+
+ /* last keying */
+ l ^= skey->blowfish.K[16];
+ r ^= skey->blowfish.K[17];
+
+ *L = r;
+ *R = l;
+}
+
+void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey)
+{
+ unsigned long i;
+ ulong32 *d = data;
+
+ for (i = 0; i < blocks; ++i) {
+ s_blowfish_encipher(d, d + 1, skey);
+ d += 2;
+ }
+}
+
+static ulong32 s_blowfish_stream2word(const unsigned char *d, int dlen, int *cur)
+{
+ unsigned int z;
+ int y = *cur;
+ ulong32 ret = 0;
+
+ for (z = 0; z < 4; z++) {
+ ret = (ret << 8) | ((ulong32)d[y++] & 255);
+ if (y == dlen) {
+ y = 0;
+ }
+ }
+
+ *cur = y;
+ return ret;
+}
+
+ /**
+ Expand the Blowfish internal state
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param data The additional data you wish to pass (can be NULL)
+ @param datalen The additional data length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int blowfish_expand(const unsigned char *key, int keylen,
+ const unsigned char *data, int datalen,
+ symmetric_key *skey)
+{
+ ulong32 x, y, A, B[2];
+ int i;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* load in key bytes (Supplied by David Hopwood) */
+ i = 0;
+ for (x = 0; x < 18; x++) {
+ A = s_blowfish_stream2word(key, keylen, &i);
+ skey->blowfish.K[x] ^= A;
+ }
+
+
+ i = 0;
+ B[0] = 0;
+ B[1] = 0;
+ for (x = 0; x < 18; x += 2) {
+ if (data != NULL) {
+ B[0] ^= s_blowfish_stream2word(data, datalen, &i);
+ B[1] ^= s_blowfish_stream2word(data, datalen, &i);
+ }
+ /* encrypt it */
+ s_blowfish_encipher(&B[0], &B[1], skey);
+ /* copy it */
+ skey->blowfish.K[x] = B[0];
+ skey->blowfish.K[x+1] = B[1];
+ }
+
+ /* encrypt S array */
+ for (x = 0; x < 4; x++) {
+ for (y = 0; y < 256; y += 2) {
+ if (data != NULL) {
+ B[0] ^= s_blowfish_stream2word(data, datalen, &i);
+ B[1] ^= s_blowfish_stream2word(data, datalen, &i);
+ }
+ /* encrypt it */
+ s_blowfish_encipher(&B[0], &B[1], skey);
+ /* copy it */
+ skey->blowfish.S[x][y] = B[0];
+ skey->blowfish.S[x][y+1] = B[1];
+ }
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(B, sizeof(B));
+#endif
+
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the Blowfish block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+*/
+int blowfish_setup(const unsigned char *key, int keylen, int num_rounds,
+ symmetric_key *skey)
+{
+ /* check key length */
+ if (keylen < 8 || keylen > 72) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ /* check rounds */
+ if (num_rounds != 0 && num_rounds != 16) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ return blowfish_setup_with_data(key, keylen, NULL, 0, skey);
+}
+
+/**
+ Alternative initialize of the Blowfish block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param data The additional data you wish to pass (can be NULL)
+ @param datalen The additional data length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+*/
+
+int blowfish_setup_with_data(const unsigned char *key, int keylen,
+ const unsigned char *data, int datalen,
+ symmetric_key *skey)
+{
+ XMEMCPY(skey->blowfish.K, ORIG_P, sizeof(ORIG_P));
+ XMEMCPY(skey->blowfish.S, ORIG_S, sizeof(ORIG_S));
+ return blowfish_expand(key, keylen, data, datalen, skey);
+}
+
+/**
+ Encrypts a block of text with Blowfish
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+ ulong32 L, R;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* load it */
+ LOAD32H(L, &pt[0]);
+ LOAD32H(R, &pt[4]);
+
+ s_blowfish_encipher(&L, &R, skey);
+
+ /* store */
+ STORE32H(L, &ct[0]);
+ STORE32H(R, &ct[4]);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_blowfish_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(ulong32) * 2 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Decrypts a block of text with Blowfish
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+ ulong32 L, R;
+ int r;
+#ifndef __GNUC__
+ const ulong32 *S1, *S2, *S3, *S4;
+#endif
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+#ifndef __GNUC__
+ S1 = skey->blowfish.S[0];
+ S2 = skey->blowfish.S[1];
+ S3 = skey->blowfish.S[2];
+ S4 = skey->blowfish.S[3];
+#endif
+
+ /* load it */
+ LOAD32H(R, &ct[0]);
+ LOAD32H(L, &ct[4]);
+
+ /* undo last keying */
+ R ^= skey->blowfish.K[17];
+ L ^= skey->blowfish.K[16];
+
+ /* do 16 rounds */
+ for (r = 15; r > 0; ) {
+ L ^= F(R); R ^= skey->blowfish.K[r--];
+ R ^= F(L); L ^= skey->blowfish.K[r--];
+ L ^= F(R); R ^= skey->blowfish.K[r--];
+ R ^= F(L); L ^= skey->blowfish.K[r--];
+ }
+
+ /* store */
+ STORE32H(L, &pt[0]);
+ STORE32H(R, &pt[4]);
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_blowfish_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(ulong32) * 2 + sizeof(int));
+ return err;
+}
+#endif
+
+
+/**
+ Performs a self-test of the Blowfish block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int blowfish_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ int err;
+ symmetric_key key;
+ static const struct {
+ unsigned char key[8], pt[8], ct[8];
+ } tests[] = {
+ {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ { 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}
+ },
+ {
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ { 0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}
+ },
+ {
+ { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ { 0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}
+ }
+ };
+ unsigned char tmp[2][8];
+ int x, y;
+
+ for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+ /* setup key */
+ if ((err = blowfish_setup(tests[x].key, 8, 16, &key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* encrypt and decrypt */
+ blowfish_ecb_encrypt(tests[x].pt, tmp[0], &key);
+ blowfish_ecb_decrypt(tmp[0], tmp[1], &key);
+
+ /* compare */
+ if ((compare_testvector(tmp[0], 8, tests[x].ct, 8, "Blowfish Encrypt", x) != 0) ||
+ (compare_testvector(tmp[1], 8, tests[x].pt, 8, "Blowfish Decrypt", x) != 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 8; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) blowfish_ecb_encrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 1000; y++) blowfish_ecb_decrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+
+
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void blowfish_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int blowfish_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+
+ if (*keysize < 8) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize > 72) {
+ *keysize = 72;
+ }
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/ciphers/camellia.c b/Sources/libtomcrypt/ciphers/camellia.c
new file mode 100644
index 00000000..733e9639
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/camellia.c
@@ -0,0 +1,720 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file camellia.c
+ Implementation by Tom St Denis of Elliptic Semiconductor
+*/
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CAMELLIA
+
+const struct ltc_cipher_descriptor camellia_desc = {
+ "camellia",
+ 23,
+ 16, 32, 16, 18,
+ &camellia_setup,
+ &camellia_ecb_encrypt,
+ &camellia_ecb_decrypt,
+ &camellia_test,
+ &camellia_done,
+ &camellia_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ulong32 SP1110[] = {
+0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700, 0xc0c0c000, 0xe5e5e500,
+0xe4e4e400, 0x85858500, 0x57575700, 0x35353500, 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100,
+0x23232300, 0xefefef00, 0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100,
+0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500, 0x92929200, 0xbdbdbd00,
+0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00, 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00,
+0x3e3e3e00, 0x30303000, 0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00,
+0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700, 0x5d5d5d00, 0x3d3d3d00,
+0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600, 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00,
+0x8b8b8b00, 0x0d0d0d00, 0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00,
+0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100, 0x84848400, 0x99999900,
+0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200, 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500,
+0x6d6d6d00, 0xb7b7b700, 0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700,
+0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00, 0x11111100, 0x1c1c1c00,
+0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600, 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200,
+0xfefefe00, 0x44444400, 0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100,
+0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00, 0x69696900, 0x50505000,
+0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00, 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700,
+0x54545400, 0x5b5b5b00, 0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200,
+0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700, 0x75757500, 0xdbdbdb00,
+0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00, 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400,
+0x87878700, 0x5c5c5c00, 0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300,
+0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00, 0xbfbfbf00, 0xe2e2e200,
+0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600, 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00,
+0x81818100, 0x96969600, 0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00,
+0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00, 0xbcbcbc00, 0x8e8e8e00,
+0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600, 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900,
+0x78787800, 0x98989800, 0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00,
+0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200, 0x8d8d8d00, 0xfafafa00,
+0x72727200, 0x07070700, 0xb9b9b900, 0x55555500, 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00,
+0x36363600, 0x49494900, 0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400,
+0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900, 0x43434300, 0xc1c1c100,
+0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400, 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00,
+};
+
+static const ulong32 SP0222[] = {
+0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e, 0x00818181, 0x00cbcbcb,
+0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a, 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282,
+0x00464646, 0x00dfdfdf, 0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242,
+0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca, 0x00252525, 0x007b7b7b,
+0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f, 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d,
+0x007c7c7c, 0x00606060, 0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434,
+0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e, 0x00bababa, 0x007a7a7a,
+0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad, 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a,
+0x00171717, 0x001a1a1a, 0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a,
+0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363, 0x00090909, 0x00333333,
+0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585, 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a,
+0x00dadada, 0x006f6f6f, 0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf,
+0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636, 0x00222222, 0x00383838,
+0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c, 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444,
+0x00fdfdfd, 0x00888888, 0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323,
+0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9, 0x00d2d2d2, 0x00a0a0a0,
+0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa, 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f,
+0x00a8a8a8, 0x00b6b6b6, 0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5,
+0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef, 0x00eaeaea, 0x00b7b7b7,
+0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5, 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929,
+0x000f0f0f, 0x00b8b8b8, 0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666,
+0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe, 0x007f7f7f, 0x00c5c5c5,
+0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c, 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676,
+0x00030303, 0x002d2d2d, 0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c,
+0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc, 0x00797979, 0x001d1d1d,
+0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d, 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2,
+0x00f0f0f0, 0x00313131, 0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575,
+0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545, 0x001b1b1b, 0x00f5f5f5,
+0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa, 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414,
+0x006c6c6c, 0x00929292, 0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949,
+0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393, 0x00868686, 0x00838383,
+0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9, 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d,
+};
+
+static const ulong32 SP3033[] = {
+0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393, 0x60006060, 0xf200f2f2,
+0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a, 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0,
+0x91009191, 0xf700f7f7, 0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090,
+0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2, 0x49004949, 0xde00dede,
+0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7, 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767,
+0x1f001f1f, 0x18001818, 0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d,
+0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3, 0xae00aeae, 0x9e009e9e,
+0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b, 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6,
+0xc500c5c5, 0x86008686, 0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696,
+0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8, 0x42004242, 0xcc00cccc,
+0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161, 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282,
+0xb600b6b6, 0xdb00dbdb, 0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb,
+0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d, 0x88008888, 0x0e000e0e,
+0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b, 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111,
+0x7f007f7f, 0x22002222, 0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8,
+0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e, 0xb400b4b4, 0x28002828,
+0x55005555, 0x68006868, 0x50005050, 0xbe00bebe, 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb,
+0x2a002a2a, 0xad00adad, 0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969,
+0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb, 0xba00baba, 0xed00eded,
+0x45004545, 0x81008181, 0x73007373, 0x6d006d6d, 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a,
+0xc300c3c3, 0x2e002e2e, 0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999,
+0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf, 0xdf00dfdf, 0x71007171,
+0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313, 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d,
+0xc000c0c0, 0x4b004b4b, 0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717,
+0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737, 0x5e005e5e, 0x47004747,
+0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b, 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac,
+0x3c003c3c, 0x4c004c4c, 0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d,
+0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151, 0xc600c6c6, 0x7d007d7d,
+0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa, 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505,
+0x1b001b1b, 0xa400a4a4, 0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252,
+0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4, 0xa100a1a1, 0xe000e0e0,
+0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a, 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f,
+};
+
+static const ulong32 SP4404[] = {
+0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057, 0xeaea00ea, 0xaeae00ae,
+0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5, 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092,
+0x86860086, 0xafaf00af, 0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b,
+0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a, 0x51510051, 0x6c6c006c,
+0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0, 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084,
+0xdfdf00df, 0xcbcb00cb, 0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004,
+0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c, 0x53530053, 0xf2f200f2,
+0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a, 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069,
+0xaaaa00aa, 0xa0a000a0, 0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064,
+0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6, 0x09090009, 0xdddd00dd,
+0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090, 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf,
+0x52520052, 0xd8d800d8, 0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063,
+0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9, 0x2f2f002f, 0xb4b400b4,
+0x78780078, 0x06060006, 0xe7e700e7, 0x71710071, 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d,
+0x72720072, 0xb9b900b9, 0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1,
+0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad, 0x77770077, 0x80800080,
+0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5, 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041,
+0xefef00ef, 0x93930093, 0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd,
+0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f, 0xc5c500c5, 0x1a1a001a,
+0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d, 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d,
+0x0d0d000d, 0x66660066, 0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099,
+0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031, 0x17170017, 0xd7d700d7,
+0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c, 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022,
+0x44440044, 0xb2b200b2, 0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050,
+0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095, 0xffff00ff, 0xd2d200d2,
+0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db, 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094,
+0x5c5c005c, 0x02020002, 0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2,
+0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b, 0xbebe00be, 0x2e2e002e,
+0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e, 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059,
+0x98980098, 0x6a6a006a, 0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa,
+0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068, 0x38380038, 0xa4a400a4,
+0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1, 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e,
+};
+
+static const ulong64 key_sigma[] = {
+ CONST64(0xA09E667F3BCC908B),
+ CONST64(0xB67AE8584CAA73B2),
+ CONST64(0xC6EF372FE94F82BE),
+ CONST64(0x54FF53A5F1D36F1C),
+ CONST64(0x10E527FADE682D1D),
+ CONST64(0xB05688C2B3E6C1FD)
+};
+
+static ulong64 F(ulong64 x)
+{
+ ulong32 D, U;
+
+#define loc(i) ((8-i)*8)
+
+ D = SP1110[(x >> loc(8)) & 0xFF] ^ SP0222[(x >> loc(5)) & 0xFF] ^ SP3033[(x >> loc(6)) & 0xFF] ^ SP4404[(x >> loc(7)) & 0xFF];
+ U = SP1110[(x >> loc(1)) & 0xFF] ^ SP0222[(x >> loc(2)) & 0xFF] ^ SP3033[(x >> loc(3)) & 0xFF] ^ SP4404[(x >> loc(4)) & 0xFF];
+
+ D ^= U;
+ U = D ^ RORc(U, 8);
+
+ return ((ulong64)U) | (((ulong64)D) << CONST64(32));
+}
+
+static void rot_128(const unsigned char *in, unsigned count, unsigned char *out)
+{
+ unsigned x, w, b;
+
+ w = count >> 3;
+ b = count & 7;
+
+ for (x = 0; x < 16; x++) {
+ out[x] = (in[(x+w)&15] << b) | (in[(x+w+1)&15] >> (8 - b));
+ }
+}
+
+int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ unsigned char T[48], kA[16], kB[16], kR[16], kL[16];
+ int x;
+ ulong64 A, B;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* Valid sizes (in bytes) are 16, 24, 32 */
+ if (keylen != 16 && keylen != 24 && keylen != 32) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ /* number of rounds */
+ skey->camellia.R = (keylen == 16) ? 18 : 24;
+
+ if (num_rounds != 0 && num_rounds != skey->camellia.R) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* expand key */
+ if (keylen == 16) {
+ for (x = 0; x < 16; x++) {
+ T[x] = key[x];
+ T[x + 16] = 0;
+ }
+ } else if (keylen == 24) {
+ for (x = 0; x < 24; x++) {
+ T[x] = key[x];
+ }
+ for (x = 24; x < 32; x++) {
+ T[x] = key[x-8] ^ 0xFF;
+ }
+ } else {
+ for (x = 0; x < 32; x++) {
+ T[x] = key[x];
+ }
+ }
+
+ for (x = 0; x < 16; x++) {
+ kL[x] = T[x];
+ kR[x] = T[x + 16];
+ }
+
+ for (x = 32; x < 48; x++) {
+ T[x] = T[x - 32] ^ T[x - 16];
+ }
+
+ /* first two rounds */
+ LOAD64H(A, T+32); LOAD64H(B, T+40);
+ B ^= F(A ^ key_sigma[0]);
+ A ^= F(B ^ key_sigma[1]);
+ STORE64H(A, T+32); STORE64H(B, T+40);
+
+ /* xor kL in */
+ for (x = 0; x < 16; x++) { T[x+32] ^= kL[x]; }
+
+ /* next two rounds */
+ LOAD64H(A, T+32); LOAD64H(B, T+40);
+ B ^= F(A ^ key_sigma[2]);
+ A ^= F(B ^ key_sigma[3]);
+ STORE64H(A, T+32); STORE64H(B, T+40);
+
+ /* grab KA */
+ for (x = 0; x < 16; x++) { kA[x] = T[x+32]; }
+
+ /* xor kR in */
+ for (x = 0; x < 16; x++) { T[x+32] ^= kR[x]; }
+
+ if (keylen == 16) {
+ /* grab whitening keys kw1 and kw2 */
+ LOAD64H(skey->camellia.kw[0], kL);
+ LOAD64H(skey->camellia.kw[1], kL+8);
+
+ /* k1-k2 */
+ LOAD64H(skey->camellia.k[0], kA);
+ LOAD64H(skey->camellia.k[1], kA+8);
+
+ /* rotate kL by 15, k3/k4 */
+ rot_128(kL, 15, T+32);
+ LOAD64H(skey->camellia.k[2], T+32);
+ LOAD64H(skey->camellia.k[3], T+40);
+
+ /* rotate kA by 15, k5/k6 */
+ rot_128(kA, 15, T+32);
+ LOAD64H(skey->camellia.k[4], T+32);
+ LOAD64H(skey->camellia.k[5], T+40);
+
+ /* rotate kA by 30, kl1, kl2 */
+ rot_128(kA, 30, T+32);
+ LOAD64H(skey->camellia.kl[0], T+32);
+ LOAD64H(skey->camellia.kl[1], T+40);
+
+ /* rotate kL by 45, k7/k8 */
+ rot_128(kL, 45, T+32);
+ LOAD64H(skey->camellia.k[6], T+32);
+ LOAD64H(skey->camellia.k[7], T+40);
+
+ /* rotate kA by 45, k9/k10 */
+ rot_128(kA, 45, T+32);
+ LOAD64H(skey->camellia.k[8], T+32);
+ rot_128(kL, 60, T+32);
+ LOAD64H(skey->camellia.k[9], T+40);
+
+ /* rotate kA by 60, k11/k12 */
+ rot_128(kA, 60, T+32);
+ LOAD64H(skey->camellia.k[10], T+32);
+ LOAD64H(skey->camellia.k[11], T+40);
+
+ /* rotate kL by 77, kl3, kl4 */
+ rot_128(kL, 77, T+32);
+ LOAD64H(skey->camellia.kl[2], T+32);
+ LOAD64H(skey->camellia.kl[3], T+40);
+
+ /* rotate kL by 94, k13/k14 */
+ rot_128(kL, 94, T+32);
+ LOAD64H(skey->camellia.k[12], T+32);
+ LOAD64H(skey->camellia.k[13], T+40);
+
+ /* rotate kA by 94, k15/k16 */
+ rot_128(kA, 94, T+32);
+ LOAD64H(skey->camellia.k[14], T+32);
+ LOAD64H(skey->camellia.k[15], T+40);
+
+ /* rotate kL by 111, k17/k18 */
+ rot_128(kL, 111, T+32);
+ LOAD64H(skey->camellia.k[16], T+32);
+ LOAD64H(skey->camellia.k[17], T+40);
+
+ /* rotate kA by 111, kw3/kw4 */
+ rot_128(kA, 111, T+32);
+ LOAD64H(skey->camellia.kw[2], T+32);
+ LOAD64H(skey->camellia.kw[3], T+40);
+ } else {
+ /* last two rounds */
+ LOAD64H(A, T+32); LOAD64H(B, T+40);
+ B ^= F(A ^ key_sigma[4]);
+ A ^= F(B ^ key_sigma[5]);
+ STORE64H(A, T+32); STORE64H(B, T+40);
+
+ /* grab kB */
+ for (x = 0; x < 16; x++) { kB[x] = T[x+32]; }
+
+ /* kw1/2 from kL*/
+ LOAD64H(skey->camellia.kw[0], kL);
+ LOAD64H(skey->camellia.kw[1], kL+8);
+
+ /* k1/k2 = kB */
+ LOAD64H(skey->camellia.k[0], kB);
+ LOAD64H(skey->camellia.k[1], kB+8);
+
+ /* k3/k4 = kR by 15 */
+ rot_128(kR, 15, T+32);
+ LOAD64H(skey->camellia.k[2], T+32);
+ LOAD64H(skey->camellia.k[3], T+40);
+
+ /* k5/k7 = kA by 15 */
+ rot_128(kA, 15, T+32);
+ LOAD64H(skey->camellia.k[4], T+32);
+ LOAD64H(skey->camellia.k[5], T+40);
+
+ /* kl1/2 = kR by 30 */
+ rot_128(kR, 30, T+32);
+ LOAD64H(skey->camellia.kl[0], T+32);
+ LOAD64H(skey->camellia.kl[1], T+40);
+
+ /* k7/k8 = kB by 30 */
+ rot_128(kB, 30, T+32);
+ LOAD64H(skey->camellia.k[6], T+32);
+ LOAD64H(skey->camellia.k[7], T+40);
+
+ /* k9/k10 = kL by 45 */
+ rot_128(kL, 45, T+32);
+ LOAD64H(skey->camellia.k[8], T+32);
+ LOAD64H(skey->camellia.k[9], T+40);
+
+ /* k11/k12 = kA by 45 */
+ rot_128(kA, 45, T+32);
+ LOAD64H(skey->camellia.k[10], T+32);
+ LOAD64H(skey->camellia.k[11], T+40);
+
+ /* kl3/4 = kL by 60 */
+ rot_128(kL, 60, T+32);
+ LOAD64H(skey->camellia.kl[2], T+32);
+ LOAD64H(skey->camellia.kl[3], T+40);
+
+ /* k13/k14 = kR by 60 */
+ rot_128(kR, 60, T+32);
+ LOAD64H(skey->camellia.k[12], T+32);
+ LOAD64H(skey->camellia.k[13], T+40);
+
+ /* k15/k16 = kB by 15 */
+ rot_128(kB, 60, T+32);
+ LOAD64H(skey->camellia.k[14], T+32);
+ LOAD64H(skey->camellia.k[15], T+40);
+
+ /* k17/k18 = kL by 77 */
+ rot_128(kL, 77, T+32);
+ LOAD64H(skey->camellia.k[16], T+32);
+ LOAD64H(skey->camellia.k[17], T+40);
+
+ /* kl5/6 = kA by 77 */
+ rot_128(kA, 77, T+32);
+ LOAD64H(skey->camellia.kl[4], T+32);
+ LOAD64H(skey->camellia.kl[5], T+40);
+
+ /* k19/k20 = kR by 94 */
+ rot_128(kR, 94, T+32);
+ LOAD64H(skey->camellia.k[18], T+32);
+ LOAD64H(skey->camellia.k[19], T+40);
+
+ /* k21/k22 = kA by 94 */
+ rot_128(kA, 94, T+32);
+ LOAD64H(skey->camellia.k[20], T+32);
+ LOAD64H(skey->camellia.k[21], T+40);
+
+ /* k23/k24 = kL by 111 */
+ rot_128(kL, 111, T+32);
+ LOAD64H(skey->camellia.k[22], T+32);
+ LOAD64H(skey->camellia.k[23], T+40);
+
+ /* kw2/kw3 = kB by 111 */
+ rot_128(kB, 111, T+32);
+ LOAD64H(skey->camellia.kw[2], T+32);
+ LOAD64H(skey->camellia.kw[3], T+40);
+ }
+
+ return CRYPT_OK;
+}
+
+int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ ulong64 L, R;
+ ulong32 a, b;
+
+ LOAD64H(L, pt+0); LOAD64H(R, pt+8);
+ L ^= skey->camellia.kw[0];
+ R ^= skey->camellia.kw[1];
+
+ /* first 6 rounds */
+ R ^= F(L ^ skey->camellia.k[0]);
+ L ^= F(R ^ skey->camellia.k[1]);
+ R ^= F(L ^ skey->camellia.k[2]);
+ L ^= F(R ^ skey->camellia.k[3]);
+ R ^= F(L ^ skey->camellia.k[4]);
+ L ^= F(R ^ skey->camellia.k[5]);
+
+ /* FL */
+ a = (ulong32)(L >> 32);
+ b = (ulong32)(L & 0xFFFFFFFFUL);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1);
+ a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU);
+ L = (((ulong64)a) << 32) | b;
+
+ /* FL^-1 */
+ a = (ulong32)(R >> 32);
+ b = (ulong32)(R & 0xFFFFFFFFUL);
+ a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1);
+ R = (((ulong64)a) << 32) | b;
+
+ /* second 6 rounds */
+ R ^= F(L ^ skey->camellia.k[6]);
+ L ^= F(R ^ skey->camellia.k[7]);
+ R ^= F(L ^ skey->camellia.k[8]);
+ L ^= F(R ^ skey->camellia.k[9]);
+ R ^= F(L ^ skey->camellia.k[10]);
+ L ^= F(R ^ skey->camellia.k[11]);
+
+ /* FL */
+ a = (ulong32)(L >> 32);
+ b = (ulong32)(L & 0xFFFFFFFFUL);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1);
+ a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU);
+ L = (((ulong64)a) << 32) | b;
+
+ /* FL^-1 */
+ a = (ulong32)(R >> 32);
+ b = (ulong32)(R & 0xFFFFFFFFUL);
+ a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1);
+ R = (((ulong64)a) << 32) | b;
+
+ /* third 6 rounds */
+ R ^= F(L ^ skey->camellia.k[12]);
+ L ^= F(R ^ skey->camellia.k[13]);
+ R ^= F(L ^ skey->camellia.k[14]);
+ L ^= F(R ^ skey->camellia.k[15]);
+ R ^= F(L ^ skey->camellia.k[16]);
+ L ^= F(R ^ skey->camellia.k[17]);
+
+ /* next FL */
+ if (skey->camellia.R == 24) {
+ /* FL */
+ a = (ulong32)(L >> 32);
+ b = (ulong32)(L & 0xFFFFFFFFUL);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1);
+ a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU);
+ L = (((ulong64)a) << 32) | b;
+
+ /* FL^-1 */
+ a = (ulong32)(R >> 32);
+ b = (ulong32)(R & 0xFFFFFFFFUL);
+ a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1);
+ R = (((ulong64)a) << 32) | b;
+
+ /* fourth 6 rounds */
+ R ^= F(L ^ skey->camellia.k[18]);
+ L ^= F(R ^ skey->camellia.k[19]);
+ R ^= F(L ^ skey->camellia.k[20]);
+ L ^= F(R ^ skey->camellia.k[21]);
+ R ^= F(L ^ skey->camellia.k[22]);
+ L ^= F(R ^ skey->camellia.k[23]);
+ }
+
+ L ^= skey->camellia.kw[3];
+ R ^= skey->camellia.kw[2];
+
+ STORE64H(R, ct+0); STORE64H(L, ct+8);
+
+ return CRYPT_OK;
+}
+
+int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ ulong64 L, R;
+ ulong32 a, b;
+
+ LOAD64H(R, ct+0); LOAD64H(L, ct+8);
+ L ^= skey->camellia.kw[3];
+ R ^= skey->camellia.kw[2];
+
+ /* next FL */
+ if (skey->camellia.R == 24) {
+ /* fourth 6 rounds */
+ L ^= F(R ^ skey->camellia.k[23]);
+ R ^= F(L ^ skey->camellia.k[22]);
+ L ^= F(R ^ skey->camellia.k[21]);
+ R ^= F(L ^ skey->camellia.k[20]);
+ L ^= F(R ^ skey->camellia.k[19]);
+ R ^= F(L ^ skey->camellia.k[18]);
+
+ /* FL */
+ a = (ulong32)(L >> 32);
+ b = (ulong32)(L & 0xFFFFFFFFUL);
+ a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1);
+ L = (((ulong64)a) << 32) | b;
+
+ /* FL^-1 */
+ a = (ulong32)(R >> 32);
+ b = (ulong32)(R & 0xFFFFFFFFUL);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1);
+ a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU);
+ R = (((ulong64)a) << 32) | b;
+
+ }
+
+ /* third 6 rounds */
+ L ^= F(R ^ skey->camellia.k[17]);
+ R ^= F(L ^ skey->camellia.k[16]);
+ L ^= F(R ^ skey->camellia.k[15]);
+ R ^= F(L ^ skey->camellia.k[14]);
+ L ^= F(R ^ skey->camellia.k[13]);
+ R ^= F(L ^ skey->camellia.k[12]);
+
+ /* FL */
+ a = (ulong32)(L >> 32);
+ b = (ulong32)(L & 0xFFFFFFFFUL);
+ a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1);
+ L = (((ulong64)a) << 32) | b;
+
+ /* FL^-1 */
+ a = (ulong32)(R >> 32);
+ b = (ulong32)(R & 0xFFFFFFFFUL);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1);
+ a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU);
+ R = (((ulong64)a) << 32) | b;
+
+ /* second 6 rounds */
+ L ^= F(R ^ skey->camellia.k[11]);
+ R ^= F(L ^ skey->camellia.k[10]);
+ L ^= F(R ^ skey->camellia.k[9]);
+ R ^= F(L ^ skey->camellia.k[8]);
+ L ^= F(R ^ skey->camellia.k[7]);
+ R ^= F(L ^ skey->camellia.k[6]);
+
+ /* FL */
+ a = (ulong32)(L >> 32);
+ b = (ulong32)(L & 0xFFFFFFFFUL);
+ a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1);
+ L = (((ulong64)a) << 32) | b;
+
+ /* FL^-1 */
+ a = (ulong32)(R >> 32);
+ b = (ulong32)(R & 0xFFFFFFFFUL);
+ b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1);
+ a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU);
+ R = (((ulong64)a) << 32) | b;
+
+ /* first 6 rounds */
+ L ^= F(R ^ skey->camellia.k[5]);
+ R ^= F(L ^ skey->camellia.k[4]);
+ L ^= F(R ^ skey->camellia.k[3]);
+ R ^= F(L ^ skey->camellia.k[2]);
+ L ^= F(R ^ skey->camellia.k[1]);
+ R ^= F(L ^ skey->camellia.k[0]);
+
+ R ^= skey->camellia.kw[1];
+ L ^= skey->camellia.kw[0];
+
+ STORE64H(R, pt+8); STORE64H(L, pt+0);
+
+ return CRYPT_OK;
+}
+
+int camellia_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ int keylen;
+ unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+
+{
+ 16,
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+ 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }
+},
+
+{
+ 24,
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+ 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }
+},
+
+
+{
+ 32,
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+ 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }
+},
+
+{
+ 32,
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 },
+ { 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+ 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 },
+ { 0x79, 0x60, 0x10, 0x9F, 0xB6, 0xDC, 0x42, 0x94,
+ 0x7F, 0xCF, 0xE5, 0x9E, 0xA3, 0xC5, 0xEB, 0x6B }
+}
+};
+ unsigned char buf[2][16];
+ symmetric_key skey;
+ int err;
+ unsigned int x;
+
+ for (x = 0; x < sizeof(tests)/sizeof(tests[0]); x++) {
+ zeromem(&skey, sizeof(skey));
+ if ((err = camellia_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = camellia_ecb_encrypt(tests[x].pt, buf[0], &skey)) != CRYPT_OK) {
+ camellia_done(&skey);
+ return err;
+ }
+ if ((err = camellia_ecb_decrypt(tests[x].ct, buf[1], &skey)) != CRYPT_OK) {
+ camellia_done(&skey);
+ return err;
+ }
+ camellia_done(&skey);
+ if (compare_testvector(tests[x].ct, 16, buf[0], 16, "Camellia Encrypt", x) ||
+ compare_testvector(tests[x].pt, 16, buf[1], 16, "Camellia Decrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+void camellia_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+int camellia_keysize(int *keysize)
+{
+ if (*keysize >= 32) { *keysize = 32; }
+ else if (*keysize >= 24) { *keysize = 24; }
+ else if (*keysize >= 16) { *keysize = 16; }
+ else return CRYPT_INVALID_KEYSIZE;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/ciphers/cast5.c b/Sources/libtomcrypt/ciphers/cast5.c
new file mode 100644
index 00000000..3b401a5c
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/cast5.c
@@ -0,0 +1,705 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+ /**
+ @file cast5.c
+ Implementation of LTC_CAST5 (RFC 2144) by Tom St Denis
+ */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CAST5
+
+const struct ltc_cipher_descriptor cast5_desc = {
+ "cast5",
+ 15,
+ 5, 16, 8, 16,
+ &cast5_setup,
+ &cast5_ecb_encrypt,
+ &cast5_ecb_decrypt,
+ &cast5_test,
+ &cast5_done,
+ &cast5_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ulong32 S1[256] = {
+0x30fb40d4UL, 0x9fa0ff0bUL, 0x6beccd2fUL, 0x3f258c7aUL, 0x1e213f2fUL, 0x9c004dd3UL,
+0x6003e540UL, 0xcf9fc949UL, 0xbfd4af27UL, 0x88bbbdb5UL, 0xe2034090UL, 0x98d09675UL,
+0x6e63a0e0UL, 0x15c361d2UL, 0xc2e7661dUL, 0x22d4ff8eUL, 0x28683b6fUL, 0xc07fd059UL,
+0xff2379c8UL, 0x775f50e2UL, 0x43c340d3UL, 0xdf2f8656UL, 0x887ca41aUL, 0xa2d2bd2dUL,
+0xa1c9e0d6UL, 0x346c4819UL, 0x61b76d87UL, 0x22540f2fUL, 0x2abe32e1UL, 0xaa54166bUL,
+0x22568e3aUL, 0xa2d341d0UL, 0x66db40c8UL, 0xa784392fUL, 0x004dff2fUL, 0x2db9d2deUL,
+0x97943facUL, 0x4a97c1d8UL, 0x527644b7UL, 0xb5f437a7UL, 0xb82cbaefUL, 0xd751d159UL,
+0x6ff7f0edUL, 0x5a097a1fUL, 0x827b68d0UL, 0x90ecf52eUL, 0x22b0c054UL, 0xbc8e5935UL,
+0x4b6d2f7fUL, 0x50bb64a2UL, 0xd2664910UL, 0xbee5812dUL, 0xb7332290UL, 0xe93b159fUL,
+0xb48ee411UL, 0x4bff345dUL, 0xfd45c240UL, 0xad31973fUL, 0xc4f6d02eUL, 0x55fc8165UL,
+0xd5b1caadUL, 0xa1ac2daeUL, 0xa2d4b76dUL, 0xc19b0c50UL, 0x882240f2UL, 0x0c6e4f38UL,
+0xa4e4bfd7UL, 0x4f5ba272UL, 0x564c1d2fUL, 0xc59c5319UL, 0xb949e354UL, 0xb04669feUL,
+0xb1b6ab8aUL, 0xc71358ddUL, 0x6385c545UL, 0x110f935dUL, 0x57538ad5UL, 0x6a390493UL,
+0xe63d37e0UL, 0x2a54f6b3UL, 0x3a787d5fUL, 0x6276a0b5UL, 0x19a6fcdfUL, 0x7a42206aUL,
+0x29f9d4d5UL, 0xf61b1891UL, 0xbb72275eUL, 0xaa508167UL, 0x38901091UL, 0xc6b505ebUL,
+0x84c7cb8cUL, 0x2ad75a0fUL, 0x874a1427UL, 0xa2d1936bUL, 0x2ad286afUL, 0xaa56d291UL,
+0xd7894360UL, 0x425c750dUL, 0x93b39e26UL, 0x187184c9UL, 0x6c00b32dUL, 0x73e2bb14UL,
+0xa0bebc3cUL, 0x54623779UL, 0x64459eabUL, 0x3f328b82UL, 0x7718cf82UL, 0x59a2cea6UL,
+0x04ee002eUL, 0x89fe78e6UL, 0x3fab0950UL, 0x325ff6c2UL, 0x81383f05UL, 0x6963c5c8UL,
+0x76cb5ad6UL, 0xd49974c9UL, 0xca180dcfUL, 0x380782d5UL, 0xc7fa5cf6UL, 0x8ac31511UL,
+0x35e79e13UL, 0x47da91d0UL, 0xf40f9086UL, 0xa7e2419eUL, 0x31366241UL, 0x051ef495UL,
+0xaa573b04UL, 0x4a805d8dUL, 0x548300d0UL, 0x00322a3cUL, 0xbf64cddfUL, 0xba57a68eUL,
+0x75c6372bUL, 0x50afd341UL, 0xa7c13275UL, 0x915a0bf5UL, 0x6b54bfabUL, 0x2b0b1426UL,
+0xab4cc9d7UL, 0x449ccd82UL, 0xf7fbf265UL, 0xab85c5f3UL, 0x1b55db94UL, 0xaad4e324UL,
+0xcfa4bd3fUL, 0x2deaa3e2UL, 0x9e204d02UL, 0xc8bd25acUL, 0xeadf55b3UL, 0xd5bd9e98UL,
+0xe31231b2UL, 0x2ad5ad6cUL, 0x954329deUL, 0xadbe4528UL, 0xd8710f69UL, 0xaa51c90fUL,
+0xaa786bf6UL, 0x22513f1eUL, 0xaa51a79bUL, 0x2ad344ccUL, 0x7b5a41f0UL, 0xd37cfbadUL,
+0x1b069505UL, 0x41ece491UL, 0xb4c332e6UL, 0x032268d4UL, 0xc9600accUL, 0xce387e6dUL,
+0xbf6bb16cUL, 0x6a70fb78UL, 0x0d03d9c9UL, 0xd4df39deUL, 0xe01063daUL, 0x4736f464UL,
+0x5ad328d8UL, 0xb347cc96UL, 0x75bb0fc3UL, 0x98511bfbUL, 0x4ffbcc35UL, 0xb58bcf6aUL,
+0xe11f0abcUL, 0xbfc5fe4aUL, 0xa70aec10UL, 0xac39570aUL, 0x3f04442fUL, 0x6188b153UL,
+0xe0397a2eUL, 0x5727cb79UL, 0x9ceb418fUL, 0x1cacd68dUL, 0x2ad37c96UL, 0x0175cb9dUL,
+0xc69dff09UL, 0xc75b65f0UL, 0xd9db40d8UL, 0xec0e7779UL, 0x4744ead4UL, 0xb11c3274UL,
+0xdd24cb9eUL, 0x7e1c54bdUL, 0xf01144f9UL, 0xd2240eb1UL, 0x9675b3fdUL, 0xa3ac3755UL,
+0xd47c27afUL, 0x51c85f4dUL, 0x56907596UL, 0xa5bb15e6UL, 0x580304f0UL, 0xca042cf1UL,
+0x011a37eaUL, 0x8dbfaadbUL, 0x35ba3e4aUL, 0x3526ffa0UL, 0xc37b4d09UL, 0xbc306ed9UL,
+0x98a52666UL, 0x5648f725UL, 0xff5e569dUL, 0x0ced63d0UL, 0x7c63b2cfUL, 0x700b45e1UL,
+0xd5ea50f1UL, 0x85a92872UL, 0xaf1fbda7UL, 0xd4234870UL, 0xa7870bf3UL, 0x2d3b4d79UL,
+0x42e04198UL, 0x0cd0ede7UL, 0x26470db8UL, 0xf881814cUL, 0x474d6ad7UL, 0x7c0c5e5cUL,
+0xd1231959UL, 0x381b7298UL, 0xf5d2f4dbUL, 0xab838653UL, 0x6e2f1e23UL, 0x83719c9eUL,
+0xbd91e046UL, 0x9a56456eUL, 0xdc39200cUL, 0x20c8c571UL, 0x962bda1cUL, 0xe1e696ffUL,
+0xb141ab08UL, 0x7cca89b9UL, 0x1a69e783UL, 0x02cc4843UL, 0xa2f7c579UL, 0x429ef47dUL,
+0x427b169cUL, 0x5ac9f049UL, 0xdd8f0f00UL, 0x5c8165bfUL};
+
+static const ulong32 S2[256] = {
+0x1f201094UL, 0xef0ba75bUL, 0x69e3cf7eUL, 0x393f4380UL, 0xfe61cf7aUL, 0xeec5207aUL,
+0x55889c94UL, 0x72fc0651UL, 0xada7ef79UL, 0x4e1d7235UL, 0xd55a63ceUL, 0xde0436baUL,
+0x99c430efUL, 0x5f0c0794UL, 0x18dcdb7dUL, 0xa1d6eff3UL, 0xa0b52f7bUL, 0x59e83605UL,
+0xee15b094UL, 0xe9ffd909UL, 0xdc440086UL, 0xef944459UL, 0xba83ccb3UL, 0xe0c3cdfbUL,
+0xd1da4181UL, 0x3b092ab1UL, 0xf997f1c1UL, 0xa5e6cf7bUL, 0x01420ddbUL, 0xe4e7ef5bUL,
+0x25a1ff41UL, 0xe180f806UL, 0x1fc41080UL, 0x179bee7aUL, 0xd37ac6a9UL, 0xfe5830a4UL,
+0x98de8b7fUL, 0x77e83f4eUL, 0x79929269UL, 0x24fa9f7bUL, 0xe113c85bUL, 0xacc40083UL,
+0xd7503525UL, 0xf7ea615fUL, 0x62143154UL, 0x0d554b63UL, 0x5d681121UL, 0xc866c359UL,
+0x3d63cf73UL, 0xcee234c0UL, 0xd4d87e87UL, 0x5c672b21UL, 0x071f6181UL, 0x39f7627fUL,
+0x361e3084UL, 0xe4eb573bUL, 0x602f64a4UL, 0xd63acd9cUL, 0x1bbc4635UL, 0x9e81032dUL,
+0x2701f50cUL, 0x99847ab4UL, 0xa0e3df79UL, 0xba6cf38cUL, 0x10843094UL, 0x2537a95eUL,
+0xf46f6ffeUL, 0xa1ff3b1fUL, 0x208cfb6aUL, 0x8f458c74UL, 0xd9e0a227UL, 0x4ec73a34UL,
+0xfc884f69UL, 0x3e4de8dfUL, 0xef0e0088UL, 0x3559648dUL, 0x8a45388cUL, 0x1d804366UL,
+0x721d9bfdUL, 0xa58684bbUL, 0xe8256333UL, 0x844e8212UL, 0x128d8098UL, 0xfed33fb4UL,
+0xce280ae1UL, 0x27e19ba5UL, 0xd5a6c252UL, 0xe49754bdUL, 0xc5d655ddUL, 0xeb667064UL,
+0x77840b4dUL, 0xa1b6a801UL, 0x84db26a9UL, 0xe0b56714UL, 0x21f043b7UL, 0xe5d05860UL,
+0x54f03084UL, 0x066ff472UL, 0xa31aa153UL, 0xdadc4755UL, 0xb5625dbfUL, 0x68561be6UL,
+0x83ca6b94UL, 0x2d6ed23bUL, 0xeccf01dbUL, 0xa6d3d0baUL, 0xb6803d5cUL, 0xaf77a709UL,
+0x33b4a34cUL, 0x397bc8d6UL, 0x5ee22b95UL, 0x5f0e5304UL, 0x81ed6f61UL, 0x20e74364UL,
+0xb45e1378UL, 0xde18639bUL, 0x881ca122UL, 0xb96726d1UL, 0x8049a7e8UL, 0x22b7da7bUL,
+0x5e552d25UL, 0x5272d237UL, 0x79d2951cUL, 0xc60d894cUL, 0x488cb402UL, 0x1ba4fe5bUL,
+0xa4b09f6bUL, 0x1ca815cfUL, 0xa20c3005UL, 0x8871df63UL, 0xb9de2fcbUL, 0x0cc6c9e9UL,
+0x0beeff53UL, 0xe3214517UL, 0xb4542835UL, 0x9f63293cUL, 0xee41e729UL, 0x6e1d2d7cUL,
+0x50045286UL, 0x1e6685f3UL, 0xf33401c6UL, 0x30a22c95UL, 0x31a70850UL, 0x60930f13UL,
+0x73f98417UL, 0xa1269859UL, 0xec645c44UL, 0x52c877a9UL, 0xcdff33a6UL, 0xa02b1741UL,
+0x7cbad9a2UL, 0x2180036fUL, 0x50d99c08UL, 0xcb3f4861UL, 0xc26bd765UL, 0x64a3f6abUL,
+0x80342676UL, 0x25a75e7bUL, 0xe4e6d1fcUL, 0x20c710e6UL, 0xcdf0b680UL, 0x17844d3bUL,
+0x31eef84dUL, 0x7e0824e4UL, 0x2ccb49ebUL, 0x846a3baeUL, 0x8ff77888UL, 0xee5d60f6UL,
+0x7af75673UL, 0x2fdd5cdbUL, 0xa11631c1UL, 0x30f66f43UL, 0xb3faec54UL, 0x157fd7faUL,
+0xef8579ccUL, 0xd152de58UL, 0xdb2ffd5eUL, 0x8f32ce19UL, 0x306af97aUL, 0x02f03ef8UL,
+0x99319ad5UL, 0xc242fa0fUL, 0xa7e3ebb0UL, 0xc68e4906UL, 0xb8da230cUL, 0x80823028UL,
+0xdcdef3c8UL, 0xd35fb171UL, 0x088a1bc8UL, 0xbec0c560UL, 0x61a3c9e8UL, 0xbca8f54dUL,
+0xc72feffaUL, 0x22822e99UL, 0x82c570b4UL, 0xd8d94e89UL, 0x8b1c34bcUL, 0x301e16e6UL,
+0x273be979UL, 0xb0ffeaa6UL, 0x61d9b8c6UL, 0x00b24869UL, 0xb7ffce3fUL, 0x08dc283bUL,
+0x43daf65aUL, 0xf7e19798UL, 0x7619b72fUL, 0x8f1c9ba4UL, 0xdc8637a0UL, 0x16a7d3b1UL,
+0x9fc393b7UL, 0xa7136eebUL, 0xc6bcc63eUL, 0x1a513742UL, 0xef6828bcUL, 0x520365d6UL,
+0x2d6a77abUL, 0x3527ed4bUL, 0x821fd216UL, 0x095c6e2eUL, 0xdb92f2fbUL, 0x5eea29cbUL,
+0x145892f5UL, 0x91584f7fUL, 0x5483697bUL, 0x2667a8ccUL, 0x85196048UL, 0x8c4baceaUL,
+0x833860d4UL, 0x0d23e0f9UL, 0x6c387e8aUL, 0x0ae6d249UL, 0xb284600cUL, 0xd835731dUL,
+0xdcb1c647UL, 0xac4c56eaUL, 0x3ebd81b3UL, 0x230eabb0UL, 0x6438bc87UL, 0xf0b5b1faUL,
+0x8f5ea2b3UL, 0xfc184642UL, 0x0a036b7aUL, 0x4fb089bdUL, 0x649da589UL, 0xa345415eUL,
+0x5c038323UL, 0x3e5d3bb9UL, 0x43d79572UL, 0x7e6dd07cUL, 0x06dfdf1eUL, 0x6c6cc4efUL,
+0x7160a539UL, 0x73bfbe70UL, 0x83877605UL, 0x4523ecf1UL};
+
+static const ulong32 S3[256] = {
+0x8defc240UL, 0x25fa5d9fUL, 0xeb903dbfUL, 0xe810c907UL, 0x47607fffUL, 0x369fe44bUL,
+0x8c1fc644UL, 0xaececa90UL, 0xbeb1f9bfUL, 0xeefbcaeaUL, 0xe8cf1950UL, 0x51df07aeUL,
+0x920e8806UL, 0xf0ad0548UL, 0xe13c8d83UL, 0x927010d5UL, 0x11107d9fUL, 0x07647db9UL,
+0xb2e3e4d4UL, 0x3d4f285eUL, 0xb9afa820UL, 0xfade82e0UL, 0xa067268bUL, 0x8272792eUL,
+0x553fb2c0UL, 0x489ae22bUL, 0xd4ef9794UL, 0x125e3fbcUL, 0x21fffceeUL, 0x825b1bfdUL,
+0x9255c5edUL, 0x1257a240UL, 0x4e1a8302UL, 0xbae07fffUL, 0x528246e7UL, 0x8e57140eUL,
+0x3373f7bfUL, 0x8c9f8188UL, 0xa6fc4ee8UL, 0xc982b5a5UL, 0xa8c01db7UL, 0x579fc264UL,
+0x67094f31UL, 0xf2bd3f5fUL, 0x40fff7c1UL, 0x1fb78dfcUL, 0x8e6bd2c1UL, 0x437be59bUL,
+0x99b03dbfUL, 0xb5dbc64bUL, 0x638dc0e6UL, 0x55819d99UL, 0xa197c81cUL, 0x4a012d6eUL,
+0xc5884a28UL, 0xccc36f71UL, 0xb843c213UL, 0x6c0743f1UL, 0x8309893cUL, 0x0feddd5fUL,
+0x2f7fe850UL, 0xd7c07f7eUL, 0x02507fbfUL, 0x5afb9a04UL, 0xa747d2d0UL, 0x1651192eUL,
+0xaf70bf3eUL, 0x58c31380UL, 0x5f98302eUL, 0x727cc3c4UL, 0x0a0fb402UL, 0x0f7fef82UL,
+0x8c96fdadUL, 0x5d2c2aaeUL, 0x8ee99a49UL, 0x50da88b8UL, 0x8427f4a0UL, 0x1eac5790UL,
+0x796fb449UL, 0x8252dc15UL, 0xefbd7d9bUL, 0xa672597dUL, 0xada840d8UL, 0x45f54504UL,
+0xfa5d7403UL, 0xe83ec305UL, 0x4f91751aUL, 0x925669c2UL, 0x23efe941UL, 0xa903f12eUL,
+0x60270df2UL, 0x0276e4b6UL, 0x94fd6574UL, 0x927985b2UL, 0x8276dbcbUL, 0x02778176UL,
+0xf8af918dUL, 0x4e48f79eUL, 0x8f616ddfUL, 0xe29d840eUL, 0x842f7d83UL, 0x340ce5c8UL,
+0x96bbb682UL, 0x93b4b148UL, 0xef303cabUL, 0x984faf28UL, 0x779faf9bUL, 0x92dc560dUL,
+0x224d1e20UL, 0x8437aa88UL, 0x7d29dc96UL, 0x2756d3dcUL, 0x8b907ceeUL, 0xb51fd240UL,
+0xe7c07ce3UL, 0xe566b4a1UL, 0xc3e9615eUL, 0x3cf8209dUL, 0x6094d1e3UL, 0xcd9ca341UL,
+0x5c76460eUL, 0x00ea983bUL, 0xd4d67881UL, 0xfd47572cUL, 0xf76cedd9UL, 0xbda8229cUL,
+0x127dadaaUL, 0x438a074eUL, 0x1f97c090UL, 0x081bdb8aUL, 0x93a07ebeUL, 0xb938ca15UL,
+0x97b03cffUL, 0x3dc2c0f8UL, 0x8d1ab2ecUL, 0x64380e51UL, 0x68cc7bfbUL, 0xd90f2788UL,
+0x12490181UL, 0x5de5ffd4UL, 0xdd7ef86aUL, 0x76a2e214UL, 0xb9a40368UL, 0x925d958fUL,
+0x4b39fffaUL, 0xba39aee9UL, 0xa4ffd30bUL, 0xfaf7933bUL, 0x6d498623UL, 0x193cbcfaUL,
+0x27627545UL, 0x825cf47aUL, 0x61bd8ba0UL, 0xd11e42d1UL, 0xcead04f4UL, 0x127ea392UL,
+0x10428db7UL, 0x8272a972UL, 0x9270c4a8UL, 0x127de50bUL, 0x285ba1c8UL, 0x3c62f44fUL,
+0x35c0eaa5UL, 0xe805d231UL, 0x428929fbUL, 0xb4fcdf82UL, 0x4fb66a53UL, 0x0e7dc15bUL,
+0x1f081fabUL, 0x108618aeUL, 0xfcfd086dUL, 0xf9ff2889UL, 0x694bcc11UL, 0x236a5caeUL,
+0x12deca4dUL, 0x2c3f8cc5UL, 0xd2d02dfeUL, 0xf8ef5896UL, 0xe4cf52daUL, 0x95155b67UL,
+0x494a488cUL, 0xb9b6a80cUL, 0x5c8f82bcUL, 0x89d36b45UL, 0x3a609437UL, 0xec00c9a9UL,
+0x44715253UL, 0x0a874b49UL, 0xd773bc40UL, 0x7c34671cUL, 0x02717ef6UL, 0x4feb5536UL,
+0xa2d02fffUL, 0xd2bf60c4UL, 0xd43f03c0UL, 0x50b4ef6dUL, 0x07478cd1UL, 0x006e1888UL,
+0xa2e53f55UL, 0xb9e6d4bcUL, 0xa2048016UL, 0x97573833UL, 0xd7207d67UL, 0xde0f8f3dUL,
+0x72f87b33UL, 0xabcc4f33UL, 0x7688c55dUL, 0x7b00a6b0UL, 0x947b0001UL, 0x570075d2UL,
+0xf9bb88f8UL, 0x8942019eUL, 0x4264a5ffUL, 0x856302e0UL, 0x72dbd92bUL, 0xee971b69UL,
+0x6ea22fdeUL, 0x5f08ae2bUL, 0xaf7a616dUL, 0xe5c98767UL, 0xcf1febd2UL, 0x61efc8c2UL,
+0xf1ac2571UL, 0xcc8239c2UL, 0x67214cb8UL, 0xb1e583d1UL, 0xb7dc3e62UL, 0x7f10bdceUL,
+0xf90a5c38UL, 0x0ff0443dUL, 0x606e6dc6UL, 0x60543a49UL, 0x5727c148UL, 0x2be98a1dUL,
+0x8ab41738UL, 0x20e1be24UL, 0xaf96da0fUL, 0x68458425UL, 0x99833be5UL, 0x600d457dUL,
+0x282f9350UL, 0x8334b362UL, 0xd91d1120UL, 0x2b6d8da0UL, 0x642b1e31UL, 0x9c305a00UL,
+0x52bce688UL, 0x1b03588aUL, 0xf7baefd5UL, 0x4142ed9cUL, 0xa4315c11UL, 0x83323ec5UL,
+0xdfef4636UL, 0xa133c501UL, 0xe9d3531cUL, 0xee353783UL};
+
+static const ulong32 S4[256] = {
+0x9db30420UL, 0x1fb6e9deUL, 0xa7be7befUL, 0xd273a298UL, 0x4a4f7bdbUL, 0x64ad8c57UL,
+0x85510443UL, 0xfa020ed1UL, 0x7e287affUL, 0xe60fb663UL, 0x095f35a1UL, 0x79ebf120UL,
+0xfd059d43UL, 0x6497b7b1UL, 0xf3641f63UL, 0x241e4adfUL, 0x28147f5fUL, 0x4fa2b8cdUL,
+0xc9430040UL, 0x0cc32220UL, 0xfdd30b30UL, 0xc0a5374fUL, 0x1d2d00d9UL, 0x24147b15UL,
+0xee4d111aUL, 0x0fca5167UL, 0x71ff904cUL, 0x2d195ffeUL, 0x1a05645fUL, 0x0c13fefeUL,
+0x081b08caUL, 0x05170121UL, 0x80530100UL, 0xe83e5efeUL, 0xac9af4f8UL, 0x7fe72701UL,
+0xd2b8ee5fUL, 0x06df4261UL, 0xbb9e9b8aUL, 0x7293ea25UL, 0xce84ffdfUL, 0xf5718801UL,
+0x3dd64b04UL, 0xa26f263bUL, 0x7ed48400UL, 0x547eebe6UL, 0x446d4ca0UL, 0x6cf3d6f5UL,
+0x2649abdfUL, 0xaea0c7f5UL, 0x36338cc1UL, 0x503f7e93UL, 0xd3772061UL, 0x11b638e1UL,
+0x72500e03UL, 0xf80eb2bbUL, 0xabe0502eUL, 0xec8d77deUL, 0x57971e81UL, 0xe14f6746UL,
+0xc9335400UL, 0x6920318fUL, 0x081dbb99UL, 0xffc304a5UL, 0x4d351805UL, 0x7f3d5ce3UL,
+0xa6c866c6UL, 0x5d5bcca9UL, 0xdaec6feaUL, 0x9f926f91UL, 0x9f46222fUL, 0x3991467dUL,
+0xa5bf6d8eUL, 0x1143c44fUL, 0x43958302UL, 0xd0214eebUL, 0x022083b8UL, 0x3fb6180cUL,
+0x18f8931eUL, 0x281658e6UL, 0x26486e3eUL, 0x8bd78a70UL, 0x7477e4c1UL, 0xb506e07cUL,
+0xf32d0a25UL, 0x79098b02UL, 0xe4eabb81UL, 0x28123b23UL, 0x69dead38UL, 0x1574ca16UL,
+0xdf871b62UL, 0x211c40b7UL, 0xa51a9ef9UL, 0x0014377bUL, 0x041e8ac8UL, 0x09114003UL,
+0xbd59e4d2UL, 0xe3d156d5UL, 0x4fe876d5UL, 0x2f91a340UL, 0x557be8deUL, 0x00eae4a7UL,
+0x0ce5c2ecUL, 0x4db4bba6UL, 0xe756bdffUL, 0xdd3369acUL, 0xec17b035UL, 0x06572327UL,
+0x99afc8b0UL, 0x56c8c391UL, 0x6b65811cUL, 0x5e146119UL, 0x6e85cb75UL, 0xbe07c002UL,
+0xc2325577UL, 0x893ff4ecUL, 0x5bbfc92dUL, 0xd0ec3b25UL, 0xb7801ab7UL, 0x8d6d3b24UL,
+0x20c763efUL, 0xc366a5fcUL, 0x9c382880UL, 0x0ace3205UL, 0xaac9548aUL, 0xeca1d7c7UL,
+0x041afa32UL, 0x1d16625aUL, 0x6701902cUL, 0x9b757a54UL, 0x31d477f7UL, 0x9126b031UL,
+0x36cc6fdbUL, 0xc70b8b46UL, 0xd9e66a48UL, 0x56e55a79UL, 0x026a4cebUL, 0x52437effUL,
+0x2f8f76b4UL, 0x0df980a5UL, 0x8674cde3UL, 0xedda04ebUL, 0x17a9be04UL, 0x2c18f4dfUL,
+0xb7747f9dUL, 0xab2af7b4UL, 0xefc34d20UL, 0x2e096b7cUL, 0x1741a254UL, 0xe5b6a035UL,
+0x213d42f6UL, 0x2c1c7c26UL, 0x61c2f50fUL, 0x6552daf9UL, 0xd2c231f8UL, 0x25130f69UL,
+0xd8167fa2UL, 0x0418f2c8UL, 0x001a96a6UL, 0x0d1526abUL, 0x63315c21UL, 0x5e0a72ecUL,
+0x49bafefdUL, 0x187908d9UL, 0x8d0dbd86UL, 0x311170a7UL, 0x3e9b640cUL, 0xcc3e10d7UL,
+0xd5cad3b6UL, 0x0caec388UL, 0xf73001e1UL, 0x6c728affUL, 0x71eae2a1UL, 0x1f9af36eUL,
+0xcfcbd12fUL, 0xc1de8417UL, 0xac07be6bUL, 0xcb44a1d8UL, 0x8b9b0f56UL, 0x013988c3UL,
+0xb1c52fcaUL, 0xb4be31cdUL, 0xd8782806UL, 0x12a3a4e2UL, 0x6f7de532UL, 0x58fd7eb6UL,
+0xd01ee900UL, 0x24adffc2UL, 0xf4990fc5UL, 0x9711aac5UL, 0x001d7b95UL, 0x82e5e7d2UL,
+0x109873f6UL, 0x00613096UL, 0xc32d9521UL, 0xada121ffUL, 0x29908415UL, 0x7fbb977fUL,
+0xaf9eb3dbUL, 0x29c9ed2aUL, 0x5ce2a465UL, 0xa730f32cUL, 0xd0aa3fe8UL, 0x8a5cc091UL,
+0xd49e2ce7UL, 0x0ce454a9UL, 0xd60acd86UL, 0x015f1919UL, 0x77079103UL, 0xdea03af6UL,
+0x78a8565eUL, 0xdee356dfUL, 0x21f05cbeUL, 0x8b75e387UL, 0xb3c50651UL, 0xb8a5c3efUL,
+0xd8eeb6d2UL, 0xe523be77UL, 0xc2154529UL, 0x2f69efdfUL, 0xafe67afbUL, 0xf470c4b2UL,
+0xf3e0eb5bUL, 0xd6cc9876UL, 0x39e4460cUL, 0x1fda8538UL, 0x1987832fUL, 0xca007367UL,
+0xa99144f8UL, 0x296b299eUL, 0x492fc295UL, 0x9266beabUL, 0xb5676e69UL, 0x9bd3dddaUL,
+0xdf7e052fUL, 0xdb25701cUL, 0x1b5e51eeUL, 0xf65324e6UL, 0x6afce36cUL, 0x0316cc04UL,
+0x8644213eUL, 0xb7dc59d0UL, 0x7965291fUL, 0xccd6fd43UL, 0x41823979UL, 0x932bcdf6UL,
+0xb657c34dUL, 0x4edfd282UL, 0x7ae5290cUL, 0x3cb9536bUL, 0x851e20feUL, 0x9833557eUL,
+0x13ecf0b0UL, 0xd3ffb372UL, 0x3f85c5c1UL, 0x0aef7ed2UL};
+
+static const ulong32 S5[256] = {
+0x7ec90c04UL, 0x2c6e74b9UL, 0x9b0e66dfUL, 0xa6337911UL, 0xb86a7fffUL, 0x1dd358f5UL,
+0x44dd9d44UL, 0x1731167fUL, 0x08fbf1faUL, 0xe7f511ccUL, 0xd2051b00UL, 0x735aba00UL,
+0x2ab722d8UL, 0x386381cbUL, 0xacf6243aUL, 0x69befd7aUL, 0xe6a2e77fUL, 0xf0c720cdUL,
+0xc4494816UL, 0xccf5c180UL, 0x38851640UL, 0x15b0a848UL, 0xe68b18cbUL, 0x4caadeffUL,
+0x5f480a01UL, 0x0412b2aaUL, 0x259814fcUL, 0x41d0efe2UL, 0x4e40b48dUL, 0x248eb6fbUL,
+0x8dba1cfeUL, 0x41a99b02UL, 0x1a550a04UL, 0xba8f65cbUL, 0x7251f4e7UL, 0x95a51725UL,
+0xc106ecd7UL, 0x97a5980aUL, 0xc539b9aaUL, 0x4d79fe6aUL, 0xf2f3f763UL, 0x68af8040UL,
+0xed0c9e56UL, 0x11b4958bUL, 0xe1eb5a88UL, 0x8709e6b0UL, 0xd7e07156UL, 0x4e29fea7UL,
+0x6366e52dUL, 0x02d1c000UL, 0xc4ac8e05UL, 0x9377f571UL, 0x0c05372aUL, 0x578535f2UL,
+0x2261be02UL, 0xd642a0c9UL, 0xdf13a280UL, 0x74b55bd2UL, 0x682199c0UL, 0xd421e5ecUL,
+0x53fb3ce8UL, 0xc8adedb3UL, 0x28a87fc9UL, 0x3d959981UL, 0x5c1ff900UL, 0xfe38d399UL,
+0x0c4eff0bUL, 0x062407eaUL, 0xaa2f4fb1UL, 0x4fb96976UL, 0x90c79505UL, 0xb0a8a774UL,
+0xef55a1ffUL, 0xe59ca2c2UL, 0xa6b62d27UL, 0xe66a4263UL, 0xdf65001fUL, 0x0ec50966UL,
+0xdfdd55bcUL, 0x29de0655UL, 0x911e739aUL, 0x17af8975UL, 0x32c7911cUL, 0x89f89468UL,
+0x0d01e980UL, 0x524755f4UL, 0x03b63cc9UL, 0x0cc844b2UL, 0xbcf3f0aaUL, 0x87ac36e9UL,
+0xe53a7426UL, 0x01b3d82bUL, 0x1a9e7449UL, 0x64ee2d7eUL, 0xcddbb1daUL, 0x01c94910UL,
+0xb868bf80UL, 0x0d26f3fdUL, 0x9342ede7UL, 0x04a5c284UL, 0x636737b6UL, 0x50f5b616UL,
+0xf24766e3UL, 0x8eca36c1UL, 0x136e05dbUL, 0xfef18391UL, 0xfb887a37UL, 0xd6e7f7d4UL,
+0xc7fb7dc9UL, 0x3063fcdfUL, 0xb6f589deUL, 0xec2941daUL, 0x26e46695UL, 0xb7566419UL,
+0xf654efc5UL, 0xd08d58b7UL, 0x48925401UL, 0xc1bacb7fUL, 0xe5ff550fUL, 0xb6083049UL,
+0x5bb5d0e8UL, 0x87d72e5aUL, 0xab6a6ee1UL, 0x223a66ceUL, 0xc62bf3cdUL, 0x9e0885f9UL,
+0x68cb3e47UL, 0x086c010fUL, 0xa21de820UL, 0xd18b69deUL, 0xf3f65777UL, 0xfa02c3f6UL,
+0x407edac3UL, 0xcbb3d550UL, 0x1793084dUL, 0xb0d70ebaUL, 0x0ab378d5UL, 0xd951fb0cUL,
+0xded7da56UL, 0x4124bbe4UL, 0x94ca0b56UL, 0x0f5755d1UL, 0xe0e1e56eUL, 0x6184b5beUL,
+0x580a249fUL, 0x94f74bc0UL, 0xe327888eUL, 0x9f7b5561UL, 0xc3dc0280UL, 0x05687715UL,
+0x646c6bd7UL, 0x44904db3UL, 0x66b4f0a3UL, 0xc0f1648aUL, 0x697ed5afUL, 0x49e92ff6UL,
+0x309e374fUL, 0x2cb6356aUL, 0x85808573UL, 0x4991f840UL, 0x76f0ae02UL, 0x083be84dUL,
+0x28421c9aUL, 0x44489406UL, 0x736e4cb8UL, 0xc1092910UL, 0x8bc95fc6UL, 0x7d869cf4UL,
+0x134f616fUL, 0x2e77118dUL, 0xb31b2be1UL, 0xaa90b472UL, 0x3ca5d717UL, 0x7d161bbaUL,
+0x9cad9010UL, 0xaf462ba2UL, 0x9fe459d2UL, 0x45d34559UL, 0xd9f2da13UL, 0xdbc65487UL,
+0xf3e4f94eUL, 0x176d486fUL, 0x097c13eaUL, 0x631da5c7UL, 0x445f7382UL, 0x175683f4UL,
+0xcdc66a97UL, 0x70be0288UL, 0xb3cdcf72UL, 0x6e5dd2f3UL, 0x20936079UL, 0x459b80a5UL,
+0xbe60e2dbUL, 0xa9c23101UL, 0xeba5315cUL, 0x224e42f2UL, 0x1c5c1572UL, 0xf6721b2cUL,
+0x1ad2fff3UL, 0x8c25404eUL, 0x324ed72fUL, 0x4067b7fdUL, 0x0523138eUL, 0x5ca3bc78UL,
+0xdc0fd66eUL, 0x75922283UL, 0x784d6b17UL, 0x58ebb16eUL, 0x44094f85UL, 0x3f481d87UL,
+0xfcfeae7bUL, 0x77b5ff76UL, 0x8c2302bfUL, 0xaaf47556UL, 0x5f46b02aUL, 0x2b092801UL,
+0x3d38f5f7UL, 0x0ca81f36UL, 0x52af4a8aUL, 0x66d5e7c0UL, 0xdf3b0874UL, 0x95055110UL,
+0x1b5ad7a8UL, 0xf61ed5adUL, 0x6cf6e479UL, 0x20758184UL, 0xd0cefa65UL, 0x88f7be58UL,
+0x4a046826UL, 0x0ff6f8f3UL, 0xa09c7f70UL, 0x5346aba0UL, 0x5ce96c28UL, 0xe176eda3UL,
+0x6bac307fUL, 0x376829d2UL, 0x85360fa9UL, 0x17e3fe2aUL, 0x24b79767UL, 0xf5a96b20UL,
+0xd6cd2595UL, 0x68ff1ebfUL, 0x7555442cUL, 0xf19f06beUL, 0xf9e0659aUL, 0xeeb9491dUL,
+0x34010718UL, 0xbb30cab8UL, 0xe822fe15UL, 0x88570983UL, 0x750e6249UL, 0xda627e55UL,
+0x5e76ffa8UL, 0xb1534546UL, 0x6d47de08UL, 0xefe9e7d4UL};
+
+static const ulong32 S6[256] = {
+0xf6fa8f9dUL, 0x2cac6ce1UL, 0x4ca34867UL, 0xe2337f7cUL, 0x95db08e7UL, 0x016843b4UL,
+0xeced5cbcUL, 0x325553acUL, 0xbf9f0960UL, 0xdfa1e2edUL, 0x83f0579dUL, 0x63ed86b9UL,
+0x1ab6a6b8UL, 0xde5ebe39UL, 0xf38ff732UL, 0x8989b138UL, 0x33f14961UL, 0xc01937bdUL,
+0xf506c6daUL, 0xe4625e7eUL, 0xa308ea99UL, 0x4e23e33cUL, 0x79cbd7ccUL, 0x48a14367UL,
+0xa3149619UL, 0xfec94bd5UL, 0xa114174aUL, 0xeaa01866UL, 0xa084db2dUL, 0x09a8486fUL,
+0xa888614aUL, 0x2900af98UL, 0x01665991UL, 0xe1992863UL, 0xc8f30c60UL, 0x2e78ef3cUL,
+0xd0d51932UL, 0xcf0fec14UL, 0xf7ca07d2UL, 0xd0a82072UL, 0xfd41197eUL, 0x9305a6b0UL,
+0xe86be3daUL, 0x74bed3cdUL, 0x372da53cUL, 0x4c7f4448UL, 0xdab5d440UL, 0x6dba0ec3UL,
+0x083919a7UL, 0x9fbaeed9UL, 0x49dbcfb0UL, 0x4e670c53UL, 0x5c3d9c01UL, 0x64bdb941UL,
+0x2c0e636aUL, 0xba7dd9cdUL, 0xea6f7388UL, 0xe70bc762UL, 0x35f29adbUL, 0x5c4cdd8dUL,
+0xf0d48d8cUL, 0xb88153e2UL, 0x08a19866UL, 0x1ae2eac8UL, 0x284caf89UL, 0xaa928223UL,
+0x9334be53UL, 0x3b3a21bfUL, 0x16434be3UL, 0x9aea3906UL, 0xefe8c36eUL, 0xf890cdd9UL,
+0x80226daeUL, 0xc340a4a3UL, 0xdf7e9c09UL, 0xa694a807UL, 0x5b7c5eccUL, 0x221db3a6UL,
+0x9a69a02fUL, 0x68818a54UL, 0xceb2296fUL, 0x53c0843aUL, 0xfe893655UL, 0x25bfe68aUL,
+0xb4628abcUL, 0xcf222ebfUL, 0x25ac6f48UL, 0xa9a99387UL, 0x53bddb65UL, 0xe76ffbe7UL,
+0xe967fd78UL, 0x0ba93563UL, 0x8e342bc1UL, 0xe8a11be9UL, 0x4980740dUL, 0xc8087dfcUL,
+0x8de4bf99UL, 0xa11101a0UL, 0x7fd37975UL, 0xda5a26c0UL, 0xe81f994fUL, 0x9528cd89UL,
+0xfd339fedUL, 0xb87834bfUL, 0x5f04456dUL, 0x22258698UL, 0xc9c4c83bUL, 0x2dc156beUL,
+0x4f628daaUL, 0x57f55ec5UL, 0xe2220abeUL, 0xd2916ebfUL, 0x4ec75b95UL, 0x24f2c3c0UL,
+0x42d15d99UL, 0xcd0d7fa0UL, 0x7b6e27ffUL, 0xa8dc8af0UL, 0x7345c106UL, 0xf41e232fUL,
+0x35162386UL, 0xe6ea8926UL, 0x3333b094UL, 0x157ec6f2UL, 0x372b74afUL, 0x692573e4UL,
+0xe9a9d848UL, 0xf3160289UL, 0x3a62ef1dUL, 0xa787e238UL, 0xf3a5f676UL, 0x74364853UL,
+0x20951063UL, 0x4576698dUL, 0xb6fad407UL, 0x592af950UL, 0x36f73523UL, 0x4cfb6e87UL,
+0x7da4cec0UL, 0x6c152daaUL, 0xcb0396a8UL, 0xc50dfe5dUL, 0xfcd707abUL, 0x0921c42fUL,
+0x89dff0bbUL, 0x5fe2be78UL, 0x448f4f33UL, 0x754613c9UL, 0x2b05d08dUL, 0x48b9d585UL,
+0xdc049441UL, 0xc8098f9bUL, 0x7dede786UL, 0xc39a3373UL, 0x42410005UL, 0x6a091751UL,
+0x0ef3c8a6UL, 0x890072d6UL, 0x28207682UL, 0xa9a9f7beUL, 0xbf32679dUL, 0xd45b5b75UL,
+0xb353fd00UL, 0xcbb0e358UL, 0x830f220aUL, 0x1f8fb214UL, 0xd372cf08UL, 0xcc3c4a13UL,
+0x8cf63166UL, 0x061c87beUL, 0x88c98f88UL, 0x6062e397UL, 0x47cf8e7aUL, 0xb6c85283UL,
+0x3cc2acfbUL, 0x3fc06976UL, 0x4e8f0252UL, 0x64d8314dUL, 0xda3870e3UL, 0x1e665459UL,
+0xc10908f0UL, 0x513021a5UL, 0x6c5b68b7UL, 0x822f8aa0UL, 0x3007cd3eUL, 0x74719eefUL,
+0xdc872681UL, 0x073340d4UL, 0x7e432fd9UL, 0x0c5ec241UL, 0x8809286cUL, 0xf592d891UL,
+0x08a930f6UL, 0x957ef305UL, 0xb7fbffbdUL, 0xc266e96fUL, 0x6fe4ac98UL, 0xb173ecc0UL,
+0xbc60b42aUL, 0x953498daUL, 0xfba1ae12UL, 0x2d4bd736UL, 0x0f25faabUL, 0xa4f3fcebUL,
+0xe2969123UL, 0x257f0c3dUL, 0x9348af49UL, 0x361400bcUL, 0xe8816f4aUL, 0x3814f200UL,
+0xa3f94043UL, 0x9c7a54c2UL, 0xbc704f57UL, 0xda41e7f9UL, 0xc25ad33aUL, 0x54f4a084UL,
+0xb17f5505UL, 0x59357cbeUL, 0xedbd15c8UL, 0x7f97c5abUL, 0xba5ac7b5UL, 0xb6f6deafUL,
+0x3a479c3aUL, 0x5302da25UL, 0x653d7e6aUL, 0x54268d49UL, 0x51a477eaUL, 0x5017d55bUL,
+0xd7d25d88UL, 0x44136c76UL, 0x0404a8c8UL, 0xb8e5a121UL, 0xb81a928aUL, 0x60ed5869UL,
+0x97c55b96UL, 0xeaec991bUL, 0x29935913UL, 0x01fdb7f1UL, 0x088e8dfaUL, 0x9ab6f6f5UL,
+0x3b4cbf9fUL, 0x4a5de3abUL, 0xe6051d35UL, 0xa0e1d855UL, 0xd36b4cf1UL, 0xf544edebUL,
+0xb0e93524UL, 0xbebb8fbdUL, 0xa2d762cfUL, 0x49c92f54UL, 0x38b5f331UL, 0x7128a454UL,
+0x48392905UL, 0xa65b1db8UL, 0x851c97bdUL, 0xd675cf2fUL};
+
+static const ulong32 S7[256] = {
+0x85e04019UL, 0x332bf567UL, 0x662dbfffUL, 0xcfc65693UL, 0x2a8d7f6fUL, 0xab9bc912UL,
+0xde6008a1UL, 0x2028da1fUL, 0x0227bce7UL, 0x4d642916UL, 0x18fac300UL, 0x50f18b82UL,
+0x2cb2cb11UL, 0xb232e75cUL, 0x4b3695f2UL, 0xb28707deUL, 0xa05fbcf6UL, 0xcd4181e9UL,
+0xe150210cUL, 0xe24ef1bdUL, 0xb168c381UL, 0xfde4e789UL, 0x5c79b0d8UL, 0x1e8bfd43UL,
+0x4d495001UL, 0x38be4341UL, 0x913cee1dUL, 0x92a79c3fUL, 0x089766beUL, 0xbaeeadf4UL,
+0x1286becfUL, 0xb6eacb19UL, 0x2660c200UL, 0x7565bde4UL, 0x64241f7aUL, 0x8248dca9UL,
+0xc3b3ad66UL, 0x28136086UL, 0x0bd8dfa8UL, 0x356d1cf2UL, 0x107789beUL, 0xb3b2e9ceUL,
+0x0502aa8fUL, 0x0bc0351eUL, 0x166bf52aUL, 0xeb12ff82UL, 0xe3486911UL, 0xd34d7516UL,
+0x4e7b3affUL, 0x5f43671bUL, 0x9cf6e037UL, 0x4981ac83UL, 0x334266ceUL, 0x8c9341b7UL,
+0xd0d854c0UL, 0xcb3a6c88UL, 0x47bc2829UL, 0x4725ba37UL, 0xa66ad22bUL, 0x7ad61f1eUL,
+0x0c5cbafaUL, 0x4437f107UL, 0xb6e79962UL, 0x42d2d816UL, 0x0a961288UL, 0xe1a5c06eUL,
+0x13749e67UL, 0x72fc081aUL, 0xb1d139f7UL, 0xf9583745UL, 0xcf19df58UL, 0xbec3f756UL,
+0xc06eba30UL, 0x07211b24UL, 0x45c28829UL, 0xc95e317fUL, 0xbc8ec511UL, 0x38bc46e9UL,
+0xc6e6fa14UL, 0xbae8584aUL, 0xad4ebc46UL, 0x468f508bUL, 0x7829435fUL, 0xf124183bUL,
+0x821dba9fUL, 0xaff60ff4UL, 0xea2c4e6dUL, 0x16e39264UL, 0x92544a8bUL, 0x009b4fc3UL,
+0xaba68cedUL, 0x9ac96f78UL, 0x06a5b79aUL, 0xb2856e6eUL, 0x1aec3ca9UL, 0xbe838688UL,
+0x0e0804e9UL, 0x55f1be56UL, 0xe7e5363bUL, 0xb3a1f25dUL, 0xf7debb85UL, 0x61fe033cUL,
+0x16746233UL, 0x3c034c28UL, 0xda6d0c74UL, 0x79aac56cUL, 0x3ce4e1adUL, 0x51f0c802UL,
+0x98f8f35aUL, 0x1626a49fUL, 0xeed82b29UL, 0x1d382fe3UL, 0x0c4fb99aUL, 0xbb325778UL,
+0x3ec6d97bUL, 0x6e77a6a9UL, 0xcb658b5cUL, 0xd45230c7UL, 0x2bd1408bUL, 0x60c03eb7UL,
+0xb9068d78UL, 0xa33754f4UL, 0xf430c87dUL, 0xc8a71302UL, 0xb96d8c32UL, 0xebd4e7beUL,
+0xbe8b9d2dUL, 0x7979fb06UL, 0xe7225308UL, 0x8b75cf77UL, 0x11ef8da4UL, 0xe083c858UL,
+0x8d6b786fUL, 0x5a6317a6UL, 0xfa5cf7a0UL, 0x5dda0033UL, 0xf28ebfb0UL, 0xf5b9c310UL,
+0xa0eac280UL, 0x08b9767aUL, 0xa3d9d2b0UL, 0x79d34217UL, 0x021a718dUL, 0x9ac6336aUL,
+0x2711fd60UL, 0x438050e3UL, 0x069908a8UL, 0x3d7fedc4UL, 0x826d2befUL, 0x4eeb8476UL,
+0x488dcf25UL, 0x36c9d566UL, 0x28e74e41UL, 0xc2610acaUL, 0x3d49a9cfUL, 0xbae3b9dfUL,
+0xb65f8de6UL, 0x92aeaf64UL, 0x3ac7d5e6UL, 0x9ea80509UL, 0xf22b017dUL, 0xa4173f70UL,
+0xdd1e16c3UL, 0x15e0d7f9UL, 0x50b1b887UL, 0x2b9f4fd5UL, 0x625aba82UL, 0x6a017962UL,
+0x2ec01b9cUL, 0x15488aa9UL, 0xd716e740UL, 0x40055a2cUL, 0x93d29a22UL, 0xe32dbf9aUL,
+0x058745b9UL, 0x3453dc1eUL, 0xd699296eUL, 0x496cff6fUL, 0x1c9f4986UL, 0xdfe2ed07UL,
+0xb87242d1UL, 0x19de7eaeUL, 0x053e561aUL, 0x15ad6f8cUL, 0x66626c1cUL, 0x7154c24cUL,
+0xea082b2aUL, 0x93eb2939UL, 0x17dcb0f0UL, 0x58d4f2aeUL, 0x9ea294fbUL, 0x52cf564cUL,
+0x9883fe66UL, 0x2ec40581UL, 0x763953c3UL, 0x01d6692eUL, 0xd3a0c108UL, 0xa1e7160eUL,
+0xe4f2dfa6UL, 0x693ed285UL, 0x74904698UL, 0x4c2b0eddUL, 0x4f757656UL, 0x5d393378UL,
+0xa132234fUL, 0x3d321c5dUL, 0xc3f5e194UL, 0x4b269301UL, 0xc79f022fUL, 0x3c997e7eUL,
+0x5e4f9504UL, 0x3ffafbbdUL, 0x76f7ad0eUL, 0x296693f4UL, 0x3d1fce6fUL, 0xc61e45beUL,
+0xd3b5ab34UL, 0xf72bf9b7UL, 0x1b0434c0UL, 0x4e72b567UL, 0x5592a33dUL, 0xb5229301UL,
+0xcfd2a87fUL, 0x60aeb767UL, 0x1814386bUL, 0x30bcc33dUL, 0x38a0c07dUL, 0xfd1606f2UL,
+0xc363519bUL, 0x589dd390UL, 0x5479f8e6UL, 0x1cb8d647UL, 0x97fd61a9UL, 0xea7759f4UL,
+0x2d57539dUL, 0x569a58cfUL, 0xe84e63adUL, 0x462e1b78UL, 0x6580f87eUL, 0xf3817914UL,
+0x91da55f4UL, 0x40a230f3UL, 0xd1988f35UL, 0xb6e318d2UL, 0x3ffa50bcUL, 0x3d40f021UL,
+0xc3c0bdaeUL, 0x4958c24cUL, 0x518f36b2UL, 0x84b1d370UL, 0x0fedce83UL, 0x878ddadaUL,
+0xf2a279c7UL, 0x94e01be8UL, 0x90716f4bUL, 0x954b8aa3UL};
+
+static const ulong32 S8[256] = {
+0xe216300dUL, 0xbbddfffcUL, 0xa7ebdabdUL, 0x35648095UL, 0x7789f8b7UL, 0xe6c1121bUL,
+0x0e241600UL, 0x052ce8b5UL, 0x11a9cfb0UL, 0xe5952f11UL, 0xece7990aUL, 0x9386d174UL,
+0x2a42931cUL, 0x76e38111UL, 0xb12def3aUL, 0x37ddddfcUL, 0xde9adeb1UL, 0x0a0cc32cUL,
+0xbe197029UL, 0x84a00940UL, 0xbb243a0fUL, 0xb4d137cfUL, 0xb44e79f0UL, 0x049eedfdUL,
+0x0b15a15dUL, 0x480d3168UL, 0x8bbbde5aUL, 0x669ded42UL, 0xc7ece831UL, 0x3f8f95e7UL,
+0x72df191bUL, 0x7580330dUL, 0x94074251UL, 0x5c7dcdfaUL, 0xabbe6d63UL, 0xaa402164UL,
+0xb301d40aUL, 0x02e7d1caUL, 0x53571daeUL, 0x7a3182a2UL, 0x12a8ddecUL, 0xfdaa335dUL,
+0x176f43e8UL, 0x71fb46d4UL, 0x38129022UL, 0xce949ad4UL, 0xb84769adUL, 0x965bd862UL,
+0x82f3d055UL, 0x66fb9767UL, 0x15b80b4eUL, 0x1d5b47a0UL, 0x4cfde06fUL, 0xc28ec4b8UL,
+0x57e8726eUL, 0x647a78fcUL, 0x99865d44UL, 0x608bd593UL, 0x6c200e03UL, 0x39dc5ff6UL,
+0x5d0b00a3UL, 0xae63aff2UL, 0x7e8bd632UL, 0x70108c0cUL, 0xbbd35049UL, 0x2998df04UL,
+0x980cf42aUL, 0x9b6df491UL, 0x9e7edd53UL, 0x06918548UL, 0x58cb7e07UL, 0x3b74ef2eUL,
+0x522fffb1UL, 0xd24708ccUL, 0x1c7e27cdUL, 0xa4eb215bUL, 0x3cf1d2e2UL, 0x19b47a38UL,
+0x424f7618UL, 0x35856039UL, 0x9d17dee7UL, 0x27eb35e6UL, 0xc9aff67bUL, 0x36baf5b8UL,
+0x09c467cdUL, 0xc18910b1UL, 0xe11dbf7bUL, 0x06cd1af8UL, 0x7170c608UL, 0x2d5e3354UL,
+0xd4de495aUL, 0x64c6d006UL, 0xbcc0c62cUL, 0x3dd00db3UL, 0x708f8f34UL, 0x77d51b42UL,
+0x264f620fUL, 0x24b8d2bfUL, 0x15c1b79eUL, 0x46a52564UL, 0xf8d7e54eUL, 0x3e378160UL,
+0x7895cda5UL, 0x859c15a5UL, 0xe6459788UL, 0xc37bc75fUL, 0xdb07ba0cUL, 0x0676a3abUL,
+0x7f229b1eUL, 0x31842e7bUL, 0x24259fd7UL, 0xf8bef472UL, 0x835ffcb8UL, 0x6df4c1f2UL,
+0x96f5b195UL, 0xfd0af0fcUL, 0xb0fe134cUL, 0xe2506d3dUL, 0x4f9b12eaUL, 0xf215f225UL,
+0xa223736fUL, 0x9fb4c428UL, 0x25d04979UL, 0x34c713f8UL, 0xc4618187UL, 0xea7a6e98UL,
+0x7cd16efcUL, 0x1436876cUL, 0xf1544107UL, 0xbedeee14UL, 0x56e9af27UL, 0xa04aa441UL,
+0x3cf7c899UL, 0x92ecbae6UL, 0xdd67016dUL, 0x151682ebUL, 0xa842eedfUL, 0xfdba60b4UL,
+0xf1907b75UL, 0x20e3030fUL, 0x24d8c29eUL, 0xe139673bUL, 0xefa63fb8UL, 0x71873054UL,
+0xb6f2cf3bUL, 0x9f326442UL, 0xcb15a4ccUL, 0xb01a4504UL, 0xf1e47d8dUL, 0x844a1be5UL,
+0xbae7dfdcUL, 0x42cbda70UL, 0xcd7dae0aUL, 0x57e85b7aUL, 0xd53f5af6UL, 0x20cf4d8cUL,
+0xcea4d428UL, 0x79d130a4UL, 0x3486ebfbUL, 0x33d3cddcUL, 0x77853b53UL, 0x37effcb5UL,
+0xc5068778UL, 0xe580b3e6UL, 0x4e68b8f4UL, 0xc5c8b37eUL, 0x0d809ea2UL, 0x398feb7cUL,
+0x132a4f94UL, 0x43b7950eUL, 0x2fee7d1cUL, 0x223613bdUL, 0xdd06caa2UL, 0x37df932bUL,
+0xc4248289UL, 0xacf3ebc3UL, 0x5715f6b7UL, 0xef3478ddUL, 0xf267616fUL, 0xc148cbe4UL,
+0x9052815eUL, 0x5e410fabUL, 0xb48a2465UL, 0x2eda7fa4UL, 0xe87b40e4UL, 0xe98ea084UL,
+0x5889e9e1UL, 0xefd390fcUL, 0xdd07d35bUL, 0xdb485694UL, 0x38d7e5b2UL, 0x57720101UL,
+0x730edebcUL, 0x5b643113UL, 0x94917e4fUL, 0x503c2fbaUL, 0x646f1282UL, 0x7523d24aUL,
+0xe0779695UL, 0xf9c17a8fUL, 0x7a5b2121UL, 0xd187b896UL, 0x29263a4dUL, 0xba510cdfUL,
+0x81f47c9fUL, 0xad1163edUL, 0xea7b5965UL, 0x1a00726eUL, 0x11403092UL, 0x00da6d77UL,
+0x4a0cdd61UL, 0xad1f4603UL, 0x605bdfb0UL, 0x9eedc364UL, 0x22ebe6a8UL, 0xcee7d28aUL,
+0xa0e736a0UL, 0x5564a6b9UL, 0x10853209UL, 0xc7eb8f37UL, 0x2de705caUL, 0x8951570fUL,
+0xdf09822bUL, 0xbd691a6cUL, 0xaa12e4f2UL, 0x87451c0fUL, 0xe0f6a27aUL, 0x3ada4819UL,
+0x4cf1764fUL, 0x0d771c2bUL, 0x67cdb156UL, 0x350d8384UL, 0x5938fa0fUL, 0x42399ef3UL,
+0x36997b07UL, 0x0e84093dUL, 0x4aa93e61UL, 0x8360d87bUL, 0x1fa98b0cUL, 0x1149382cUL,
+0xe97625a5UL, 0x0614d1b7UL, 0x0e25244bUL, 0x0c768347UL, 0x589e8d82UL, 0x0d2059d1UL,
+0xa466bb1eUL, 0xf8da0a82UL, 0x04f19130UL, 0xba6e4ec0UL, 0x99265164UL, 0x1ee7230dUL,
+0x50b2ad80UL, 0xeaee6801UL, 0x8db2a283UL, 0xea8bf59eUL};
+
+/* returns the i'th byte of a variable */
+#ifdef _MSC_VER
+ #define GB(x, i) ((unsigned char)((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3))))
+#else
+ #define GB(x, i) (((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))&255)
+#endif
+
+ /**
+ Initialize the LTC_CAST5 block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+#ifdef LTC_CLEAN_STACK
+static int s_cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+ ulong32 x[4], z[4];
+ unsigned char buf[16];
+ int y, i;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (num_rounds != 12 && num_rounds != 16 && num_rounds != 0) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (num_rounds == 12 && keylen > 10) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (keylen < 5 || keylen > 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ /* extend the key as required */
+ zeromem(buf, sizeof(buf));
+ XMEMCPY(buf, key, (size_t)keylen);
+
+ /* load and start the awful looking network */
+ for (y = 0; y < 4; y++) {
+ LOAD32H(x[3-y],buf+4*y);
+ }
+
+ for (i = y = 0; y < 2; y++) {
+ z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)];
+ z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)];
+ z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)];
+ z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)];
+ skey->cast5.K[i++] = S5[GB(z, 0x8)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0x7)] ^ S8[GB(z, 0x6)] ^ S5[GB(z, 0x2)];
+ skey->cast5.K[i++] = S5[GB(z, 0xA)] ^ S6[GB(z, 0xB)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S6[GB(z, 0x6)];
+ skey->cast5.K[i++] = S5[GB(z, 0xC)] ^ S6[GB(z, 0xd)] ^ S7[GB(z, 0x3)] ^ S8[GB(z, 0x2)] ^ S7[GB(z, 0x9)];
+ skey->cast5.K[i++] = S5[GB(z, 0xE)] ^ S6[GB(z, 0xF)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x0)] ^ S8[GB(z, 0xc)];
+
+ x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)];
+ x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)];
+ x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)];
+ x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)];
+ skey->cast5.K[i++] = S5[GB(x, 0x3)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0xc)] ^ S8[GB(x, 0xd)] ^ S5[GB(x, 0x8)];
+ skey->cast5.K[i++] = S5[GB(x, 0x1)] ^ S6[GB(x, 0x0)] ^ S7[GB(x, 0xe)] ^ S8[GB(x, 0xf)] ^ S6[GB(x, 0xd)];
+ skey->cast5.K[i++] = S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x8)] ^ S8[GB(x, 0x9)] ^ S7[GB(x, 0x3)];
+ skey->cast5.K[i++] = S5[GB(x, 0x5)] ^ S6[GB(x, 0x4)] ^ S7[GB(x, 0xa)] ^ S8[GB(x, 0xb)] ^ S8[GB(x, 0x7)];
+
+ /* second half */
+ z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)];
+ z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)];
+ z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)];
+ z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)];
+ skey->cast5.K[i++] = S5[GB(z, 0x3)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0xc)] ^ S8[GB(z, 0xd)] ^ S5[GB(z, 0x9)];
+ skey->cast5.K[i++] = S5[GB(z, 0x1)] ^ S6[GB(z, 0x0)] ^ S7[GB(z, 0xe)] ^ S8[GB(z, 0xf)] ^ S6[GB(z, 0xc)];
+ skey->cast5.K[i++] = S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x8)] ^ S8[GB(z, 0x9)] ^ S7[GB(z, 0x2)];
+ skey->cast5.K[i++] = S5[GB(z, 0x5)] ^ S6[GB(z, 0x4)] ^ S7[GB(z, 0xa)] ^ S8[GB(z, 0xb)] ^ S8[GB(z, 0x6)];
+
+ x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)];
+ x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)];
+ x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)];
+ x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)];
+ skey->cast5.K[i++] = S5[GB(x, 0x8)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0x7)] ^ S8[GB(x, 0x6)] ^ S5[GB(x, 0x3)];
+ skey->cast5.K[i++] = S5[GB(x, 0xa)] ^ S6[GB(x, 0xb)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S6[GB(x, 0x7)];
+ skey->cast5.K[i++] = S5[GB(x, 0xc)] ^ S6[GB(x, 0xd)] ^ S7[GB(x, 0x3)] ^ S8[GB(x, 0x2)] ^ S7[GB(x, 0x8)];
+ skey->cast5.K[i++] = S5[GB(x, 0xe)] ^ S6[GB(x, 0xf)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x0)] ^ S8[GB(x, 0xd)];
+ }
+
+ skey->cast5.keylen = keylen;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, sizeof(buf));
+ zeromem(x, sizeof(x));
+ zeromem(z, sizeof(z));
+#endif
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int z;
+ z = s_cast5_setup(key, keylen, num_rounds, skey);
+ burn_stack(sizeof(ulong32)*8 + 16 + sizeof(int)*2);
+ return z;
+}
+#endif
+
+LTC_INLINE static ulong32 FI(ulong32 R, ulong32 Km, ulong32 Kr)
+{
+ ulong32 I;
+ I = (Km + R);
+ I = ROL(I, Kr);
+ return ((S1[LTC_BYTE(I, 3)] ^ S2[LTC_BYTE(I,2)]) - S3[LTC_BYTE(I,1)]) + S4[LTC_BYTE(I,0)];
+}
+
+LTC_INLINE static ulong32 FII(ulong32 R, ulong32 Km, ulong32 Kr)
+{
+ ulong32 I;
+ I = (Km ^ R);
+ I = ROL(I, Kr);
+ return ((S1[LTC_BYTE(I, 3)] - S2[LTC_BYTE(I,2)]) + S3[LTC_BYTE(I,1)]) ^ S4[LTC_BYTE(I,0)];
+}
+
+LTC_INLINE static ulong32 FIII(ulong32 R, ulong32 Km, ulong32 Kr)
+{
+ ulong32 I;
+ I = (Km - R);
+ I = ROL(I, Kr);
+ return ((S1[LTC_BYTE(I, 3)] + S2[LTC_BYTE(I,2)]) ^ S3[LTC_BYTE(I,1)]) - S4[LTC_BYTE(I,0)];
+}
+
+/**
+ Encrypts a block of text with LTC_CAST5
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+ ulong32 R, L;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ LOAD32H(L,&pt[0]);
+ LOAD32H(R,&pt[4]);
+ L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]);
+ R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]);
+ L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]);
+ R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]);
+ L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]);
+ R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]);
+ L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]);
+ R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]);
+ L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]);
+ R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]);
+ L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]);
+ R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]);
+ if (skey->cast5.keylen > 10) {
+ L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]);
+ R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]);
+ L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]);
+ R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]);
+ }
+ STORE32H(R,&ct[0]);
+ STORE32H(L,&ct[4]);
+ return CRYPT_OK;
+}
+
+
+#ifdef LTC_CLEAN_STACK
+int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_cast5_ecb_encrypt(pt,ct,skey);
+ burn_stack(sizeof(ulong32)*3);
+ return err;
+}
+#endif
+
+/**
+ Decrypts a block of text with LTC_CAST5
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+ ulong32 R, L;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ LOAD32H(R,&ct[0]);
+ LOAD32H(L,&ct[4]);
+ if (skey->cast5.keylen > 10) {
+ R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]);
+ L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]);
+ R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]);
+ L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]);
+ }
+ R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]);
+ L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]);
+ R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]);
+ L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]);
+ R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]);
+ L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]);
+ R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]);
+ L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]);
+ R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]);
+ L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]);
+ R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]);
+ L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]);
+ STORE32H(L,&pt[0]);
+ STORE32H(R,&pt[4]);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_cast5_ecb_decrypt(ct,pt,skey);
+ burn_stack(sizeof(ulong32)*3);
+ return err;
+}
+#endif
+
+/**
+ Performs a self-test of the LTC_CAST5 block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int cast5_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ int keylen;
+ unsigned char key[16];
+ unsigned char pt[8];
+ unsigned char ct[8];
+ } tests[] = {
+ { 16,
+ {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
+ {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ {0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2}
+ },
+ { 10,
+ {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ {0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B},
+ },
+ { 5,
+ {0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ {0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E}
+ }
+ };
+ int i, y, err;
+ symmetric_key key;
+ unsigned char tmp[2][8];
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ if ((err = cast5_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+ cast5_ecb_encrypt(tests[i].pt, tmp[0], &key);
+ cast5_ecb_decrypt(tmp[0], tmp[1], &key);
+ if ((compare_testvector(tmp[0], 8, tests[i].ct, 8, "CAST5 Encrypt", i) != 0) ||
+ (compare_testvector(tmp[1], 8, tests[i].pt, 8, "CAST5 Decrypt", i) != 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 8; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) cast5_ecb_encrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 1000; y++) cast5_ecb_decrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void cast5_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int cast5_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 5) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize > 16) {
+ *keysize = 16;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/ciphers/des.c b/Sources/libtomcrypt/ciphers/des.c
new file mode 100644
index 00000000..eca87e57
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/des.c
@@ -0,0 +1,2242 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file des.c
+ DES code submitted by Dobes Vandermeer
+*/
+
+#ifdef LTC_DES
+
+#define EN0 0
+#define DE1 1
+
+const struct ltc_cipher_descriptor des_desc =
+{
+ "des",
+ 13,
+ 8, 8, 8, 16,
+ &des_setup,
+ &des_ecb_encrypt,
+ &des_ecb_decrypt,
+ &des_test,
+ &des_done,
+ &des_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+const struct ltc_cipher_descriptor des3_desc =
+{
+ "3des",
+ 14,
+ 16, 24, 8, 16,
+ &des3_setup,
+ &des3_ecb_encrypt,
+ &des3_ecb_decrypt,
+ &des3_test,
+ &des3_done,
+ &des3_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+const struct ltc_cipher_descriptor desx_desc =
+{
+ "desx",
+ 27,
+ 24, 24, 8, 16,
+ &desx_setup,
+ &desx_ecb_encrypt,
+ &desx_ecb_decrypt,
+ &desx_test,
+ &desx_done,
+ &desx_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ulong32 bytebit[8] =
+{
+ 0200, 0100, 040, 020, 010, 04, 02, 01
+};
+
+static const ulong32 bigbyte[24] =
+{
+ 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL,
+ 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL,
+ 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL,
+ 0x800UL, 0x400UL, 0x200UL, 0x100UL,
+ 0x80UL, 0x40UL, 0x20UL, 0x10UL,
+ 0x8UL, 0x4UL, 0x2UL, 0x1L
+};
+
+/* Use the key schedule specific in the standard (ANSI X3.92-1981) */
+
+static const unsigned char pc1[56] = {
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
+};
+
+static const unsigned char totrot[16] = {
+ 1, 2, 4, 6,
+ 8, 10, 12, 14,
+ 15, 17, 19, 21,
+ 23, 25, 27, 28
+};
+
+static const unsigned char pc2[48] = {
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
+};
+
+
+static const ulong32 SP1[64] =
+{
+ 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
+ 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
+ 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
+ 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
+ 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
+ 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
+ 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
+ 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
+ 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
+ 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
+ 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
+ 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
+ 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
+ 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
+ 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
+ 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
+};
+
+static const ulong32 SP2[64] =
+{
+ 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
+ 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
+ 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
+ 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
+ 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
+ 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
+ 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
+ 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
+ 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
+ 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
+ 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
+ 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
+ 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
+ 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
+ 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
+ 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
+};
+
+static const ulong32 SP3[64] =
+{
+ 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
+ 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
+ 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
+ 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
+ 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
+ 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
+ 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
+ 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
+ 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
+ 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
+ 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
+ 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
+ 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
+ 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
+ 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
+ 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
+};
+
+static const ulong32 SP4[64] =
+{
+ 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
+ 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
+ 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
+ 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
+ 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
+ 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
+ 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
+ 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
+ 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
+ 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
+ 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
+ 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
+ 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
+ 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
+ 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
+ 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
+};
+
+static const ulong32 SP5[64] =
+{
+ 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
+ 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
+ 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
+ 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
+ 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
+ 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
+ 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
+ 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
+ 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
+ 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
+ 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
+ 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
+ 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
+ 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
+ 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
+ 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
+};
+
+static const ulong32 SP6[64] =
+{
+ 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
+ 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
+ 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
+ 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
+ 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
+ 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
+ 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
+ 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
+ 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
+ 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
+ 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
+ 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
+ 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
+ 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
+ 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
+ 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
+};
+
+static const ulong32 SP7[64] =
+{
+ 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
+ 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
+ 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
+ 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
+ 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
+ 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
+ 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
+ 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
+ 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
+ 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
+ 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
+ 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
+ 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
+ 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
+ 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
+ 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
+};
+
+static const ulong32 SP8[64] =
+{
+ 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
+ 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
+ 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
+ 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
+ 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
+ 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
+ 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
+ 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
+ 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
+ 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
+ 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
+ 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
+ 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
+ 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
+ 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
+ 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
+};
+
+#ifndef LTC_SMALL_CODE
+
+static const ulong64 des_ip[8][256] = {
+
+{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000000000010), CONST64(0x0000001000000010),
+ CONST64(0x0000100000000000), CONST64(0x0000101000000000), CONST64(0x0000100000000010), CONST64(0x0000101000000010),
+ CONST64(0x0000000000001000), CONST64(0x0000001000001000), CONST64(0x0000000000001010), CONST64(0x0000001000001010),
+ CONST64(0x0000100000001000), CONST64(0x0000101000001000), CONST64(0x0000100000001010), CONST64(0x0000101000001010),
+ CONST64(0x0010000000000000), CONST64(0x0010001000000000), CONST64(0x0010000000000010), CONST64(0x0010001000000010),
+ CONST64(0x0010100000000000), CONST64(0x0010101000000000), CONST64(0x0010100000000010), CONST64(0x0010101000000010),
+ CONST64(0x0010000000001000), CONST64(0x0010001000001000), CONST64(0x0010000000001010), CONST64(0x0010001000001010),
+ CONST64(0x0010100000001000), CONST64(0x0010101000001000), CONST64(0x0010100000001010), CONST64(0x0010101000001010),
+ CONST64(0x0000000000100000), CONST64(0x0000001000100000), CONST64(0x0000000000100010), CONST64(0x0000001000100010),
+ CONST64(0x0000100000100000), CONST64(0x0000101000100000), CONST64(0x0000100000100010), CONST64(0x0000101000100010),
+ CONST64(0x0000000000101000), CONST64(0x0000001000101000), CONST64(0x0000000000101010), CONST64(0x0000001000101010),
+ CONST64(0x0000100000101000), CONST64(0x0000101000101000), CONST64(0x0000100000101010), CONST64(0x0000101000101010),
+ CONST64(0x0010000000100000), CONST64(0x0010001000100000), CONST64(0x0010000000100010), CONST64(0x0010001000100010),
+ CONST64(0x0010100000100000), CONST64(0x0010101000100000), CONST64(0x0010100000100010), CONST64(0x0010101000100010),
+ CONST64(0x0010000000101000), CONST64(0x0010001000101000), CONST64(0x0010000000101010), CONST64(0x0010001000101010),
+ CONST64(0x0010100000101000), CONST64(0x0010101000101000), CONST64(0x0010100000101010), CONST64(0x0010101000101010),
+ CONST64(0x1000000000000000), CONST64(0x1000001000000000), CONST64(0x1000000000000010), CONST64(0x1000001000000010),
+ CONST64(0x1000100000000000), CONST64(0x1000101000000000), CONST64(0x1000100000000010), CONST64(0x1000101000000010),
+ CONST64(0x1000000000001000), CONST64(0x1000001000001000), CONST64(0x1000000000001010), CONST64(0x1000001000001010),
+ CONST64(0x1000100000001000), CONST64(0x1000101000001000), CONST64(0x1000100000001010), CONST64(0x1000101000001010),
+ CONST64(0x1010000000000000), CONST64(0x1010001000000000), CONST64(0x1010000000000010), CONST64(0x1010001000000010),
+ CONST64(0x1010100000000000), CONST64(0x1010101000000000), CONST64(0x1010100000000010), CONST64(0x1010101000000010),
+ CONST64(0x1010000000001000), CONST64(0x1010001000001000), CONST64(0x1010000000001010), CONST64(0x1010001000001010),
+ CONST64(0x1010100000001000), CONST64(0x1010101000001000), CONST64(0x1010100000001010), CONST64(0x1010101000001010),
+ CONST64(0x1000000000100000), CONST64(0x1000001000100000), CONST64(0x1000000000100010), CONST64(0x1000001000100010),
+ CONST64(0x1000100000100000), CONST64(0x1000101000100000), CONST64(0x1000100000100010), CONST64(0x1000101000100010),
+ CONST64(0x1000000000101000), CONST64(0x1000001000101000), CONST64(0x1000000000101010), CONST64(0x1000001000101010),
+ CONST64(0x1000100000101000), CONST64(0x1000101000101000), CONST64(0x1000100000101010), CONST64(0x1000101000101010),
+ CONST64(0x1010000000100000), CONST64(0x1010001000100000), CONST64(0x1010000000100010), CONST64(0x1010001000100010),
+ CONST64(0x1010100000100000), CONST64(0x1010101000100000), CONST64(0x1010100000100010), CONST64(0x1010101000100010),
+ CONST64(0x1010000000101000), CONST64(0x1010001000101000), CONST64(0x1010000000101010), CONST64(0x1010001000101010),
+ CONST64(0x1010100000101000), CONST64(0x1010101000101000), CONST64(0x1010100000101010), CONST64(0x1010101000101010),
+ CONST64(0x0000000010000000), CONST64(0x0000001010000000), CONST64(0x0000000010000010), CONST64(0x0000001010000010),
+ CONST64(0x0000100010000000), CONST64(0x0000101010000000), CONST64(0x0000100010000010), CONST64(0x0000101010000010),
+ CONST64(0x0000000010001000), CONST64(0x0000001010001000), CONST64(0x0000000010001010), CONST64(0x0000001010001010),
+ CONST64(0x0000100010001000), CONST64(0x0000101010001000), CONST64(0x0000100010001010), CONST64(0x0000101010001010),
+ CONST64(0x0010000010000000), CONST64(0x0010001010000000), CONST64(0x0010000010000010), CONST64(0x0010001010000010),
+ CONST64(0x0010100010000000), CONST64(0x0010101010000000), CONST64(0x0010100010000010), CONST64(0x0010101010000010),
+ CONST64(0x0010000010001000), CONST64(0x0010001010001000), CONST64(0x0010000010001010), CONST64(0x0010001010001010),
+ CONST64(0x0010100010001000), CONST64(0x0010101010001000), CONST64(0x0010100010001010), CONST64(0x0010101010001010),
+ CONST64(0x0000000010100000), CONST64(0x0000001010100000), CONST64(0x0000000010100010), CONST64(0x0000001010100010),
+ CONST64(0x0000100010100000), CONST64(0x0000101010100000), CONST64(0x0000100010100010), CONST64(0x0000101010100010),
+ CONST64(0x0000000010101000), CONST64(0x0000001010101000), CONST64(0x0000000010101010), CONST64(0x0000001010101010),
+ CONST64(0x0000100010101000), CONST64(0x0000101010101000), CONST64(0x0000100010101010), CONST64(0x0000101010101010),
+ CONST64(0x0010000010100000), CONST64(0x0010001010100000), CONST64(0x0010000010100010), CONST64(0x0010001010100010),
+ CONST64(0x0010100010100000), CONST64(0x0010101010100000), CONST64(0x0010100010100010), CONST64(0x0010101010100010),
+ CONST64(0x0010000010101000), CONST64(0x0010001010101000), CONST64(0x0010000010101010), CONST64(0x0010001010101010),
+ CONST64(0x0010100010101000), CONST64(0x0010101010101000), CONST64(0x0010100010101010), CONST64(0x0010101010101010),
+ CONST64(0x1000000010000000), CONST64(0x1000001010000000), CONST64(0x1000000010000010), CONST64(0x1000001010000010),
+ CONST64(0x1000100010000000), CONST64(0x1000101010000000), CONST64(0x1000100010000010), CONST64(0x1000101010000010),
+ CONST64(0x1000000010001000), CONST64(0x1000001010001000), CONST64(0x1000000010001010), CONST64(0x1000001010001010),
+ CONST64(0x1000100010001000), CONST64(0x1000101010001000), CONST64(0x1000100010001010), CONST64(0x1000101010001010),
+ CONST64(0x1010000010000000), CONST64(0x1010001010000000), CONST64(0x1010000010000010), CONST64(0x1010001010000010),
+ CONST64(0x1010100010000000), CONST64(0x1010101010000000), CONST64(0x1010100010000010), CONST64(0x1010101010000010),
+ CONST64(0x1010000010001000), CONST64(0x1010001010001000), CONST64(0x1010000010001010), CONST64(0x1010001010001010),
+ CONST64(0x1010100010001000), CONST64(0x1010101010001000), CONST64(0x1010100010001010), CONST64(0x1010101010001010),
+ CONST64(0x1000000010100000), CONST64(0x1000001010100000), CONST64(0x1000000010100010), CONST64(0x1000001010100010),
+ CONST64(0x1000100010100000), CONST64(0x1000101010100000), CONST64(0x1000100010100010), CONST64(0x1000101010100010),
+ CONST64(0x1000000010101000), CONST64(0x1000001010101000), CONST64(0x1000000010101010), CONST64(0x1000001010101010),
+ CONST64(0x1000100010101000), CONST64(0x1000101010101000), CONST64(0x1000100010101010), CONST64(0x1000101010101010),
+ CONST64(0x1010000010100000), CONST64(0x1010001010100000), CONST64(0x1010000010100010), CONST64(0x1010001010100010),
+ CONST64(0x1010100010100000), CONST64(0x1010101010100000), CONST64(0x1010100010100010), CONST64(0x1010101010100010),
+ CONST64(0x1010000010101000), CONST64(0x1010001010101000), CONST64(0x1010000010101010), CONST64(0x1010001010101010),
+ CONST64(0x1010100010101000), CONST64(0x1010101010101000), CONST64(0x1010100010101010), CONST64(0x1010101010101010)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000000000008), CONST64(0x0000000800000008),
+ CONST64(0x0000080000000000), CONST64(0x0000080800000000), CONST64(0x0000080000000008), CONST64(0x0000080800000008),
+ CONST64(0x0000000000000800), CONST64(0x0000000800000800), CONST64(0x0000000000000808), CONST64(0x0000000800000808),
+ CONST64(0x0000080000000800), CONST64(0x0000080800000800), CONST64(0x0000080000000808), CONST64(0x0000080800000808),
+ CONST64(0x0008000000000000), CONST64(0x0008000800000000), CONST64(0x0008000000000008), CONST64(0x0008000800000008),
+ CONST64(0x0008080000000000), CONST64(0x0008080800000000), CONST64(0x0008080000000008), CONST64(0x0008080800000008),
+ CONST64(0x0008000000000800), CONST64(0x0008000800000800), CONST64(0x0008000000000808), CONST64(0x0008000800000808),
+ CONST64(0x0008080000000800), CONST64(0x0008080800000800), CONST64(0x0008080000000808), CONST64(0x0008080800000808),
+ CONST64(0x0000000000080000), CONST64(0x0000000800080000), CONST64(0x0000000000080008), CONST64(0x0000000800080008),
+ CONST64(0x0000080000080000), CONST64(0x0000080800080000), CONST64(0x0000080000080008), CONST64(0x0000080800080008),
+ CONST64(0x0000000000080800), CONST64(0x0000000800080800), CONST64(0x0000000000080808), CONST64(0x0000000800080808),
+ CONST64(0x0000080000080800), CONST64(0x0000080800080800), CONST64(0x0000080000080808), CONST64(0x0000080800080808),
+ CONST64(0x0008000000080000), CONST64(0x0008000800080000), CONST64(0x0008000000080008), CONST64(0x0008000800080008),
+ CONST64(0x0008080000080000), CONST64(0x0008080800080000), CONST64(0x0008080000080008), CONST64(0x0008080800080008),
+ CONST64(0x0008000000080800), CONST64(0x0008000800080800), CONST64(0x0008000000080808), CONST64(0x0008000800080808),
+ CONST64(0x0008080000080800), CONST64(0x0008080800080800), CONST64(0x0008080000080808), CONST64(0x0008080800080808),
+ CONST64(0x0800000000000000), CONST64(0x0800000800000000), CONST64(0x0800000000000008), CONST64(0x0800000800000008),
+ CONST64(0x0800080000000000), CONST64(0x0800080800000000), CONST64(0x0800080000000008), CONST64(0x0800080800000008),
+ CONST64(0x0800000000000800), CONST64(0x0800000800000800), CONST64(0x0800000000000808), CONST64(0x0800000800000808),
+ CONST64(0x0800080000000800), CONST64(0x0800080800000800), CONST64(0x0800080000000808), CONST64(0x0800080800000808),
+ CONST64(0x0808000000000000), CONST64(0x0808000800000000), CONST64(0x0808000000000008), CONST64(0x0808000800000008),
+ CONST64(0x0808080000000000), CONST64(0x0808080800000000), CONST64(0x0808080000000008), CONST64(0x0808080800000008),
+ CONST64(0x0808000000000800), CONST64(0x0808000800000800), CONST64(0x0808000000000808), CONST64(0x0808000800000808),
+ CONST64(0x0808080000000800), CONST64(0x0808080800000800), CONST64(0x0808080000000808), CONST64(0x0808080800000808),
+ CONST64(0x0800000000080000), CONST64(0x0800000800080000), CONST64(0x0800000000080008), CONST64(0x0800000800080008),
+ CONST64(0x0800080000080000), CONST64(0x0800080800080000), CONST64(0x0800080000080008), CONST64(0x0800080800080008),
+ CONST64(0x0800000000080800), CONST64(0x0800000800080800), CONST64(0x0800000000080808), CONST64(0x0800000800080808),
+ CONST64(0x0800080000080800), CONST64(0x0800080800080800), CONST64(0x0800080000080808), CONST64(0x0800080800080808),
+ CONST64(0x0808000000080000), CONST64(0x0808000800080000), CONST64(0x0808000000080008), CONST64(0x0808000800080008),
+ CONST64(0x0808080000080000), CONST64(0x0808080800080000), CONST64(0x0808080000080008), CONST64(0x0808080800080008),
+ CONST64(0x0808000000080800), CONST64(0x0808000800080800), CONST64(0x0808000000080808), CONST64(0x0808000800080808),
+ CONST64(0x0808080000080800), CONST64(0x0808080800080800), CONST64(0x0808080000080808), CONST64(0x0808080800080808),
+ CONST64(0x0000000008000000), CONST64(0x0000000808000000), CONST64(0x0000000008000008), CONST64(0x0000000808000008),
+ CONST64(0x0000080008000000), CONST64(0x0000080808000000), CONST64(0x0000080008000008), CONST64(0x0000080808000008),
+ CONST64(0x0000000008000800), CONST64(0x0000000808000800), CONST64(0x0000000008000808), CONST64(0x0000000808000808),
+ CONST64(0x0000080008000800), CONST64(0x0000080808000800), CONST64(0x0000080008000808), CONST64(0x0000080808000808),
+ CONST64(0x0008000008000000), CONST64(0x0008000808000000), CONST64(0x0008000008000008), CONST64(0x0008000808000008),
+ CONST64(0x0008080008000000), CONST64(0x0008080808000000), CONST64(0x0008080008000008), CONST64(0x0008080808000008),
+ CONST64(0x0008000008000800), CONST64(0x0008000808000800), CONST64(0x0008000008000808), CONST64(0x0008000808000808),
+ CONST64(0x0008080008000800), CONST64(0x0008080808000800), CONST64(0x0008080008000808), CONST64(0x0008080808000808),
+ CONST64(0x0000000008080000), CONST64(0x0000000808080000), CONST64(0x0000000008080008), CONST64(0x0000000808080008),
+ CONST64(0x0000080008080000), CONST64(0x0000080808080000), CONST64(0x0000080008080008), CONST64(0x0000080808080008),
+ CONST64(0x0000000008080800), CONST64(0x0000000808080800), CONST64(0x0000000008080808), CONST64(0x0000000808080808),
+ CONST64(0x0000080008080800), CONST64(0x0000080808080800), CONST64(0x0000080008080808), CONST64(0x0000080808080808),
+ CONST64(0x0008000008080000), CONST64(0x0008000808080000), CONST64(0x0008000008080008), CONST64(0x0008000808080008),
+ CONST64(0x0008080008080000), CONST64(0x0008080808080000), CONST64(0x0008080008080008), CONST64(0x0008080808080008),
+ CONST64(0x0008000008080800), CONST64(0x0008000808080800), CONST64(0x0008000008080808), CONST64(0x0008000808080808),
+ CONST64(0x0008080008080800), CONST64(0x0008080808080800), CONST64(0x0008080008080808), CONST64(0x0008080808080808),
+ CONST64(0x0800000008000000), CONST64(0x0800000808000000), CONST64(0x0800000008000008), CONST64(0x0800000808000008),
+ CONST64(0x0800080008000000), CONST64(0x0800080808000000), CONST64(0x0800080008000008), CONST64(0x0800080808000008),
+ CONST64(0x0800000008000800), CONST64(0x0800000808000800), CONST64(0x0800000008000808), CONST64(0x0800000808000808),
+ CONST64(0x0800080008000800), CONST64(0x0800080808000800), CONST64(0x0800080008000808), CONST64(0x0800080808000808),
+ CONST64(0x0808000008000000), CONST64(0x0808000808000000), CONST64(0x0808000008000008), CONST64(0x0808000808000008),
+ CONST64(0x0808080008000000), CONST64(0x0808080808000000), CONST64(0x0808080008000008), CONST64(0x0808080808000008),
+ CONST64(0x0808000008000800), CONST64(0x0808000808000800), CONST64(0x0808000008000808), CONST64(0x0808000808000808),
+ CONST64(0x0808080008000800), CONST64(0x0808080808000800), CONST64(0x0808080008000808), CONST64(0x0808080808000808),
+ CONST64(0x0800000008080000), CONST64(0x0800000808080000), CONST64(0x0800000008080008), CONST64(0x0800000808080008),
+ CONST64(0x0800080008080000), CONST64(0x0800080808080000), CONST64(0x0800080008080008), CONST64(0x0800080808080008),
+ CONST64(0x0800000008080800), CONST64(0x0800000808080800), CONST64(0x0800000008080808), CONST64(0x0800000808080808),
+ CONST64(0x0800080008080800), CONST64(0x0800080808080800), CONST64(0x0800080008080808), CONST64(0x0800080808080808),
+ CONST64(0x0808000008080000), CONST64(0x0808000808080000), CONST64(0x0808000008080008), CONST64(0x0808000808080008),
+ CONST64(0x0808080008080000), CONST64(0x0808080808080000), CONST64(0x0808080008080008), CONST64(0x0808080808080008),
+ CONST64(0x0808000008080800), CONST64(0x0808000808080800), CONST64(0x0808000008080808), CONST64(0x0808000808080808),
+ CONST64(0x0808080008080800), CONST64(0x0808080808080800), CONST64(0x0808080008080808), CONST64(0x0808080808080808)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000000000004), CONST64(0x0000000400000004),
+ CONST64(0x0000040000000000), CONST64(0x0000040400000000), CONST64(0x0000040000000004), CONST64(0x0000040400000004),
+ CONST64(0x0000000000000400), CONST64(0x0000000400000400), CONST64(0x0000000000000404), CONST64(0x0000000400000404),
+ CONST64(0x0000040000000400), CONST64(0x0000040400000400), CONST64(0x0000040000000404), CONST64(0x0000040400000404),
+ CONST64(0x0004000000000000), CONST64(0x0004000400000000), CONST64(0x0004000000000004), CONST64(0x0004000400000004),
+ CONST64(0x0004040000000000), CONST64(0x0004040400000000), CONST64(0x0004040000000004), CONST64(0x0004040400000004),
+ CONST64(0x0004000000000400), CONST64(0x0004000400000400), CONST64(0x0004000000000404), CONST64(0x0004000400000404),
+ CONST64(0x0004040000000400), CONST64(0x0004040400000400), CONST64(0x0004040000000404), CONST64(0x0004040400000404),
+ CONST64(0x0000000000040000), CONST64(0x0000000400040000), CONST64(0x0000000000040004), CONST64(0x0000000400040004),
+ CONST64(0x0000040000040000), CONST64(0x0000040400040000), CONST64(0x0000040000040004), CONST64(0x0000040400040004),
+ CONST64(0x0000000000040400), CONST64(0x0000000400040400), CONST64(0x0000000000040404), CONST64(0x0000000400040404),
+ CONST64(0x0000040000040400), CONST64(0x0000040400040400), CONST64(0x0000040000040404), CONST64(0x0000040400040404),
+ CONST64(0x0004000000040000), CONST64(0x0004000400040000), CONST64(0x0004000000040004), CONST64(0x0004000400040004),
+ CONST64(0x0004040000040000), CONST64(0x0004040400040000), CONST64(0x0004040000040004), CONST64(0x0004040400040004),
+ CONST64(0x0004000000040400), CONST64(0x0004000400040400), CONST64(0x0004000000040404), CONST64(0x0004000400040404),
+ CONST64(0x0004040000040400), CONST64(0x0004040400040400), CONST64(0x0004040000040404), CONST64(0x0004040400040404),
+ CONST64(0x0400000000000000), CONST64(0x0400000400000000), CONST64(0x0400000000000004), CONST64(0x0400000400000004),
+ CONST64(0x0400040000000000), CONST64(0x0400040400000000), CONST64(0x0400040000000004), CONST64(0x0400040400000004),
+ CONST64(0x0400000000000400), CONST64(0x0400000400000400), CONST64(0x0400000000000404), CONST64(0x0400000400000404),
+ CONST64(0x0400040000000400), CONST64(0x0400040400000400), CONST64(0x0400040000000404), CONST64(0x0400040400000404),
+ CONST64(0x0404000000000000), CONST64(0x0404000400000000), CONST64(0x0404000000000004), CONST64(0x0404000400000004),
+ CONST64(0x0404040000000000), CONST64(0x0404040400000000), CONST64(0x0404040000000004), CONST64(0x0404040400000004),
+ CONST64(0x0404000000000400), CONST64(0x0404000400000400), CONST64(0x0404000000000404), CONST64(0x0404000400000404),
+ CONST64(0x0404040000000400), CONST64(0x0404040400000400), CONST64(0x0404040000000404), CONST64(0x0404040400000404),
+ CONST64(0x0400000000040000), CONST64(0x0400000400040000), CONST64(0x0400000000040004), CONST64(0x0400000400040004),
+ CONST64(0x0400040000040000), CONST64(0x0400040400040000), CONST64(0x0400040000040004), CONST64(0x0400040400040004),
+ CONST64(0x0400000000040400), CONST64(0x0400000400040400), CONST64(0x0400000000040404), CONST64(0x0400000400040404),
+ CONST64(0x0400040000040400), CONST64(0x0400040400040400), CONST64(0x0400040000040404), CONST64(0x0400040400040404),
+ CONST64(0x0404000000040000), CONST64(0x0404000400040000), CONST64(0x0404000000040004), CONST64(0x0404000400040004),
+ CONST64(0x0404040000040000), CONST64(0x0404040400040000), CONST64(0x0404040000040004), CONST64(0x0404040400040004),
+ CONST64(0x0404000000040400), CONST64(0x0404000400040400), CONST64(0x0404000000040404), CONST64(0x0404000400040404),
+ CONST64(0x0404040000040400), CONST64(0x0404040400040400), CONST64(0x0404040000040404), CONST64(0x0404040400040404),
+ CONST64(0x0000000004000000), CONST64(0x0000000404000000), CONST64(0x0000000004000004), CONST64(0x0000000404000004),
+ CONST64(0x0000040004000000), CONST64(0x0000040404000000), CONST64(0x0000040004000004), CONST64(0x0000040404000004),
+ CONST64(0x0000000004000400), CONST64(0x0000000404000400), CONST64(0x0000000004000404), CONST64(0x0000000404000404),
+ CONST64(0x0000040004000400), CONST64(0x0000040404000400), CONST64(0x0000040004000404), CONST64(0x0000040404000404),
+ CONST64(0x0004000004000000), CONST64(0x0004000404000000), CONST64(0x0004000004000004), CONST64(0x0004000404000004),
+ CONST64(0x0004040004000000), CONST64(0x0004040404000000), CONST64(0x0004040004000004), CONST64(0x0004040404000004),
+ CONST64(0x0004000004000400), CONST64(0x0004000404000400), CONST64(0x0004000004000404), CONST64(0x0004000404000404),
+ CONST64(0x0004040004000400), CONST64(0x0004040404000400), CONST64(0x0004040004000404), CONST64(0x0004040404000404),
+ CONST64(0x0000000004040000), CONST64(0x0000000404040000), CONST64(0x0000000004040004), CONST64(0x0000000404040004),
+ CONST64(0x0000040004040000), CONST64(0x0000040404040000), CONST64(0x0000040004040004), CONST64(0x0000040404040004),
+ CONST64(0x0000000004040400), CONST64(0x0000000404040400), CONST64(0x0000000004040404), CONST64(0x0000000404040404),
+ CONST64(0x0000040004040400), CONST64(0x0000040404040400), CONST64(0x0000040004040404), CONST64(0x0000040404040404),
+ CONST64(0x0004000004040000), CONST64(0x0004000404040000), CONST64(0x0004000004040004), CONST64(0x0004000404040004),
+ CONST64(0x0004040004040000), CONST64(0x0004040404040000), CONST64(0x0004040004040004), CONST64(0x0004040404040004),
+ CONST64(0x0004000004040400), CONST64(0x0004000404040400), CONST64(0x0004000004040404), CONST64(0x0004000404040404),
+ CONST64(0x0004040004040400), CONST64(0x0004040404040400), CONST64(0x0004040004040404), CONST64(0x0004040404040404),
+ CONST64(0x0400000004000000), CONST64(0x0400000404000000), CONST64(0x0400000004000004), CONST64(0x0400000404000004),
+ CONST64(0x0400040004000000), CONST64(0x0400040404000000), CONST64(0x0400040004000004), CONST64(0x0400040404000004),
+ CONST64(0x0400000004000400), CONST64(0x0400000404000400), CONST64(0x0400000004000404), CONST64(0x0400000404000404),
+ CONST64(0x0400040004000400), CONST64(0x0400040404000400), CONST64(0x0400040004000404), CONST64(0x0400040404000404),
+ CONST64(0x0404000004000000), CONST64(0x0404000404000000), CONST64(0x0404000004000004), CONST64(0x0404000404000004),
+ CONST64(0x0404040004000000), CONST64(0x0404040404000000), CONST64(0x0404040004000004), CONST64(0x0404040404000004),
+ CONST64(0x0404000004000400), CONST64(0x0404000404000400), CONST64(0x0404000004000404), CONST64(0x0404000404000404),
+ CONST64(0x0404040004000400), CONST64(0x0404040404000400), CONST64(0x0404040004000404), CONST64(0x0404040404000404),
+ CONST64(0x0400000004040000), CONST64(0x0400000404040000), CONST64(0x0400000004040004), CONST64(0x0400000404040004),
+ CONST64(0x0400040004040000), CONST64(0x0400040404040000), CONST64(0x0400040004040004), CONST64(0x0400040404040004),
+ CONST64(0x0400000004040400), CONST64(0x0400000404040400), CONST64(0x0400000004040404), CONST64(0x0400000404040404),
+ CONST64(0x0400040004040400), CONST64(0x0400040404040400), CONST64(0x0400040004040404), CONST64(0x0400040404040404),
+ CONST64(0x0404000004040000), CONST64(0x0404000404040000), CONST64(0x0404000004040004), CONST64(0x0404000404040004),
+ CONST64(0x0404040004040000), CONST64(0x0404040404040000), CONST64(0x0404040004040004), CONST64(0x0404040404040004),
+ CONST64(0x0404000004040400), CONST64(0x0404000404040400), CONST64(0x0404000004040404), CONST64(0x0404000404040404),
+ CONST64(0x0404040004040400), CONST64(0x0404040404040400), CONST64(0x0404040004040404), CONST64(0x0404040404040404)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000000000002), CONST64(0x0000000200000002),
+ CONST64(0x0000020000000000), CONST64(0x0000020200000000), CONST64(0x0000020000000002), CONST64(0x0000020200000002),
+ CONST64(0x0000000000000200), CONST64(0x0000000200000200), CONST64(0x0000000000000202), CONST64(0x0000000200000202),
+ CONST64(0x0000020000000200), CONST64(0x0000020200000200), CONST64(0x0000020000000202), CONST64(0x0000020200000202),
+ CONST64(0x0002000000000000), CONST64(0x0002000200000000), CONST64(0x0002000000000002), CONST64(0x0002000200000002),
+ CONST64(0x0002020000000000), CONST64(0x0002020200000000), CONST64(0x0002020000000002), CONST64(0x0002020200000002),
+ CONST64(0x0002000000000200), CONST64(0x0002000200000200), CONST64(0x0002000000000202), CONST64(0x0002000200000202),
+ CONST64(0x0002020000000200), CONST64(0x0002020200000200), CONST64(0x0002020000000202), CONST64(0x0002020200000202),
+ CONST64(0x0000000000020000), CONST64(0x0000000200020000), CONST64(0x0000000000020002), CONST64(0x0000000200020002),
+ CONST64(0x0000020000020000), CONST64(0x0000020200020000), CONST64(0x0000020000020002), CONST64(0x0000020200020002),
+ CONST64(0x0000000000020200), CONST64(0x0000000200020200), CONST64(0x0000000000020202), CONST64(0x0000000200020202),
+ CONST64(0x0000020000020200), CONST64(0x0000020200020200), CONST64(0x0000020000020202), CONST64(0x0000020200020202),
+ CONST64(0x0002000000020000), CONST64(0x0002000200020000), CONST64(0x0002000000020002), CONST64(0x0002000200020002),
+ CONST64(0x0002020000020000), CONST64(0x0002020200020000), CONST64(0x0002020000020002), CONST64(0x0002020200020002),
+ CONST64(0x0002000000020200), CONST64(0x0002000200020200), CONST64(0x0002000000020202), CONST64(0x0002000200020202),
+ CONST64(0x0002020000020200), CONST64(0x0002020200020200), CONST64(0x0002020000020202), CONST64(0x0002020200020202),
+ CONST64(0x0200000000000000), CONST64(0x0200000200000000), CONST64(0x0200000000000002), CONST64(0x0200000200000002),
+ CONST64(0x0200020000000000), CONST64(0x0200020200000000), CONST64(0x0200020000000002), CONST64(0x0200020200000002),
+ CONST64(0x0200000000000200), CONST64(0x0200000200000200), CONST64(0x0200000000000202), CONST64(0x0200000200000202),
+ CONST64(0x0200020000000200), CONST64(0x0200020200000200), CONST64(0x0200020000000202), CONST64(0x0200020200000202),
+ CONST64(0x0202000000000000), CONST64(0x0202000200000000), CONST64(0x0202000000000002), CONST64(0x0202000200000002),
+ CONST64(0x0202020000000000), CONST64(0x0202020200000000), CONST64(0x0202020000000002), CONST64(0x0202020200000002),
+ CONST64(0x0202000000000200), CONST64(0x0202000200000200), CONST64(0x0202000000000202), CONST64(0x0202000200000202),
+ CONST64(0x0202020000000200), CONST64(0x0202020200000200), CONST64(0x0202020000000202), CONST64(0x0202020200000202),
+ CONST64(0x0200000000020000), CONST64(0x0200000200020000), CONST64(0x0200000000020002), CONST64(0x0200000200020002),
+ CONST64(0x0200020000020000), CONST64(0x0200020200020000), CONST64(0x0200020000020002), CONST64(0x0200020200020002),
+ CONST64(0x0200000000020200), CONST64(0x0200000200020200), CONST64(0x0200000000020202), CONST64(0x0200000200020202),
+ CONST64(0x0200020000020200), CONST64(0x0200020200020200), CONST64(0x0200020000020202), CONST64(0x0200020200020202),
+ CONST64(0x0202000000020000), CONST64(0x0202000200020000), CONST64(0x0202000000020002), CONST64(0x0202000200020002),
+ CONST64(0x0202020000020000), CONST64(0x0202020200020000), CONST64(0x0202020000020002), CONST64(0x0202020200020002),
+ CONST64(0x0202000000020200), CONST64(0x0202000200020200), CONST64(0x0202000000020202), CONST64(0x0202000200020202),
+ CONST64(0x0202020000020200), CONST64(0x0202020200020200), CONST64(0x0202020000020202), CONST64(0x0202020200020202),
+ CONST64(0x0000000002000000), CONST64(0x0000000202000000), CONST64(0x0000000002000002), CONST64(0x0000000202000002),
+ CONST64(0x0000020002000000), CONST64(0x0000020202000000), CONST64(0x0000020002000002), CONST64(0x0000020202000002),
+ CONST64(0x0000000002000200), CONST64(0x0000000202000200), CONST64(0x0000000002000202), CONST64(0x0000000202000202),
+ CONST64(0x0000020002000200), CONST64(0x0000020202000200), CONST64(0x0000020002000202), CONST64(0x0000020202000202),
+ CONST64(0x0002000002000000), CONST64(0x0002000202000000), CONST64(0x0002000002000002), CONST64(0x0002000202000002),
+ CONST64(0x0002020002000000), CONST64(0x0002020202000000), CONST64(0x0002020002000002), CONST64(0x0002020202000002),
+ CONST64(0x0002000002000200), CONST64(0x0002000202000200), CONST64(0x0002000002000202), CONST64(0x0002000202000202),
+ CONST64(0x0002020002000200), CONST64(0x0002020202000200), CONST64(0x0002020002000202), CONST64(0x0002020202000202),
+ CONST64(0x0000000002020000), CONST64(0x0000000202020000), CONST64(0x0000000002020002), CONST64(0x0000000202020002),
+ CONST64(0x0000020002020000), CONST64(0x0000020202020000), CONST64(0x0000020002020002), CONST64(0x0000020202020002),
+ CONST64(0x0000000002020200), CONST64(0x0000000202020200), CONST64(0x0000000002020202), CONST64(0x0000000202020202),
+ CONST64(0x0000020002020200), CONST64(0x0000020202020200), CONST64(0x0000020002020202), CONST64(0x0000020202020202),
+ CONST64(0x0002000002020000), CONST64(0x0002000202020000), CONST64(0x0002000002020002), CONST64(0x0002000202020002),
+ CONST64(0x0002020002020000), CONST64(0x0002020202020000), CONST64(0x0002020002020002), CONST64(0x0002020202020002),
+ CONST64(0x0002000002020200), CONST64(0x0002000202020200), CONST64(0x0002000002020202), CONST64(0x0002000202020202),
+ CONST64(0x0002020002020200), CONST64(0x0002020202020200), CONST64(0x0002020002020202), CONST64(0x0002020202020202),
+ CONST64(0x0200000002000000), CONST64(0x0200000202000000), CONST64(0x0200000002000002), CONST64(0x0200000202000002),
+ CONST64(0x0200020002000000), CONST64(0x0200020202000000), CONST64(0x0200020002000002), CONST64(0x0200020202000002),
+ CONST64(0x0200000002000200), CONST64(0x0200000202000200), CONST64(0x0200000002000202), CONST64(0x0200000202000202),
+ CONST64(0x0200020002000200), CONST64(0x0200020202000200), CONST64(0x0200020002000202), CONST64(0x0200020202000202),
+ CONST64(0x0202000002000000), CONST64(0x0202000202000000), CONST64(0x0202000002000002), CONST64(0x0202000202000002),
+ CONST64(0x0202020002000000), CONST64(0x0202020202000000), CONST64(0x0202020002000002), CONST64(0x0202020202000002),
+ CONST64(0x0202000002000200), CONST64(0x0202000202000200), CONST64(0x0202000002000202), CONST64(0x0202000202000202),
+ CONST64(0x0202020002000200), CONST64(0x0202020202000200), CONST64(0x0202020002000202), CONST64(0x0202020202000202),
+ CONST64(0x0200000002020000), CONST64(0x0200000202020000), CONST64(0x0200000002020002), CONST64(0x0200000202020002),
+ CONST64(0x0200020002020000), CONST64(0x0200020202020000), CONST64(0x0200020002020002), CONST64(0x0200020202020002),
+ CONST64(0x0200000002020200), CONST64(0x0200000202020200), CONST64(0x0200000002020202), CONST64(0x0200000202020202),
+ CONST64(0x0200020002020200), CONST64(0x0200020202020200), CONST64(0x0200020002020202), CONST64(0x0200020202020202),
+ CONST64(0x0202000002020000), CONST64(0x0202000202020000), CONST64(0x0202000002020002), CONST64(0x0202000202020002),
+ CONST64(0x0202020002020000), CONST64(0x0202020202020000), CONST64(0x0202020002020002), CONST64(0x0202020202020002),
+ CONST64(0x0202000002020200), CONST64(0x0202000202020200), CONST64(0x0202000002020202), CONST64(0x0202000202020202),
+ CONST64(0x0202020002020200), CONST64(0x0202020202020200), CONST64(0x0202020002020202), CONST64(0x0202020202020202)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000010000000000), CONST64(0x0000000000000100), CONST64(0x0000010000000100),
+ CONST64(0x0001000000000000), CONST64(0x0001010000000000), CONST64(0x0001000000000100), CONST64(0x0001010000000100),
+ CONST64(0x0000000000010000), CONST64(0x0000010000010000), CONST64(0x0000000000010100), CONST64(0x0000010000010100),
+ CONST64(0x0001000000010000), CONST64(0x0001010000010000), CONST64(0x0001000000010100), CONST64(0x0001010000010100),
+ CONST64(0x0100000000000000), CONST64(0x0100010000000000), CONST64(0x0100000000000100), CONST64(0x0100010000000100),
+ CONST64(0x0101000000000000), CONST64(0x0101010000000000), CONST64(0x0101000000000100), CONST64(0x0101010000000100),
+ CONST64(0x0100000000010000), CONST64(0x0100010000010000), CONST64(0x0100000000010100), CONST64(0x0100010000010100),
+ CONST64(0x0101000000010000), CONST64(0x0101010000010000), CONST64(0x0101000000010100), CONST64(0x0101010000010100),
+ CONST64(0x0000000001000000), CONST64(0x0000010001000000), CONST64(0x0000000001000100), CONST64(0x0000010001000100),
+ CONST64(0x0001000001000000), CONST64(0x0001010001000000), CONST64(0x0001000001000100), CONST64(0x0001010001000100),
+ CONST64(0x0000000001010000), CONST64(0x0000010001010000), CONST64(0x0000000001010100), CONST64(0x0000010001010100),
+ CONST64(0x0001000001010000), CONST64(0x0001010001010000), CONST64(0x0001000001010100), CONST64(0x0001010001010100),
+ CONST64(0x0100000001000000), CONST64(0x0100010001000000), CONST64(0x0100000001000100), CONST64(0x0100010001000100),
+ CONST64(0x0101000001000000), CONST64(0x0101010001000000), CONST64(0x0101000001000100), CONST64(0x0101010001000100),
+ CONST64(0x0100000001010000), CONST64(0x0100010001010000), CONST64(0x0100000001010100), CONST64(0x0100010001010100),
+ CONST64(0x0101000001010000), CONST64(0x0101010001010000), CONST64(0x0101000001010100), CONST64(0x0101010001010100),
+ CONST64(0x0000000100000000), CONST64(0x0000010100000000), CONST64(0x0000000100000100), CONST64(0x0000010100000100),
+ CONST64(0x0001000100000000), CONST64(0x0001010100000000), CONST64(0x0001000100000100), CONST64(0x0001010100000100),
+ CONST64(0x0000000100010000), CONST64(0x0000010100010000), CONST64(0x0000000100010100), CONST64(0x0000010100010100),
+ CONST64(0x0001000100010000), CONST64(0x0001010100010000), CONST64(0x0001000100010100), CONST64(0x0001010100010100),
+ CONST64(0x0100000100000000), CONST64(0x0100010100000000), CONST64(0x0100000100000100), CONST64(0x0100010100000100),
+ CONST64(0x0101000100000000), CONST64(0x0101010100000000), CONST64(0x0101000100000100), CONST64(0x0101010100000100),
+ CONST64(0x0100000100010000), CONST64(0x0100010100010000), CONST64(0x0100000100010100), CONST64(0x0100010100010100),
+ CONST64(0x0101000100010000), CONST64(0x0101010100010000), CONST64(0x0101000100010100), CONST64(0x0101010100010100),
+ CONST64(0x0000000101000000), CONST64(0x0000010101000000), CONST64(0x0000000101000100), CONST64(0x0000010101000100),
+ CONST64(0x0001000101000000), CONST64(0x0001010101000000), CONST64(0x0001000101000100), CONST64(0x0001010101000100),
+ CONST64(0x0000000101010000), CONST64(0x0000010101010000), CONST64(0x0000000101010100), CONST64(0x0000010101010100),
+ CONST64(0x0001000101010000), CONST64(0x0001010101010000), CONST64(0x0001000101010100), CONST64(0x0001010101010100),
+ CONST64(0x0100000101000000), CONST64(0x0100010101000000), CONST64(0x0100000101000100), CONST64(0x0100010101000100),
+ CONST64(0x0101000101000000), CONST64(0x0101010101000000), CONST64(0x0101000101000100), CONST64(0x0101010101000100),
+ CONST64(0x0100000101010000), CONST64(0x0100010101010000), CONST64(0x0100000101010100), CONST64(0x0100010101010100),
+ CONST64(0x0101000101010000), CONST64(0x0101010101010000), CONST64(0x0101000101010100), CONST64(0x0101010101010100),
+ CONST64(0x0000000000000001), CONST64(0x0000010000000001), CONST64(0x0000000000000101), CONST64(0x0000010000000101),
+ CONST64(0x0001000000000001), CONST64(0x0001010000000001), CONST64(0x0001000000000101), CONST64(0x0001010000000101),
+ CONST64(0x0000000000010001), CONST64(0x0000010000010001), CONST64(0x0000000000010101), CONST64(0x0000010000010101),
+ CONST64(0x0001000000010001), CONST64(0x0001010000010001), CONST64(0x0001000000010101), CONST64(0x0001010000010101),
+ CONST64(0x0100000000000001), CONST64(0x0100010000000001), CONST64(0x0100000000000101), CONST64(0x0100010000000101),
+ CONST64(0x0101000000000001), CONST64(0x0101010000000001), CONST64(0x0101000000000101), CONST64(0x0101010000000101),
+ CONST64(0x0100000000010001), CONST64(0x0100010000010001), CONST64(0x0100000000010101), CONST64(0x0100010000010101),
+ CONST64(0x0101000000010001), CONST64(0x0101010000010001), CONST64(0x0101000000010101), CONST64(0x0101010000010101),
+ CONST64(0x0000000001000001), CONST64(0x0000010001000001), CONST64(0x0000000001000101), CONST64(0x0000010001000101),
+ CONST64(0x0001000001000001), CONST64(0x0001010001000001), CONST64(0x0001000001000101), CONST64(0x0001010001000101),
+ CONST64(0x0000000001010001), CONST64(0x0000010001010001), CONST64(0x0000000001010101), CONST64(0x0000010001010101),
+ CONST64(0x0001000001010001), CONST64(0x0001010001010001), CONST64(0x0001000001010101), CONST64(0x0001010001010101),
+ CONST64(0x0100000001000001), CONST64(0x0100010001000001), CONST64(0x0100000001000101), CONST64(0x0100010001000101),
+ CONST64(0x0101000001000001), CONST64(0x0101010001000001), CONST64(0x0101000001000101), CONST64(0x0101010001000101),
+ CONST64(0x0100000001010001), CONST64(0x0100010001010001), CONST64(0x0100000001010101), CONST64(0x0100010001010101),
+ CONST64(0x0101000001010001), CONST64(0x0101010001010001), CONST64(0x0101000001010101), CONST64(0x0101010001010101),
+ CONST64(0x0000000100000001), CONST64(0x0000010100000001), CONST64(0x0000000100000101), CONST64(0x0000010100000101),
+ CONST64(0x0001000100000001), CONST64(0x0001010100000001), CONST64(0x0001000100000101), CONST64(0x0001010100000101),
+ CONST64(0x0000000100010001), CONST64(0x0000010100010001), CONST64(0x0000000100010101), CONST64(0x0000010100010101),
+ CONST64(0x0001000100010001), CONST64(0x0001010100010001), CONST64(0x0001000100010101), CONST64(0x0001010100010101),
+ CONST64(0x0100000100000001), CONST64(0x0100010100000001), CONST64(0x0100000100000101), CONST64(0x0100010100000101),
+ CONST64(0x0101000100000001), CONST64(0x0101010100000001), CONST64(0x0101000100000101), CONST64(0x0101010100000101),
+ CONST64(0x0100000100010001), CONST64(0x0100010100010001), CONST64(0x0100000100010101), CONST64(0x0100010100010101),
+ CONST64(0x0101000100010001), CONST64(0x0101010100010001), CONST64(0x0101000100010101), CONST64(0x0101010100010101),
+ CONST64(0x0000000101000001), CONST64(0x0000010101000001), CONST64(0x0000000101000101), CONST64(0x0000010101000101),
+ CONST64(0x0001000101000001), CONST64(0x0001010101000001), CONST64(0x0001000101000101), CONST64(0x0001010101000101),
+ CONST64(0x0000000101010001), CONST64(0x0000010101010001), CONST64(0x0000000101010101), CONST64(0x0000010101010101),
+ CONST64(0x0001000101010001), CONST64(0x0001010101010001), CONST64(0x0001000101010101), CONST64(0x0001010101010101),
+ CONST64(0x0100000101000001), CONST64(0x0100010101000001), CONST64(0x0100000101000101), CONST64(0x0100010101000101),
+ CONST64(0x0101000101000001), CONST64(0x0101010101000001), CONST64(0x0101000101000101), CONST64(0x0101010101000101),
+ CONST64(0x0100000101010001), CONST64(0x0100010101010001), CONST64(0x0100000101010101), CONST64(0x0100010101010101),
+ CONST64(0x0101000101010001), CONST64(0x0101010101010001), CONST64(0x0101000101010101), CONST64(0x0101010101010101)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000000000080), CONST64(0x0000008000000080),
+ CONST64(0x0000800000000000), CONST64(0x0000808000000000), CONST64(0x0000800000000080), CONST64(0x0000808000000080),
+ CONST64(0x0000000000008000), CONST64(0x0000008000008000), CONST64(0x0000000000008080), CONST64(0x0000008000008080),
+ CONST64(0x0000800000008000), CONST64(0x0000808000008000), CONST64(0x0000800000008080), CONST64(0x0000808000008080),
+ CONST64(0x0080000000000000), CONST64(0x0080008000000000), CONST64(0x0080000000000080), CONST64(0x0080008000000080),
+ CONST64(0x0080800000000000), CONST64(0x0080808000000000), CONST64(0x0080800000000080), CONST64(0x0080808000000080),
+ CONST64(0x0080000000008000), CONST64(0x0080008000008000), CONST64(0x0080000000008080), CONST64(0x0080008000008080),
+ CONST64(0x0080800000008000), CONST64(0x0080808000008000), CONST64(0x0080800000008080), CONST64(0x0080808000008080),
+ CONST64(0x0000000000800000), CONST64(0x0000008000800000), CONST64(0x0000000000800080), CONST64(0x0000008000800080),
+ CONST64(0x0000800000800000), CONST64(0x0000808000800000), CONST64(0x0000800000800080), CONST64(0x0000808000800080),
+ CONST64(0x0000000000808000), CONST64(0x0000008000808000), CONST64(0x0000000000808080), CONST64(0x0000008000808080),
+ CONST64(0x0000800000808000), CONST64(0x0000808000808000), CONST64(0x0000800000808080), CONST64(0x0000808000808080),
+ CONST64(0x0080000000800000), CONST64(0x0080008000800000), CONST64(0x0080000000800080), CONST64(0x0080008000800080),
+ CONST64(0x0080800000800000), CONST64(0x0080808000800000), CONST64(0x0080800000800080), CONST64(0x0080808000800080),
+ CONST64(0x0080000000808000), CONST64(0x0080008000808000), CONST64(0x0080000000808080), CONST64(0x0080008000808080),
+ CONST64(0x0080800000808000), CONST64(0x0080808000808000), CONST64(0x0080800000808080), CONST64(0x0080808000808080),
+ CONST64(0x8000000000000000), CONST64(0x8000008000000000), CONST64(0x8000000000000080), CONST64(0x8000008000000080),
+ CONST64(0x8000800000000000), CONST64(0x8000808000000000), CONST64(0x8000800000000080), CONST64(0x8000808000000080),
+ CONST64(0x8000000000008000), CONST64(0x8000008000008000), CONST64(0x8000000000008080), CONST64(0x8000008000008080),
+ CONST64(0x8000800000008000), CONST64(0x8000808000008000), CONST64(0x8000800000008080), CONST64(0x8000808000008080),
+ CONST64(0x8080000000000000), CONST64(0x8080008000000000), CONST64(0x8080000000000080), CONST64(0x8080008000000080),
+ CONST64(0x8080800000000000), CONST64(0x8080808000000000), CONST64(0x8080800000000080), CONST64(0x8080808000000080),
+ CONST64(0x8080000000008000), CONST64(0x8080008000008000), CONST64(0x8080000000008080), CONST64(0x8080008000008080),
+ CONST64(0x8080800000008000), CONST64(0x8080808000008000), CONST64(0x8080800000008080), CONST64(0x8080808000008080),
+ CONST64(0x8000000000800000), CONST64(0x8000008000800000), CONST64(0x8000000000800080), CONST64(0x8000008000800080),
+ CONST64(0x8000800000800000), CONST64(0x8000808000800000), CONST64(0x8000800000800080), CONST64(0x8000808000800080),
+ CONST64(0x8000000000808000), CONST64(0x8000008000808000), CONST64(0x8000000000808080), CONST64(0x8000008000808080),
+ CONST64(0x8000800000808000), CONST64(0x8000808000808000), CONST64(0x8000800000808080), CONST64(0x8000808000808080),
+ CONST64(0x8080000000800000), CONST64(0x8080008000800000), CONST64(0x8080000000800080), CONST64(0x8080008000800080),
+ CONST64(0x8080800000800000), CONST64(0x8080808000800000), CONST64(0x8080800000800080), CONST64(0x8080808000800080),
+ CONST64(0x8080000000808000), CONST64(0x8080008000808000), CONST64(0x8080000000808080), CONST64(0x8080008000808080),
+ CONST64(0x8080800000808000), CONST64(0x8080808000808000), CONST64(0x8080800000808080), CONST64(0x8080808000808080),
+ CONST64(0x0000000080000000), CONST64(0x0000008080000000), CONST64(0x0000000080000080), CONST64(0x0000008080000080),
+ CONST64(0x0000800080000000), CONST64(0x0000808080000000), CONST64(0x0000800080000080), CONST64(0x0000808080000080),
+ CONST64(0x0000000080008000), CONST64(0x0000008080008000), CONST64(0x0000000080008080), CONST64(0x0000008080008080),
+ CONST64(0x0000800080008000), CONST64(0x0000808080008000), CONST64(0x0000800080008080), CONST64(0x0000808080008080),
+ CONST64(0x0080000080000000), CONST64(0x0080008080000000), CONST64(0x0080000080000080), CONST64(0x0080008080000080),
+ CONST64(0x0080800080000000), CONST64(0x0080808080000000), CONST64(0x0080800080000080), CONST64(0x0080808080000080),
+ CONST64(0x0080000080008000), CONST64(0x0080008080008000), CONST64(0x0080000080008080), CONST64(0x0080008080008080),
+ CONST64(0x0080800080008000), CONST64(0x0080808080008000), CONST64(0x0080800080008080), CONST64(0x0080808080008080),
+ CONST64(0x0000000080800000), CONST64(0x0000008080800000), CONST64(0x0000000080800080), CONST64(0x0000008080800080),
+ CONST64(0x0000800080800000), CONST64(0x0000808080800000), CONST64(0x0000800080800080), CONST64(0x0000808080800080),
+ CONST64(0x0000000080808000), CONST64(0x0000008080808000), CONST64(0x0000000080808080), CONST64(0x0000008080808080),
+ CONST64(0x0000800080808000), CONST64(0x0000808080808000), CONST64(0x0000800080808080), CONST64(0x0000808080808080),
+ CONST64(0x0080000080800000), CONST64(0x0080008080800000), CONST64(0x0080000080800080), CONST64(0x0080008080800080),
+ CONST64(0x0080800080800000), CONST64(0x0080808080800000), CONST64(0x0080800080800080), CONST64(0x0080808080800080),
+ CONST64(0x0080000080808000), CONST64(0x0080008080808000), CONST64(0x0080000080808080), CONST64(0x0080008080808080),
+ CONST64(0x0080800080808000), CONST64(0x0080808080808000), CONST64(0x0080800080808080), CONST64(0x0080808080808080),
+ CONST64(0x8000000080000000), CONST64(0x8000008080000000), CONST64(0x8000000080000080), CONST64(0x8000008080000080),
+ CONST64(0x8000800080000000), CONST64(0x8000808080000000), CONST64(0x8000800080000080), CONST64(0x8000808080000080),
+ CONST64(0x8000000080008000), CONST64(0x8000008080008000), CONST64(0x8000000080008080), CONST64(0x8000008080008080),
+ CONST64(0x8000800080008000), CONST64(0x8000808080008000), CONST64(0x8000800080008080), CONST64(0x8000808080008080),
+ CONST64(0x8080000080000000), CONST64(0x8080008080000000), CONST64(0x8080000080000080), CONST64(0x8080008080000080),
+ CONST64(0x8080800080000000), CONST64(0x8080808080000000), CONST64(0x8080800080000080), CONST64(0x8080808080000080),
+ CONST64(0x8080000080008000), CONST64(0x8080008080008000), CONST64(0x8080000080008080), CONST64(0x8080008080008080),
+ CONST64(0x8080800080008000), CONST64(0x8080808080008000), CONST64(0x8080800080008080), CONST64(0x8080808080008080),
+ CONST64(0x8000000080800000), CONST64(0x8000008080800000), CONST64(0x8000000080800080), CONST64(0x8000008080800080),
+ CONST64(0x8000800080800000), CONST64(0x8000808080800000), CONST64(0x8000800080800080), CONST64(0x8000808080800080),
+ CONST64(0x8000000080808000), CONST64(0x8000008080808000), CONST64(0x8000000080808080), CONST64(0x8000008080808080),
+ CONST64(0x8000800080808000), CONST64(0x8000808080808000), CONST64(0x8000800080808080), CONST64(0x8000808080808080),
+ CONST64(0x8080000080800000), CONST64(0x8080008080800000), CONST64(0x8080000080800080), CONST64(0x8080008080800080),
+ CONST64(0x8080800080800000), CONST64(0x8080808080800000), CONST64(0x8080800080800080), CONST64(0x8080808080800080),
+ CONST64(0x8080000080808000), CONST64(0x8080008080808000), CONST64(0x8080000080808080), CONST64(0x8080008080808080),
+ CONST64(0x8080800080808000), CONST64(0x8080808080808000), CONST64(0x8080800080808080), CONST64(0x8080808080808080)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000000000040), CONST64(0x0000004000000040),
+ CONST64(0x0000400000000000), CONST64(0x0000404000000000), CONST64(0x0000400000000040), CONST64(0x0000404000000040),
+ CONST64(0x0000000000004000), CONST64(0x0000004000004000), CONST64(0x0000000000004040), CONST64(0x0000004000004040),
+ CONST64(0x0000400000004000), CONST64(0x0000404000004000), CONST64(0x0000400000004040), CONST64(0x0000404000004040),
+ CONST64(0x0040000000000000), CONST64(0x0040004000000000), CONST64(0x0040000000000040), CONST64(0x0040004000000040),
+ CONST64(0x0040400000000000), CONST64(0x0040404000000000), CONST64(0x0040400000000040), CONST64(0x0040404000000040),
+ CONST64(0x0040000000004000), CONST64(0x0040004000004000), CONST64(0x0040000000004040), CONST64(0x0040004000004040),
+ CONST64(0x0040400000004000), CONST64(0x0040404000004000), CONST64(0x0040400000004040), CONST64(0x0040404000004040),
+ CONST64(0x0000000000400000), CONST64(0x0000004000400000), CONST64(0x0000000000400040), CONST64(0x0000004000400040),
+ CONST64(0x0000400000400000), CONST64(0x0000404000400000), CONST64(0x0000400000400040), CONST64(0x0000404000400040),
+ CONST64(0x0000000000404000), CONST64(0x0000004000404000), CONST64(0x0000000000404040), CONST64(0x0000004000404040),
+ CONST64(0x0000400000404000), CONST64(0x0000404000404000), CONST64(0x0000400000404040), CONST64(0x0000404000404040),
+ CONST64(0x0040000000400000), CONST64(0x0040004000400000), CONST64(0x0040000000400040), CONST64(0x0040004000400040),
+ CONST64(0x0040400000400000), CONST64(0x0040404000400000), CONST64(0x0040400000400040), CONST64(0x0040404000400040),
+ CONST64(0x0040000000404000), CONST64(0x0040004000404000), CONST64(0x0040000000404040), CONST64(0x0040004000404040),
+ CONST64(0x0040400000404000), CONST64(0x0040404000404000), CONST64(0x0040400000404040), CONST64(0x0040404000404040),
+ CONST64(0x4000000000000000), CONST64(0x4000004000000000), CONST64(0x4000000000000040), CONST64(0x4000004000000040),
+ CONST64(0x4000400000000000), CONST64(0x4000404000000000), CONST64(0x4000400000000040), CONST64(0x4000404000000040),
+ CONST64(0x4000000000004000), CONST64(0x4000004000004000), CONST64(0x4000000000004040), CONST64(0x4000004000004040),
+ CONST64(0x4000400000004000), CONST64(0x4000404000004000), CONST64(0x4000400000004040), CONST64(0x4000404000004040),
+ CONST64(0x4040000000000000), CONST64(0x4040004000000000), CONST64(0x4040000000000040), CONST64(0x4040004000000040),
+ CONST64(0x4040400000000000), CONST64(0x4040404000000000), CONST64(0x4040400000000040), CONST64(0x4040404000000040),
+ CONST64(0x4040000000004000), CONST64(0x4040004000004000), CONST64(0x4040000000004040), CONST64(0x4040004000004040),
+ CONST64(0x4040400000004000), CONST64(0x4040404000004000), CONST64(0x4040400000004040), CONST64(0x4040404000004040),
+ CONST64(0x4000000000400000), CONST64(0x4000004000400000), CONST64(0x4000000000400040), CONST64(0x4000004000400040),
+ CONST64(0x4000400000400000), CONST64(0x4000404000400000), CONST64(0x4000400000400040), CONST64(0x4000404000400040),
+ CONST64(0x4000000000404000), CONST64(0x4000004000404000), CONST64(0x4000000000404040), CONST64(0x4000004000404040),
+ CONST64(0x4000400000404000), CONST64(0x4000404000404000), CONST64(0x4000400000404040), CONST64(0x4000404000404040),
+ CONST64(0x4040000000400000), CONST64(0x4040004000400000), CONST64(0x4040000000400040), CONST64(0x4040004000400040),
+ CONST64(0x4040400000400000), CONST64(0x4040404000400000), CONST64(0x4040400000400040), CONST64(0x4040404000400040),
+ CONST64(0x4040000000404000), CONST64(0x4040004000404000), CONST64(0x4040000000404040), CONST64(0x4040004000404040),
+ CONST64(0x4040400000404000), CONST64(0x4040404000404000), CONST64(0x4040400000404040), CONST64(0x4040404000404040),
+ CONST64(0x0000000040000000), CONST64(0x0000004040000000), CONST64(0x0000000040000040), CONST64(0x0000004040000040),
+ CONST64(0x0000400040000000), CONST64(0x0000404040000000), CONST64(0x0000400040000040), CONST64(0x0000404040000040),
+ CONST64(0x0000000040004000), CONST64(0x0000004040004000), CONST64(0x0000000040004040), CONST64(0x0000004040004040),
+ CONST64(0x0000400040004000), CONST64(0x0000404040004000), CONST64(0x0000400040004040), CONST64(0x0000404040004040),
+ CONST64(0x0040000040000000), CONST64(0x0040004040000000), CONST64(0x0040000040000040), CONST64(0x0040004040000040),
+ CONST64(0x0040400040000000), CONST64(0x0040404040000000), CONST64(0x0040400040000040), CONST64(0x0040404040000040),
+ CONST64(0x0040000040004000), CONST64(0x0040004040004000), CONST64(0x0040000040004040), CONST64(0x0040004040004040),
+ CONST64(0x0040400040004000), CONST64(0x0040404040004000), CONST64(0x0040400040004040), CONST64(0x0040404040004040),
+ CONST64(0x0000000040400000), CONST64(0x0000004040400000), CONST64(0x0000000040400040), CONST64(0x0000004040400040),
+ CONST64(0x0000400040400000), CONST64(0x0000404040400000), CONST64(0x0000400040400040), CONST64(0x0000404040400040),
+ CONST64(0x0000000040404000), CONST64(0x0000004040404000), CONST64(0x0000000040404040), CONST64(0x0000004040404040),
+ CONST64(0x0000400040404000), CONST64(0x0000404040404000), CONST64(0x0000400040404040), CONST64(0x0000404040404040),
+ CONST64(0x0040000040400000), CONST64(0x0040004040400000), CONST64(0x0040000040400040), CONST64(0x0040004040400040),
+ CONST64(0x0040400040400000), CONST64(0x0040404040400000), CONST64(0x0040400040400040), CONST64(0x0040404040400040),
+ CONST64(0x0040000040404000), CONST64(0x0040004040404000), CONST64(0x0040000040404040), CONST64(0x0040004040404040),
+ CONST64(0x0040400040404000), CONST64(0x0040404040404000), CONST64(0x0040400040404040), CONST64(0x0040404040404040),
+ CONST64(0x4000000040000000), CONST64(0x4000004040000000), CONST64(0x4000000040000040), CONST64(0x4000004040000040),
+ CONST64(0x4000400040000000), CONST64(0x4000404040000000), CONST64(0x4000400040000040), CONST64(0x4000404040000040),
+ CONST64(0x4000000040004000), CONST64(0x4000004040004000), CONST64(0x4000000040004040), CONST64(0x4000004040004040),
+ CONST64(0x4000400040004000), CONST64(0x4000404040004000), CONST64(0x4000400040004040), CONST64(0x4000404040004040),
+ CONST64(0x4040000040000000), CONST64(0x4040004040000000), CONST64(0x4040000040000040), CONST64(0x4040004040000040),
+ CONST64(0x4040400040000000), CONST64(0x4040404040000000), CONST64(0x4040400040000040), CONST64(0x4040404040000040),
+ CONST64(0x4040000040004000), CONST64(0x4040004040004000), CONST64(0x4040000040004040), CONST64(0x4040004040004040),
+ CONST64(0x4040400040004000), CONST64(0x4040404040004000), CONST64(0x4040400040004040), CONST64(0x4040404040004040),
+ CONST64(0x4000000040400000), CONST64(0x4000004040400000), CONST64(0x4000000040400040), CONST64(0x4000004040400040),
+ CONST64(0x4000400040400000), CONST64(0x4000404040400000), CONST64(0x4000400040400040), CONST64(0x4000404040400040),
+ CONST64(0x4000000040404000), CONST64(0x4000004040404000), CONST64(0x4000000040404040), CONST64(0x4000004040404040),
+ CONST64(0x4000400040404000), CONST64(0x4000404040404000), CONST64(0x4000400040404040), CONST64(0x4000404040404040),
+ CONST64(0x4040000040400000), CONST64(0x4040004040400000), CONST64(0x4040000040400040), CONST64(0x4040004040400040),
+ CONST64(0x4040400040400000), CONST64(0x4040404040400000), CONST64(0x4040400040400040), CONST64(0x4040404040400040),
+ CONST64(0x4040000040404000), CONST64(0x4040004040404000), CONST64(0x4040000040404040), CONST64(0x4040004040404040),
+ CONST64(0x4040400040404000), CONST64(0x4040404040404000), CONST64(0x4040400040404040), CONST64(0x4040404040404040)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000000000020), CONST64(0x0000002000000020),
+ CONST64(0x0000200000000000), CONST64(0x0000202000000000), CONST64(0x0000200000000020), CONST64(0x0000202000000020),
+ CONST64(0x0000000000002000), CONST64(0x0000002000002000), CONST64(0x0000000000002020), CONST64(0x0000002000002020),
+ CONST64(0x0000200000002000), CONST64(0x0000202000002000), CONST64(0x0000200000002020), CONST64(0x0000202000002020),
+ CONST64(0x0020000000000000), CONST64(0x0020002000000000), CONST64(0x0020000000000020), CONST64(0x0020002000000020),
+ CONST64(0x0020200000000000), CONST64(0x0020202000000000), CONST64(0x0020200000000020), CONST64(0x0020202000000020),
+ CONST64(0x0020000000002000), CONST64(0x0020002000002000), CONST64(0x0020000000002020), CONST64(0x0020002000002020),
+ CONST64(0x0020200000002000), CONST64(0x0020202000002000), CONST64(0x0020200000002020), CONST64(0x0020202000002020),
+ CONST64(0x0000000000200000), CONST64(0x0000002000200000), CONST64(0x0000000000200020), CONST64(0x0000002000200020),
+ CONST64(0x0000200000200000), CONST64(0x0000202000200000), CONST64(0x0000200000200020), CONST64(0x0000202000200020),
+ CONST64(0x0000000000202000), CONST64(0x0000002000202000), CONST64(0x0000000000202020), CONST64(0x0000002000202020),
+ CONST64(0x0000200000202000), CONST64(0x0000202000202000), CONST64(0x0000200000202020), CONST64(0x0000202000202020),
+ CONST64(0x0020000000200000), CONST64(0x0020002000200000), CONST64(0x0020000000200020), CONST64(0x0020002000200020),
+ CONST64(0x0020200000200000), CONST64(0x0020202000200000), CONST64(0x0020200000200020), CONST64(0x0020202000200020),
+ CONST64(0x0020000000202000), CONST64(0x0020002000202000), CONST64(0x0020000000202020), CONST64(0x0020002000202020),
+ CONST64(0x0020200000202000), CONST64(0x0020202000202000), CONST64(0x0020200000202020), CONST64(0x0020202000202020),
+ CONST64(0x2000000000000000), CONST64(0x2000002000000000), CONST64(0x2000000000000020), CONST64(0x2000002000000020),
+ CONST64(0x2000200000000000), CONST64(0x2000202000000000), CONST64(0x2000200000000020), CONST64(0x2000202000000020),
+ CONST64(0x2000000000002000), CONST64(0x2000002000002000), CONST64(0x2000000000002020), CONST64(0x2000002000002020),
+ CONST64(0x2000200000002000), CONST64(0x2000202000002000), CONST64(0x2000200000002020), CONST64(0x2000202000002020),
+ CONST64(0x2020000000000000), CONST64(0x2020002000000000), CONST64(0x2020000000000020), CONST64(0x2020002000000020),
+ CONST64(0x2020200000000000), CONST64(0x2020202000000000), CONST64(0x2020200000000020), CONST64(0x2020202000000020),
+ CONST64(0x2020000000002000), CONST64(0x2020002000002000), CONST64(0x2020000000002020), CONST64(0x2020002000002020),
+ CONST64(0x2020200000002000), CONST64(0x2020202000002000), CONST64(0x2020200000002020), CONST64(0x2020202000002020),
+ CONST64(0x2000000000200000), CONST64(0x2000002000200000), CONST64(0x2000000000200020), CONST64(0x2000002000200020),
+ CONST64(0x2000200000200000), CONST64(0x2000202000200000), CONST64(0x2000200000200020), CONST64(0x2000202000200020),
+ CONST64(0x2000000000202000), CONST64(0x2000002000202000), CONST64(0x2000000000202020), CONST64(0x2000002000202020),
+ CONST64(0x2000200000202000), CONST64(0x2000202000202000), CONST64(0x2000200000202020), CONST64(0x2000202000202020),
+ CONST64(0x2020000000200000), CONST64(0x2020002000200000), CONST64(0x2020000000200020), CONST64(0x2020002000200020),
+ CONST64(0x2020200000200000), CONST64(0x2020202000200000), CONST64(0x2020200000200020), CONST64(0x2020202000200020),
+ CONST64(0x2020000000202000), CONST64(0x2020002000202000), CONST64(0x2020000000202020), CONST64(0x2020002000202020),
+ CONST64(0x2020200000202000), CONST64(0x2020202000202000), CONST64(0x2020200000202020), CONST64(0x2020202000202020),
+ CONST64(0x0000000020000000), CONST64(0x0000002020000000), CONST64(0x0000000020000020), CONST64(0x0000002020000020),
+ CONST64(0x0000200020000000), CONST64(0x0000202020000000), CONST64(0x0000200020000020), CONST64(0x0000202020000020),
+ CONST64(0x0000000020002000), CONST64(0x0000002020002000), CONST64(0x0000000020002020), CONST64(0x0000002020002020),
+ CONST64(0x0000200020002000), CONST64(0x0000202020002000), CONST64(0x0000200020002020), CONST64(0x0000202020002020),
+ CONST64(0x0020000020000000), CONST64(0x0020002020000000), CONST64(0x0020000020000020), CONST64(0x0020002020000020),
+ CONST64(0x0020200020000000), CONST64(0x0020202020000000), CONST64(0x0020200020000020), CONST64(0x0020202020000020),
+ CONST64(0x0020000020002000), CONST64(0x0020002020002000), CONST64(0x0020000020002020), CONST64(0x0020002020002020),
+ CONST64(0x0020200020002000), CONST64(0x0020202020002000), CONST64(0x0020200020002020), CONST64(0x0020202020002020),
+ CONST64(0x0000000020200000), CONST64(0x0000002020200000), CONST64(0x0000000020200020), CONST64(0x0000002020200020),
+ CONST64(0x0000200020200000), CONST64(0x0000202020200000), CONST64(0x0000200020200020), CONST64(0x0000202020200020),
+ CONST64(0x0000000020202000), CONST64(0x0000002020202000), CONST64(0x0000000020202020), CONST64(0x0000002020202020),
+ CONST64(0x0000200020202000), CONST64(0x0000202020202000), CONST64(0x0000200020202020), CONST64(0x0000202020202020),
+ CONST64(0x0020000020200000), CONST64(0x0020002020200000), CONST64(0x0020000020200020), CONST64(0x0020002020200020),
+ CONST64(0x0020200020200000), CONST64(0x0020202020200000), CONST64(0x0020200020200020), CONST64(0x0020202020200020),
+ CONST64(0x0020000020202000), CONST64(0x0020002020202000), CONST64(0x0020000020202020), CONST64(0x0020002020202020),
+ CONST64(0x0020200020202000), CONST64(0x0020202020202000), CONST64(0x0020200020202020), CONST64(0x0020202020202020),
+ CONST64(0x2000000020000000), CONST64(0x2000002020000000), CONST64(0x2000000020000020), CONST64(0x2000002020000020),
+ CONST64(0x2000200020000000), CONST64(0x2000202020000000), CONST64(0x2000200020000020), CONST64(0x2000202020000020),
+ CONST64(0x2000000020002000), CONST64(0x2000002020002000), CONST64(0x2000000020002020), CONST64(0x2000002020002020),
+ CONST64(0x2000200020002000), CONST64(0x2000202020002000), CONST64(0x2000200020002020), CONST64(0x2000202020002020),
+ CONST64(0x2020000020000000), CONST64(0x2020002020000000), CONST64(0x2020000020000020), CONST64(0x2020002020000020),
+ CONST64(0x2020200020000000), CONST64(0x2020202020000000), CONST64(0x2020200020000020), CONST64(0x2020202020000020),
+ CONST64(0x2020000020002000), CONST64(0x2020002020002000), CONST64(0x2020000020002020), CONST64(0x2020002020002020),
+ CONST64(0x2020200020002000), CONST64(0x2020202020002000), CONST64(0x2020200020002020), CONST64(0x2020202020002020),
+ CONST64(0x2000000020200000), CONST64(0x2000002020200000), CONST64(0x2000000020200020), CONST64(0x2000002020200020),
+ CONST64(0x2000200020200000), CONST64(0x2000202020200000), CONST64(0x2000200020200020), CONST64(0x2000202020200020),
+ CONST64(0x2000000020202000), CONST64(0x2000002020202000), CONST64(0x2000000020202020), CONST64(0x2000002020202020),
+ CONST64(0x2000200020202000), CONST64(0x2000202020202000), CONST64(0x2000200020202020), CONST64(0x2000202020202020),
+ CONST64(0x2020000020200000), CONST64(0x2020002020200000), CONST64(0x2020000020200020), CONST64(0x2020002020200020),
+ CONST64(0x2020200020200000), CONST64(0x2020202020200000), CONST64(0x2020200020200020), CONST64(0x2020202020200020),
+ CONST64(0x2020000020202000), CONST64(0x2020002020202000), CONST64(0x2020000020202020), CONST64(0x2020002020202020),
+ CONST64(0x2020200020202000), CONST64(0x2020202020202000), CONST64(0x2020200020202020), CONST64(0x2020202020202020)
+ }};
+
+static const ulong64 des_fp[8][256] = {
+
+{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000002000000), CONST64(0x0000008002000000),
+ CONST64(0x0000000000020000), CONST64(0x0000008000020000), CONST64(0x0000000002020000), CONST64(0x0000008002020000),
+ CONST64(0x0000000000000200), CONST64(0x0000008000000200), CONST64(0x0000000002000200), CONST64(0x0000008002000200),
+ CONST64(0x0000000000020200), CONST64(0x0000008000020200), CONST64(0x0000000002020200), CONST64(0x0000008002020200),
+ CONST64(0x0000000000000002), CONST64(0x0000008000000002), CONST64(0x0000000002000002), CONST64(0x0000008002000002),
+ CONST64(0x0000000000020002), CONST64(0x0000008000020002), CONST64(0x0000000002020002), CONST64(0x0000008002020002),
+ CONST64(0x0000000000000202), CONST64(0x0000008000000202), CONST64(0x0000000002000202), CONST64(0x0000008002000202),
+ CONST64(0x0000000000020202), CONST64(0x0000008000020202), CONST64(0x0000000002020202), CONST64(0x0000008002020202),
+ CONST64(0x0200000000000000), CONST64(0x0200008000000000), CONST64(0x0200000002000000), CONST64(0x0200008002000000),
+ CONST64(0x0200000000020000), CONST64(0x0200008000020000), CONST64(0x0200000002020000), CONST64(0x0200008002020000),
+ CONST64(0x0200000000000200), CONST64(0x0200008000000200), CONST64(0x0200000002000200), CONST64(0x0200008002000200),
+ CONST64(0x0200000000020200), CONST64(0x0200008000020200), CONST64(0x0200000002020200), CONST64(0x0200008002020200),
+ CONST64(0x0200000000000002), CONST64(0x0200008000000002), CONST64(0x0200000002000002), CONST64(0x0200008002000002),
+ CONST64(0x0200000000020002), CONST64(0x0200008000020002), CONST64(0x0200000002020002), CONST64(0x0200008002020002),
+ CONST64(0x0200000000000202), CONST64(0x0200008000000202), CONST64(0x0200000002000202), CONST64(0x0200008002000202),
+ CONST64(0x0200000000020202), CONST64(0x0200008000020202), CONST64(0x0200000002020202), CONST64(0x0200008002020202),
+ CONST64(0x0002000000000000), CONST64(0x0002008000000000), CONST64(0x0002000002000000), CONST64(0x0002008002000000),
+ CONST64(0x0002000000020000), CONST64(0x0002008000020000), CONST64(0x0002000002020000), CONST64(0x0002008002020000),
+ CONST64(0x0002000000000200), CONST64(0x0002008000000200), CONST64(0x0002000002000200), CONST64(0x0002008002000200),
+ CONST64(0x0002000000020200), CONST64(0x0002008000020200), CONST64(0x0002000002020200), CONST64(0x0002008002020200),
+ CONST64(0x0002000000000002), CONST64(0x0002008000000002), CONST64(0x0002000002000002), CONST64(0x0002008002000002),
+ CONST64(0x0002000000020002), CONST64(0x0002008000020002), CONST64(0x0002000002020002), CONST64(0x0002008002020002),
+ CONST64(0x0002000000000202), CONST64(0x0002008000000202), CONST64(0x0002000002000202), CONST64(0x0002008002000202),
+ CONST64(0x0002000000020202), CONST64(0x0002008000020202), CONST64(0x0002000002020202), CONST64(0x0002008002020202),
+ CONST64(0x0202000000000000), CONST64(0x0202008000000000), CONST64(0x0202000002000000), CONST64(0x0202008002000000),
+ CONST64(0x0202000000020000), CONST64(0x0202008000020000), CONST64(0x0202000002020000), CONST64(0x0202008002020000),
+ CONST64(0x0202000000000200), CONST64(0x0202008000000200), CONST64(0x0202000002000200), CONST64(0x0202008002000200),
+ CONST64(0x0202000000020200), CONST64(0x0202008000020200), CONST64(0x0202000002020200), CONST64(0x0202008002020200),
+ CONST64(0x0202000000000002), CONST64(0x0202008000000002), CONST64(0x0202000002000002), CONST64(0x0202008002000002),
+ CONST64(0x0202000000020002), CONST64(0x0202008000020002), CONST64(0x0202000002020002), CONST64(0x0202008002020002),
+ CONST64(0x0202000000000202), CONST64(0x0202008000000202), CONST64(0x0202000002000202), CONST64(0x0202008002000202),
+ CONST64(0x0202000000020202), CONST64(0x0202008000020202), CONST64(0x0202000002020202), CONST64(0x0202008002020202),
+ CONST64(0x0000020000000000), CONST64(0x0000028000000000), CONST64(0x0000020002000000), CONST64(0x0000028002000000),
+ CONST64(0x0000020000020000), CONST64(0x0000028000020000), CONST64(0x0000020002020000), CONST64(0x0000028002020000),
+ CONST64(0x0000020000000200), CONST64(0x0000028000000200), CONST64(0x0000020002000200), CONST64(0x0000028002000200),
+ CONST64(0x0000020000020200), CONST64(0x0000028000020200), CONST64(0x0000020002020200), CONST64(0x0000028002020200),
+ CONST64(0x0000020000000002), CONST64(0x0000028000000002), CONST64(0x0000020002000002), CONST64(0x0000028002000002),
+ CONST64(0x0000020000020002), CONST64(0x0000028000020002), CONST64(0x0000020002020002), CONST64(0x0000028002020002),
+ CONST64(0x0000020000000202), CONST64(0x0000028000000202), CONST64(0x0000020002000202), CONST64(0x0000028002000202),
+ CONST64(0x0000020000020202), CONST64(0x0000028000020202), CONST64(0x0000020002020202), CONST64(0x0000028002020202),
+ CONST64(0x0200020000000000), CONST64(0x0200028000000000), CONST64(0x0200020002000000), CONST64(0x0200028002000000),
+ CONST64(0x0200020000020000), CONST64(0x0200028000020000), CONST64(0x0200020002020000), CONST64(0x0200028002020000),
+ CONST64(0x0200020000000200), CONST64(0x0200028000000200), CONST64(0x0200020002000200), CONST64(0x0200028002000200),
+ CONST64(0x0200020000020200), CONST64(0x0200028000020200), CONST64(0x0200020002020200), CONST64(0x0200028002020200),
+ CONST64(0x0200020000000002), CONST64(0x0200028000000002), CONST64(0x0200020002000002), CONST64(0x0200028002000002),
+ CONST64(0x0200020000020002), CONST64(0x0200028000020002), CONST64(0x0200020002020002), CONST64(0x0200028002020002),
+ CONST64(0x0200020000000202), CONST64(0x0200028000000202), CONST64(0x0200020002000202), CONST64(0x0200028002000202),
+ CONST64(0x0200020000020202), CONST64(0x0200028000020202), CONST64(0x0200020002020202), CONST64(0x0200028002020202),
+ CONST64(0x0002020000000000), CONST64(0x0002028000000000), CONST64(0x0002020002000000), CONST64(0x0002028002000000),
+ CONST64(0x0002020000020000), CONST64(0x0002028000020000), CONST64(0x0002020002020000), CONST64(0x0002028002020000),
+ CONST64(0x0002020000000200), CONST64(0x0002028000000200), CONST64(0x0002020002000200), CONST64(0x0002028002000200),
+ CONST64(0x0002020000020200), CONST64(0x0002028000020200), CONST64(0x0002020002020200), CONST64(0x0002028002020200),
+ CONST64(0x0002020000000002), CONST64(0x0002028000000002), CONST64(0x0002020002000002), CONST64(0x0002028002000002),
+ CONST64(0x0002020000020002), CONST64(0x0002028000020002), CONST64(0x0002020002020002), CONST64(0x0002028002020002),
+ CONST64(0x0002020000000202), CONST64(0x0002028000000202), CONST64(0x0002020002000202), CONST64(0x0002028002000202),
+ CONST64(0x0002020000020202), CONST64(0x0002028000020202), CONST64(0x0002020002020202), CONST64(0x0002028002020202),
+ CONST64(0x0202020000000000), CONST64(0x0202028000000000), CONST64(0x0202020002000000), CONST64(0x0202028002000000),
+ CONST64(0x0202020000020000), CONST64(0x0202028000020000), CONST64(0x0202020002020000), CONST64(0x0202028002020000),
+ CONST64(0x0202020000000200), CONST64(0x0202028000000200), CONST64(0x0202020002000200), CONST64(0x0202028002000200),
+ CONST64(0x0202020000020200), CONST64(0x0202028000020200), CONST64(0x0202020002020200), CONST64(0x0202028002020200),
+ CONST64(0x0202020000000002), CONST64(0x0202028000000002), CONST64(0x0202020002000002), CONST64(0x0202028002000002),
+ CONST64(0x0202020000020002), CONST64(0x0202028000020002), CONST64(0x0202020002020002), CONST64(0x0202028002020002),
+ CONST64(0x0202020000000202), CONST64(0x0202028000000202), CONST64(0x0202020002000202), CONST64(0x0202028002000202),
+ CONST64(0x0202020000020202), CONST64(0x0202028000020202), CONST64(0x0202020002020202), CONST64(0x0202028002020202)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000008000000), CONST64(0x0000000208000000),
+ CONST64(0x0000000000080000), CONST64(0x0000000200080000), CONST64(0x0000000008080000), CONST64(0x0000000208080000),
+ CONST64(0x0000000000000800), CONST64(0x0000000200000800), CONST64(0x0000000008000800), CONST64(0x0000000208000800),
+ CONST64(0x0000000000080800), CONST64(0x0000000200080800), CONST64(0x0000000008080800), CONST64(0x0000000208080800),
+ CONST64(0x0000000000000008), CONST64(0x0000000200000008), CONST64(0x0000000008000008), CONST64(0x0000000208000008),
+ CONST64(0x0000000000080008), CONST64(0x0000000200080008), CONST64(0x0000000008080008), CONST64(0x0000000208080008),
+ CONST64(0x0000000000000808), CONST64(0x0000000200000808), CONST64(0x0000000008000808), CONST64(0x0000000208000808),
+ CONST64(0x0000000000080808), CONST64(0x0000000200080808), CONST64(0x0000000008080808), CONST64(0x0000000208080808),
+ CONST64(0x0800000000000000), CONST64(0x0800000200000000), CONST64(0x0800000008000000), CONST64(0x0800000208000000),
+ CONST64(0x0800000000080000), CONST64(0x0800000200080000), CONST64(0x0800000008080000), CONST64(0x0800000208080000),
+ CONST64(0x0800000000000800), CONST64(0x0800000200000800), CONST64(0x0800000008000800), CONST64(0x0800000208000800),
+ CONST64(0x0800000000080800), CONST64(0x0800000200080800), CONST64(0x0800000008080800), CONST64(0x0800000208080800),
+ CONST64(0x0800000000000008), CONST64(0x0800000200000008), CONST64(0x0800000008000008), CONST64(0x0800000208000008),
+ CONST64(0x0800000000080008), CONST64(0x0800000200080008), CONST64(0x0800000008080008), CONST64(0x0800000208080008),
+ CONST64(0x0800000000000808), CONST64(0x0800000200000808), CONST64(0x0800000008000808), CONST64(0x0800000208000808),
+ CONST64(0x0800000000080808), CONST64(0x0800000200080808), CONST64(0x0800000008080808), CONST64(0x0800000208080808),
+ CONST64(0x0008000000000000), CONST64(0x0008000200000000), CONST64(0x0008000008000000), CONST64(0x0008000208000000),
+ CONST64(0x0008000000080000), CONST64(0x0008000200080000), CONST64(0x0008000008080000), CONST64(0x0008000208080000),
+ CONST64(0x0008000000000800), CONST64(0x0008000200000800), CONST64(0x0008000008000800), CONST64(0x0008000208000800),
+ CONST64(0x0008000000080800), CONST64(0x0008000200080800), CONST64(0x0008000008080800), CONST64(0x0008000208080800),
+ CONST64(0x0008000000000008), CONST64(0x0008000200000008), CONST64(0x0008000008000008), CONST64(0x0008000208000008),
+ CONST64(0x0008000000080008), CONST64(0x0008000200080008), CONST64(0x0008000008080008), CONST64(0x0008000208080008),
+ CONST64(0x0008000000000808), CONST64(0x0008000200000808), CONST64(0x0008000008000808), CONST64(0x0008000208000808),
+ CONST64(0x0008000000080808), CONST64(0x0008000200080808), CONST64(0x0008000008080808), CONST64(0x0008000208080808),
+ CONST64(0x0808000000000000), CONST64(0x0808000200000000), CONST64(0x0808000008000000), CONST64(0x0808000208000000),
+ CONST64(0x0808000000080000), CONST64(0x0808000200080000), CONST64(0x0808000008080000), CONST64(0x0808000208080000),
+ CONST64(0x0808000000000800), CONST64(0x0808000200000800), CONST64(0x0808000008000800), CONST64(0x0808000208000800),
+ CONST64(0x0808000000080800), CONST64(0x0808000200080800), CONST64(0x0808000008080800), CONST64(0x0808000208080800),
+ CONST64(0x0808000000000008), CONST64(0x0808000200000008), CONST64(0x0808000008000008), CONST64(0x0808000208000008),
+ CONST64(0x0808000000080008), CONST64(0x0808000200080008), CONST64(0x0808000008080008), CONST64(0x0808000208080008),
+ CONST64(0x0808000000000808), CONST64(0x0808000200000808), CONST64(0x0808000008000808), CONST64(0x0808000208000808),
+ CONST64(0x0808000000080808), CONST64(0x0808000200080808), CONST64(0x0808000008080808), CONST64(0x0808000208080808),
+ CONST64(0x0000080000000000), CONST64(0x0000080200000000), CONST64(0x0000080008000000), CONST64(0x0000080208000000),
+ CONST64(0x0000080000080000), CONST64(0x0000080200080000), CONST64(0x0000080008080000), CONST64(0x0000080208080000),
+ CONST64(0x0000080000000800), CONST64(0x0000080200000800), CONST64(0x0000080008000800), CONST64(0x0000080208000800),
+ CONST64(0x0000080000080800), CONST64(0x0000080200080800), CONST64(0x0000080008080800), CONST64(0x0000080208080800),
+ CONST64(0x0000080000000008), CONST64(0x0000080200000008), CONST64(0x0000080008000008), CONST64(0x0000080208000008),
+ CONST64(0x0000080000080008), CONST64(0x0000080200080008), CONST64(0x0000080008080008), CONST64(0x0000080208080008),
+ CONST64(0x0000080000000808), CONST64(0x0000080200000808), CONST64(0x0000080008000808), CONST64(0x0000080208000808),
+ CONST64(0x0000080000080808), CONST64(0x0000080200080808), CONST64(0x0000080008080808), CONST64(0x0000080208080808),
+ CONST64(0x0800080000000000), CONST64(0x0800080200000000), CONST64(0x0800080008000000), CONST64(0x0800080208000000),
+ CONST64(0x0800080000080000), CONST64(0x0800080200080000), CONST64(0x0800080008080000), CONST64(0x0800080208080000),
+ CONST64(0x0800080000000800), CONST64(0x0800080200000800), CONST64(0x0800080008000800), CONST64(0x0800080208000800),
+ CONST64(0x0800080000080800), CONST64(0x0800080200080800), CONST64(0x0800080008080800), CONST64(0x0800080208080800),
+ CONST64(0x0800080000000008), CONST64(0x0800080200000008), CONST64(0x0800080008000008), CONST64(0x0800080208000008),
+ CONST64(0x0800080000080008), CONST64(0x0800080200080008), CONST64(0x0800080008080008), CONST64(0x0800080208080008),
+ CONST64(0x0800080000000808), CONST64(0x0800080200000808), CONST64(0x0800080008000808), CONST64(0x0800080208000808),
+ CONST64(0x0800080000080808), CONST64(0x0800080200080808), CONST64(0x0800080008080808), CONST64(0x0800080208080808),
+ CONST64(0x0008080000000000), CONST64(0x0008080200000000), CONST64(0x0008080008000000), CONST64(0x0008080208000000),
+ CONST64(0x0008080000080000), CONST64(0x0008080200080000), CONST64(0x0008080008080000), CONST64(0x0008080208080000),
+ CONST64(0x0008080000000800), CONST64(0x0008080200000800), CONST64(0x0008080008000800), CONST64(0x0008080208000800),
+ CONST64(0x0008080000080800), CONST64(0x0008080200080800), CONST64(0x0008080008080800), CONST64(0x0008080208080800),
+ CONST64(0x0008080000000008), CONST64(0x0008080200000008), CONST64(0x0008080008000008), CONST64(0x0008080208000008),
+ CONST64(0x0008080000080008), CONST64(0x0008080200080008), CONST64(0x0008080008080008), CONST64(0x0008080208080008),
+ CONST64(0x0008080000000808), CONST64(0x0008080200000808), CONST64(0x0008080008000808), CONST64(0x0008080208000808),
+ CONST64(0x0008080000080808), CONST64(0x0008080200080808), CONST64(0x0008080008080808), CONST64(0x0008080208080808),
+ CONST64(0x0808080000000000), CONST64(0x0808080200000000), CONST64(0x0808080008000000), CONST64(0x0808080208000000),
+ CONST64(0x0808080000080000), CONST64(0x0808080200080000), CONST64(0x0808080008080000), CONST64(0x0808080208080000),
+ CONST64(0x0808080000000800), CONST64(0x0808080200000800), CONST64(0x0808080008000800), CONST64(0x0808080208000800),
+ CONST64(0x0808080000080800), CONST64(0x0808080200080800), CONST64(0x0808080008080800), CONST64(0x0808080208080800),
+ CONST64(0x0808080000000008), CONST64(0x0808080200000008), CONST64(0x0808080008000008), CONST64(0x0808080208000008),
+ CONST64(0x0808080000080008), CONST64(0x0808080200080008), CONST64(0x0808080008080008), CONST64(0x0808080208080008),
+ CONST64(0x0808080000000808), CONST64(0x0808080200000808), CONST64(0x0808080008000808), CONST64(0x0808080208000808),
+ CONST64(0x0808080000080808), CONST64(0x0808080200080808), CONST64(0x0808080008080808), CONST64(0x0808080208080808)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000020000000), CONST64(0x0000000820000000),
+ CONST64(0x0000000000200000), CONST64(0x0000000800200000), CONST64(0x0000000020200000), CONST64(0x0000000820200000),
+ CONST64(0x0000000000002000), CONST64(0x0000000800002000), CONST64(0x0000000020002000), CONST64(0x0000000820002000),
+ CONST64(0x0000000000202000), CONST64(0x0000000800202000), CONST64(0x0000000020202000), CONST64(0x0000000820202000),
+ CONST64(0x0000000000000020), CONST64(0x0000000800000020), CONST64(0x0000000020000020), CONST64(0x0000000820000020),
+ CONST64(0x0000000000200020), CONST64(0x0000000800200020), CONST64(0x0000000020200020), CONST64(0x0000000820200020),
+ CONST64(0x0000000000002020), CONST64(0x0000000800002020), CONST64(0x0000000020002020), CONST64(0x0000000820002020),
+ CONST64(0x0000000000202020), CONST64(0x0000000800202020), CONST64(0x0000000020202020), CONST64(0x0000000820202020),
+ CONST64(0x2000000000000000), CONST64(0x2000000800000000), CONST64(0x2000000020000000), CONST64(0x2000000820000000),
+ CONST64(0x2000000000200000), CONST64(0x2000000800200000), CONST64(0x2000000020200000), CONST64(0x2000000820200000),
+ CONST64(0x2000000000002000), CONST64(0x2000000800002000), CONST64(0x2000000020002000), CONST64(0x2000000820002000),
+ CONST64(0x2000000000202000), CONST64(0x2000000800202000), CONST64(0x2000000020202000), CONST64(0x2000000820202000),
+ CONST64(0x2000000000000020), CONST64(0x2000000800000020), CONST64(0x2000000020000020), CONST64(0x2000000820000020),
+ CONST64(0x2000000000200020), CONST64(0x2000000800200020), CONST64(0x2000000020200020), CONST64(0x2000000820200020),
+ CONST64(0x2000000000002020), CONST64(0x2000000800002020), CONST64(0x2000000020002020), CONST64(0x2000000820002020),
+ CONST64(0x2000000000202020), CONST64(0x2000000800202020), CONST64(0x2000000020202020), CONST64(0x2000000820202020),
+ CONST64(0x0020000000000000), CONST64(0x0020000800000000), CONST64(0x0020000020000000), CONST64(0x0020000820000000),
+ CONST64(0x0020000000200000), CONST64(0x0020000800200000), CONST64(0x0020000020200000), CONST64(0x0020000820200000),
+ CONST64(0x0020000000002000), CONST64(0x0020000800002000), CONST64(0x0020000020002000), CONST64(0x0020000820002000),
+ CONST64(0x0020000000202000), CONST64(0x0020000800202000), CONST64(0x0020000020202000), CONST64(0x0020000820202000),
+ CONST64(0x0020000000000020), CONST64(0x0020000800000020), CONST64(0x0020000020000020), CONST64(0x0020000820000020),
+ CONST64(0x0020000000200020), CONST64(0x0020000800200020), CONST64(0x0020000020200020), CONST64(0x0020000820200020),
+ CONST64(0x0020000000002020), CONST64(0x0020000800002020), CONST64(0x0020000020002020), CONST64(0x0020000820002020),
+ CONST64(0x0020000000202020), CONST64(0x0020000800202020), CONST64(0x0020000020202020), CONST64(0x0020000820202020),
+ CONST64(0x2020000000000000), CONST64(0x2020000800000000), CONST64(0x2020000020000000), CONST64(0x2020000820000000),
+ CONST64(0x2020000000200000), CONST64(0x2020000800200000), CONST64(0x2020000020200000), CONST64(0x2020000820200000),
+ CONST64(0x2020000000002000), CONST64(0x2020000800002000), CONST64(0x2020000020002000), CONST64(0x2020000820002000),
+ CONST64(0x2020000000202000), CONST64(0x2020000800202000), CONST64(0x2020000020202000), CONST64(0x2020000820202000),
+ CONST64(0x2020000000000020), CONST64(0x2020000800000020), CONST64(0x2020000020000020), CONST64(0x2020000820000020),
+ CONST64(0x2020000000200020), CONST64(0x2020000800200020), CONST64(0x2020000020200020), CONST64(0x2020000820200020),
+ CONST64(0x2020000000002020), CONST64(0x2020000800002020), CONST64(0x2020000020002020), CONST64(0x2020000820002020),
+ CONST64(0x2020000000202020), CONST64(0x2020000800202020), CONST64(0x2020000020202020), CONST64(0x2020000820202020),
+ CONST64(0x0000200000000000), CONST64(0x0000200800000000), CONST64(0x0000200020000000), CONST64(0x0000200820000000),
+ CONST64(0x0000200000200000), CONST64(0x0000200800200000), CONST64(0x0000200020200000), CONST64(0x0000200820200000),
+ CONST64(0x0000200000002000), CONST64(0x0000200800002000), CONST64(0x0000200020002000), CONST64(0x0000200820002000),
+ CONST64(0x0000200000202000), CONST64(0x0000200800202000), CONST64(0x0000200020202000), CONST64(0x0000200820202000),
+ CONST64(0x0000200000000020), CONST64(0x0000200800000020), CONST64(0x0000200020000020), CONST64(0x0000200820000020),
+ CONST64(0x0000200000200020), CONST64(0x0000200800200020), CONST64(0x0000200020200020), CONST64(0x0000200820200020),
+ CONST64(0x0000200000002020), CONST64(0x0000200800002020), CONST64(0x0000200020002020), CONST64(0x0000200820002020),
+ CONST64(0x0000200000202020), CONST64(0x0000200800202020), CONST64(0x0000200020202020), CONST64(0x0000200820202020),
+ CONST64(0x2000200000000000), CONST64(0x2000200800000000), CONST64(0x2000200020000000), CONST64(0x2000200820000000),
+ CONST64(0x2000200000200000), CONST64(0x2000200800200000), CONST64(0x2000200020200000), CONST64(0x2000200820200000),
+ CONST64(0x2000200000002000), CONST64(0x2000200800002000), CONST64(0x2000200020002000), CONST64(0x2000200820002000),
+ CONST64(0x2000200000202000), CONST64(0x2000200800202000), CONST64(0x2000200020202000), CONST64(0x2000200820202000),
+ CONST64(0x2000200000000020), CONST64(0x2000200800000020), CONST64(0x2000200020000020), CONST64(0x2000200820000020),
+ CONST64(0x2000200000200020), CONST64(0x2000200800200020), CONST64(0x2000200020200020), CONST64(0x2000200820200020),
+ CONST64(0x2000200000002020), CONST64(0x2000200800002020), CONST64(0x2000200020002020), CONST64(0x2000200820002020),
+ CONST64(0x2000200000202020), CONST64(0x2000200800202020), CONST64(0x2000200020202020), CONST64(0x2000200820202020),
+ CONST64(0x0020200000000000), CONST64(0x0020200800000000), CONST64(0x0020200020000000), CONST64(0x0020200820000000),
+ CONST64(0x0020200000200000), CONST64(0x0020200800200000), CONST64(0x0020200020200000), CONST64(0x0020200820200000),
+ CONST64(0x0020200000002000), CONST64(0x0020200800002000), CONST64(0x0020200020002000), CONST64(0x0020200820002000),
+ CONST64(0x0020200000202000), CONST64(0x0020200800202000), CONST64(0x0020200020202000), CONST64(0x0020200820202000),
+ CONST64(0x0020200000000020), CONST64(0x0020200800000020), CONST64(0x0020200020000020), CONST64(0x0020200820000020),
+ CONST64(0x0020200000200020), CONST64(0x0020200800200020), CONST64(0x0020200020200020), CONST64(0x0020200820200020),
+ CONST64(0x0020200000002020), CONST64(0x0020200800002020), CONST64(0x0020200020002020), CONST64(0x0020200820002020),
+ CONST64(0x0020200000202020), CONST64(0x0020200800202020), CONST64(0x0020200020202020), CONST64(0x0020200820202020),
+ CONST64(0x2020200000000000), CONST64(0x2020200800000000), CONST64(0x2020200020000000), CONST64(0x2020200820000000),
+ CONST64(0x2020200000200000), CONST64(0x2020200800200000), CONST64(0x2020200020200000), CONST64(0x2020200820200000),
+ CONST64(0x2020200000002000), CONST64(0x2020200800002000), CONST64(0x2020200020002000), CONST64(0x2020200820002000),
+ CONST64(0x2020200000202000), CONST64(0x2020200800202000), CONST64(0x2020200020202000), CONST64(0x2020200820202000),
+ CONST64(0x2020200000000020), CONST64(0x2020200800000020), CONST64(0x2020200020000020), CONST64(0x2020200820000020),
+ CONST64(0x2020200000200020), CONST64(0x2020200800200020), CONST64(0x2020200020200020), CONST64(0x2020200820200020),
+ CONST64(0x2020200000002020), CONST64(0x2020200800002020), CONST64(0x2020200020002020), CONST64(0x2020200820002020),
+ CONST64(0x2020200000202020), CONST64(0x2020200800202020), CONST64(0x2020200020202020), CONST64(0x2020200820202020)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000080000000), CONST64(0x0000002080000000),
+ CONST64(0x0000000000800000), CONST64(0x0000002000800000), CONST64(0x0000000080800000), CONST64(0x0000002080800000),
+ CONST64(0x0000000000008000), CONST64(0x0000002000008000), CONST64(0x0000000080008000), CONST64(0x0000002080008000),
+ CONST64(0x0000000000808000), CONST64(0x0000002000808000), CONST64(0x0000000080808000), CONST64(0x0000002080808000),
+ CONST64(0x0000000000000080), CONST64(0x0000002000000080), CONST64(0x0000000080000080), CONST64(0x0000002080000080),
+ CONST64(0x0000000000800080), CONST64(0x0000002000800080), CONST64(0x0000000080800080), CONST64(0x0000002080800080),
+ CONST64(0x0000000000008080), CONST64(0x0000002000008080), CONST64(0x0000000080008080), CONST64(0x0000002080008080),
+ CONST64(0x0000000000808080), CONST64(0x0000002000808080), CONST64(0x0000000080808080), CONST64(0x0000002080808080),
+ CONST64(0x8000000000000000), CONST64(0x8000002000000000), CONST64(0x8000000080000000), CONST64(0x8000002080000000),
+ CONST64(0x8000000000800000), CONST64(0x8000002000800000), CONST64(0x8000000080800000), CONST64(0x8000002080800000),
+ CONST64(0x8000000000008000), CONST64(0x8000002000008000), CONST64(0x8000000080008000), CONST64(0x8000002080008000),
+ CONST64(0x8000000000808000), CONST64(0x8000002000808000), CONST64(0x8000000080808000), CONST64(0x8000002080808000),
+ CONST64(0x8000000000000080), CONST64(0x8000002000000080), CONST64(0x8000000080000080), CONST64(0x8000002080000080),
+ CONST64(0x8000000000800080), CONST64(0x8000002000800080), CONST64(0x8000000080800080), CONST64(0x8000002080800080),
+ CONST64(0x8000000000008080), CONST64(0x8000002000008080), CONST64(0x8000000080008080), CONST64(0x8000002080008080),
+ CONST64(0x8000000000808080), CONST64(0x8000002000808080), CONST64(0x8000000080808080), CONST64(0x8000002080808080),
+ CONST64(0x0080000000000000), CONST64(0x0080002000000000), CONST64(0x0080000080000000), CONST64(0x0080002080000000),
+ CONST64(0x0080000000800000), CONST64(0x0080002000800000), CONST64(0x0080000080800000), CONST64(0x0080002080800000),
+ CONST64(0x0080000000008000), CONST64(0x0080002000008000), CONST64(0x0080000080008000), CONST64(0x0080002080008000),
+ CONST64(0x0080000000808000), CONST64(0x0080002000808000), CONST64(0x0080000080808000), CONST64(0x0080002080808000),
+ CONST64(0x0080000000000080), CONST64(0x0080002000000080), CONST64(0x0080000080000080), CONST64(0x0080002080000080),
+ CONST64(0x0080000000800080), CONST64(0x0080002000800080), CONST64(0x0080000080800080), CONST64(0x0080002080800080),
+ CONST64(0x0080000000008080), CONST64(0x0080002000008080), CONST64(0x0080000080008080), CONST64(0x0080002080008080),
+ CONST64(0x0080000000808080), CONST64(0x0080002000808080), CONST64(0x0080000080808080), CONST64(0x0080002080808080),
+ CONST64(0x8080000000000000), CONST64(0x8080002000000000), CONST64(0x8080000080000000), CONST64(0x8080002080000000),
+ CONST64(0x8080000000800000), CONST64(0x8080002000800000), CONST64(0x8080000080800000), CONST64(0x8080002080800000),
+ CONST64(0x8080000000008000), CONST64(0x8080002000008000), CONST64(0x8080000080008000), CONST64(0x8080002080008000),
+ CONST64(0x8080000000808000), CONST64(0x8080002000808000), CONST64(0x8080000080808000), CONST64(0x8080002080808000),
+ CONST64(0x8080000000000080), CONST64(0x8080002000000080), CONST64(0x8080000080000080), CONST64(0x8080002080000080),
+ CONST64(0x8080000000800080), CONST64(0x8080002000800080), CONST64(0x8080000080800080), CONST64(0x8080002080800080),
+ CONST64(0x8080000000008080), CONST64(0x8080002000008080), CONST64(0x8080000080008080), CONST64(0x8080002080008080),
+ CONST64(0x8080000000808080), CONST64(0x8080002000808080), CONST64(0x8080000080808080), CONST64(0x8080002080808080),
+ CONST64(0x0000800000000000), CONST64(0x0000802000000000), CONST64(0x0000800080000000), CONST64(0x0000802080000000),
+ CONST64(0x0000800000800000), CONST64(0x0000802000800000), CONST64(0x0000800080800000), CONST64(0x0000802080800000),
+ CONST64(0x0000800000008000), CONST64(0x0000802000008000), CONST64(0x0000800080008000), CONST64(0x0000802080008000),
+ CONST64(0x0000800000808000), CONST64(0x0000802000808000), CONST64(0x0000800080808000), CONST64(0x0000802080808000),
+ CONST64(0x0000800000000080), CONST64(0x0000802000000080), CONST64(0x0000800080000080), CONST64(0x0000802080000080),
+ CONST64(0x0000800000800080), CONST64(0x0000802000800080), CONST64(0x0000800080800080), CONST64(0x0000802080800080),
+ CONST64(0x0000800000008080), CONST64(0x0000802000008080), CONST64(0x0000800080008080), CONST64(0x0000802080008080),
+ CONST64(0x0000800000808080), CONST64(0x0000802000808080), CONST64(0x0000800080808080), CONST64(0x0000802080808080),
+ CONST64(0x8000800000000000), CONST64(0x8000802000000000), CONST64(0x8000800080000000), CONST64(0x8000802080000000),
+ CONST64(0x8000800000800000), CONST64(0x8000802000800000), CONST64(0x8000800080800000), CONST64(0x8000802080800000),
+ CONST64(0x8000800000008000), CONST64(0x8000802000008000), CONST64(0x8000800080008000), CONST64(0x8000802080008000),
+ CONST64(0x8000800000808000), CONST64(0x8000802000808000), CONST64(0x8000800080808000), CONST64(0x8000802080808000),
+ CONST64(0x8000800000000080), CONST64(0x8000802000000080), CONST64(0x8000800080000080), CONST64(0x8000802080000080),
+ CONST64(0x8000800000800080), CONST64(0x8000802000800080), CONST64(0x8000800080800080), CONST64(0x8000802080800080),
+ CONST64(0x8000800000008080), CONST64(0x8000802000008080), CONST64(0x8000800080008080), CONST64(0x8000802080008080),
+ CONST64(0x8000800000808080), CONST64(0x8000802000808080), CONST64(0x8000800080808080), CONST64(0x8000802080808080),
+ CONST64(0x0080800000000000), CONST64(0x0080802000000000), CONST64(0x0080800080000000), CONST64(0x0080802080000000),
+ CONST64(0x0080800000800000), CONST64(0x0080802000800000), CONST64(0x0080800080800000), CONST64(0x0080802080800000),
+ CONST64(0x0080800000008000), CONST64(0x0080802000008000), CONST64(0x0080800080008000), CONST64(0x0080802080008000),
+ CONST64(0x0080800000808000), CONST64(0x0080802000808000), CONST64(0x0080800080808000), CONST64(0x0080802080808000),
+ CONST64(0x0080800000000080), CONST64(0x0080802000000080), CONST64(0x0080800080000080), CONST64(0x0080802080000080),
+ CONST64(0x0080800000800080), CONST64(0x0080802000800080), CONST64(0x0080800080800080), CONST64(0x0080802080800080),
+ CONST64(0x0080800000008080), CONST64(0x0080802000008080), CONST64(0x0080800080008080), CONST64(0x0080802080008080),
+ CONST64(0x0080800000808080), CONST64(0x0080802000808080), CONST64(0x0080800080808080), CONST64(0x0080802080808080),
+ CONST64(0x8080800000000000), CONST64(0x8080802000000000), CONST64(0x8080800080000000), CONST64(0x8080802080000000),
+ CONST64(0x8080800000800000), CONST64(0x8080802000800000), CONST64(0x8080800080800000), CONST64(0x8080802080800000),
+ CONST64(0x8080800000008000), CONST64(0x8080802000008000), CONST64(0x8080800080008000), CONST64(0x8080802080008000),
+ CONST64(0x8080800000808000), CONST64(0x8080802000808000), CONST64(0x8080800080808000), CONST64(0x8080802080808000),
+ CONST64(0x8080800000000080), CONST64(0x8080802000000080), CONST64(0x8080800080000080), CONST64(0x8080802080000080),
+ CONST64(0x8080800000800080), CONST64(0x8080802000800080), CONST64(0x8080800080800080), CONST64(0x8080802080800080),
+ CONST64(0x8080800000008080), CONST64(0x8080802000008080), CONST64(0x8080800080008080), CONST64(0x8080802080008080),
+ CONST64(0x8080800000808080), CONST64(0x8080802000808080), CONST64(0x8080800080808080), CONST64(0x8080802080808080)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000001000000), CONST64(0x0000004001000000),
+ CONST64(0x0000000000010000), CONST64(0x0000004000010000), CONST64(0x0000000001010000), CONST64(0x0000004001010000),
+ CONST64(0x0000000000000100), CONST64(0x0000004000000100), CONST64(0x0000000001000100), CONST64(0x0000004001000100),
+ CONST64(0x0000000000010100), CONST64(0x0000004000010100), CONST64(0x0000000001010100), CONST64(0x0000004001010100),
+ CONST64(0x0000000000000001), CONST64(0x0000004000000001), CONST64(0x0000000001000001), CONST64(0x0000004001000001),
+ CONST64(0x0000000000010001), CONST64(0x0000004000010001), CONST64(0x0000000001010001), CONST64(0x0000004001010001),
+ CONST64(0x0000000000000101), CONST64(0x0000004000000101), CONST64(0x0000000001000101), CONST64(0x0000004001000101),
+ CONST64(0x0000000000010101), CONST64(0x0000004000010101), CONST64(0x0000000001010101), CONST64(0x0000004001010101),
+ CONST64(0x0100000000000000), CONST64(0x0100004000000000), CONST64(0x0100000001000000), CONST64(0x0100004001000000),
+ CONST64(0x0100000000010000), CONST64(0x0100004000010000), CONST64(0x0100000001010000), CONST64(0x0100004001010000),
+ CONST64(0x0100000000000100), CONST64(0x0100004000000100), CONST64(0x0100000001000100), CONST64(0x0100004001000100),
+ CONST64(0x0100000000010100), CONST64(0x0100004000010100), CONST64(0x0100000001010100), CONST64(0x0100004001010100),
+ CONST64(0x0100000000000001), CONST64(0x0100004000000001), CONST64(0x0100000001000001), CONST64(0x0100004001000001),
+ CONST64(0x0100000000010001), CONST64(0x0100004000010001), CONST64(0x0100000001010001), CONST64(0x0100004001010001),
+ CONST64(0x0100000000000101), CONST64(0x0100004000000101), CONST64(0x0100000001000101), CONST64(0x0100004001000101),
+ CONST64(0x0100000000010101), CONST64(0x0100004000010101), CONST64(0x0100000001010101), CONST64(0x0100004001010101),
+ CONST64(0x0001000000000000), CONST64(0x0001004000000000), CONST64(0x0001000001000000), CONST64(0x0001004001000000),
+ CONST64(0x0001000000010000), CONST64(0x0001004000010000), CONST64(0x0001000001010000), CONST64(0x0001004001010000),
+ CONST64(0x0001000000000100), CONST64(0x0001004000000100), CONST64(0x0001000001000100), CONST64(0x0001004001000100),
+ CONST64(0x0001000000010100), CONST64(0x0001004000010100), CONST64(0x0001000001010100), CONST64(0x0001004001010100),
+ CONST64(0x0001000000000001), CONST64(0x0001004000000001), CONST64(0x0001000001000001), CONST64(0x0001004001000001),
+ CONST64(0x0001000000010001), CONST64(0x0001004000010001), CONST64(0x0001000001010001), CONST64(0x0001004001010001),
+ CONST64(0x0001000000000101), CONST64(0x0001004000000101), CONST64(0x0001000001000101), CONST64(0x0001004001000101),
+ CONST64(0x0001000000010101), CONST64(0x0001004000010101), CONST64(0x0001000001010101), CONST64(0x0001004001010101),
+ CONST64(0x0101000000000000), CONST64(0x0101004000000000), CONST64(0x0101000001000000), CONST64(0x0101004001000000),
+ CONST64(0x0101000000010000), CONST64(0x0101004000010000), CONST64(0x0101000001010000), CONST64(0x0101004001010000),
+ CONST64(0x0101000000000100), CONST64(0x0101004000000100), CONST64(0x0101000001000100), CONST64(0x0101004001000100),
+ CONST64(0x0101000000010100), CONST64(0x0101004000010100), CONST64(0x0101000001010100), CONST64(0x0101004001010100),
+ CONST64(0x0101000000000001), CONST64(0x0101004000000001), CONST64(0x0101000001000001), CONST64(0x0101004001000001),
+ CONST64(0x0101000000010001), CONST64(0x0101004000010001), CONST64(0x0101000001010001), CONST64(0x0101004001010001),
+ CONST64(0x0101000000000101), CONST64(0x0101004000000101), CONST64(0x0101000001000101), CONST64(0x0101004001000101),
+ CONST64(0x0101000000010101), CONST64(0x0101004000010101), CONST64(0x0101000001010101), CONST64(0x0101004001010101),
+ CONST64(0x0000010000000000), CONST64(0x0000014000000000), CONST64(0x0000010001000000), CONST64(0x0000014001000000),
+ CONST64(0x0000010000010000), CONST64(0x0000014000010000), CONST64(0x0000010001010000), CONST64(0x0000014001010000),
+ CONST64(0x0000010000000100), CONST64(0x0000014000000100), CONST64(0x0000010001000100), CONST64(0x0000014001000100),
+ CONST64(0x0000010000010100), CONST64(0x0000014000010100), CONST64(0x0000010001010100), CONST64(0x0000014001010100),
+ CONST64(0x0000010000000001), CONST64(0x0000014000000001), CONST64(0x0000010001000001), CONST64(0x0000014001000001),
+ CONST64(0x0000010000010001), CONST64(0x0000014000010001), CONST64(0x0000010001010001), CONST64(0x0000014001010001),
+ CONST64(0x0000010000000101), CONST64(0x0000014000000101), CONST64(0x0000010001000101), CONST64(0x0000014001000101),
+ CONST64(0x0000010000010101), CONST64(0x0000014000010101), CONST64(0x0000010001010101), CONST64(0x0000014001010101),
+ CONST64(0x0100010000000000), CONST64(0x0100014000000000), CONST64(0x0100010001000000), CONST64(0x0100014001000000),
+ CONST64(0x0100010000010000), CONST64(0x0100014000010000), CONST64(0x0100010001010000), CONST64(0x0100014001010000),
+ CONST64(0x0100010000000100), CONST64(0x0100014000000100), CONST64(0x0100010001000100), CONST64(0x0100014001000100),
+ CONST64(0x0100010000010100), CONST64(0x0100014000010100), CONST64(0x0100010001010100), CONST64(0x0100014001010100),
+ CONST64(0x0100010000000001), CONST64(0x0100014000000001), CONST64(0x0100010001000001), CONST64(0x0100014001000001),
+ CONST64(0x0100010000010001), CONST64(0x0100014000010001), CONST64(0x0100010001010001), CONST64(0x0100014001010001),
+ CONST64(0x0100010000000101), CONST64(0x0100014000000101), CONST64(0x0100010001000101), CONST64(0x0100014001000101),
+ CONST64(0x0100010000010101), CONST64(0x0100014000010101), CONST64(0x0100010001010101), CONST64(0x0100014001010101),
+ CONST64(0x0001010000000000), CONST64(0x0001014000000000), CONST64(0x0001010001000000), CONST64(0x0001014001000000),
+ CONST64(0x0001010000010000), CONST64(0x0001014000010000), CONST64(0x0001010001010000), CONST64(0x0001014001010000),
+ CONST64(0x0001010000000100), CONST64(0x0001014000000100), CONST64(0x0001010001000100), CONST64(0x0001014001000100),
+ CONST64(0x0001010000010100), CONST64(0x0001014000010100), CONST64(0x0001010001010100), CONST64(0x0001014001010100),
+ CONST64(0x0001010000000001), CONST64(0x0001014000000001), CONST64(0x0001010001000001), CONST64(0x0001014001000001),
+ CONST64(0x0001010000010001), CONST64(0x0001014000010001), CONST64(0x0001010001010001), CONST64(0x0001014001010001),
+ CONST64(0x0001010000000101), CONST64(0x0001014000000101), CONST64(0x0001010001000101), CONST64(0x0001014001000101),
+ CONST64(0x0001010000010101), CONST64(0x0001014000010101), CONST64(0x0001010001010101), CONST64(0x0001014001010101),
+ CONST64(0x0101010000000000), CONST64(0x0101014000000000), CONST64(0x0101010001000000), CONST64(0x0101014001000000),
+ CONST64(0x0101010000010000), CONST64(0x0101014000010000), CONST64(0x0101010001010000), CONST64(0x0101014001010000),
+ CONST64(0x0101010000000100), CONST64(0x0101014000000100), CONST64(0x0101010001000100), CONST64(0x0101014001000100),
+ CONST64(0x0101010000010100), CONST64(0x0101014000010100), CONST64(0x0101010001010100), CONST64(0x0101014001010100),
+ CONST64(0x0101010000000001), CONST64(0x0101014000000001), CONST64(0x0101010001000001), CONST64(0x0101014001000001),
+ CONST64(0x0101010000010001), CONST64(0x0101014000010001), CONST64(0x0101010001010001), CONST64(0x0101014001010001),
+ CONST64(0x0101010000000101), CONST64(0x0101014000000101), CONST64(0x0101010001000101), CONST64(0x0101014001000101),
+ CONST64(0x0101010000010101), CONST64(0x0101014000010101), CONST64(0x0101010001010101), CONST64(0x0101014001010101)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000000100000000), CONST64(0x0000000004000000), CONST64(0x0000000104000000),
+ CONST64(0x0000000000040000), CONST64(0x0000000100040000), CONST64(0x0000000004040000), CONST64(0x0000000104040000),
+ CONST64(0x0000000000000400), CONST64(0x0000000100000400), CONST64(0x0000000004000400), CONST64(0x0000000104000400),
+ CONST64(0x0000000000040400), CONST64(0x0000000100040400), CONST64(0x0000000004040400), CONST64(0x0000000104040400),
+ CONST64(0x0000000000000004), CONST64(0x0000000100000004), CONST64(0x0000000004000004), CONST64(0x0000000104000004),
+ CONST64(0x0000000000040004), CONST64(0x0000000100040004), CONST64(0x0000000004040004), CONST64(0x0000000104040004),
+ CONST64(0x0000000000000404), CONST64(0x0000000100000404), CONST64(0x0000000004000404), CONST64(0x0000000104000404),
+ CONST64(0x0000000000040404), CONST64(0x0000000100040404), CONST64(0x0000000004040404), CONST64(0x0000000104040404),
+ CONST64(0x0400000000000000), CONST64(0x0400000100000000), CONST64(0x0400000004000000), CONST64(0x0400000104000000),
+ CONST64(0x0400000000040000), CONST64(0x0400000100040000), CONST64(0x0400000004040000), CONST64(0x0400000104040000),
+ CONST64(0x0400000000000400), CONST64(0x0400000100000400), CONST64(0x0400000004000400), CONST64(0x0400000104000400),
+ CONST64(0x0400000000040400), CONST64(0x0400000100040400), CONST64(0x0400000004040400), CONST64(0x0400000104040400),
+ CONST64(0x0400000000000004), CONST64(0x0400000100000004), CONST64(0x0400000004000004), CONST64(0x0400000104000004),
+ CONST64(0x0400000000040004), CONST64(0x0400000100040004), CONST64(0x0400000004040004), CONST64(0x0400000104040004),
+ CONST64(0x0400000000000404), CONST64(0x0400000100000404), CONST64(0x0400000004000404), CONST64(0x0400000104000404),
+ CONST64(0x0400000000040404), CONST64(0x0400000100040404), CONST64(0x0400000004040404), CONST64(0x0400000104040404),
+ CONST64(0x0004000000000000), CONST64(0x0004000100000000), CONST64(0x0004000004000000), CONST64(0x0004000104000000),
+ CONST64(0x0004000000040000), CONST64(0x0004000100040000), CONST64(0x0004000004040000), CONST64(0x0004000104040000),
+ CONST64(0x0004000000000400), CONST64(0x0004000100000400), CONST64(0x0004000004000400), CONST64(0x0004000104000400),
+ CONST64(0x0004000000040400), CONST64(0x0004000100040400), CONST64(0x0004000004040400), CONST64(0x0004000104040400),
+ CONST64(0x0004000000000004), CONST64(0x0004000100000004), CONST64(0x0004000004000004), CONST64(0x0004000104000004),
+ CONST64(0x0004000000040004), CONST64(0x0004000100040004), CONST64(0x0004000004040004), CONST64(0x0004000104040004),
+ CONST64(0x0004000000000404), CONST64(0x0004000100000404), CONST64(0x0004000004000404), CONST64(0x0004000104000404),
+ CONST64(0x0004000000040404), CONST64(0x0004000100040404), CONST64(0x0004000004040404), CONST64(0x0004000104040404),
+ CONST64(0x0404000000000000), CONST64(0x0404000100000000), CONST64(0x0404000004000000), CONST64(0x0404000104000000),
+ CONST64(0x0404000000040000), CONST64(0x0404000100040000), CONST64(0x0404000004040000), CONST64(0x0404000104040000),
+ CONST64(0x0404000000000400), CONST64(0x0404000100000400), CONST64(0x0404000004000400), CONST64(0x0404000104000400),
+ CONST64(0x0404000000040400), CONST64(0x0404000100040400), CONST64(0x0404000004040400), CONST64(0x0404000104040400),
+ CONST64(0x0404000000000004), CONST64(0x0404000100000004), CONST64(0x0404000004000004), CONST64(0x0404000104000004),
+ CONST64(0x0404000000040004), CONST64(0x0404000100040004), CONST64(0x0404000004040004), CONST64(0x0404000104040004),
+ CONST64(0x0404000000000404), CONST64(0x0404000100000404), CONST64(0x0404000004000404), CONST64(0x0404000104000404),
+ CONST64(0x0404000000040404), CONST64(0x0404000100040404), CONST64(0x0404000004040404), CONST64(0x0404000104040404),
+ CONST64(0x0000040000000000), CONST64(0x0000040100000000), CONST64(0x0000040004000000), CONST64(0x0000040104000000),
+ CONST64(0x0000040000040000), CONST64(0x0000040100040000), CONST64(0x0000040004040000), CONST64(0x0000040104040000),
+ CONST64(0x0000040000000400), CONST64(0x0000040100000400), CONST64(0x0000040004000400), CONST64(0x0000040104000400),
+ CONST64(0x0000040000040400), CONST64(0x0000040100040400), CONST64(0x0000040004040400), CONST64(0x0000040104040400),
+ CONST64(0x0000040000000004), CONST64(0x0000040100000004), CONST64(0x0000040004000004), CONST64(0x0000040104000004),
+ CONST64(0x0000040000040004), CONST64(0x0000040100040004), CONST64(0x0000040004040004), CONST64(0x0000040104040004),
+ CONST64(0x0000040000000404), CONST64(0x0000040100000404), CONST64(0x0000040004000404), CONST64(0x0000040104000404),
+ CONST64(0x0000040000040404), CONST64(0x0000040100040404), CONST64(0x0000040004040404), CONST64(0x0000040104040404),
+ CONST64(0x0400040000000000), CONST64(0x0400040100000000), CONST64(0x0400040004000000), CONST64(0x0400040104000000),
+ CONST64(0x0400040000040000), CONST64(0x0400040100040000), CONST64(0x0400040004040000), CONST64(0x0400040104040000),
+ CONST64(0x0400040000000400), CONST64(0x0400040100000400), CONST64(0x0400040004000400), CONST64(0x0400040104000400),
+ CONST64(0x0400040000040400), CONST64(0x0400040100040400), CONST64(0x0400040004040400), CONST64(0x0400040104040400),
+ CONST64(0x0400040000000004), CONST64(0x0400040100000004), CONST64(0x0400040004000004), CONST64(0x0400040104000004),
+ CONST64(0x0400040000040004), CONST64(0x0400040100040004), CONST64(0x0400040004040004), CONST64(0x0400040104040004),
+ CONST64(0x0400040000000404), CONST64(0x0400040100000404), CONST64(0x0400040004000404), CONST64(0x0400040104000404),
+ CONST64(0x0400040000040404), CONST64(0x0400040100040404), CONST64(0x0400040004040404), CONST64(0x0400040104040404),
+ CONST64(0x0004040000000000), CONST64(0x0004040100000000), CONST64(0x0004040004000000), CONST64(0x0004040104000000),
+ CONST64(0x0004040000040000), CONST64(0x0004040100040000), CONST64(0x0004040004040000), CONST64(0x0004040104040000),
+ CONST64(0x0004040000000400), CONST64(0x0004040100000400), CONST64(0x0004040004000400), CONST64(0x0004040104000400),
+ CONST64(0x0004040000040400), CONST64(0x0004040100040400), CONST64(0x0004040004040400), CONST64(0x0004040104040400),
+ CONST64(0x0004040000000004), CONST64(0x0004040100000004), CONST64(0x0004040004000004), CONST64(0x0004040104000004),
+ CONST64(0x0004040000040004), CONST64(0x0004040100040004), CONST64(0x0004040004040004), CONST64(0x0004040104040004),
+ CONST64(0x0004040000000404), CONST64(0x0004040100000404), CONST64(0x0004040004000404), CONST64(0x0004040104000404),
+ CONST64(0x0004040000040404), CONST64(0x0004040100040404), CONST64(0x0004040004040404), CONST64(0x0004040104040404),
+ CONST64(0x0404040000000000), CONST64(0x0404040100000000), CONST64(0x0404040004000000), CONST64(0x0404040104000000),
+ CONST64(0x0404040000040000), CONST64(0x0404040100040000), CONST64(0x0404040004040000), CONST64(0x0404040104040000),
+ CONST64(0x0404040000000400), CONST64(0x0404040100000400), CONST64(0x0404040004000400), CONST64(0x0404040104000400),
+ CONST64(0x0404040000040400), CONST64(0x0404040100040400), CONST64(0x0404040004040400), CONST64(0x0404040104040400),
+ CONST64(0x0404040000000004), CONST64(0x0404040100000004), CONST64(0x0404040004000004), CONST64(0x0404040104000004),
+ CONST64(0x0404040000040004), CONST64(0x0404040100040004), CONST64(0x0404040004040004), CONST64(0x0404040104040004),
+ CONST64(0x0404040000000404), CONST64(0x0404040100000404), CONST64(0x0404040004000404), CONST64(0x0404040104000404),
+ CONST64(0x0404040000040404), CONST64(0x0404040100040404), CONST64(0x0404040004040404), CONST64(0x0404040104040404)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000010000000), CONST64(0x0000000410000000),
+ CONST64(0x0000000000100000), CONST64(0x0000000400100000), CONST64(0x0000000010100000), CONST64(0x0000000410100000),
+ CONST64(0x0000000000001000), CONST64(0x0000000400001000), CONST64(0x0000000010001000), CONST64(0x0000000410001000),
+ CONST64(0x0000000000101000), CONST64(0x0000000400101000), CONST64(0x0000000010101000), CONST64(0x0000000410101000),
+ CONST64(0x0000000000000010), CONST64(0x0000000400000010), CONST64(0x0000000010000010), CONST64(0x0000000410000010),
+ CONST64(0x0000000000100010), CONST64(0x0000000400100010), CONST64(0x0000000010100010), CONST64(0x0000000410100010),
+ CONST64(0x0000000000001010), CONST64(0x0000000400001010), CONST64(0x0000000010001010), CONST64(0x0000000410001010),
+ CONST64(0x0000000000101010), CONST64(0x0000000400101010), CONST64(0x0000000010101010), CONST64(0x0000000410101010),
+ CONST64(0x1000000000000000), CONST64(0x1000000400000000), CONST64(0x1000000010000000), CONST64(0x1000000410000000),
+ CONST64(0x1000000000100000), CONST64(0x1000000400100000), CONST64(0x1000000010100000), CONST64(0x1000000410100000),
+ CONST64(0x1000000000001000), CONST64(0x1000000400001000), CONST64(0x1000000010001000), CONST64(0x1000000410001000),
+ CONST64(0x1000000000101000), CONST64(0x1000000400101000), CONST64(0x1000000010101000), CONST64(0x1000000410101000),
+ CONST64(0x1000000000000010), CONST64(0x1000000400000010), CONST64(0x1000000010000010), CONST64(0x1000000410000010),
+ CONST64(0x1000000000100010), CONST64(0x1000000400100010), CONST64(0x1000000010100010), CONST64(0x1000000410100010),
+ CONST64(0x1000000000001010), CONST64(0x1000000400001010), CONST64(0x1000000010001010), CONST64(0x1000000410001010),
+ CONST64(0x1000000000101010), CONST64(0x1000000400101010), CONST64(0x1000000010101010), CONST64(0x1000000410101010),
+ CONST64(0x0010000000000000), CONST64(0x0010000400000000), CONST64(0x0010000010000000), CONST64(0x0010000410000000),
+ CONST64(0x0010000000100000), CONST64(0x0010000400100000), CONST64(0x0010000010100000), CONST64(0x0010000410100000),
+ CONST64(0x0010000000001000), CONST64(0x0010000400001000), CONST64(0x0010000010001000), CONST64(0x0010000410001000),
+ CONST64(0x0010000000101000), CONST64(0x0010000400101000), CONST64(0x0010000010101000), CONST64(0x0010000410101000),
+ CONST64(0x0010000000000010), CONST64(0x0010000400000010), CONST64(0x0010000010000010), CONST64(0x0010000410000010),
+ CONST64(0x0010000000100010), CONST64(0x0010000400100010), CONST64(0x0010000010100010), CONST64(0x0010000410100010),
+ CONST64(0x0010000000001010), CONST64(0x0010000400001010), CONST64(0x0010000010001010), CONST64(0x0010000410001010),
+ CONST64(0x0010000000101010), CONST64(0x0010000400101010), CONST64(0x0010000010101010), CONST64(0x0010000410101010),
+ CONST64(0x1010000000000000), CONST64(0x1010000400000000), CONST64(0x1010000010000000), CONST64(0x1010000410000000),
+ CONST64(0x1010000000100000), CONST64(0x1010000400100000), CONST64(0x1010000010100000), CONST64(0x1010000410100000),
+ CONST64(0x1010000000001000), CONST64(0x1010000400001000), CONST64(0x1010000010001000), CONST64(0x1010000410001000),
+ CONST64(0x1010000000101000), CONST64(0x1010000400101000), CONST64(0x1010000010101000), CONST64(0x1010000410101000),
+ CONST64(0x1010000000000010), CONST64(0x1010000400000010), CONST64(0x1010000010000010), CONST64(0x1010000410000010),
+ CONST64(0x1010000000100010), CONST64(0x1010000400100010), CONST64(0x1010000010100010), CONST64(0x1010000410100010),
+ CONST64(0x1010000000001010), CONST64(0x1010000400001010), CONST64(0x1010000010001010), CONST64(0x1010000410001010),
+ CONST64(0x1010000000101010), CONST64(0x1010000400101010), CONST64(0x1010000010101010), CONST64(0x1010000410101010),
+ CONST64(0x0000100000000000), CONST64(0x0000100400000000), CONST64(0x0000100010000000), CONST64(0x0000100410000000),
+ CONST64(0x0000100000100000), CONST64(0x0000100400100000), CONST64(0x0000100010100000), CONST64(0x0000100410100000),
+ CONST64(0x0000100000001000), CONST64(0x0000100400001000), CONST64(0x0000100010001000), CONST64(0x0000100410001000),
+ CONST64(0x0000100000101000), CONST64(0x0000100400101000), CONST64(0x0000100010101000), CONST64(0x0000100410101000),
+ CONST64(0x0000100000000010), CONST64(0x0000100400000010), CONST64(0x0000100010000010), CONST64(0x0000100410000010),
+ CONST64(0x0000100000100010), CONST64(0x0000100400100010), CONST64(0x0000100010100010), CONST64(0x0000100410100010),
+ CONST64(0x0000100000001010), CONST64(0x0000100400001010), CONST64(0x0000100010001010), CONST64(0x0000100410001010),
+ CONST64(0x0000100000101010), CONST64(0x0000100400101010), CONST64(0x0000100010101010), CONST64(0x0000100410101010),
+ CONST64(0x1000100000000000), CONST64(0x1000100400000000), CONST64(0x1000100010000000), CONST64(0x1000100410000000),
+ CONST64(0x1000100000100000), CONST64(0x1000100400100000), CONST64(0x1000100010100000), CONST64(0x1000100410100000),
+ CONST64(0x1000100000001000), CONST64(0x1000100400001000), CONST64(0x1000100010001000), CONST64(0x1000100410001000),
+ CONST64(0x1000100000101000), CONST64(0x1000100400101000), CONST64(0x1000100010101000), CONST64(0x1000100410101000),
+ CONST64(0x1000100000000010), CONST64(0x1000100400000010), CONST64(0x1000100010000010), CONST64(0x1000100410000010),
+ CONST64(0x1000100000100010), CONST64(0x1000100400100010), CONST64(0x1000100010100010), CONST64(0x1000100410100010),
+ CONST64(0x1000100000001010), CONST64(0x1000100400001010), CONST64(0x1000100010001010), CONST64(0x1000100410001010),
+ CONST64(0x1000100000101010), CONST64(0x1000100400101010), CONST64(0x1000100010101010), CONST64(0x1000100410101010),
+ CONST64(0x0010100000000000), CONST64(0x0010100400000000), CONST64(0x0010100010000000), CONST64(0x0010100410000000),
+ CONST64(0x0010100000100000), CONST64(0x0010100400100000), CONST64(0x0010100010100000), CONST64(0x0010100410100000),
+ CONST64(0x0010100000001000), CONST64(0x0010100400001000), CONST64(0x0010100010001000), CONST64(0x0010100410001000),
+ CONST64(0x0010100000101000), CONST64(0x0010100400101000), CONST64(0x0010100010101000), CONST64(0x0010100410101000),
+ CONST64(0x0010100000000010), CONST64(0x0010100400000010), CONST64(0x0010100010000010), CONST64(0x0010100410000010),
+ CONST64(0x0010100000100010), CONST64(0x0010100400100010), CONST64(0x0010100010100010), CONST64(0x0010100410100010),
+ CONST64(0x0010100000001010), CONST64(0x0010100400001010), CONST64(0x0010100010001010), CONST64(0x0010100410001010),
+ CONST64(0x0010100000101010), CONST64(0x0010100400101010), CONST64(0x0010100010101010), CONST64(0x0010100410101010),
+ CONST64(0x1010100000000000), CONST64(0x1010100400000000), CONST64(0x1010100010000000), CONST64(0x1010100410000000),
+ CONST64(0x1010100000100000), CONST64(0x1010100400100000), CONST64(0x1010100010100000), CONST64(0x1010100410100000),
+ CONST64(0x1010100000001000), CONST64(0x1010100400001000), CONST64(0x1010100010001000), CONST64(0x1010100410001000),
+ CONST64(0x1010100000101000), CONST64(0x1010100400101000), CONST64(0x1010100010101000), CONST64(0x1010100410101000),
+ CONST64(0x1010100000000010), CONST64(0x1010100400000010), CONST64(0x1010100010000010), CONST64(0x1010100410000010),
+ CONST64(0x1010100000100010), CONST64(0x1010100400100010), CONST64(0x1010100010100010), CONST64(0x1010100410100010),
+ CONST64(0x1010100000001010), CONST64(0x1010100400001010), CONST64(0x1010100010001010), CONST64(0x1010100410001010),
+ CONST64(0x1010100000101010), CONST64(0x1010100400101010), CONST64(0x1010100010101010), CONST64(0x1010100410101010)
+ },
+{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000040000000), CONST64(0x0000001040000000),
+ CONST64(0x0000000000400000), CONST64(0x0000001000400000), CONST64(0x0000000040400000), CONST64(0x0000001040400000),
+ CONST64(0x0000000000004000), CONST64(0x0000001000004000), CONST64(0x0000000040004000), CONST64(0x0000001040004000),
+ CONST64(0x0000000000404000), CONST64(0x0000001000404000), CONST64(0x0000000040404000), CONST64(0x0000001040404000),
+ CONST64(0x0000000000000040), CONST64(0x0000001000000040), CONST64(0x0000000040000040), CONST64(0x0000001040000040),
+ CONST64(0x0000000000400040), CONST64(0x0000001000400040), CONST64(0x0000000040400040), CONST64(0x0000001040400040),
+ CONST64(0x0000000000004040), CONST64(0x0000001000004040), CONST64(0x0000000040004040), CONST64(0x0000001040004040),
+ CONST64(0x0000000000404040), CONST64(0x0000001000404040), CONST64(0x0000000040404040), CONST64(0x0000001040404040),
+ CONST64(0x4000000000000000), CONST64(0x4000001000000000), CONST64(0x4000000040000000), CONST64(0x4000001040000000),
+ CONST64(0x4000000000400000), CONST64(0x4000001000400000), CONST64(0x4000000040400000), CONST64(0x4000001040400000),
+ CONST64(0x4000000000004000), CONST64(0x4000001000004000), CONST64(0x4000000040004000), CONST64(0x4000001040004000),
+ CONST64(0x4000000000404000), CONST64(0x4000001000404000), CONST64(0x4000000040404000), CONST64(0x4000001040404000),
+ CONST64(0x4000000000000040), CONST64(0x4000001000000040), CONST64(0x4000000040000040), CONST64(0x4000001040000040),
+ CONST64(0x4000000000400040), CONST64(0x4000001000400040), CONST64(0x4000000040400040), CONST64(0x4000001040400040),
+ CONST64(0x4000000000004040), CONST64(0x4000001000004040), CONST64(0x4000000040004040), CONST64(0x4000001040004040),
+ CONST64(0x4000000000404040), CONST64(0x4000001000404040), CONST64(0x4000000040404040), CONST64(0x4000001040404040),
+ CONST64(0x0040000000000000), CONST64(0x0040001000000000), CONST64(0x0040000040000000), CONST64(0x0040001040000000),
+ CONST64(0x0040000000400000), CONST64(0x0040001000400000), CONST64(0x0040000040400000), CONST64(0x0040001040400000),
+ CONST64(0x0040000000004000), CONST64(0x0040001000004000), CONST64(0x0040000040004000), CONST64(0x0040001040004000),
+ CONST64(0x0040000000404000), CONST64(0x0040001000404000), CONST64(0x0040000040404000), CONST64(0x0040001040404000),
+ CONST64(0x0040000000000040), CONST64(0x0040001000000040), CONST64(0x0040000040000040), CONST64(0x0040001040000040),
+ CONST64(0x0040000000400040), CONST64(0x0040001000400040), CONST64(0x0040000040400040), CONST64(0x0040001040400040),
+ CONST64(0x0040000000004040), CONST64(0x0040001000004040), CONST64(0x0040000040004040), CONST64(0x0040001040004040),
+ CONST64(0x0040000000404040), CONST64(0x0040001000404040), CONST64(0x0040000040404040), CONST64(0x0040001040404040),
+ CONST64(0x4040000000000000), CONST64(0x4040001000000000), CONST64(0x4040000040000000), CONST64(0x4040001040000000),
+ CONST64(0x4040000000400000), CONST64(0x4040001000400000), CONST64(0x4040000040400000), CONST64(0x4040001040400000),
+ CONST64(0x4040000000004000), CONST64(0x4040001000004000), CONST64(0x4040000040004000), CONST64(0x4040001040004000),
+ CONST64(0x4040000000404000), CONST64(0x4040001000404000), CONST64(0x4040000040404000), CONST64(0x4040001040404000),
+ CONST64(0x4040000000000040), CONST64(0x4040001000000040), CONST64(0x4040000040000040), CONST64(0x4040001040000040),
+ CONST64(0x4040000000400040), CONST64(0x4040001000400040), CONST64(0x4040000040400040), CONST64(0x4040001040400040),
+ CONST64(0x4040000000004040), CONST64(0x4040001000004040), CONST64(0x4040000040004040), CONST64(0x4040001040004040),
+ CONST64(0x4040000000404040), CONST64(0x4040001000404040), CONST64(0x4040000040404040), CONST64(0x4040001040404040),
+ CONST64(0x0000400000000000), CONST64(0x0000401000000000), CONST64(0x0000400040000000), CONST64(0x0000401040000000),
+ CONST64(0x0000400000400000), CONST64(0x0000401000400000), CONST64(0x0000400040400000), CONST64(0x0000401040400000),
+ CONST64(0x0000400000004000), CONST64(0x0000401000004000), CONST64(0x0000400040004000), CONST64(0x0000401040004000),
+ CONST64(0x0000400000404000), CONST64(0x0000401000404000), CONST64(0x0000400040404000), CONST64(0x0000401040404000),
+ CONST64(0x0000400000000040), CONST64(0x0000401000000040), CONST64(0x0000400040000040), CONST64(0x0000401040000040),
+ CONST64(0x0000400000400040), CONST64(0x0000401000400040), CONST64(0x0000400040400040), CONST64(0x0000401040400040),
+ CONST64(0x0000400000004040), CONST64(0x0000401000004040), CONST64(0x0000400040004040), CONST64(0x0000401040004040),
+ CONST64(0x0000400000404040), CONST64(0x0000401000404040), CONST64(0x0000400040404040), CONST64(0x0000401040404040),
+ CONST64(0x4000400000000000), CONST64(0x4000401000000000), CONST64(0x4000400040000000), CONST64(0x4000401040000000),
+ CONST64(0x4000400000400000), CONST64(0x4000401000400000), CONST64(0x4000400040400000), CONST64(0x4000401040400000),
+ CONST64(0x4000400000004000), CONST64(0x4000401000004000), CONST64(0x4000400040004000), CONST64(0x4000401040004000),
+ CONST64(0x4000400000404000), CONST64(0x4000401000404000), CONST64(0x4000400040404000), CONST64(0x4000401040404000),
+ CONST64(0x4000400000000040), CONST64(0x4000401000000040), CONST64(0x4000400040000040), CONST64(0x4000401040000040),
+ CONST64(0x4000400000400040), CONST64(0x4000401000400040), CONST64(0x4000400040400040), CONST64(0x4000401040400040),
+ CONST64(0x4000400000004040), CONST64(0x4000401000004040), CONST64(0x4000400040004040), CONST64(0x4000401040004040),
+ CONST64(0x4000400000404040), CONST64(0x4000401000404040), CONST64(0x4000400040404040), CONST64(0x4000401040404040),
+ CONST64(0x0040400000000000), CONST64(0x0040401000000000), CONST64(0x0040400040000000), CONST64(0x0040401040000000),
+ CONST64(0x0040400000400000), CONST64(0x0040401000400000), CONST64(0x0040400040400000), CONST64(0x0040401040400000),
+ CONST64(0x0040400000004000), CONST64(0x0040401000004000), CONST64(0x0040400040004000), CONST64(0x0040401040004000),
+ CONST64(0x0040400000404000), CONST64(0x0040401000404000), CONST64(0x0040400040404000), CONST64(0x0040401040404000),
+ CONST64(0x0040400000000040), CONST64(0x0040401000000040), CONST64(0x0040400040000040), CONST64(0x0040401040000040),
+ CONST64(0x0040400000400040), CONST64(0x0040401000400040), CONST64(0x0040400040400040), CONST64(0x0040401040400040),
+ CONST64(0x0040400000004040), CONST64(0x0040401000004040), CONST64(0x0040400040004040), CONST64(0x0040401040004040),
+ CONST64(0x0040400000404040), CONST64(0x0040401000404040), CONST64(0x0040400040404040), CONST64(0x0040401040404040),
+ CONST64(0x4040400000000000), CONST64(0x4040401000000000), CONST64(0x4040400040000000), CONST64(0x4040401040000000),
+ CONST64(0x4040400000400000), CONST64(0x4040401000400000), CONST64(0x4040400040400000), CONST64(0x4040401040400000),
+ CONST64(0x4040400000004000), CONST64(0x4040401000004000), CONST64(0x4040400040004000), CONST64(0x4040401040004000),
+ CONST64(0x4040400000404000), CONST64(0x4040401000404000), CONST64(0x4040400040404000), CONST64(0x4040401040404000),
+ CONST64(0x4040400000000040), CONST64(0x4040401000000040), CONST64(0x4040400040000040), CONST64(0x4040401040000040),
+ CONST64(0x4040400000400040), CONST64(0x4040401000400040), CONST64(0x4040400040400040), CONST64(0x4040401040400040),
+ CONST64(0x4040400000004040), CONST64(0x4040401000004040), CONST64(0x4040400040004040), CONST64(0x4040401040004040),
+ CONST64(0x4040400000404040), CONST64(0x4040401000404040), CONST64(0x4040400040404040), CONST64(0x4040401040404040)
+ }};
+
+#endif
+
+
+static void cookey(const ulong32 *raw1, ulong32 *keyout);
+
+#ifdef LTC_CLEAN_STACK
+static void s_deskey(const unsigned char *key, short edf, ulong32 *keyout)
+#else
+static void deskey(const unsigned char *key, short edf, ulong32 *keyout)
+#endif
+{
+ ulong32 i, j, l, m, n, kn[32];
+ unsigned char pc1m[56], pcr[56];
+
+ for (j=0; j < 56; j++) {
+ l = (ulong32)pc1[j];
+ m = l & 7;
+ pc1m[j] = (unsigned char)((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
+ }
+
+ for (i=0; i < 16; i++) {
+ if (edf == DE1) {
+ m = (15 - i) << 1;
+ } else {
+ m = i << 1;
+ }
+ n = m + 1;
+ kn[m] = kn[n] = 0L;
+ for (j=0; j < 28; j++) {
+ l = j + (ulong32)totrot[i];
+ if (l < 28) {
+ pcr[j] = pc1m[l];
+ } else {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+ for (/*j = 28*/; j < 56; j++) {
+ l = j + (ulong32)totrot[i];
+ if (l < 56) {
+ pcr[j] = pc1m[l];
+ } else {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+ for (j=0; j < 24; j++) {
+ if ((int)pcr[(int)pc2[j]] != 0) {
+ kn[m] |= bigbyte[j];
+ }
+ if ((int)pcr[(int)pc2[j+24]] != 0) {
+ kn[n] |= bigbyte[j];
+ }
+ }
+ }
+
+ cookey(kn, keyout);
+}
+
+#ifdef LTC_CLEAN_STACK
+static void deskey(const unsigned char *key, short edf, ulong32 *keyout)
+{
+ s_deskey(key, edf, keyout);
+ burn_stack(sizeof(int)*5 + sizeof(ulong32)*32 + sizeof(unsigned char)*112);
+}
+#endif
+
+#ifdef LTC_CLEAN_STACK
+static void s_cookey(const ulong32 *raw1, ulong32 *keyout)
+#else
+static void cookey(const ulong32 *raw1, ulong32 *keyout)
+#endif
+{
+ ulong32 *cook;
+ const ulong32 *raw0;
+ ulong32 dough[32];
+ int i;
+
+ cook = dough;
+ for(i=0; i < 16; i++, raw1++)
+ {
+ raw0 = raw1++;
+ *cook = (*raw0 & 0x00fc0000L) << 6;
+ *cook |= (*raw0 & 0x00000fc0L) << 10;
+ *cook |= (*raw1 & 0x00fc0000L) >> 10;
+ *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
+ *cook = (*raw0 & 0x0003f000L) << 12;
+ *cook |= (*raw0 & 0x0000003fL) << 16;
+ *cook |= (*raw1 & 0x0003f000L) >> 4;
+ *cook++ |= (*raw1 & 0x0000003fL);
+ }
+
+ XMEMCPY(keyout, dough, sizeof(dough));
+}
+
+#ifdef LTC_CLEAN_STACK
+static void cookey(const ulong32 *raw1, ulong32 *keyout)
+{
+ s_cookey(raw1, keyout);
+ burn_stack(sizeof(ulong32 *) * 2 + sizeof(ulong32)*32 + sizeof(int));
+}
+#endif
+
+#ifndef LTC_CLEAN_STACK
+static void desfunc(ulong32 *block, const ulong32 *keys)
+#else
+static void s_desfunc(ulong32 *block, const ulong32 *keys)
+#endif
+{
+ ulong32 work, right, leftt;
+ int cur_round;
+
+ leftt = block[0];
+ right = block[1];
+
+#ifdef LTC_SMALL_CODE
+ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
+ right ^= work;
+ leftt ^= (work << 4);
+
+ work = ((leftt >> 16) ^ right) & 0x0000ffffL;
+ right ^= work;
+ leftt ^= (work << 16);
+
+ work = ((right >> 2) ^ leftt) & 0x33333333L;
+ leftt ^= work;
+ right ^= (work << 2);
+
+ work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
+ leftt ^= work;
+ right ^= (work << 8);
+
+ right = ROLc(right, 1);
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+
+ leftt ^= work;
+ right ^= work;
+ leftt = ROLc(leftt, 1);
+#else
+ {
+ ulong64 tmp;
+ tmp = des_ip[0][LTC_BYTE(leftt, 0)] ^
+ des_ip[1][LTC_BYTE(leftt, 1)] ^
+ des_ip[2][LTC_BYTE(leftt, 2)] ^
+ des_ip[3][LTC_BYTE(leftt, 3)] ^
+ des_ip[4][LTC_BYTE(right, 0)] ^
+ des_ip[5][LTC_BYTE(right, 1)] ^
+ des_ip[6][LTC_BYTE(right, 2)] ^
+ des_ip[7][LTC_BYTE(right, 3)];
+ leftt = (ulong32)(tmp >> 32);
+ right = (ulong32)(tmp & 0xFFFFFFFFUL);
+ }
+#endif
+
+ for (cur_round = 0; cur_round < 8; cur_round++) {
+ work = RORc(right, 4) ^ *keys++;
+ leftt ^= SP7[work & 0x3fL]
+ ^ SP5[(work >> 8) & 0x3fL]
+ ^ SP3[(work >> 16) & 0x3fL]
+ ^ SP1[(work >> 24) & 0x3fL];
+ work = right ^ *keys++;
+ leftt ^= SP8[ work & 0x3fL]
+ ^ SP6[(work >> 8) & 0x3fL]
+ ^ SP4[(work >> 16) & 0x3fL]
+ ^ SP2[(work >> 24) & 0x3fL];
+
+ work = RORc(leftt, 4) ^ *keys++;
+ right ^= SP7[ work & 0x3fL]
+ ^ SP5[(work >> 8) & 0x3fL]
+ ^ SP3[(work >> 16) & 0x3fL]
+ ^ SP1[(work >> 24) & 0x3fL];
+ work = leftt ^ *keys++;
+ right ^= SP8[ work & 0x3fL]
+ ^ SP6[(work >> 8) & 0x3fL]
+ ^ SP4[(work >> 16) & 0x3fL]
+ ^ SP2[(work >> 24) & 0x3fL];
+ }
+
+#ifdef LTC_SMALL_CODE
+ right = RORc(right, 1);
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = RORc(leftt, 1);
+ work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
+ right ^= work;
+ leftt ^= (work << 8);
+ /* -- */
+ work = ((leftt >> 2) ^ right) & 0x33333333L;
+ right ^= work;
+ leftt ^= (work << 2);
+ work = ((right >> 16) ^ leftt) & 0x0000ffffL;
+ leftt ^= work;
+ right ^= (work << 16);
+ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
+ leftt ^= work;
+ right ^= (work << 4);
+#else
+ {
+ ulong64 tmp;
+ tmp = des_fp[0][LTC_BYTE(leftt, 0)] ^
+ des_fp[1][LTC_BYTE(leftt, 1)] ^
+ des_fp[2][LTC_BYTE(leftt, 2)] ^
+ des_fp[3][LTC_BYTE(leftt, 3)] ^
+ des_fp[4][LTC_BYTE(right, 0)] ^
+ des_fp[5][LTC_BYTE(right, 1)] ^
+ des_fp[6][LTC_BYTE(right, 2)] ^
+ des_fp[7][LTC_BYTE(right, 3)];
+ leftt = (ulong32)(tmp >> 32);
+ right = (ulong32)(tmp & 0xFFFFFFFFUL);
+ }
+#endif
+
+ block[0] = right;
+ block[1] = leftt;
+}
+
+#ifdef LTC_CLEAN_STACK
+static void desfunc(ulong32 *block, const ulong32 *keys)
+{
+ s_desfunc(block, keys);
+ burn_stack(sizeof(ulong32) * 4 + sizeof(int));
+}
+#endif
+
+ /**
+ Initialize the DES block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (num_rounds != 0 && num_rounds != 16) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (keylen != 8) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ deskey(key, EN0, skey->des.ek);
+ deskey(key, DE1, skey->des.dk);
+
+ return CRYPT_OK;
+}
+
+ /**
+ Initialize the DES-X block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int desx_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ if(num_rounds != 0 && num_rounds != 16) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (keylen != 24) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ deskey(key, EN0, skey->desx.ek);
+ deskey(key, DE1, skey->desx.dk);
+
+ LOAD32H(skey->desx.k[0][0], key + 8);
+ LOAD32H(skey->desx.k[0][1], key + 12);
+ LOAD32H(skey->desx.k[1][0], key + 16);
+ LOAD32H(skey->desx.k[1][1], key + 20);
+
+ return CRYPT_OK;
+}
+
+ /**
+ Initialize the 3DES-EDE block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if(num_rounds != 0 && num_rounds != 16) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (keylen != 24 && keylen != 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ deskey(key, EN0, skey->des3.ek[0]);
+ deskey(key+8, DE1, skey->des3.ek[1]);
+ if (keylen == 24) {
+ deskey(key+16, EN0, skey->des3.ek[2]);
+ } else {
+ /* two-key 3DES: K3=K1 */
+ deskey(key, EN0, skey->des3.ek[2]);
+ }
+
+ deskey(key, DE1, skey->des3.dk[2]);
+ deskey(key+8, EN0, skey->des3.dk[1]);
+ if (keylen == 24) {
+ deskey(key+16, DE1, skey->des3.dk[0]);
+ } else {
+ /* two-key 3DES: K3=K1 */
+ deskey(key, DE1, skey->des3.dk[0]);
+ }
+
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with DES
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ ulong32 work[2];
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ LOAD32H(work[0], pt+0);
+ LOAD32H(work[1], pt+4);
+ desfunc(work, skey->des.ek);
+ STORE32H(work[0],ct+0);
+ STORE32H(work[1],ct+4);
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with DES
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ ulong32 work[2];
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ LOAD32H(work[0], ct+0);
+ LOAD32H(work[1], ct+4);
+ desfunc(work, skey->des.dk);
+ STORE32H(work[0],pt+0);
+ STORE32H(work[1],pt+4);
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with DES-X
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int desx_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ ulong32 work[2];
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ LOAD32H(work[0], pt+0);
+ LOAD32H(work[1], pt+4);
+ work[0] ^= skey->desx.k[0][0];
+ work[1] ^= skey->desx.k[0][1];
+ desfunc(work, skey->desx.ek);
+ work[0] ^= skey->desx.k[1][0];
+ work[1] ^= skey->desx.k[1][1];
+ STORE32H(work[0],ct+0);
+ STORE32H(work[1],ct+4);
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with DES-X
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int desx_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ ulong32 work[2];
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ LOAD32H(work[0], ct+0);
+ LOAD32H(work[1], ct+4);
+ work[0] ^= skey->desx.k[1][0];
+ work[1] ^= skey->desx.k[1][1];
+ desfunc(work, skey->des.dk);
+ work[0] ^= skey->desx.k[0][0];
+ work[1] ^= skey->desx.k[0][1];
+ STORE32H(work[0],pt+0);
+ STORE32H(work[1],pt+4);
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with 3DES-EDE
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ ulong32 work[2];
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ LOAD32H(work[0], pt+0);
+ LOAD32H(work[1], pt+4);
+ desfunc(work, skey->des3.ek[0]);
+ desfunc(work, skey->des3.ek[1]);
+ desfunc(work, skey->des3.ek[2]);
+ STORE32H(work[0],ct+0);
+ STORE32H(work[1],ct+4);
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with 3DES-EDE
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ ulong32 work[2];
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ LOAD32H(work[0], ct+0);
+ LOAD32H(work[1], ct+4);
+ desfunc(work, skey->des3.dk[0]);
+ desfunc(work, skey->des3.dk[1]);
+ desfunc(work, skey->des3.dk[2]);
+ STORE32H(work[0],pt+0);
+ STORE32H(work[1],pt+4);
+ return CRYPT_OK;
+}
+
+/**
+ Performs a self-test of the DES block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int des_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct des_test_case {
+ unsigned char key[8], txt[8], out[8];
+ } cases[] = {
+ { { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 },
+ { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA },
+ { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F },
+ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 },
+ { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF },
+ { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F },
+ { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 },
+ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A },
+ { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+
+ { { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x95, 0xA8, 0xD7, 0x28, 0x13, 0xDA, 0xA9, 0x4D } },
+ { { 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0E, 0xEC, 0x14, 0x87, 0xDD, 0x8C, 0x26, 0xD5 } },
+ { { 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7A, 0xD1, 0x6F, 0xFB, 0x79, 0xC4, 0x59, 0x26 } },
+ { { 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xD3, 0x74, 0x62, 0x94, 0xCA, 0x6A, 0x6C, 0xF3 } },
+ { { 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x80, 0x9F, 0x5F, 0x87, 0x3C, 0x1F, 0xD7, 0x61 } },
+ { { 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xC0, 0x2F, 0xAF, 0xFE, 0xC9, 0x89, 0xD1, 0xFC } },
+ { { 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x15, 0xAA, 0x1D, 0x33, 0xE7, 0x2F, 0x10 } },
+ { { 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x20, 0x55, 0x12, 0x33, 0x50, 0xC0, 0x08, 0x58 } },
+ { { 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xDF, 0x3B, 0x99, 0xD6, 0x57, 0x73, 0x97, 0xC8 } },
+ { { 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x31, 0xFE, 0x17, 0x36, 0x9B, 0x52, 0x88, 0xC9 } },
+ { { 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xDF, 0xDD, 0x3C, 0xC6, 0x4D, 0xAE, 0x16, 0x42 } },
+ { { 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x17, 0x8C, 0x83, 0xCE, 0x2B, 0x39, 0x9D, 0x94 } },
+ { { 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x50, 0xF6, 0x36, 0x32, 0x4A, 0x9B, 0x7F, 0x80 } },
+ { { 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xA8, 0x46, 0x8E, 0xE3, 0xBC, 0x18, 0xF0, 0x6D } },
+ { { 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xA2, 0xDC, 0x9E, 0x92, 0xFD, 0x3C, 0xDE, 0x92 } },
+ { { 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xCA, 0xC0, 0x9F, 0x79, 0x7D, 0x03, 0x12, 0x87 } },
+ { { 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x90, 0xBA, 0x68, 0x0B, 0x22, 0xAE, 0xB5, 0x25 } },
+ { { 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xCE, 0x7A, 0x24, 0xF3, 0x50, 0xE2, 0x80, 0xB6 } },
+ { { 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x88, 0x2B, 0xFF, 0x0A, 0xA0, 0x1A, 0x0B, 0x87 } },
+ { { 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xC2 } },
+ { { 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xC7, 0x15, 0x16, 0xC2, 0x9C, 0x75, 0xD1, 0x70 } },
+ { { 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x51, 0x99, 0xC2, 0x9A, 0x52, 0xC9, 0xF0, 0x59 } },
+ { { 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xC2, 0x2F, 0x0A, 0x29, 0x4A, 0x71, 0xF2, 0x9F } },
+ { { 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xEE, 0x37, 0x14, 0x83, 0x71, 0x4C, 0x02, 0xEA } },
+ { { 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xA8, 0x1F, 0xBD, 0x44, 0x8F, 0x9E, 0x52, 0x2F } },
+ { { 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4F, 0x64, 0x4C, 0x92, 0xE1, 0x92, 0xDF, 0xED } },
+ { { 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x1A, 0xFA, 0x9A, 0x66, 0xA6, 0xDF, 0x92, 0xAE } },
+ { { 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xB3, 0xC1, 0xCC, 0x71, 0x5C, 0xB8, 0x79, 0xD8 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x19, 0xD0, 0x32, 0xE6, 0x4A, 0xB0, 0xBD, 0x8B } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3C, 0xFA, 0xA7, 0xA7, 0xDC, 0x87, 0x20, 0xDC } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xB7, 0x26, 0x5F, 0x7F, 0x44, 0x7A, 0xC6, 0xF3 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x9D, 0xB7, 0x3B, 0x3C, 0x0D, 0x16, 0x3F, 0x54 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x81, 0x81, 0xB6, 0x5B, 0xAB, 0xF4, 0xA9, 0x75 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x93, 0xC9, 0xB6, 0x40, 0x42, 0xEA, 0xA2, 0x40 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x86, 0x38, 0x80, 0x9E, 0x87, 0x87, 0x87, 0xA0 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x41, 0xB9, 0xA7, 0x9A, 0xF7, 0x9A, 0xC2, 0x08 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7A, 0x9B, 0xE4, 0x2F, 0x20, 0x09, 0xA8, 0x92 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x29, 0x03, 0x8D, 0x56, 0xBA, 0x6D, 0x27, 0x45 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x54, 0x95, 0xC6, 0xAB, 0xF1, 0xE5, 0xDF, 0x51 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xAE, 0x13, 0xDB, 0xD5, 0x61, 0x48, 0x89, 0x33 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x02, 0x4D, 0x1F, 0xFA, 0x89, 0x04, 0xE3, 0x89 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xD1, 0x39, 0x97, 0x12, 0xF9, 0x9B, 0xF0, 0x2E } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x14, 0xC1, 0xD7, 0xC1, 0xCF, 0xFE, 0xC7, 0x9E } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x1D, 0xE5, 0x27, 0x9D, 0xAE, 0x3B, 0xED, 0x6F } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xE9, 0x41, 0xA3, 0x3F, 0x85, 0x50, 0x13, 0x03 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xDA, 0x99, 0xDB, 0xBC, 0x9A, 0x03, 0xF3, 0x79 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xB7, 0xFC, 0x92, 0xF9, 0x1D, 0x8E, 0x92, 0xE9 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xAE, 0x8E, 0x5C, 0xAA, 0x3C, 0xA0, 0x4E, 0x85 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x9C, 0xC6, 0x2D, 0xF4, 0x3B, 0x6E, 0xED, 0x74 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xD8, 0x63, 0xDB, 0xB5, 0xC5, 0x9A, 0x91, 0xA0 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xA1, 0xAB, 0x21, 0x90, 0x54, 0x5B, 0x91, 0xD7 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x08, 0x75, 0x04, 0x1E, 0x64, 0xC5, 0x70, 0xF7 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x5A, 0x59, 0x45, 0x28, 0xBE, 0xBE, 0xF1, 0xCC } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xFC, 0xDB, 0x32, 0x91, 0xDE, 0x21, 0xF0, 0xC0 } },
+ { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x86, 0x9E, 0xFD, 0x7F, 0x9F, 0x26, 0x5A, 0x09 } },
+
+ /*** more test cases you could add if you are not convinced (the above test cases aren't really too good):
+
+ key plaintext ciphertext
+ 0000000000000000 0000000000000000 8CA64DE9C1B123A7
+ FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58
+ 3000000000000000 1000000000000001 958E6E627A05557B
+ 1111111111111111 1111111111111111 F40379AB9E0EC533
+ 0123456789ABCDEF 1111111111111111 17668DFC7292532D
+ 1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD
+ 0000000000000000 0000000000000000 8CA64DE9C1B123A7
+ FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4
+ 7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B
+ 0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271
+ 07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A
+ 3849674C2602319E 51454B582DDF440A 7178876E01F19B2A
+ 04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095
+ 0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B
+ 0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09
+ 43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A
+ 07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F
+ 04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088
+ 37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77
+ 1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A
+ 584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56
+ 025816164629B007 480D39006EE762F2 A1F9915541020B56
+ 49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556
+ 4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC
+ 49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A
+ 018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41
+ 1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793
+ 0101010101010101 0123456789ABCDEF 617B3A0CE8F07100
+ 1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606
+ E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7
+ 0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451
+ FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE
+ 0123456789ABCDEF 0000000000000000 D5D44FF720683D0D
+ FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2
+
+ http://www.ecs.soton.ac.uk/~prw99r/ez438/vectors.txt
+ ***/
+ };
+ unsigned char key[8], pt[8], ct[8], tmp[8];
+ symmetric_key skey;
+ int i, err;
+
+ for (i = 0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++)
+ {
+ if ((err = des_setup(cases[i].key, 8, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+
+ des_ecb_encrypt(cases[i].txt, ct, &skey);
+
+ if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "DES Encrypt", i) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ des_ecb_decrypt(ct, pt, &skey);
+
+ if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "DES Decrypt", i) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */
+
+ for (i = 0; i < 8; i++) key[i] = i;
+
+ if ((err = des_setup(key, 8, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+
+ for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0;
+ for (i = 0; i < 1000; i++) des_ecb_encrypt(tmp, tmp, &skey);
+ for (i = 0; i < 1000; i++) des_ecb_decrypt(tmp, tmp, &skey);
+
+ if (compare_testvector(tmp, 8, pt, 8, "DES", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+ #endif
+}
+
+int desx_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ unsigned char key[24], pt[8], tmp[8];
+ symmetric_key skey;
+ int i, err;
+
+ if ((err = des_test()) != CRYPT_OK) {
+ return err;
+ }
+
+ /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */
+
+ for (i = 0; i < 24; i++) key[i] = i;
+
+ if ((err = desx_setup(key, 24, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+
+ for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0;
+ for (i = 0; i < 1000; i++) desx_ecb_encrypt(tmp, tmp, &skey);
+ for (i = 0; i < 1000; i++) desx_ecb_decrypt(tmp, tmp, &skey);
+
+ if (compare_testvector(tmp, 8, pt, 8, "DES-X", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+ #endif
+}
+
+int des3_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct des3_test_case {
+ unsigned char key[16], txt[8], out[8];
+ } cases[] = {
+ /*
+ https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/des/Triple-Des-2-Key-128-64.unverified.test-vectors
+ */
+ { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xFA, 0xFD, 0x50, 0x84, 0x37, 0x4F, 0xCE, 0x34 } },
+ { { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x60, 0xCC, 0x37, 0xB7, 0xB5, 0x37, 0xA1, 0xDC } },
+ { { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xBE, 0x3E, 0x73, 0x04, 0xFE, 0x92, 0xC2, 0xBC } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 },
+ { 0xE5, 0xA9, 0xE3, 0x80, 0x03, 0xA5, 0xA0, 0xFD },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
+ { 0xE4, 0xFC, 0x19, 0xD6, 0x94, 0x63, 0xB7, 0x83 },
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 } },
+ };
+ unsigned char key[24], pt[8], ct[8], tmp[8];
+ symmetric_key skey;
+ int i, err;
+
+ if ((err = des_test()) != CRYPT_OK) {
+ return err;
+ }
+
+ for (i = 0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++)
+ {
+ if ((err = des3_setup(cases[i].key, 16, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+
+ des3_ecb_encrypt(cases[i].txt, ct, &skey);
+
+ if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "3DES Encrypt", i) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ des3_ecb_decrypt(ct, pt, &skey);
+
+ if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "3DES Decrypt", i) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */
+
+ for (i = 0; i < 24; i++) key[i] = i;
+
+ if ((err = des3_setup(key, 24, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+
+ for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0;
+ for (i = 0; i < 1000; i++) des3_ecb_encrypt(tmp, tmp, &skey);
+ for (i = 0; i < 1000; i++) des3_ecb_decrypt(tmp, tmp, &skey);
+
+ if (compare_testvector(tmp, 8, pt, 8, "3DES", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void des_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void desx_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void des3_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int des_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if(*keysize < 8) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ *keysize = 8;
+ return CRYPT_OK;
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int desx_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if(*keysize < 24) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ *keysize = 24;
+ return CRYPT_OK;
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int des3_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize < 24) {
+ *keysize = 16;
+ return CRYPT_OK;
+ }
+ *keysize = 24;
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/ciphers/idea.c b/Sources/libtomcrypt/ciphers/idea.c
new file mode 100644
index 00000000..b195a4c9
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/idea.c
@@ -0,0 +1,250 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* Based on idea.cpp - originally written and placed in the public domain by Wei Dai
+ https://github.com/weidai11/cryptopp/blob/master/idea.cpp
+
+ Patents should be expired. On 2017-10-16 wikipedia says:
+ https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
+
+ A patent application for IDEA was first filed in Switzerland (CH A 1690/90) on May 18, 1990,
+ then an international patent application was filed under the Patent Cooperation Treaty on
+ May 16, 1991. Patents were eventually granted in Austria, France, Germany, Italy, the Netherlands,
+ Spain, Sweden, Switzerland, the United Kingdom, (European Patent Register entry for European
+ patent no. 0482154, filed May 16, 1991, issued June 22, 1994 and expired May 16, 2011),
+ the United States (U.S. Patent 5,214,703, issued May 25, 1993 and expired January 7, 2012)
+ and Japan (JP 3225440) (expired May 16, 2011).
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_IDEA
+
+const struct ltc_cipher_descriptor idea_desc = {
+ "idea",
+ 24, /* cipher_ID */
+ 16, 16, 8, 8, /* min_key_len, max_key_len, block_len, default_rounds */
+ &idea_setup,
+ &idea_ecb_encrypt,
+ &idea_ecb_decrypt,
+ &idea_test,
+ &idea_done,
+ &idea_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+typedef unsigned short int ushort16;
+
+#define LOW16(x) ((x)&0xffff) /* compiler should be able to optimize this away if x is 16 bits */
+#define HIGH16(x) ((x)>>16)
+#define MUL(a,b) { \
+ ulong32 p = (ulong32)LOW16(a) * b; \
+ if (p) { \
+ p = LOW16(p) - HIGH16(p); \
+ a = (ushort16)p - (ushort16)HIGH16(p); \
+ } \
+ else \
+ a = 1 - a - b; \
+ }
+#define STORE16(x,y) { (y)[0] = (unsigned char)(((x)>>8)&255); (y)[1] = (unsigned char)((x)&255); }
+#define LOAD16(x,y) { x = ((ushort16)((y)[0] & 255)<<8) | ((ushort16)((y)[1] & 255)); }
+
+static ushort16 s_mul_inv(ushort16 x)
+{
+ ushort16 y = x;
+ unsigned i;
+
+ for (i = 0; i < 15; i++) {
+ MUL(y, LOW16(y));
+ MUL(y, x);
+ }
+ return LOW16(y);
+}
+
+static ushort16 s_add_inv(ushort16 x)
+{
+ return LOW16(0 - x);
+}
+
+static int s_setup_key(const unsigned char *key, symmetric_key *skey)
+{
+ int i, j;
+ ushort16 *e_key = skey->idea.ek;
+ ushort16 *d_key = skey->idea.dk;
+
+ /* prepare enc key */
+ for (i = 0; i < 8; i++) {
+ LOAD16(e_key[i], key + 2 * i);
+ }
+ for (; i < LTC_IDEA_KEYLEN; i++) {
+ j = (i - i % 8) - 8;
+ e_key[i] = LOW16((e_key[j+(i+1)%8] << 9) | (e_key[j+(i+2)%8] >> 7));
+ }
+
+ /* prepare dec key */
+ for (i = 0; i < LTC_IDEA_ROUNDS; i++) {
+ d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]);
+ d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1+(i>0 ? 1 : 0)]);
+ d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2-(i>0 ? 1 : 0)]);
+ d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]);
+ d_key[i*6+4] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+4];
+ d_key[i*6+5] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+5];
+ }
+ d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]);
+ d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1]);
+ d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2]);
+ d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]);
+
+ return CRYPT_OK;
+}
+
+static int s_process_block(const unsigned char *in, unsigned char *out, const ushort16 *m_key)
+{
+ int i;
+ ushort16 x0, x1, x2, x3, t0, t1;
+
+ LOAD16(x0, in + 0);
+ LOAD16(x1, in + 2);
+ LOAD16(x2, in + 4);
+ LOAD16(x3, in + 6);
+
+ for (i = 0; i < LTC_IDEA_ROUNDS; i++) {
+ MUL(x0, m_key[i*6+0]);
+ x1 += m_key[i*6+1];
+ x2 += m_key[i*6+2];
+ MUL(x3, m_key[i*6+3]);
+ t0 = x0^x2;
+ MUL(t0, m_key[i*6+4]);
+ t1 = t0 + (x1^x3);
+ MUL(t1, m_key[i*6+5]);
+ t0 += t1;
+ x0 ^= t1;
+ x3 ^= t0;
+ t0 ^= x1;
+ x1 = x2^t1;
+ x2 = t0;
+ }
+
+ MUL(x0, m_key[LTC_IDEA_ROUNDS*6+0]);
+ x2 += m_key[LTC_IDEA_ROUNDS*6+1];
+ x1 += m_key[LTC_IDEA_ROUNDS*6+2];
+ MUL(x3, m_key[LTC_IDEA_ROUNDS*6+3]);
+
+ STORE16(x0, out + 0);
+ STORE16(x2, out + 2);
+ STORE16(x1, out + 4);
+ STORE16(x3, out + 6);
+
+ return CRYPT_OK;
+}
+
+int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (num_rounds != 0 && num_rounds != 8) return CRYPT_INVALID_ROUNDS;
+ if (keylen != 16) return CRYPT_INVALID_KEYSIZE;
+
+ return s_setup_key(key, skey);
+}
+
+int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_process_block(pt, ct, skey->idea.ek);
+#ifdef LTC_CLEAN_STACK
+ burn_stack(sizeof(ushort16) * 6 + sizeof(int));
+#endif
+ return err;
+}
+
+int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_process_block(ct, pt, skey->idea.dk);
+#ifdef LTC_CLEAN_STACK
+ burn_stack(sizeof(ushort16) * 6 + sizeof(int));
+#endif
+ return err;
+}
+
+void idea_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+int idea_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ *keysize = 16;
+ return CRYPT_OK;
+}
+
+int idea_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ unsigned char key[16], pt[8], ct[8];
+ } tests[] = {
+ {
+ /* key */ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* ct */ { 0xB1, 0xF5, 0xF7, 0xF8, 0x79, 0x01, 0x37, 0x0F }
+ },
+ {
+ /* key */ { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* ct */ { 0xB3, 0x92, 0x7D, 0xFF, 0xB6, 0x35, 0x86, 0x26 }
+ },
+ {
+ /* key */ { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* ct */ { 0xE9, 0x87, 0xE0, 0x02, 0x9F, 0xB9, 0x97, 0x85 }
+ },
+ {
+ /* key */ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* ct */ { 0x75, 0x4A, 0x03, 0xCE, 0x08, 0xDB, 0x7D, 0xAA }
+ },
+ {
+ /* key */ { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* ct */ { 0xF0, 0x15, 0xF9, 0xFB, 0x0C, 0xFC, 0x7E, 0x1C }
+ },
+ };
+
+ unsigned char buf[2][8];
+ symmetric_key key;
+ int err, x;
+
+ if (sizeof(ushort16) != 2) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ if ((err = idea_setup(tests[x].key, 16, 8, &key)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = idea_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(buf[0], 8, tests[x].ct, 8, "IDEA Encrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ if ((err = idea_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(buf[1], 8, tests[x].pt, 8, "IDEA Decrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/ciphers/kasumi.c b/Sources/libtomcrypt/ciphers/kasumi.c
new file mode 100644
index 00000000..1ade9d69
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/kasumi.c
@@ -0,0 +1,307 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file kasumi.c
+ Implementation of the 3GPP Kasumi block cipher
+ Derived from the 3GPP standard source code
+*/
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_KASUMI
+
+typedef unsigned u16;
+
+#define ROL16(x, y) ((((x)<<(y)) | ((x)>>(16-(y)))) & 0xFFFF)
+
+const struct ltc_cipher_descriptor kasumi_desc = {
+ "kasumi",
+ 21,
+ 16, 16, 8, 8,
+ &kasumi_setup,
+ &kasumi_ecb_encrypt,
+ &kasumi_ecb_decrypt,
+ &kasumi_test,
+ &kasumi_done,
+ &kasumi_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static u16 FI( u16 in, u16 subkey )
+{
+ u16 nine, seven;
+ static const u16 S7[128] = {
+ 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18,123, 33,
+ 55,113, 39,114, 21, 67, 65, 12, 47, 73, 46, 27, 25,111,124, 81,
+ 53, 9,121, 79, 52, 60, 58, 48,101,127, 40,120,104, 70, 71, 43,
+ 20,122, 72, 61, 23,109, 13,100, 77, 1, 16, 7, 82, 10,105, 98,
+ 117,116, 76, 11, 89,106, 0,125,118, 99, 86, 69, 30, 57,126, 87,
+ 112, 51, 17, 5, 95, 14, 90, 84, 91, 8, 35,103, 32, 97, 28, 66,
+ 102, 31, 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29,115, 44,
+ 64,107,108, 24,110, 83, 36, 78, 42, 19, 15, 41, 88,119, 59, 3 };
+ static const u16 S9[512] = {
+ 167,239,161,379,391,334, 9,338, 38,226, 48,358,452,385, 90,397,
+ 183,253,147,331,415,340, 51,362,306,500,262, 82,216,159,356,177,
+ 175,241,489, 37,206, 17, 0,333, 44,254,378, 58,143,220, 81,400,
+ 95, 3,315,245, 54,235,218,405,472,264,172,494,371,290,399, 76,
+ 165,197,395,121,257,480,423,212,240, 28,462,176,406,507,288,223,
+ 501,407,249,265, 89,186,221,428,164, 74,440,196,458,421,350,163,
+ 232,158,134,354, 13,250,491,142,191, 69,193,425,152,227,366,135,
+ 344,300,276,242,437,320,113,278, 11,243, 87,317, 36, 93,496, 27,
+ 487,446,482, 41, 68,156,457,131,326,403,339, 20, 39,115,442,124,
+ 475,384,508, 53,112,170,479,151,126,169, 73,268,279,321,168,364,
+ 363,292, 46,499,393,327,324, 24,456,267,157,460,488,426,309,229,
+ 439,506,208,271,349,401,434,236, 16,209,359, 52, 56,120,199,277,
+ 465,416,252,287,246, 6, 83,305,420,345,153,502, 65, 61,244,282,
+ 173,222,418, 67,386,368,261,101,476,291,195,430, 49, 79,166,330,
+ 280,383,373,128,382,408,155,495,367,388,274,107,459,417, 62,454,
+ 132,225,203,316,234, 14,301, 91,503,286,424,211,347,307,140,374,
+ 35,103,125,427, 19,214,453,146,498,314,444,230,256,329,198,285,
+ 50,116, 78,410, 10,205,510,171,231, 45,139,467, 29, 86,505, 32,
+ 72, 26,342,150,313,490,431,238,411,325,149,473, 40,119,174,355,
+ 185,233,389, 71,448,273,372, 55,110,178,322, 12,469,392,369,190,
+ 1,109,375,137,181, 88, 75,308,260,484, 98,272,370,275,412,111,
+ 336,318, 4,504,492,259,304, 77,337,435, 21,357,303,332,483, 18,
+ 47, 85, 25,497,474,289,100,269,296,478,270,106, 31,104,433, 84,
+ 414,486,394, 96, 99,154,511,148,413,361,409,255,162,215,302,201,
+ 266,351,343,144,441,365,108,298,251, 34,182,509,138,210,335,133,
+ 311,352,328,141,396,346,123,319,450,281,429,228,443,481, 92,404,
+ 485,422,248,297, 23,213,130,466, 22,217,283, 70,294,360,419,127,
+ 312,377, 7,468,194, 2,117,295,463,258,224,447,247,187, 80,398,
+ 284,353,105,390,299,471,470,184, 57,200,348, 63,204,188, 33,451,
+ 97, 30,310,219, 94,160,129,493, 64,179,263,102,189,207,114,402,
+ 438,477,387,122,192, 42,381, 5,145,118,180,449,293,323,136,380,
+ 43, 66, 60,455,341,445,202,432, 8,237, 15,376,436,464, 59,461};
+
+ /* The sixteen bit input is split into two unequal halves, *
+ * nine bits and seven bits - as is the subkey */
+
+ nine = (u16)(in>>7)&0x1FF;
+ seven = (u16)(in&0x7F);
+
+ /* Now run the various operations */
+ nine = (u16)(S9[nine] ^ seven);
+ seven = (u16)(S7[seven] ^ (nine & 0x7F));
+ seven ^= (subkey>>9);
+ nine ^= (subkey&0x1FF);
+ nine = (u16)(S9[nine] ^ seven);
+ seven = (u16)(S7[seven] ^ (nine & 0x7F));
+ return (u16)(seven<<9) + nine;
+}
+
+static ulong32 FO( ulong32 in, int round_no, const symmetric_key *key)
+{
+ u16 left, right;
+
+ /* Split the input into two 16-bit words */
+ left = (u16)(in>>16);
+ right = (u16) in&0xFFFF;
+
+ /* Now apply the same basic transformation three times */
+ left ^= key->kasumi.KOi1[round_no];
+ left = FI( left, key->kasumi.KIi1[round_no] );
+ left ^= right;
+
+ right ^= key->kasumi.KOi2[round_no];
+ right = FI( right, key->kasumi.KIi2[round_no] );
+ right ^= left;
+
+ left ^= key->kasumi.KOi3[round_no];
+ left = FI( left, key->kasumi.KIi3[round_no] );
+ left ^= right;
+
+ return (((ulong32)right)<<16)+left;
+}
+
+static ulong32 FL( ulong32 in, int round_no, const symmetric_key *key )
+{
+ u16 l, r, a, b;
+ /* split out the left and right halves */
+ l = (u16)(in>>16);
+ r = (u16)(in)&0xFFFF;
+ /* do the FL() operations */
+ a = (u16) (l & key->kasumi.KLi1[round_no]);
+ r ^= ROL16(a,1);
+ b = (u16)(r | key->kasumi.KLi2[round_no]);
+ l ^= ROL16(b,1);
+ /* put the two halves back together */
+
+ return (((ulong32)l)<<16) + r;
+}
+
+int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ ulong32 left, right, temp;
+ int n;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ LOAD32H(left, pt);
+ LOAD32H(right, pt+4);
+
+ for (n = 0; n <= 7; ) {
+ temp = FL(left, n, skey);
+ temp = FO(temp, n++, skey);
+ right ^= temp;
+ temp = FO(right, n, skey);
+ temp = FL(temp, n++, skey);
+ left ^= temp;
+ }
+
+ STORE32H(left, ct);
+ STORE32H(right, ct+4);
+
+ return CRYPT_OK;
+}
+
+int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ ulong32 left, right, temp;
+ int n;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ LOAD32H(left, ct);
+ LOAD32H(right, ct+4);
+
+ for (n = 7; n >= 0; ) {
+ temp = FO(right, n, skey);
+ temp = FL(temp, n--, skey);
+ left ^= temp;
+ temp = FL(left, n, skey);
+ temp = FO(temp, n--, skey);
+ right ^= temp;
+ }
+
+ STORE32H(left, pt);
+ STORE32H(right, pt+4);
+
+ return CRYPT_OK;
+}
+
+int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ static const u16 C[8] = { 0x0123,0x4567,0x89AB,0xCDEF, 0xFEDC,0xBA98,0x7654,0x3210 };
+ u16 ukey[8], Kprime[8];
+ int n;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (keylen != 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if (num_rounds != 0 && num_rounds != 8) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* Start by ensuring the subkeys are endian correct on a 16-bit basis */
+ for (n = 0; n < 8; n++ ) {
+ ukey[n] = (((u16)key[2*n]) << 8) | key[2*n+1];
+ }
+
+ /* Now build the K'[] keys */
+ for (n = 0; n < 8; n++) {
+ Kprime[n] = ukey[n] ^ C[n];
+ }
+
+ /* Finally construct the various sub keys */
+ for(n = 0; n < 8; n++) {
+ skey->kasumi.KLi1[n] = ROL16(ukey[n],1);
+ skey->kasumi.KLi2[n] = Kprime[(n+2)&0x7];
+ skey->kasumi.KOi1[n] = ROL16(ukey[(n+1)&0x7],5);
+ skey->kasumi.KOi2[n] = ROL16(ukey[(n+5)&0x7],8);
+ skey->kasumi.KOi3[n] = ROL16(ukey[(n+6)&0x7],13);
+ skey->kasumi.KIi1[n] = Kprime[(n+4)&0x7];
+ skey->kasumi.KIi2[n] = Kprime[(n+3)&0x7];
+ skey->kasumi.KIi3[n] = Kprime[(n+7)&0x7];
+ }
+
+ return CRYPT_OK;
+}
+
+void kasumi_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+int kasumi_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize >= 16) {
+ *keysize = 16;
+ return CRYPT_OK;
+ }
+ return CRYPT_INVALID_KEYSIZE;
+}
+
+int kasumi_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ unsigned char key[16], pt[8], ct[8];
+ } tests[] = {
+
+{
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4B, 0x58, 0xA7, 0x71, 0xAF, 0xC7, 0xE5, 0xE8 }
+},
+
+{
+ { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7E, 0xEF, 0x11, 0x3C, 0x95, 0xBB, 0x5A, 0x77 }
+},
+
+{
+ { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x5F, 0x14, 0x06, 0x86, 0xD7, 0xAD, 0x5A, 0x39 },
+},
+
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2E, 0x14, 0x91, 0xCF, 0x70, 0xAA, 0x46, 0x5D }
+},
+
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xB5, 0x45, 0x86, 0xF4, 0xAB, 0x9A, 0xE5, 0x46 }
+},
+
+};
+ unsigned char buf[2][8];
+ symmetric_key key;
+ int err, x;
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ if ((err = kasumi_setup(tests[x].key, 16, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = kasumi_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = kasumi_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(buf[1], 8, tests[x].pt, 8, "Kasumi Decrypt", x) ||
+ compare_testvector(buf[0], 8, tests[x].ct, 8, "Kasumi Encrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/ciphers/khazad.c b/Sources/libtomcrypt/ciphers/khazad.c
new file mode 100644
index 00000000..72cbda87
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/khazad.c
@@ -0,0 +1,840 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file khazad.c
+ Khazad implementation derived from public domain source
+ Authors: Paulo S.L.M. Barreto and Vincent Rijmen.
+*/
+
+#ifdef LTC_KHAZAD
+
+const struct ltc_cipher_descriptor khazad_desc = {
+ "khazad",
+ 18,
+ 16, 16, 8, 8,
+ &khazad_setup,
+ &khazad_ecb_encrypt,
+ &khazad_ecb_decrypt,
+ &khazad_test,
+ &khazad_done,
+ &khazad_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#define R 8
+
+static const ulong64 T0[256] = {
+ CONST64(0xbad3d268bbb96a01), CONST64(0x54fc4d19e59a66b1), CONST64(0x2f71bc93e26514cd), CONST64(0x749ccdb925871b51),
+ CONST64(0x53f55102f7a257a4), CONST64(0xd3686bb8d0d6be03), CONST64(0xd26b6fbdd6deb504), CONST64(0x4dd72964b35285fe),
+ CONST64(0x50f05d0dfdba4aad), CONST64(0xace98a26cf09e063), CONST64(0x8d8a0e83091c9684), CONST64(0xbfdcc679a5914d1a),
+ CONST64(0x7090ddad3da7374d), CONST64(0x52f65507f1aa5ca3), CONST64(0x9ab352c87ba417e1), CONST64(0x4cd42d61b55a8ef9),
+ CONST64(0xea238f65460320ac), CONST64(0xd56273a6c4e68411), CONST64(0x97a466f155cc68c2), CONST64(0xd16e63b2dcc6a80d),
+ CONST64(0x3355ccffaa85d099), CONST64(0x51f35908fbb241aa), CONST64(0x5bed712ac7e20f9c), CONST64(0xa6f7a204f359ae55),
+ CONST64(0xde7f5f81febec120), CONST64(0x48d83d75ad7aa2e5), CONST64(0xa8e59a32d729cc7f), CONST64(0x99b65ec771bc0ae8),
+ CONST64(0xdb704b90e096e63b), CONST64(0x3256c8faac8ddb9e), CONST64(0xb7c4e65195d11522), CONST64(0xfc19d72b32b3aace),
+ CONST64(0xe338ab48704b7393), CONST64(0x9ebf42dc63843bfd), CONST64(0x91ae7eef41fc52d0), CONST64(0x9bb056cd7dac1ce6),
+ CONST64(0xe23baf4d76437894), CONST64(0xbbd0d66dbdb16106), CONST64(0x41c319589b32f1da), CONST64(0x6eb2a5cb7957e517),
+ CONST64(0xa5f2ae0bf941b35c), CONST64(0xcb400bc08016564b), CONST64(0x6bbdb1da677fc20c), CONST64(0x95a26efb59dc7ecc),
+ CONST64(0xa1febe1fe1619f40), CONST64(0xf308eb1810cbc3e3), CONST64(0xb1cefe4f81e12f30), CONST64(0x0206080a0c10160e),
+ CONST64(0xcc4917db922e675e), CONST64(0xc45137f3a26e3f66), CONST64(0x1d2774694ee8cf53), CONST64(0x143c504478a09c6c),
+ CONST64(0xc3582be8b0560e73), CONST64(0x63a591f2573f9a34), CONST64(0xda734f95e69eed3c), CONST64(0x5de76934d3d2358e),
+ CONST64(0x5fe1613edfc22380), CONST64(0xdc79578bf2aed72e), CONST64(0x7d87e99413cf486e), CONST64(0xcd4a13de94266c59),
+ CONST64(0x7f81e19e1fdf5e60), CONST64(0x5aee752fc1ea049b), CONST64(0x6cb4adc17547f319), CONST64(0x5ce46d31d5da3e89),
+ CONST64(0xf704fb0c08ebefff), CONST64(0x266a98bed42d47f2), CONST64(0xff1cdb2438abb7c7), CONST64(0xed2a937e543b11b9),
+ CONST64(0xe825876f4a1336a2), CONST64(0x9dba4ed3699c26f4), CONST64(0x6fb1a1ce7f5fee10), CONST64(0x8e8f028c03048b8d),
+ CONST64(0x192b647d56c8e34f), CONST64(0xa0fdba1ae7699447), CONST64(0xf00de7171ad3deea), CONST64(0x89861e97113cba98),
+ CONST64(0x0f113c332278692d), CONST64(0x07091c1b12383115), CONST64(0xafec8629c511fd6a), CONST64(0xfb10cb30208b9bdb),
+ CONST64(0x0818202830405838), CONST64(0x153f54417ea8976b), CONST64(0x0d1734392e687f23), CONST64(0x040c101418202c1c),
+ CONST64(0x0103040506080b07), CONST64(0x64ac8de94507ab21), CONST64(0xdf7c5b84f8b6ca27), CONST64(0x769ac5b329970d5f),
+ CONST64(0x798bf9800bef6472), CONST64(0xdd7a538ef4a6dc29), CONST64(0x3d47f4c98ef5b2b3), CONST64(0x163a584e74b08a62),
+ CONST64(0x3f41fcc382e5a4bd), CONST64(0x3759dcebb2a5fc85), CONST64(0x6db7a9c4734ff81e), CONST64(0x3848e0d890dd95a8),
+ CONST64(0xb9d6de67b1a17708), CONST64(0x7395d1a237bf2a44), CONST64(0xe926836a4c1b3da5), CONST64(0x355fd4e1beb5ea8b),
+ CONST64(0x55ff491ce3926db6), CONST64(0x7193d9a83baf3c4a), CONST64(0x7b8df18a07ff727c), CONST64(0x8c890a860f149d83),
+ CONST64(0x7296d5a731b72143), CONST64(0x88851a921734b19f), CONST64(0xf607ff090ee3e4f8), CONST64(0x2a7ea882fc4d33d6),
+ CONST64(0x3e42f8c684edafba), CONST64(0x5ee2653bd9ca2887), CONST64(0x27699cbbd2254cf5), CONST64(0x46ca0543890ac0cf),
+ CONST64(0x0c14303c28607424), CONST64(0x65af89ec430fa026), CONST64(0x68b8bdd56d67df05), CONST64(0x61a399f85b2f8c3a),
+ CONST64(0x03050c0f0a181d09), CONST64(0xc15e23e2bc46187d), CONST64(0x57f94116ef827bb8), CONST64(0xd6677fa9cefe9918),
+ CONST64(0xd976439aec86f035), CONST64(0x58e87d25cdfa1295), CONST64(0xd875479fea8efb32), CONST64(0x66aa85e34917bd2f),
+ CONST64(0xd7647bacc8f6921f), CONST64(0x3a4ee8d29ccd83a6), CONST64(0xc84507cf8a0e4b42), CONST64(0x3c44f0cc88fdb9b4),
+ CONST64(0xfa13cf35268390dc), CONST64(0x96a762f453c463c5), CONST64(0xa7f4a601f551a552), CONST64(0x98b55ac277b401ef),
+ CONST64(0xec29977b52331abe), CONST64(0xb8d5da62b7a97c0f), CONST64(0xc7543bfca876226f), CONST64(0xaeef822cc319f66d),
+ CONST64(0x69bbb9d06b6fd402), CONST64(0x4bdd317aa762bfec), CONST64(0xabe0963ddd31d176), CONST64(0xa9e69e37d121c778),
+ CONST64(0x67a981e64f1fb628), CONST64(0x0a1e28223c504e36), CONST64(0x47c901468f02cbc8), CONST64(0xf20bef1d16c3c8e4),
+ CONST64(0xb5c2ee5b99c1032c), CONST64(0x226688aacc0d6bee), CONST64(0xe532b356647b4981), CONST64(0xee2f9f715e230cb0),
+ CONST64(0xbedfc27ca399461d), CONST64(0x2b7dac87fa4538d1), CONST64(0x819e3ebf217ce2a0), CONST64(0x1236485a6c90a67e),
+ CONST64(0x839836b52d6cf4ae), CONST64(0x1b2d6c775ad8f541), CONST64(0x0e1238362470622a), CONST64(0x23658cafca0560e9),
+ CONST64(0xf502f30604fbf9f1), CONST64(0x45cf094c8312ddc6), CONST64(0x216384a5c61576e7), CONST64(0xce4f1fd19e3e7150),
+ CONST64(0x49db3970ab72a9e2), CONST64(0x2c74b09ce87d09c4), CONST64(0xf916c33a2c9b8dd5), CONST64(0xe637bf596e635488),
+ CONST64(0xb6c7e25493d91e25), CONST64(0x2878a088f05d25d8), CONST64(0x17395c4b72b88165), CONST64(0x829b32b02b64ffa9),
+ CONST64(0x1a2e68725cd0fe46), CONST64(0x8b80169d1d2cac96), CONST64(0xfe1fdf213ea3bcc0), CONST64(0x8a8312981b24a791),
+ CONST64(0x091b242d3648533f), CONST64(0xc94603ca8c064045), CONST64(0x879426a1354cd8b2), CONST64(0x4ed2256bb94a98f7),
+ CONST64(0xe13ea3427c5b659d), CONST64(0x2e72b896e46d1fca), CONST64(0xe431b75362734286), CONST64(0xe03da7477a536e9a),
+ CONST64(0xeb208b60400b2bab), CONST64(0x90ad7aea47f459d7), CONST64(0xa4f1aa0eff49b85b), CONST64(0x1e22786644f0d25a),
+ CONST64(0x85922eab395ccebc), CONST64(0x60a09dfd5d27873d), CONST64(0x0000000000000000), CONST64(0x256f94b1de355afb),
+ CONST64(0xf401f70302f3f2f6), CONST64(0xf10ee3121cdbd5ed), CONST64(0x94a16afe5fd475cb), CONST64(0x0b1d2c273a584531),
+ CONST64(0xe734bb5c686b5f8f), CONST64(0x759fc9bc238f1056), CONST64(0xef2c9b74582b07b7), CONST64(0x345cd0e4b8bde18c),
+ CONST64(0x3153c4f5a695c697), CONST64(0xd46177a3c2ee8f16), CONST64(0xd06d67b7dacea30a), CONST64(0x869722a43344d3b5),
+ CONST64(0x7e82e59b19d75567), CONST64(0xadea8e23c901eb64), CONST64(0xfd1ad32e34bba1c9), CONST64(0x297ba48df6552edf),
+ CONST64(0x3050c0f0a09dcd90), CONST64(0x3b4decd79ac588a1), CONST64(0x9fbc46d9658c30fa), CONST64(0xf815c73f2a9386d2),
+ CONST64(0xc6573ff9ae7e2968), CONST64(0x13354c5f6a98ad79), CONST64(0x060a181e14303a12), CONST64(0x050f14111e28271b),
+ CONST64(0xc55233f6a4663461), CONST64(0x113344556688bb77), CONST64(0x7799c1b62f9f0658), CONST64(0x7c84ed9115c74369),
+ CONST64(0x7a8ef58f01f7797b), CONST64(0x7888fd850de76f75), CONST64(0x365ad8eeb4adf782), CONST64(0x1c24706c48e0c454),
+ CONST64(0x394be4dd96d59eaf), CONST64(0x59eb7920cbf21992), CONST64(0x1828607850c0e848), CONST64(0x56fa4513e98a70bf),
+ CONST64(0xb3c8f6458df1393e), CONST64(0xb0cdfa4a87e92437), CONST64(0x246c90b4d83d51fc), CONST64(0x206080a0c01d7de0),
+ CONST64(0xb2cbf2408bf93239), CONST64(0x92ab72e04be44fd9), CONST64(0xa3f8b615ed71894e), CONST64(0xc05d27e7ba4e137a),
+ CONST64(0x44cc0d49851ad6c1), CONST64(0x62a695f751379133), CONST64(0x103040506080b070), CONST64(0xb4c1ea5e9fc9082b),
+ CONST64(0x84912aae3f54c5bb), CONST64(0x43c511529722e7d4), CONST64(0x93a876e54dec44de), CONST64(0xc25b2fedb65e0574),
+ CONST64(0x4ade357fa16ab4eb), CONST64(0xbddace73a9815b14), CONST64(0x8f8c0689050c808a), CONST64(0x2d77b499ee7502c3),
+ CONST64(0xbcd9ca76af895013), CONST64(0x9cb94ad66f942df3), CONST64(0x6abeb5df6177c90b), CONST64(0x40c01d5d9d3afadd),
+ CONST64(0xcf4c1bd498367a57), CONST64(0xa2fbb210eb798249), CONST64(0x809d3aba2774e9a7), CONST64(0x4fd1216ebf4293f0),
+ CONST64(0x1f217c6342f8d95d), CONST64(0xca430fc5861e5d4c), CONST64(0xaae39238db39da71), CONST64(0x42c61557912aecd3),
+};
+
+static const ulong64 T1[256] = {
+ CONST64(0xd3ba68d2b9bb016a), CONST64(0xfc54194d9ae5b166), CONST64(0x712f93bc65e2cd14), CONST64(0x9c74b9cd8725511b),
+ CONST64(0xf5530251a2f7a457), CONST64(0x68d3b86bd6d003be), CONST64(0x6bd2bd6fded604b5), CONST64(0xd74d642952b3fe85),
+ CONST64(0xf0500d5dbafdad4a), CONST64(0xe9ac268a09cf63e0), CONST64(0x8a8d830e1c098496), CONST64(0xdcbf79c691a51a4d),
+ CONST64(0x9070addda73d4d37), CONST64(0xf6520755aaf1a35c), CONST64(0xb39ac852a47be117), CONST64(0xd44c612d5ab5f98e),
+ CONST64(0x23ea658f0346ac20), CONST64(0x62d5a673e6c41184), CONST64(0xa497f166cc55c268), CONST64(0x6ed1b263c6dc0da8),
+ CONST64(0x5533ffcc85aa99d0), CONST64(0xf3510859b2fbaa41), CONST64(0xed5b2a71e2c79c0f), CONST64(0xf7a604a259f355ae),
+ CONST64(0x7fde815fbefe20c1), CONST64(0xd848753d7aade5a2), CONST64(0xe5a8329a29d77fcc), CONST64(0xb699c75ebc71e80a),
+ CONST64(0x70db904b96e03be6), CONST64(0x5632fac88dac9edb), CONST64(0xc4b751e6d1952215), CONST64(0x19fc2bd7b332ceaa),
+ CONST64(0x38e348ab4b709373), CONST64(0xbf9edc428463fd3b), CONST64(0xae91ef7efc41d052), CONST64(0xb09bcd56ac7de61c),
+ CONST64(0x3be24daf43769478), CONST64(0xd0bb6dd6b1bd0661), CONST64(0xc3415819329bdaf1), CONST64(0xb26ecba5577917e5),
+ CONST64(0xf2a50bae41f95cb3), CONST64(0x40cbc00b16804b56), CONST64(0xbd6bdab17f670cc2), CONST64(0xa295fb6edc59cc7e),
+ CONST64(0xfea11fbe61e1409f), CONST64(0x08f318ebcb10e3c3), CONST64(0xceb14ffee181302f), CONST64(0x06020a08100c0e16),
+ CONST64(0x49ccdb172e925e67), CONST64(0x51c4f3376ea2663f), CONST64(0x271d6974e84e53cf), CONST64(0x3c144450a0786c9c),
+ CONST64(0x58c3e82b56b0730e), CONST64(0xa563f2913f57349a), CONST64(0x73da954f9ee63ced), CONST64(0xe75d3469d2d38e35),
+ CONST64(0xe15f3e61c2df8023), CONST64(0x79dc8b57aef22ed7), CONST64(0x877d94e9cf136e48), CONST64(0x4acdde132694596c),
+ CONST64(0x817f9ee1df1f605e), CONST64(0xee5a2f75eac19b04), CONST64(0xb46cc1ad477519f3), CONST64(0xe45c316ddad5893e),
+ CONST64(0x04f70cfbeb08ffef), CONST64(0x6a26be982dd4f247), CONST64(0x1cff24dbab38c7b7), CONST64(0x2aed7e933b54b911),
+ CONST64(0x25e86f87134aa236), CONST64(0xba9dd34e9c69f426), CONST64(0xb16fcea15f7f10ee), CONST64(0x8f8e8c0204038d8b),
+ CONST64(0x2b197d64c8564fe3), CONST64(0xfda01aba69e74794), CONST64(0x0df017e7d31aeade), CONST64(0x8689971e3c1198ba),
+ CONST64(0x110f333c78222d69), CONST64(0x09071b1c38121531), CONST64(0xecaf298611c56afd), CONST64(0x10fb30cb8b20db9b),
+ CONST64(0x1808282040303858), CONST64(0x3f154154a87e6b97), CONST64(0x170d3934682e237f), CONST64(0x0c04141020181c2c),
+ CONST64(0x030105040806070b), CONST64(0xac64e98d074521ab), CONST64(0x7cdf845bb6f827ca), CONST64(0x9a76b3c597295f0d),
+ CONST64(0x8b7980f9ef0b7264), CONST64(0x7add8e53a6f429dc), CONST64(0x473dc9f4f58eb3b2), CONST64(0x3a164e58b074628a),
+ CONST64(0x413fc3fce582bda4), CONST64(0x5937ebdca5b285fc), CONST64(0xb76dc4a94f731ef8), CONST64(0x4838d8e0dd90a895),
+ CONST64(0xd6b967dea1b10877), CONST64(0x9573a2d1bf37442a), CONST64(0x26e96a831b4ca53d), CONST64(0x5f35e1d4b5be8bea),
+ CONST64(0xff551c4992e3b66d), CONST64(0x9371a8d9af3b4a3c), CONST64(0x8d7b8af1ff077c72), CONST64(0x898c860a140f839d),
+ CONST64(0x9672a7d5b7314321), CONST64(0x8588921a34179fb1), CONST64(0x07f609ffe30ef8e4), CONST64(0x7e2a82a84dfcd633),
+ CONST64(0x423ec6f8ed84baaf), CONST64(0xe25e3b65cad98728), CONST64(0x6927bb9c25d2f54c), CONST64(0xca4643050a89cfc0),
+ CONST64(0x140c3c3060282474), CONST64(0xaf65ec890f4326a0), CONST64(0xb868d5bd676d05df), CONST64(0xa361f8992f5b3a8c),
+ CONST64(0x05030f0c180a091d), CONST64(0x5ec1e22346bc7d18), CONST64(0xf957164182efb87b), CONST64(0x67d6a97ffece1899),
+ CONST64(0x76d99a4386ec35f0), CONST64(0xe858257dfacd9512), CONST64(0x75d89f478eea32fb), CONST64(0xaa66e38517492fbd),
+ CONST64(0x64d7ac7bf6c81f92), CONST64(0x4e3ad2e8cd9ca683), CONST64(0x45c8cf070e8a424b), CONST64(0x443cccf0fd88b4b9),
+ CONST64(0x13fa35cf8326dc90), CONST64(0xa796f462c453c563), CONST64(0xf4a701a651f552a5), CONST64(0xb598c25ab477ef01),
+ CONST64(0x29ec7b973352be1a), CONST64(0xd5b862daa9b70f7c), CONST64(0x54c7fc3b76a86f22), CONST64(0xefae2c8219c36df6),
+ CONST64(0xbb69d0b96f6b02d4), CONST64(0xdd4b7a3162a7ecbf), CONST64(0xe0ab3d9631dd76d1), CONST64(0xe6a9379e21d178c7),
+ CONST64(0xa967e6811f4f28b6), CONST64(0x1e0a2228503c364e), CONST64(0xc9474601028fc8cb), CONST64(0x0bf21defc316e4c8),
+ CONST64(0xc2b55beec1992c03), CONST64(0x6622aa880dccee6b), CONST64(0x32e556b37b648149), CONST64(0x2fee719f235eb00c),
+ CONST64(0xdfbe7cc299a31d46), CONST64(0x7d2b87ac45fad138), CONST64(0x9e81bf3e7c21a0e2), CONST64(0x36125a48906c7ea6),
+ CONST64(0x9883b5366c2daef4), CONST64(0x2d1b776cd85a41f5), CONST64(0x120e363870242a62), CONST64(0x6523af8c05cae960),
+ CONST64(0x02f506f3fb04f1f9), CONST64(0xcf454c091283c6dd), CONST64(0x6321a58415c6e776), CONST64(0x4fced11f3e9e5071),
+ CONST64(0xdb49703972abe2a9), CONST64(0x742c9cb07de8c409), CONST64(0x16f93ac39b2cd58d), CONST64(0x37e659bf636e8854),
+ CONST64(0xc7b654e2d993251e), CONST64(0x782888a05df0d825), CONST64(0x39174b5cb8726581), CONST64(0x9b82b032642ba9ff),
+ CONST64(0x2e1a7268d05c46fe), CONST64(0x808b9d162c1d96ac), CONST64(0x1ffe21dfa33ec0bc), CONST64(0x838a9812241b91a7),
+ CONST64(0x1b092d2448363f53), CONST64(0x46c9ca03068c4540), CONST64(0x9487a1264c35b2d8), CONST64(0xd24e6b254ab9f798),
+ CONST64(0x3ee142a35b7c9d65), CONST64(0x722e96b86de4ca1f), CONST64(0x31e453b773628642), CONST64(0x3de047a7537a9a6e),
+ CONST64(0x20eb608b0b40ab2b), CONST64(0xad90ea7af447d759), CONST64(0xf1a40eaa49ff5bb8), CONST64(0x221e6678f0445ad2),
+ CONST64(0x9285ab2e5c39bcce), CONST64(0xa060fd9d275d3d87), CONST64(0x0000000000000000), CONST64(0x6f25b19435defb5a),
+ CONST64(0x01f403f7f302f6f2), CONST64(0x0ef112e3db1cedd5), CONST64(0xa194fe6ad45fcb75), CONST64(0x1d0b272c583a3145),
+ CONST64(0x34e75cbb6b688f5f), CONST64(0x9f75bcc98f235610), CONST64(0x2cef749b2b58b707), CONST64(0x5c34e4d0bdb88ce1),
+ CONST64(0x5331f5c495a697c6), CONST64(0x61d4a377eec2168f), CONST64(0x6dd0b767ceda0aa3), CONST64(0x9786a4224433b5d3),
+ CONST64(0x827e9be5d7196755), CONST64(0xeaad238e01c964eb), CONST64(0x1afd2ed3bb34c9a1), CONST64(0x7b298da455f6df2e),
+ CONST64(0x5030f0c09da090cd), CONST64(0x4d3bd7ecc59aa188), CONST64(0xbc9fd9468c65fa30), CONST64(0x15f83fc7932ad286),
+ CONST64(0x57c6f93f7eae6829), CONST64(0x35135f4c986a79ad), CONST64(0x0a061e183014123a), CONST64(0x0f051114281e1b27),
+ CONST64(0x52c5f63366a46134), CONST64(0x33115544886677bb), CONST64(0x9977b6c19f2f5806), CONST64(0x847c91edc7156943),
+ CONST64(0x8e7a8ff5f7017b79), CONST64(0x887885fde70d756f), CONST64(0x5a36eed8adb482f7), CONST64(0x241c6c70e04854c4),
+ CONST64(0x4b39dde4d596af9e), CONST64(0xeb592079f2cb9219), CONST64(0x28187860c05048e8), CONST64(0xfa5613458ae9bf70),
+ CONST64(0xc8b345f6f18d3e39), CONST64(0xcdb04afae9873724), CONST64(0x6c24b4903dd8fc51), CONST64(0x6020a0801dc0e07d),
+ CONST64(0xcbb240f2f98b3932), CONST64(0xab92e072e44bd94f), CONST64(0xf8a315b671ed4e89), CONST64(0x5dc0e7274eba7a13),
+ CONST64(0xcc44490d1a85c1d6), CONST64(0xa662f79537513391), CONST64(0x30105040806070b0), CONST64(0xc1b45eeac99f2b08),
+ CONST64(0x9184ae2a543fbbc5), CONST64(0xc54352112297d4e7), CONST64(0xa893e576ec4dde44), CONST64(0x5bc2ed2f5eb67405),
+ CONST64(0xde4a7f356aa1ebb4), CONST64(0xdabd73ce81a9145b), CONST64(0x8c8f89060c058a80), CONST64(0x772d99b475eec302),
+ CONST64(0xd9bc76ca89af1350), CONST64(0xb99cd64a946ff32d), CONST64(0xbe6adfb577610bc9), CONST64(0xc0405d1d3a9dddfa),
+ CONST64(0x4ccfd41b3698577a), CONST64(0xfba210b279eb4982), CONST64(0x9d80ba3a7427a7e9), CONST64(0xd14f6e2142bff093),
+ CONST64(0x211f637cf8425dd9), CONST64(0x43cac50f1e864c5d), CONST64(0xe3aa389239db71da), CONST64(0xc64257152a91d3ec),
+};
+
+static const ulong64 T2[256] = {
+ CONST64(0xd268bad36a01bbb9), CONST64(0x4d1954fc66b1e59a), CONST64(0xbc932f7114cde265), CONST64(0xcdb9749c1b512587),
+ CONST64(0x510253f557a4f7a2), CONST64(0x6bb8d368be03d0d6), CONST64(0x6fbdd26bb504d6de), CONST64(0x29644dd785feb352),
+ CONST64(0x5d0d50f04aadfdba), CONST64(0x8a26ace9e063cf09), CONST64(0x0e838d8a9684091c), CONST64(0xc679bfdc4d1aa591),
+ CONST64(0xddad7090374d3da7), CONST64(0x550752f65ca3f1aa), CONST64(0x52c89ab317e17ba4), CONST64(0x2d614cd48ef9b55a),
+ CONST64(0x8f65ea2320ac4603), CONST64(0x73a6d5628411c4e6), CONST64(0x66f197a468c255cc), CONST64(0x63b2d16ea80ddcc6),
+ CONST64(0xccff3355d099aa85), CONST64(0x590851f341aafbb2), CONST64(0x712a5bed0f9cc7e2), CONST64(0xa204a6f7ae55f359),
+ CONST64(0x5f81de7fc120febe), CONST64(0x3d7548d8a2e5ad7a), CONST64(0x9a32a8e5cc7fd729), CONST64(0x5ec799b60ae871bc),
+ CONST64(0x4b90db70e63be096), CONST64(0xc8fa3256db9eac8d), CONST64(0xe651b7c4152295d1), CONST64(0xd72bfc19aace32b3),
+ CONST64(0xab48e3387393704b), CONST64(0x42dc9ebf3bfd6384), CONST64(0x7eef91ae52d041fc), CONST64(0x56cd9bb01ce67dac),
+ CONST64(0xaf4de23b78947643), CONST64(0xd66dbbd06106bdb1), CONST64(0x195841c3f1da9b32), CONST64(0xa5cb6eb2e5177957),
+ CONST64(0xae0ba5f2b35cf941), CONST64(0x0bc0cb40564b8016), CONST64(0xb1da6bbdc20c677f), CONST64(0x6efb95a27ecc59dc),
+ CONST64(0xbe1fa1fe9f40e161), CONST64(0xeb18f308c3e310cb), CONST64(0xfe4fb1ce2f3081e1), CONST64(0x080a0206160e0c10),
+ CONST64(0x17dbcc49675e922e), CONST64(0x37f3c4513f66a26e), CONST64(0x74691d27cf534ee8), CONST64(0x5044143c9c6c78a0),
+ CONST64(0x2be8c3580e73b056), CONST64(0x91f263a59a34573f), CONST64(0x4f95da73ed3ce69e), CONST64(0x69345de7358ed3d2),
+ CONST64(0x613e5fe12380dfc2), CONST64(0x578bdc79d72ef2ae), CONST64(0xe9947d87486e13cf), CONST64(0x13decd4a6c599426),
+ CONST64(0xe19e7f815e601fdf), CONST64(0x752f5aee049bc1ea), CONST64(0xadc16cb4f3197547), CONST64(0x6d315ce43e89d5da),
+ CONST64(0xfb0cf704efff08eb), CONST64(0x98be266a47f2d42d), CONST64(0xdb24ff1cb7c738ab), CONST64(0x937eed2a11b9543b),
+ CONST64(0x876fe82536a24a13), CONST64(0x4ed39dba26f4699c), CONST64(0xa1ce6fb1ee107f5f), CONST64(0x028c8e8f8b8d0304),
+ CONST64(0x647d192be34f56c8), CONST64(0xba1aa0fd9447e769), CONST64(0xe717f00ddeea1ad3), CONST64(0x1e978986ba98113c),
+ CONST64(0x3c330f11692d2278), CONST64(0x1c1b070931151238), CONST64(0x8629afecfd6ac511), CONST64(0xcb30fb109bdb208b),
+ CONST64(0x2028081858383040), CONST64(0x5441153f976b7ea8), CONST64(0x34390d177f232e68), CONST64(0x1014040c2c1c1820),
+ CONST64(0x040501030b070608), CONST64(0x8de964acab214507), CONST64(0x5b84df7cca27f8b6), CONST64(0xc5b3769a0d5f2997),
+ CONST64(0xf980798b64720bef), CONST64(0x538edd7adc29f4a6), CONST64(0xf4c93d47b2b38ef5), CONST64(0x584e163a8a6274b0),
+ CONST64(0xfcc33f41a4bd82e5), CONST64(0xdceb3759fc85b2a5), CONST64(0xa9c46db7f81e734f), CONST64(0xe0d8384895a890dd),
+ CONST64(0xde67b9d67708b1a1), CONST64(0xd1a273952a4437bf), CONST64(0x836ae9263da54c1b), CONST64(0xd4e1355fea8bbeb5),
+ CONST64(0x491c55ff6db6e392), CONST64(0xd9a871933c4a3baf), CONST64(0xf18a7b8d727c07ff), CONST64(0x0a868c899d830f14),
+ CONST64(0xd5a77296214331b7), CONST64(0x1a928885b19f1734), CONST64(0xff09f607e4f80ee3), CONST64(0xa8822a7e33d6fc4d),
+ CONST64(0xf8c63e42afba84ed), CONST64(0x653b5ee22887d9ca), CONST64(0x9cbb27694cf5d225), CONST64(0x054346cac0cf890a),
+ CONST64(0x303c0c1474242860), CONST64(0x89ec65afa026430f), CONST64(0xbdd568b8df056d67), CONST64(0x99f861a38c3a5b2f),
+ CONST64(0x0c0f03051d090a18), CONST64(0x23e2c15e187dbc46), CONST64(0x411657f97bb8ef82), CONST64(0x7fa9d6679918cefe),
+ CONST64(0x439ad976f035ec86), CONST64(0x7d2558e81295cdfa), CONST64(0x479fd875fb32ea8e), CONST64(0x85e366aabd2f4917),
+ CONST64(0x7bacd764921fc8f6), CONST64(0xe8d23a4e83a69ccd), CONST64(0x07cfc8454b428a0e), CONST64(0xf0cc3c44b9b488fd),
+ CONST64(0xcf35fa1390dc2683), CONST64(0x62f496a763c553c4), CONST64(0xa601a7f4a552f551), CONST64(0x5ac298b501ef77b4),
+ CONST64(0x977bec291abe5233), CONST64(0xda62b8d57c0fb7a9), CONST64(0x3bfcc754226fa876), CONST64(0x822caeeff66dc319),
+ CONST64(0xb9d069bbd4026b6f), CONST64(0x317a4bddbfeca762), CONST64(0x963dabe0d176dd31), CONST64(0x9e37a9e6c778d121),
+ CONST64(0x81e667a9b6284f1f), CONST64(0x28220a1e4e363c50), CONST64(0x014647c9cbc88f02), CONST64(0xef1df20bc8e416c3),
+ CONST64(0xee5bb5c2032c99c1), CONST64(0x88aa22666beecc0d), CONST64(0xb356e5324981647b), CONST64(0x9f71ee2f0cb05e23),
+ CONST64(0xc27cbedf461da399), CONST64(0xac872b7d38d1fa45), CONST64(0x3ebf819ee2a0217c), CONST64(0x485a1236a67e6c90),
+ CONST64(0x36b58398f4ae2d6c), CONST64(0x6c771b2df5415ad8), CONST64(0x38360e12622a2470), CONST64(0x8caf236560e9ca05),
+ CONST64(0xf306f502f9f104fb), CONST64(0x094c45cfddc68312), CONST64(0x84a5216376e7c615), CONST64(0x1fd1ce4f71509e3e),
+ CONST64(0x397049dba9e2ab72), CONST64(0xb09c2c7409c4e87d), CONST64(0xc33af9168dd52c9b), CONST64(0xbf59e63754886e63),
+ CONST64(0xe254b6c71e2593d9), CONST64(0xa088287825d8f05d), CONST64(0x5c4b1739816572b8), CONST64(0x32b0829bffa92b64),
+ CONST64(0x68721a2efe465cd0), CONST64(0x169d8b80ac961d2c), CONST64(0xdf21fe1fbcc03ea3), CONST64(0x12988a83a7911b24),
+ CONST64(0x242d091b533f3648), CONST64(0x03cac94640458c06), CONST64(0x26a18794d8b2354c), CONST64(0x256b4ed298f7b94a),
+ CONST64(0xa342e13e659d7c5b), CONST64(0xb8962e721fcae46d), CONST64(0xb753e43142866273), CONST64(0xa747e03d6e9a7a53),
+ CONST64(0x8b60eb202bab400b), CONST64(0x7aea90ad59d747f4), CONST64(0xaa0ea4f1b85bff49), CONST64(0x78661e22d25a44f0),
+ CONST64(0x2eab8592cebc395c), CONST64(0x9dfd60a0873d5d27), CONST64(0x0000000000000000), CONST64(0x94b1256f5afbde35),
+ CONST64(0xf703f401f2f602f3), CONST64(0xe312f10ed5ed1cdb), CONST64(0x6afe94a175cb5fd4), CONST64(0x2c270b1d45313a58),
+ CONST64(0xbb5ce7345f8f686b), CONST64(0xc9bc759f1056238f), CONST64(0x9b74ef2c07b7582b), CONST64(0xd0e4345ce18cb8bd),
+ CONST64(0xc4f53153c697a695), CONST64(0x77a3d4618f16c2ee), CONST64(0x67b7d06da30adace), CONST64(0x22a48697d3b53344),
+ CONST64(0xe59b7e82556719d7), CONST64(0x8e23adeaeb64c901), CONST64(0xd32efd1aa1c934bb), CONST64(0xa48d297b2edff655),
+ CONST64(0xc0f03050cd90a09d), CONST64(0xecd73b4d88a19ac5), CONST64(0x46d99fbc30fa658c), CONST64(0xc73ff81586d22a93),
+ CONST64(0x3ff9c6572968ae7e), CONST64(0x4c5f1335ad796a98), CONST64(0x181e060a3a121430), CONST64(0x1411050f271b1e28),
+ CONST64(0x33f6c5523461a466), CONST64(0x44551133bb776688), CONST64(0xc1b6779906582f9f), CONST64(0xed917c84436915c7),
+ CONST64(0xf58f7a8e797b01f7), CONST64(0xfd8578886f750de7), CONST64(0xd8ee365af782b4ad), CONST64(0x706c1c24c45448e0),
+ CONST64(0xe4dd394b9eaf96d5), CONST64(0x792059eb1992cbf2), CONST64(0x60781828e84850c0), CONST64(0x451356fa70bfe98a),
+ CONST64(0xf645b3c8393e8df1), CONST64(0xfa4ab0cd243787e9), CONST64(0x90b4246c51fcd83d), CONST64(0x80a020607de0c01d),
+ CONST64(0xf240b2cb32398bf9), CONST64(0x72e092ab4fd94be4), CONST64(0xb615a3f8894eed71), CONST64(0x27e7c05d137aba4e),
+ CONST64(0x0d4944ccd6c1851a), CONST64(0x95f762a691335137), CONST64(0x40501030b0706080), CONST64(0xea5eb4c1082b9fc9),
+ CONST64(0x2aae8491c5bb3f54), CONST64(0x115243c5e7d49722), CONST64(0x76e593a844de4dec), CONST64(0x2fedc25b0574b65e),
+ CONST64(0x357f4adeb4eba16a), CONST64(0xce73bdda5b14a981), CONST64(0x06898f8c808a050c), CONST64(0xb4992d7702c3ee75),
+ CONST64(0xca76bcd95013af89), CONST64(0x4ad69cb92df36f94), CONST64(0xb5df6abec90b6177), CONST64(0x1d5d40c0fadd9d3a),
+ CONST64(0x1bd4cf4c7a579836), CONST64(0xb210a2fb8249eb79), CONST64(0x3aba809de9a72774), CONST64(0x216e4fd193f0bf42),
+ CONST64(0x7c631f21d95d42f8), CONST64(0x0fc5ca435d4c861e), CONST64(0x9238aae3da71db39), CONST64(0x155742c6ecd3912a),
+};
+
+static const ulong64 T3[256] = {
+ CONST64(0x68d2d3ba016ab9bb), CONST64(0x194dfc54b1669ae5), CONST64(0x93bc712fcd1465e2), CONST64(0xb9cd9c74511b8725),
+ CONST64(0x0251f553a457a2f7), CONST64(0xb86b68d303bed6d0), CONST64(0xbd6f6bd204b5ded6), CONST64(0x6429d74dfe8552b3),
+ CONST64(0x0d5df050ad4abafd), CONST64(0x268ae9ac63e009cf), CONST64(0x830e8a8d84961c09), CONST64(0x79c6dcbf1a4d91a5),
+ CONST64(0xaddd90704d37a73d), CONST64(0x0755f652a35caaf1), CONST64(0xc852b39ae117a47b), CONST64(0x612dd44cf98e5ab5),
+ CONST64(0x658f23eaac200346), CONST64(0xa67362d51184e6c4), CONST64(0xf166a497c268cc55), CONST64(0xb2636ed10da8c6dc),
+ CONST64(0xffcc553399d085aa), CONST64(0x0859f351aa41b2fb), CONST64(0x2a71ed5b9c0fe2c7), CONST64(0x04a2f7a655ae59f3),
+ CONST64(0x815f7fde20c1befe), CONST64(0x753dd848e5a27aad), CONST64(0x329ae5a87fcc29d7), CONST64(0xc75eb699e80abc71),
+ CONST64(0x904b70db3be696e0), CONST64(0xfac856329edb8dac), CONST64(0x51e6c4b72215d195), CONST64(0x2bd719fcceaab332),
+ CONST64(0x48ab38e393734b70), CONST64(0xdc42bf9efd3b8463), CONST64(0xef7eae91d052fc41), CONST64(0xcd56b09be61cac7d),
+ CONST64(0x4daf3be294784376), CONST64(0x6dd6d0bb0661b1bd), CONST64(0x5819c341daf1329b), CONST64(0xcba5b26e17e55779),
+ CONST64(0x0baef2a55cb341f9), CONST64(0xc00b40cb4b561680), CONST64(0xdab1bd6b0cc27f67), CONST64(0xfb6ea295cc7edc59),
+ CONST64(0x1fbefea1409f61e1), CONST64(0x18eb08f3e3c3cb10), CONST64(0x4ffeceb1302fe181), CONST64(0x0a0806020e16100c),
+ CONST64(0xdb1749cc5e672e92), CONST64(0xf33751c4663f6ea2), CONST64(0x6974271d53cfe84e), CONST64(0x44503c146c9ca078),
+ CONST64(0xe82b58c3730e56b0), CONST64(0xf291a563349a3f57), CONST64(0x954f73da3ced9ee6), CONST64(0x3469e75d8e35d2d3),
+ CONST64(0x3e61e15f8023c2df), CONST64(0x8b5779dc2ed7aef2), CONST64(0x94e9877d6e48cf13), CONST64(0xde134acd596c2694),
+ CONST64(0x9ee1817f605edf1f), CONST64(0x2f75ee5a9b04eac1), CONST64(0xc1adb46c19f34775), CONST64(0x316de45c893edad5),
+ CONST64(0x0cfb04f7ffefeb08), CONST64(0xbe986a26f2472dd4), CONST64(0x24db1cffc7b7ab38), CONST64(0x7e932aedb9113b54),
+ CONST64(0x6f8725e8a236134a), CONST64(0xd34eba9df4269c69), CONST64(0xcea1b16f10ee5f7f), CONST64(0x8c028f8e8d8b0403),
+ CONST64(0x7d642b194fe3c856), CONST64(0x1abafda0479469e7), CONST64(0x17e70df0eaded31a), CONST64(0x971e868998ba3c11),
+ CONST64(0x333c110f2d697822), CONST64(0x1b1c090715313812), CONST64(0x2986ecaf6afd11c5), CONST64(0x30cb10fbdb9b8b20),
+ CONST64(0x2820180838584030), CONST64(0x41543f156b97a87e), CONST64(0x3934170d237f682e), CONST64(0x14100c041c2c2018),
+ CONST64(0x05040301070b0806), CONST64(0xe98dac6421ab0745), CONST64(0x845b7cdf27cab6f8), CONST64(0xb3c59a765f0d9729),
+ CONST64(0x80f98b797264ef0b), CONST64(0x8e537add29dca6f4), CONST64(0xc9f4473db3b2f58e), CONST64(0x4e583a16628ab074),
+ CONST64(0xc3fc413fbda4e582), CONST64(0xebdc593785fca5b2), CONST64(0xc4a9b76d1ef84f73), CONST64(0xd8e04838a895dd90),
+ CONST64(0x67ded6b90877a1b1), CONST64(0xa2d19573442abf37), CONST64(0x6a8326e9a53d1b4c), CONST64(0xe1d45f358beab5be),
+ CONST64(0x1c49ff55b66d92e3), CONST64(0xa8d993714a3caf3b), CONST64(0x8af18d7b7c72ff07), CONST64(0x860a898c839d140f),
+ CONST64(0xa7d596724321b731), CONST64(0x921a85889fb13417), CONST64(0x09ff07f6f8e4e30e), CONST64(0x82a87e2ad6334dfc),
+ CONST64(0xc6f8423ebaafed84), CONST64(0x3b65e25e8728cad9), CONST64(0xbb9c6927f54c25d2), CONST64(0x4305ca46cfc00a89),
+ CONST64(0x3c30140c24746028), CONST64(0xec89af6526a00f43), CONST64(0xd5bdb86805df676d), CONST64(0xf899a3613a8c2f5b),
+ CONST64(0x0f0c0503091d180a), CONST64(0xe2235ec17d1846bc), CONST64(0x1641f957b87b82ef), CONST64(0xa97f67d61899fece),
+ CONST64(0x9a4376d935f086ec), CONST64(0x257de8589512facd), CONST64(0x9f4775d832fb8eea), CONST64(0xe385aa662fbd1749),
+ CONST64(0xac7b64d71f92f6c8), CONST64(0xd2e84e3aa683cd9c), CONST64(0xcf0745c8424b0e8a), CONST64(0xccf0443cb4b9fd88),
+ CONST64(0x35cf13fadc908326), CONST64(0xf462a796c563c453), CONST64(0x01a6f4a752a551f5), CONST64(0xc25ab598ef01b477),
+ CONST64(0x7b9729ecbe1a3352), CONST64(0x62dad5b80f7ca9b7), CONST64(0xfc3b54c76f2276a8), CONST64(0x2c82efae6df619c3),
+ CONST64(0xd0b9bb6902d46f6b), CONST64(0x7a31dd4becbf62a7), CONST64(0x3d96e0ab76d131dd), CONST64(0x379ee6a978c721d1),
+ CONST64(0xe681a96728b61f4f), CONST64(0x22281e0a364e503c), CONST64(0x4601c947c8cb028f), CONST64(0x1def0bf2e4c8c316),
+ CONST64(0x5beec2b52c03c199), CONST64(0xaa886622ee6b0dcc), CONST64(0x56b332e581497b64), CONST64(0x719f2feeb00c235e),
+ CONST64(0x7cc2dfbe1d4699a3), CONST64(0x87ac7d2bd13845fa), CONST64(0xbf3e9e81a0e27c21), CONST64(0x5a4836127ea6906c),
+ CONST64(0xb5369883aef46c2d), CONST64(0x776c2d1b41f5d85a), CONST64(0x3638120e2a627024), CONST64(0xaf8c6523e96005ca),
+ CONST64(0x06f302f5f1f9fb04), CONST64(0x4c09cf45c6dd1283), CONST64(0xa5846321e77615c6), CONST64(0xd11f4fce50713e9e),
+ CONST64(0x7039db49e2a972ab), CONST64(0x9cb0742cc4097de8), CONST64(0x3ac316f9d58d9b2c), CONST64(0x59bf37e68854636e),
+ CONST64(0x54e2c7b6251ed993), CONST64(0x88a07828d8255df0), CONST64(0x4b5c39176581b872), CONST64(0xb0329b82a9ff642b),
+ CONST64(0x72682e1a46fed05c), CONST64(0x9d16808b96ac2c1d), CONST64(0x21df1ffec0bca33e), CONST64(0x9812838a91a7241b),
+ CONST64(0x2d241b093f534836), CONST64(0xca0346c94540068c), CONST64(0xa1269487b2d84c35), CONST64(0x6b25d24ef7984ab9),
+ CONST64(0x42a33ee19d655b7c), CONST64(0x96b8722eca1f6de4), CONST64(0x53b731e486427362), CONST64(0x47a73de09a6e537a),
+ CONST64(0x608b20ebab2b0b40), CONST64(0xea7aad90d759f447), CONST64(0x0eaaf1a45bb849ff), CONST64(0x6678221e5ad2f044),
+ CONST64(0xab2e9285bcce5c39), CONST64(0xfd9da0603d87275d), CONST64(0x0000000000000000), CONST64(0xb1946f25fb5a35de),
+ CONST64(0x03f701f4f6f2f302), CONST64(0x12e30ef1edd5db1c), CONST64(0xfe6aa194cb75d45f), CONST64(0x272c1d0b3145583a),
+ CONST64(0x5cbb34e78f5f6b68), CONST64(0xbcc99f7556108f23), CONST64(0x749b2cefb7072b58), CONST64(0xe4d05c348ce1bdb8),
+ CONST64(0xf5c4533197c695a6), CONST64(0xa37761d4168feec2), CONST64(0xb7676dd00aa3ceda), CONST64(0xa4229786b5d34433),
+ CONST64(0x9be5827e6755d719), CONST64(0x238eeaad64eb01c9), CONST64(0x2ed31afdc9a1bb34), CONST64(0x8da47b29df2e55f6),
+ CONST64(0xf0c0503090cd9da0), CONST64(0xd7ec4d3ba188c59a), CONST64(0xd946bc9ffa308c65), CONST64(0x3fc715f8d286932a),
+ CONST64(0xf93f57c668297eae), CONST64(0x5f4c351379ad986a), CONST64(0x1e180a06123a3014), CONST64(0x11140f051b27281e),
+ CONST64(0xf63352c5613466a4), CONST64(0x5544331177bb8866), CONST64(0xb6c1997758069f2f), CONST64(0x91ed847c6943c715),
+ CONST64(0x8ff58e7a7b79f701), CONST64(0x85fd8878756fe70d), CONST64(0xeed85a3682f7adb4), CONST64(0x6c70241c54c4e048),
+ CONST64(0xdde44b39af9ed596), CONST64(0x2079eb599219f2cb), CONST64(0x7860281848e8c050), CONST64(0x1345fa56bf708ae9),
+ CONST64(0x45f6c8b33e39f18d), CONST64(0x4afacdb03724e987), CONST64(0xb4906c24fc513dd8), CONST64(0xa0806020e07d1dc0),
+ CONST64(0x40f2cbb23932f98b), CONST64(0xe072ab92d94fe44b), CONST64(0x15b6f8a34e8971ed), CONST64(0xe7275dc07a134eba),
+ CONST64(0x490dcc44c1d61a85), CONST64(0xf795a66233913751), CONST64(0x5040301070b08060), CONST64(0x5eeac1b42b08c99f),
+ CONST64(0xae2a9184bbc5543f), CONST64(0x5211c543d4e72297), CONST64(0xe576a893de44ec4d), CONST64(0xed2f5bc274055eb6),
+ CONST64(0x7f35de4aebb46aa1), CONST64(0x73cedabd145b81a9), CONST64(0x89068c8f8a800c05), CONST64(0x99b4772dc30275ee),
+ CONST64(0x76cad9bc135089af), CONST64(0xd64ab99cf32d946f), CONST64(0xdfb5be6a0bc97761), CONST64(0x5d1dc040ddfa3a9d),
+ CONST64(0xd41b4ccf577a3698), CONST64(0x10b2fba2498279eb), CONST64(0xba3a9d80a7e97427), CONST64(0x6e21d14ff09342bf),
+ CONST64(0x637c211f5dd9f842), CONST64(0xc50f43ca4c5d1e86), CONST64(0x3892e3aa71da39db), CONST64(0x5715c642d3ec2a91),
+};
+
+static const ulong64 T4[256] = {
+ CONST64(0xbbb96a01bad3d268), CONST64(0xe59a66b154fc4d19), CONST64(0xe26514cd2f71bc93), CONST64(0x25871b51749ccdb9),
+ CONST64(0xf7a257a453f55102), CONST64(0xd0d6be03d3686bb8), CONST64(0xd6deb504d26b6fbd), CONST64(0xb35285fe4dd72964),
+ CONST64(0xfdba4aad50f05d0d), CONST64(0xcf09e063ace98a26), CONST64(0x091c96848d8a0e83), CONST64(0xa5914d1abfdcc679),
+ CONST64(0x3da7374d7090ddad), CONST64(0xf1aa5ca352f65507), CONST64(0x7ba417e19ab352c8), CONST64(0xb55a8ef94cd42d61),
+ CONST64(0x460320acea238f65), CONST64(0xc4e68411d56273a6), CONST64(0x55cc68c297a466f1), CONST64(0xdcc6a80dd16e63b2),
+ CONST64(0xaa85d0993355ccff), CONST64(0xfbb241aa51f35908), CONST64(0xc7e20f9c5bed712a), CONST64(0xf359ae55a6f7a204),
+ CONST64(0xfebec120de7f5f81), CONST64(0xad7aa2e548d83d75), CONST64(0xd729cc7fa8e59a32), CONST64(0x71bc0ae899b65ec7),
+ CONST64(0xe096e63bdb704b90), CONST64(0xac8ddb9e3256c8fa), CONST64(0x95d11522b7c4e651), CONST64(0x32b3aacefc19d72b),
+ CONST64(0x704b7393e338ab48), CONST64(0x63843bfd9ebf42dc), CONST64(0x41fc52d091ae7eef), CONST64(0x7dac1ce69bb056cd),
+ CONST64(0x76437894e23baf4d), CONST64(0xbdb16106bbd0d66d), CONST64(0x9b32f1da41c31958), CONST64(0x7957e5176eb2a5cb),
+ CONST64(0xf941b35ca5f2ae0b), CONST64(0x8016564bcb400bc0), CONST64(0x677fc20c6bbdb1da), CONST64(0x59dc7ecc95a26efb),
+ CONST64(0xe1619f40a1febe1f), CONST64(0x10cbc3e3f308eb18), CONST64(0x81e12f30b1cefe4f), CONST64(0x0c10160e0206080a),
+ CONST64(0x922e675ecc4917db), CONST64(0xa26e3f66c45137f3), CONST64(0x4ee8cf531d277469), CONST64(0x78a09c6c143c5044),
+ CONST64(0xb0560e73c3582be8), CONST64(0x573f9a3463a591f2), CONST64(0xe69eed3cda734f95), CONST64(0xd3d2358e5de76934),
+ CONST64(0xdfc223805fe1613e), CONST64(0xf2aed72edc79578b), CONST64(0x13cf486e7d87e994), CONST64(0x94266c59cd4a13de),
+ CONST64(0x1fdf5e607f81e19e), CONST64(0xc1ea049b5aee752f), CONST64(0x7547f3196cb4adc1), CONST64(0xd5da3e895ce46d31),
+ CONST64(0x08ebeffff704fb0c), CONST64(0xd42d47f2266a98be), CONST64(0x38abb7c7ff1cdb24), CONST64(0x543b11b9ed2a937e),
+ CONST64(0x4a1336a2e825876f), CONST64(0x699c26f49dba4ed3), CONST64(0x7f5fee106fb1a1ce), CONST64(0x03048b8d8e8f028c),
+ CONST64(0x56c8e34f192b647d), CONST64(0xe7699447a0fdba1a), CONST64(0x1ad3deeaf00de717), CONST64(0x113cba9889861e97),
+ CONST64(0x2278692d0f113c33), CONST64(0x1238311507091c1b), CONST64(0xc511fd6aafec8629), CONST64(0x208b9bdbfb10cb30),
+ CONST64(0x3040583808182028), CONST64(0x7ea8976b153f5441), CONST64(0x2e687f230d173439), CONST64(0x18202c1c040c1014),
+ CONST64(0x06080b0701030405), CONST64(0x4507ab2164ac8de9), CONST64(0xf8b6ca27df7c5b84), CONST64(0x29970d5f769ac5b3),
+ CONST64(0x0bef6472798bf980), CONST64(0xf4a6dc29dd7a538e), CONST64(0x8ef5b2b33d47f4c9), CONST64(0x74b08a62163a584e),
+ CONST64(0x82e5a4bd3f41fcc3), CONST64(0xb2a5fc853759dceb), CONST64(0x734ff81e6db7a9c4), CONST64(0x90dd95a83848e0d8),
+ CONST64(0xb1a17708b9d6de67), CONST64(0x37bf2a447395d1a2), CONST64(0x4c1b3da5e926836a), CONST64(0xbeb5ea8b355fd4e1),
+ CONST64(0xe3926db655ff491c), CONST64(0x3baf3c4a7193d9a8), CONST64(0x07ff727c7b8df18a), CONST64(0x0f149d838c890a86),
+ CONST64(0x31b721437296d5a7), CONST64(0x1734b19f88851a92), CONST64(0x0ee3e4f8f607ff09), CONST64(0xfc4d33d62a7ea882),
+ CONST64(0x84edafba3e42f8c6), CONST64(0xd9ca28875ee2653b), CONST64(0xd2254cf527699cbb), CONST64(0x890ac0cf46ca0543),
+ CONST64(0x286074240c14303c), CONST64(0x430fa02665af89ec), CONST64(0x6d67df0568b8bdd5), CONST64(0x5b2f8c3a61a399f8),
+ CONST64(0x0a181d0903050c0f), CONST64(0xbc46187dc15e23e2), CONST64(0xef827bb857f94116), CONST64(0xcefe9918d6677fa9),
+ CONST64(0xec86f035d976439a), CONST64(0xcdfa129558e87d25), CONST64(0xea8efb32d875479f), CONST64(0x4917bd2f66aa85e3),
+ CONST64(0xc8f6921fd7647bac), CONST64(0x9ccd83a63a4ee8d2), CONST64(0x8a0e4b42c84507cf), CONST64(0x88fdb9b43c44f0cc),
+ CONST64(0x268390dcfa13cf35), CONST64(0x53c463c596a762f4), CONST64(0xf551a552a7f4a601), CONST64(0x77b401ef98b55ac2),
+ CONST64(0x52331abeec29977b), CONST64(0xb7a97c0fb8d5da62), CONST64(0xa876226fc7543bfc), CONST64(0xc319f66daeef822c),
+ CONST64(0x6b6fd40269bbb9d0), CONST64(0xa762bfec4bdd317a), CONST64(0xdd31d176abe0963d), CONST64(0xd121c778a9e69e37),
+ CONST64(0x4f1fb62867a981e6), CONST64(0x3c504e360a1e2822), CONST64(0x8f02cbc847c90146), CONST64(0x16c3c8e4f20bef1d),
+ CONST64(0x99c1032cb5c2ee5b), CONST64(0xcc0d6bee226688aa), CONST64(0x647b4981e532b356), CONST64(0x5e230cb0ee2f9f71),
+ CONST64(0xa399461dbedfc27c), CONST64(0xfa4538d12b7dac87), CONST64(0x217ce2a0819e3ebf), CONST64(0x6c90a67e1236485a),
+ CONST64(0x2d6cf4ae839836b5), CONST64(0x5ad8f5411b2d6c77), CONST64(0x2470622a0e123836), CONST64(0xca0560e923658caf),
+ CONST64(0x04fbf9f1f502f306), CONST64(0x8312ddc645cf094c), CONST64(0xc61576e7216384a5), CONST64(0x9e3e7150ce4f1fd1),
+ CONST64(0xab72a9e249db3970), CONST64(0xe87d09c42c74b09c), CONST64(0x2c9b8dd5f916c33a), CONST64(0x6e635488e637bf59),
+ CONST64(0x93d91e25b6c7e254), CONST64(0xf05d25d82878a088), CONST64(0x72b8816517395c4b), CONST64(0x2b64ffa9829b32b0),
+ CONST64(0x5cd0fe461a2e6872), CONST64(0x1d2cac968b80169d), CONST64(0x3ea3bcc0fe1fdf21), CONST64(0x1b24a7918a831298),
+ CONST64(0x3648533f091b242d), CONST64(0x8c064045c94603ca), CONST64(0x354cd8b2879426a1), CONST64(0xb94a98f74ed2256b),
+ CONST64(0x7c5b659de13ea342), CONST64(0xe46d1fca2e72b896), CONST64(0x62734286e431b753), CONST64(0x7a536e9ae03da747),
+ CONST64(0x400b2babeb208b60), CONST64(0x47f459d790ad7aea), CONST64(0xff49b85ba4f1aa0e), CONST64(0x44f0d25a1e227866),
+ CONST64(0x395ccebc85922eab), CONST64(0x5d27873d60a09dfd), CONST64(0x0000000000000000), CONST64(0xde355afb256f94b1),
+ CONST64(0x02f3f2f6f401f703), CONST64(0x1cdbd5edf10ee312), CONST64(0x5fd475cb94a16afe), CONST64(0x3a5845310b1d2c27),
+ CONST64(0x686b5f8fe734bb5c), CONST64(0x238f1056759fc9bc), CONST64(0x582b07b7ef2c9b74), CONST64(0xb8bde18c345cd0e4),
+ CONST64(0xa695c6973153c4f5), CONST64(0xc2ee8f16d46177a3), CONST64(0xdacea30ad06d67b7), CONST64(0x3344d3b5869722a4),
+ CONST64(0x19d755677e82e59b), CONST64(0xc901eb64adea8e23), CONST64(0x34bba1c9fd1ad32e), CONST64(0xf6552edf297ba48d),
+ CONST64(0xa09dcd903050c0f0), CONST64(0x9ac588a13b4decd7), CONST64(0x658c30fa9fbc46d9), CONST64(0x2a9386d2f815c73f),
+ CONST64(0xae7e2968c6573ff9), CONST64(0x6a98ad7913354c5f), CONST64(0x14303a12060a181e), CONST64(0x1e28271b050f1411),
+ CONST64(0xa4663461c55233f6), CONST64(0x6688bb7711334455), CONST64(0x2f9f06587799c1b6), CONST64(0x15c743697c84ed91),
+ CONST64(0x01f7797b7a8ef58f), CONST64(0x0de76f757888fd85), CONST64(0xb4adf782365ad8ee), CONST64(0x48e0c4541c24706c),
+ CONST64(0x96d59eaf394be4dd), CONST64(0xcbf2199259eb7920), CONST64(0x50c0e84818286078), CONST64(0xe98a70bf56fa4513),
+ CONST64(0x8df1393eb3c8f645), CONST64(0x87e92437b0cdfa4a), CONST64(0xd83d51fc246c90b4), CONST64(0xc01d7de0206080a0),
+ CONST64(0x8bf93239b2cbf240), CONST64(0x4be44fd992ab72e0), CONST64(0xed71894ea3f8b615), CONST64(0xba4e137ac05d27e7),
+ CONST64(0x851ad6c144cc0d49), CONST64(0x5137913362a695f7), CONST64(0x6080b07010304050), CONST64(0x9fc9082bb4c1ea5e),
+ CONST64(0x3f54c5bb84912aae), CONST64(0x9722e7d443c51152), CONST64(0x4dec44de93a876e5), CONST64(0xb65e0574c25b2fed),
+ CONST64(0xa16ab4eb4ade357f), CONST64(0xa9815b14bddace73), CONST64(0x050c808a8f8c0689), CONST64(0xee7502c32d77b499),
+ CONST64(0xaf895013bcd9ca76), CONST64(0x6f942df39cb94ad6), CONST64(0x6177c90b6abeb5df), CONST64(0x9d3afadd40c01d5d),
+ CONST64(0x98367a57cf4c1bd4), CONST64(0xeb798249a2fbb210), CONST64(0x2774e9a7809d3aba), CONST64(0xbf4293f04fd1216e),
+ CONST64(0x42f8d95d1f217c63), CONST64(0x861e5d4cca430fc5), CONST64(0xdb39da71aae39238), CONST64(0x912aecd342c61557),
+};
+
+static const ulong64 T5[256] = {
+ CONST64(0xb9bb016ad3ba68d2), CONST64(0x9ae5b166fc54194d), CONST64(0x65e2cd14712f93bc), CONST64(0x8725511b9c74b9cd),
+ CONST64(0xa2f7a457f5530251), CONST64(0xd6d003be68d3b86b), CONST64(0xded604b56bd2bd6f), CONST64(0x52b3fe85d74d6429),
+ CONST64(0xbafdad4af0500d5d), CONST64(0x09cf63e0e9ac268a), CONST64(0x1c0984968a8d830e), CONST64(0x91a51a4ddcbf79c6),
+ CONST64(0xa73d4d379070addd), CONST64(0xaaf1a35cf6520755), CONST64(0xa47be117b39ac852), CONST64(0x5ab5f98ed44c612d),
+ CONST64(0x0346ac2023ea658f), CONST64(0xe6c4118462d5a673), CONST64(0xcc55c268a497f166), CONST64(0xc6dc0da86ed1b263),
+ CONST64(0x85aa99d05533ffcc), CONST64(0xb2fbaa41f3510859), CONST64(0xe2c79c0fed5b2a71), CONST64(0x59f355aef7a604a2),
+ CONST64(0xbefe20c17fde815f), CONST64(0x7aade5a2d848753d), CONST64(0x29d77fcce5a8329a), CONST64(0xbc71e80ab699c75e),
+ CONST64(0x96e03be670db904b), CONST64(0x8dac9edb5632fac8), CONST64(0xd1952215c4b751e6), CONST64(0xb332ceaa19fc2bd7),
+ CONST64(0x4b70937338e348ab), CONST64(0x8463fd3bbf9edc42), CONST64(0xfc41d052ae91ef7e), CONST64(0xac7de61cb09bcd56),
+ CONST64(0x437694783be24daf), CONST64(0xb1bd0661d0bb6dd6), CONST64(0x329bdaf1c3415819), CONST64(0x577917e5b26ecba5),
+ CONST64(0x41f95cb3f2a50bae), CONST64(0x16804b5640cbc00b), CONST64(0x7f670cc2bd6bdab1), CONST64(0xdc59cc7ea295fb6e),
+ CONST64(0x61e1409ffea11fbe), CONST64(0xcb10e3c308f318eb), CONST64(0xe181302fceb14ffe), CONST64(0x100c0e1606020a08),
+ CONST64(0x2e925e6749ccdb17), CONST64(0x6ea2663f51c4f337), CONST64(0xe84e53cf271d6974), CONST64(0xa0786c9c3c144450),
+ CONST64(0x56b0730e58c3e82b), CONST64(0x3f57349aa563f291), CONST64(0x9ee63ced73da954f), CONST64(0xd2d38e35e75d3469),
+ CONST64(0xc2df8023e15f3e61), CONST64(0xaef22ed779dc8b57), CONST64(0xcf136e48877d94e9), CONST64(0x2694596c4acdde13),
+ CONST64(0xdf1f605e817f9ee1), CONST64(0xeac19b04ee5a2f75), CONST64(0x477519f3b46cc1ad), CONST64(0xdad5893ee45c316d),
+ CONST64(0xeb08ffef04f70cfb), CONST64(0x2dd4f2476a26be98), CONST64(0xab38c7b71cff24db), CONST64(0x3b54b9112aed7e93),
+ CONST64(0x134aa23625e86f87), CONST64(0x9c69f426ba9dd34e), CONST64(0x5f7f10eeb16fcea1), CONST64(0x04038d8b8f8e8c02),
+ CONST64(0xc8564fe32b197d64), CONST64(0x69e74794fda01aba), CONST64(0xd31aeade0df017e7), CONST64(0x3c1198ba8689971e),
+ CONST64(0x78222d69110f333c), CONST64(0x3812153109071b1c), CONST64(0x11c56afdecaf2986), CONST64(0x8b20db9b10fb30cb),
+ CONST64(0x4030385818082820), CONST64(0xa87e6b973f154154), CONST64(0x682e237f170d3934), CONST64(0x20181c2c0c041410),
+ CONST64(0x0806070b03010504), CONST64(0x074521abac64e98d), CONST64(0xb6f827ca7cdf845b), CONST64(0x97295f0d9a76b3c5),
+ CONST64(0xef0b72648b7980f9), CONST64(0xa6f429dc7add8e53), CONST64(0xf58eb3b2473dc9f4), CONST64(0xb074628a3a164e58),
+ CONST64(0xe582bda4413fc3fc), CONST64(0xa5b285fc5937ebdc), CONST64(0x4f731ef8b76dc4a9), CONST64(0xdd90a8954838d8e0),
+ CONST64(0xa1b10877d6b967de), CONST64(0xbf37442a9573a2d1), CONST64(0x1b4ca53d26e96a83), CONST64(0xb5be8bea5f35e1d4),
+ CONST64(0x92e3b66dff551c49), CONST64(0xaf3b4a3c9371a8d9), CONST64(0xff077c728d7b8af1), CONST64(0x140f839d898c860a),
+ CONST64(0xb73143219672a7d5), CONST64(0x34179fb18588921a), CONST64(0xe30ef8e407f609ff), CONST64(0x4dfcd6337e2a82a8),
+ CONST64(0xed84baaf423ec6f8), CONST64(0xcad98728e25e3b65), CONST64(0x25d2f54c6927bb9c), CONST64(0x0a89cfc0ca464305),
+ CONST64(0x60282474140c3c30), CONST64(0x0f4326a0af65ec89), CONST64(0x676d05dfb868d5bd), CONST64(0x2f5b3a8ca361f899),
+ CONST64(0x180a091d05030f0c), CONST64(0x46bc7d185ec1e223), CONST64(0x82efb87bf9571641), CONST64(0xfece189967d6a97f),
+ CONST64(0x86ec35f076d99a43), CONST64(0xfacd9512e858257d), CONST64(0x8eea32fb75d89f47), CONST64(0x17492fbdaa66e385),
+ CONST64(0xf6c81f9264d7ac7b), CONST64(0xcd9ca6834e3ad2e8), CONST64(0x0e8a424b45c8cf07), CONST64(0xfd88b4b9443cccf0),
+ CONST64(0x8326dc9013fa35cf), CONST64(0xc453c563a796f462), CONST64(0x51f552a5f4a701a6), CONST64(0xb477ef01b598c25a),
+ CONST64(0x3352be1a29ec7b97), CONST64(0xa9b70f7cd5b862da), CONST64(0x76a86f2254c7fc3b), CONST64(0x19c36df6efae2c82),
+ CONST64(0x6f6b02d4bb69d0b9), CONST64(0x62a7ecbfdd4b7a31), CONST64(0x31dd76d1e0ab3d96), CONST64(0x21d178c7e6a9379e),
+ CONST64(0x1f4f28b6a967e681), CONST64(0x503c364e1e0a2228), CONST64(0x028fc8cbc9474601), CONST64(0xc316e4c80bf21def),
+ CONST64(0xc1992c03c2b55bee), CONST64(0x0dccee6b6622aa88), CONST64(0x7b64814932e556b3), CONST64(0x235eb00c2fee719f),
+ CONST64(0x99a31d46dfbe7cc2), CONST64(0x45fad1387d2b87ac), CONST64(0x7c21a0e29e81bf3e), CONST64(0x906c7ea636125a48),
+ CONST64(0x6c2daef49883b536), CONST64(0xd85a41f52d1b776c), CONST64(0x70242a62120e3638), CONST64(0x05cae9606523af8c),
+ CONST64(0xfb04f1f902f506f3), CONST64(0x1283c6ddcf454c09), CONST64(0x15c6e7766321a584), CONST64(0x3e9e50714fced11f),
+ CONST64(0x72abe2a9db497039), CONST64(0x7de8c409742c9cb0), CONST64(0x9b2cd58d16f93ac3), CONST64(0x636e885437e659bf),
+ CONST64(0xd993251ec7b654e2), CONST64(0x5df0d825782888a0), CONST64(0xb872658139174b5c), CONST64(0x642ba9ff9b82b032),
+ CONST64(0xd05c46fe2e1a7268), CONST64(0x2c1d96ac808b9d16), CONST64(0xa33ec0bc1ffe21df), CONST64(0x241b91a7838a9812),
+ CONST64(0x48363f531b092d24), CONST64(0x068c454046c9ca03), CONST64(0x4c35b2d89487a126), CONST64(0x4ab9f798d24e6b25),
+ CONST64(0x5b7c9d653ee142a3), CONST64(0x6de4ca1f722e96b8), CONST64(0x7362864231e453b7), CONST64(0x537a9a6e3de047a7),
+ CONST64(0x0b40ab2b20eb608b), CONST64(0xf447d759ad90ea7a), CONST64(0x49ff5bb8f1a40eaa), CONST64(0xf0445ad2221e6678),
+ CONST64(0x5c39bcce9285ab2e), CONST64(0x275d3d87a060fd9d), CONST64(0x0000000000000000), CONST64(0x35defb5a6f25b194),
+ CONST64(0xf302f6f201f403f7), CONST64(0xdb1cedd50ef112e3), CONST64(0xd45fcb75a194fe6a), CONST64(0x583a31451d0b272c),
+ CONST64(0x6b688f5f34e75cbb), CONST64(0x8f2356109f75bcc9), CONST64(0x2b58b7072cef749b), CONST64(0xbdb88ce15c34e4d0),
+ CONST64(0x95a697c65331f5c4), CONST64(0xeec2168f61d4a377), CONST64(0xceda0aa36dd0b767), CONST64(0x4433b5d39786a422),
+ CONST64(0xd7196755827e9be5), CONST64(0x01c964ebeaad238e), CONST64(0xbb34c9a11afd2ed3), CONST64(0x55f6df2e7b298da4),
+ CONST64(0x9da090cd5030f0c0), CONST64(0xc59aa1884d3bd7ec), CONST64(0x8c65fa30bc9fd946), CONST64(0x932ad28615f83fc7),
+ CONST64(0x7eae682957c6f93f), CONST64(0x986a79ad35135f4c), CONST64(0x3014123a0a061e18), CONST64(0x281e1b270f051114),
+ CONST64(0x66a4613452c5f633), CONST64(0x886677bb33115544), CONST64(0x9f2f58069977b6c1), CONST64(0xc7156943847c91ed),
+ CONST64(0xf7017b798e7a8ff5), CONST64(0xe70d756f887885fd), CONST64(0xadb482f75a36eed8), CONST64(0xe04854c4241c6c70),
+ CONST64(0xd596af9e4b39dde4), CONST64(0xf2cb9219eb592079), CONST64(0xc05048e828187860), CONST64(0x8ae9bf70fa561345),
+ CONST64(0xf18d3e39c8b345f6), CONST64(0xe9873724cdb04afa), CONST64(0x3dd8fc516c24b490), CONST64(0x1dc0e07d6020a080),
+ CONST64(0xf98b3932cbb240f2), CONST64(0xe44bd94fab92e072), CONST64(0x71ed4e89f8a315b6), CONST64(0x4eba7a135dc0e727),
+ CONST64(0x1a85c1d6cc44490d), CONST64(0x37513391a662f795), CONST64(0x806070b030105040), CONST64(0xc99f2b08c1b45eea),
+ CONST64(0x543fbbc59184ae2a), CONST64(0x2297d4e7c5435211), CONST64(0xec4dde44a893e576), CONST64(0x5eb674055bc2ed2f),
+ CONST64(0x6aa1ebb4de4a7f35), CONST64(0x81a9145bdabd73ce), CONST64(0x0c058a808c8f8906), CONST64(0x75eec302772d99b4),
+ CONST64(0x89af1350d9bc76ca), CONST64(0x946ff32db99cd64a), CONST64(0x77610bc9be6adfb5), CONST64(0x3a9dddfac0405d1d),
+ CONST64(0x3698577a4ccfd41b), CONST64(0x79eb4982fba210b2), CONST64(0x7427a7e99d80ba3a), CONST64(0x42bff093d14f6e21),
+ CONST64(0xf8425dd9211f637c), CONST64(0x1e864c5d43cac50f), CONST64(0x39db71dae3aa3892), CONST64(0x2a91d3ecc6425715),
+};
+
+static const ulong64 T6[256] = {
+ CONST64(0x6a01bbb9d268bad3), CONST64(0x66b1e59a4d1954fc), CONST64(0x14cde265bc932f71), CONST64(0x1b512587cdb9749c),
+ CONST64(0x57a4f7a2510253f5), CONST64(0xbe03d0d66bb8d368), CONST64(0xb504d6de6fbdd26b), CONST64(0x85feb35229644dd7),
+ CONST64(0x4aadfdba5d0d50f0), CONST64(0xe063cf098a26ace9), CONST64(0x9684091c0e838d8a), CONST64(0x4d1aa591c679bfdc),
+ CONST64(0x374d3da7ddad7090), CONST64(0x5ca3f1aa550752f6), CONST64(0x17e17ba452c89ab3), CONST64(0x8ef9b55a2d614cd4),
+ CONST64(0x20ac46038f65ea23), CONST64(0x8411c4e673a6d562), CONST64(0x68c255cc66f197a4), CONST64(0xa80ddcc663b2d16e),
+ CONST64(0xd099aa85ccff3355), CONST64(0x41aafbb2590851f3), CONST64(0x0f9cc7e2712a5bed), CONST64(0xae55f359a204a6f7),
+ CONST64(0xc120febe5f81de7f), CONST64(0xa2e5ad7a3d7548d8), CONST64(0xcc7fd7299a32a8e5), CONST64(0x0ae871bc5ec799b6),
+ CONST64(0xe63be0964b90db70), CONST64(0xdb9eac8dc8fa3256), CONST64(0x152295d1e651b7c4), CONST64(0xaace32b3d72bfc19),
+ CONST64(0x7393704bab48e338), CONST64(0x3bfd638442dc9ebf), CONST64(0x52d041fc7eef91ae), CONST64(0x1ce67dac56cd9bb0),
+ CONST64(0x78947643af4de23b), CONST64(0x6106bdb1d66dbbd0), CONST64(0xf1da9b32195841c3), CONST64(0xe5177957a5cb6eb2),
+ CONST64(0xb35cf941ae0ba5f2), CONST64(0x564b80160bc0cb40), CONST64(0xc20c677fb1da6bbd), CONST64(0x7ecc59dc6efb95a2),
+ CONST64(0x9f40e161be1fa1fe), CONST64(0xc3e310cbeb18f308), CONST64(0x2f3081e1fe4fb1ce), CONST64(0x160e0c10080a0206),
+ CONST64(0x675e922e17dbcc49), CONST64(0x3f66a26e37f3c451), CONST64(0xcf534ee874691d27), CONST64(0x9c6c78a05044143c),
+ CONST64(0x0e73b0562be8c358), CONST64(0x9a34573f91f263a5), CONST64(0xed3ce69e4f95da73), CONST64(0x358ed3d269345de7),
+ CONST64(0x2380dfc2613e5fe1), CONST64(0xd72ef2ae578bdc79), CONST64(0x486e13cfe9947d87), CONST64(0x6c59942613decd4a),
+ CONST64(0x5e601fdfe19e7f81), CONST64(0x049bc1ea752f5aee), CONST64(0xf3197547adc16cb4), CONST64(0x3e89d5da6d315ce4),
+ CONST64(0xefff08ebfb0cf704), CONST64(0x47f2d42d98be266a), CONST64(0xb7c738abdb24ff1c), CONST64(0x11b9543b937eed2a),
+ CONST64(0x36a24a13876fe825), CONST64(0x26f4699c4ed39dba), CONST64(0xee107f5fa1ce6fb1), CONST64(0x8b8d0304028c8e8f),
+ CONST64(0xe34f56c8647d192b), CONST64(0x9447e769ba1aa0fd), CONST64(0xdeea1ad3e717f00d), CONST64(0xba98113c1e978986),
+ CONST64(0x692d22783c330f11), CONST64(0x311512381c1b0709), CONST64(0xfd6ac5118629afec), CONST64(0x9bdb208bcb30fb10),
+ CONST64(0x5838304020280818), CONST64(0x976b7ea85441153f), CONST64(0x7f232e6834390d17), CONST64(0x2c1c18201014040c),
+ CONST64(0x0b07060804050103), CONST64(0xab2145078de964ac), CONST64(0xca27f8b65b84df7c), CONST64(0x0d5f2997c5b3769a),
+ CONST64(0x64720beff980798b), CONST64(0xdc29f4a6538edd7a), CONST64(0xb2b38ef5f4c93d47), CONST64(0x8a6274b0584e163a),
+ CONST64(0xa4bd82e5fcc33f41), CONST64(0xfc85b2a5dceb3759), CONST64(0xf81e734fa9c46db7), CONST64(0x95a890dde0d83848),
+ CONST64(0x7708b1a1de67b9d6), CONST64(0x2a4437bfd1a27395), CONST64(0x3da54c1b836ae926), CONST64(0xea8bbeb5d4e1355f),
+ CONST64(0x6db6e392491c55ff), CONST64(0x3c4a3bafd9a87193), CONST64(0x727c07fff18a7b8d), CONST64(0x9d830f140a868c89),
+ CONST64(0x214331b7d5a77296), CONST64(0xb19f17341a928885), CONST64(0xe4f80ee3ff09f607), CONST64(0x33d6fc4da8822a7e),
+ CONST64(0xafba84edf8c63e42), CONST64(0x2887d9ca653b5ee2), CONST64(0x4cf5d2259cbb2769), CONST64(0xc0cf890a054346ca),
+ CONST64(0x74242860303c0c14), CONST64(0xa026430f89ec65af), CONST64(0xdf056d67bdd568b8), CONST64(0x8c3a5b2f99f861a3),
+ CONST64(0x1d090a180c0f0305), CONST64(0x187dbc4623e2c15e), CONST64(0x7bb8ef82411657f9), CONST64(0x9918cefe7fa9d667),
+ CONST64(0xf035ec86439ad976), CONST64(0x1295cdfa7d2558e8), CONST64(0xfb32ea8e479fd875), CONST64(0xbd2f491785e366aa),
+ CONST64(0x921fc8f67bacd764), CONST64(0x83a69ccde8d23a4e), CONST64(0x4b428a0e07cfc845), CONST64(0xb9b488fdf0cc3c44),
+ CONST64(0x90dc2683cf35fa13), CONST64(0x63c553c462f496a7), CONST64(0xa552f551a601a7f4), CONST64(0x01ef77b45ac298b5),
+ CONST64(0x1abe5233977bec29), CONST64(0x7c0fb7a9da62b8d5), CONST64(0x226fa8763bfcc754), CONST64(0xf66dc319822caeef),
+ CONST64(0xd4026b6fb9d069bb), CONST64(0xbfeca762317a4bdd), CONST64(0xd176dd31963dabe0), CONST64(0xc778d1219e37a9e6),
+ CONST64(0xb6284f1f81e667a9), CONST64(0x4e363c5028220a1e), CONST64(0xcbc88f02014647c9), CONST64(0xc8e416c3ef1df20b),
+ CONST64(0x032c99c1ee5bb5c2), CONST64(0x6beecc0d88aa2266), CONST64(0x4981647bb356e532), CONST64(0x0cb05e239f71ee2f),
+ CONST64(0x461da399c27cbedf), CONST64(0x38d1fa45ac872b7d), CONST64(0xe2a0217c3ebf819e), CONST64(0xa67e6c90485a1236),
+ CONST64(0xf4ae2d6c36b58398), CONST64(0xf5415ad86c771b2d), CONST64(0x622a247038360e12), CONST64(0x60e9ca058caf2365),
+ CONST64(0xf9f104fbf306f502), CONST64(0xddc68312094c45cf), CONST64(0x76e7c61584a52163), CONST64(0x71509e3e1fd1ce4f),
+ CONST64(0xa9e2ab72397049db), CONST64(0x09c4e87db09c2c74), CONST64(0x8dd52c9bc33af916), CONST64(0x54886e63bf59e637),
+ CONST64(0x1e2593d9e254b6c7), CONST64(0x25d8f05da0882878), CONST64(0x816572b85c4b1739), CONST64(0xffa92b6432b0829b),
+ CONST64(0xfe465cd068721a2e), CONST64(0xac961d2c169d8b80), CONST64(0xbcc03ea3df21fe1f), CONST64(0xa7911b2412988a83),
+ CONST64(0x533f3648242d091b), CONST64(0x40458c0603cac946), CONST64(0xd8b2354c26a18794), CONST64(0x98f7b94a256b4ed2),
+ CONST64(0x659d7c5ba342e13e), CONST64(0x1fcae46db8962e72), CONST64(0x42866273b753e431), CONST64(0x6e9a7a53a747e03d),
+ CONST64(0x2bab400b8b60eb20), CONST64(0x59d747f47aea90ad), CONST64(0xb85bff49aa0ea4f1), CONST64(0xd25a44f078661e22),
+ CONST64(0xcebc395c2eab8592), CONST64(0x873d5d279dfd60a0), CONST64(0x0000000000000000), CONST64(0x5afbde3594b1256f),
+ CONST64(0xf2f602f3f703f401), CONST64(0xd5ed1cdbe312f10e), CONST64(0x75cb5fd46afe94a1), CONST64(0x45313a582c270b1d),
+ CONST64(0x5f8f686bbb5ce734), CONST64(0x1056238fc9bc759f), CONST64(0x07b7582b9b74ef2c), CONST64(0xe18cb8bdd0e4345c),
+ CONST64(0xc697a695c4f53153), CONST64(0x8f16c2ee77a3d461), CONST64(0xa30adace67b7d06d), CONST64(0xd3b5334422a48697),
+ CONST64(0x556719d7e59b7e82), CONST64(0xeb64c9018e23adea), CONST64(0xa1c934bbd32efd1a), CONST64(0x2edff655a48d297b),
+ CONST64(0xcd90a09dc0f03050), CONST64(0x88a19ac5ecd73b4d), CONST64(0x30fa658c46d99fbc), CONST64(0x86d22a93c73ff815),
+ CONST64(0x2968ae7e3ff9c657), CONST64(0xad796a984c5f1335), CONST64(0x3a121430181e060a), CONST64(0x271b1e281411050f),
+ CONST64(0x3461a46633f6c552), CONST64(0xbb77668844551133), CONST64(0x06582f9fc1b67799), CONST64(0x436915c7ed917c84),
+ CONST64(0x797b01f7f58f7a8e), CONST64(0x6f750de7fd857888), CONST64(0xf782b4add8ee365a), CONST64(0xc45448e0706c1c24),
+ CONST64(0x9eaf96d5e4dd394b), CONST64(0x1992cbf2792059eb), CONST64(0xe84850c060781828), CONST64(0x70bfe98a451356fa),
+ CONST64(0x393e8df1f645b3c8), CONST64(0x243787e9fa4ab0cd), CONST64(0x51fcd83d90b4246c), CONST64(0x7de0c01d80a02060),
+ CONST64(0x32398bf9f240b2cb), CONST64(0x4fd94be472e092ab), CONST64(0x894eed71b615a3f8), CONST64(0x137aba4e27e7c05d),
+ CONST64(0xd6c1851a0d4944cc), CONST64(0x9133513795f762a6), CONST64(0xb070608040501030), CONST64(0x082b9fc9ea5eb4c1),
+ CONST64(0xc5bb3f542aae8491), CONST64(0xe7d49722115243c5), CONST64(0x44de4dec76e593a8), CONST64(0x0574b65e2fedc25b),
+ CONST64(0xb4eba16a357f4ade), CONST64(0x5b14a981ce73bdda), CONST64(0x808a050c06898f8c), CONST64(0x02c3ee75b4992d77),
+ CONST64(0x5013af89ca76bcd9), CONST64(0x2df36f944ad69cb9), CONST64(0xc90b6177b5df6abe), CONST64(0xfadd9d3a1d5d40c0),
+ CONST64(0x7a5798361bd4cf4c), CONST64(0x8249eb79b210a2fb), CONST64(0xe9a727743aba809d), CONST64(0x93f0bf42216e4fd1),
+ CONST64(0xd95d42f87c631f21), CONST64(0x5d4c861e0fc5ca43), CONST64(0xda71db399238aae3), CONST64(0xecd3912a155742c6),
+};
+
+static const ulong64 T7[256] = {
+ CONST64(0x016ab9bb68d2d3ba), CONST64(0xb1669ae5194dfc54), CONST64(0xcd1465e293bc712f), CONST64(0x511b8725b9cd9c74),
+ CONST64(0xa457a2f70251f553), CONST64(0x03bed6d0b86b68d3), CONST64(0x04b5ded6bd6f6bd2), CONST64(0xfe8552b36429d74d),
+ CONST64(0xad4abafd0d5df050), CONST64(0x63e009cf268ae9ac), CONST64(0x84961c09830e8a8d), CONST64(0x1a4d91a579c6dcbf),
+ CONST64(0x4d37a73daddd9070), CONST64(0xa35caaf10755f652), CONST64(0xe117a47bc852b39a), CONST64(0xf98e5ab5612dd44c),
+ CONST64(0xac200346658f23ea), CONST64(0x1184e6c4a67362d5), CONST64(0xc268cc55f166a497), CONST64(0x0da8c6dcb2636ed1),
+ CONST64(0x99d085aaffcc5533), CONST64(0xaa41b2fb0859f351), CONST64(0x9c0fe2c72a71ed5b), CONST64(0x55ae59f304a2f7a6),
+ CONST64(0x20c1befe815f7fde), CONST64(0xe5a27aad753dd848), CONST64(0x7fcc29d7329ae5a8), CONST64(0xe80abc71c75eb699),
+ CONST64(0x3be696e0904b70db), CONST64(0x9edb8dacfac85632), CONST64(0x2215d19551e6c4b7), CONST64(0xceaab3322bd719fc),
+ CONST64(0x93734b7048ab38e3), CONST64(0xfd3b8463dc42bf9e), CONST64(0xd052fc41ef7eae91), CONST64(0xe61cac7dcd56b09b),
+ CONST64(0x947843764daf3be2), CONST64(0x0661b1bd6dd6d0bb), CONST64(0xdaf1329b5819c341), CONST64(0x17e55779cba5b26e),
+ CONST64(0x5cb341f90baef2a5), CONST64(0x4b561680c00b40cb), CONST64(0x0cc27f67dab1bd6b), CONST64(0xcc7edc59fb6ea295),
+ CONST64(0x409f61e11fbefea1), CONST64(0xe3c3cb1018eb08f3), CONST64(0x302fe1814ffeceb1), CONST64(0x0e16100c0a080602),
+ CONST64(0x5e672e92db1749cc), CONST64(0x663f6ea2f33751c4), CONST64(0x53cfe84e6974271d), CONST64(0x6c9ca07844503c14),
+ CONST64(0x730e56b0e82b58c3), CONST64(0x349a3f57f291a563), CONST64(0x3ced9ee6954f73da), CONST64(0x8e35d2d33469e75d),
+ CONST64(0x8023c2df3e61e15f), CONST64(0x2ed7aef28b5779dc), CONST64(0x6e48cf1394e9877d), CONST64(0x596c2694de134acd),
+ CONST64(0x605edf1f9ee1817f), CONST64(0x9b04eac12f75ee5a), CONST64(0x19f34775c1adb46c), CONST64(0x893edad5316de45c),
+ CONST64(0xffefeb080cfb04f7), CONST64(0xf2472dd4be986a26), CONST64(0xc7b7ab3824db1cff), CONST64(0xb9113b547e932aed),
+ CONST64(0xa236134a6f8725e8), CONST64(0xf4269c69d34eba9d), CONST64(0x10ee5f7fcea1b16f), CONST64(0x8d8b04038c028f8e),
+ CONST64(0x4fe3c8567d642b19), CONST64(0x479469e71abafda0), CONST64(0xeaded31a17e70df0), CONST64(0x98ba3c11971e8689),
+ CONST64(0x2d697822333c110f), CONST64(0x153138121b1c0907), CONST64(0x6afd11c52986ecaf), CONST64(0xdb9b8b2030cb10fb),
+ CONST64(0x3858403028201808), CONST64(0x6b97a87e41543f15), CONST64(0x237f682e3934170d), CONST64(0x1c2c201814100c04),
+ CONST64(0x070b080605040301), CONST64(0x21ab0745e98dac64), CONST64(0x27cab6f8845b7cdf), CONST64(0x5f0d9729b3c59a76),
+ CONST64(0x7264ef0b80f98b79), CONST64(0x29dca6f48e537add), CONST64(0xb3b2f58ec9f4473d), CONST64(0x628ab0744e583a16),
+ CONST64(0xbda4e582c3fc413f), CONST64(0x85fca5b2ebdc5937), CONST64(0x1ef84f73c4a9b76d), CONST64(0xa895dd90d8e04838),
+ CONST64(0x0877a1b167ded6b9), CONST64(0x442abf37a2d19573), CONST64(0xa53d1b4c6a8326e9), CONST64(0x8beab5bee1d45f35),
+ CONST64(0xb66d92e31c49ff55), CONST64(0x4a3caf3ba8d99371), CONST64(0x7c72ff078af18d7b), CONST64(0x839d140f860a898c),
+ CONST64(0x4321b731a7d59672), CONST64(0x9fb13417921a8588), CONST64(0xf8e4e30e09ff07f6), CONST64(0xd6334dfc82a87e2a),
+ CONST64(0xbaafed84c6f8423e), CONST64(0x8728cad93b65e25e), CONST64(0xf54c25d2bb9c6927), CONST64(0xcfc00a894305ca46),
+ CONST64(0x247460283c30140c), CONST64(0x26a00f43ec89af65), CONST64(0x05df676dd5bdb868), CONST64(0x3a8c2f5bf899a361),
+ CONST64(0x091d180a0f0c0503), CONST64(0x7d1846bce2235ec1), CONST64(0xb87b82ef1641f957), CONST64(0x1899fecea97f67d6),
+ CONST64(0x35f086ec9a4376d9), CONST64(0x9512facd257de858), CONST64(0x32fb8eea9f4775d8), CONST64(0x2fbd1749e385aa66),
+ CONST64(0x1f92f6c8ac7b64d7), CONST64(0xa683cd9cd2e84e3a), CONST64(0x424b0e8acf0745c8), CONST64(0xb4b9fd88ccf0443c),
+ CONST64(0xdc90832635cf13fa), CONST64(0xc563c453f462a796), CONST64(0x52a551f501a6f4a7), CONST64(0xef01b477c25ab598),
+ CONST64(0xbe1a33527b9729ec), CONST64(0x0f7ca9b762dad5b8), CONST64(0x6f2276a8fc3b54c7), CONST64(0x6df619c32c82efae),
+ CONST64(0x02d46f6bd0b9bb69), CONST64(0xecbf62a77a31dd4b), CONST64(0x76d131dd3d96e0ab), CONST64(0x78c721d1379ee6a9),
+ CONST64(0x28b61f4fe681a967), CONST64(0x364e503c22281e0a), CONST64(0xc8cb028f4601c947), CONST64(0xe4c8c3161def0bf2),
+ CONST64(0x2c03c1995beec2b5), CONST64(0xee6b0dccaa886622), CONST64(0x81497b6456b332e5), CONST64(0xb00c235e719f2fee),
+ CONST64(0x1d4699a37cc2dfbe), CONST64(0xd13845fa87ac7d2b), CONST64(0xa0e27c21bf3e9e81), CONST64(0x7ea6906c5a483612),
+ CONST64(0xaef46c2db5369883), CONST64(0x41f5d85a776c2d1b), CONST64(0x2a6270243638120e), CONST64(0xe96005caaf8c6523),
+ CONST64(0xf1f9fb0406f302f5), CONST64(0xc6dd12834c09cf45), CONST64(0xe77615c6a5846321), CONST64(0x50713e9ed11f4fce),
+ CONST64(0xe2a972ab7039db49), CONST64(0xc4097de89cb0742c), CONST64(0xd58d9b2c3ac316f9), CONST64(0x8854636e59bf37e6),
+ CONST64(0x251ed99354e2c7b6), CONST64(0xd8255df088a07828), CONST64(0x6581b8724b5c3917), CONST64(0xa9ff642bb0329b82),
+ CONST64(0x46fed05c72682e1a), CONST64(0x96ac2c1d9d16808b), CONST64(0xc0bca33e21df1ffe), CONST64(0x91a7241b9812838a),
+ CONST64(0x3f5348362d241b09), CONST64(0x4540068cca0346c9), CONST64(0xb2d84c35a1269487), CONST64(0xf7984ab96b25d24e),
+ CONST64(0x9d655b7c42a33ee1), CONST64(0xca1f6de496b8722e), CONST64(0x8642736253b731e4), CONST64(0x9a6e537a47a73de0),
+ CONST64(0xab2b0b40608b20eb), CONST64(0xd759f447ea7aad90), CONST64(0x5bb849ff0eaaf1a4), CONST64(0x5ad2f0446678221e),
+ CONST64(0xbcce5c39ab2e9285), CONST64(0x3d87275dfd9da060), CONST64(0x0000000000000000), CONST64(0xfb5a35deb1946f25),
+ CONST64(0xf6f2f30203f701f4), CONST64(0xedd5db1c12e30ef1), CONST64(0xcb75d45ffe6aa194), CONST64(0x3145583a272c1d0b),
+ CONST64(0x8f5f6b685cbb34e7), CONST64(0x56108f23bcc99f75), CONST64(0xb7072b58749b2cef), CONST64(0x8ce1bdb8e4d05c34),
+ CONST64(0x97c695a6f5c45331), CONST64(0x168feec2a37761d4), CONST64(0x0aa3cedab7676dd0), CONST64(0xb5d34433a4229786),
+ CONST64(0x6755d7199be5827e), CONST64(0x64eb01c9238eeaad), CONST64(0xc9a1bb342ed31afd), CONST64(0xdf2e55f68da47b29),
+ CONST64(0x90cd9da0f0c05030), CONST64(0xa188c59ad7ec4d3b), CONST64(0xfa308c65d946bc9f), CONST64(0xd286932a3fc715f8),
+ CONST64(0x68297eaef93f57c6), CONST64(0x79ad986a5f4c3513), CONST64(0x123a30141e180a06), CONST64(0x1b27281e11140f05),
+ CONST64(0x613466a4f63352c5), CONST64(0x77bb886655443311), CONST64(0x58069f2fb6c19977), CONST64(0x6943c71591ed847c),
+ CONST64(0x7b79f7018ff58e7a), CONST64(0x756fe70d85fd8878), CONST64(0x82f7adb4eed85a36), CONST64(0x54c4e0486c70241c),
+ CONST64(0xaf9ed596dde44b39), CONST64(0x9219f2cb2079eb59), CONST64(0x48e8c05078602818), CONST64(0xbf708ae91345fa56),
+ CONST64(0x3e39f18d45f6c8b3), CONST64(0x3724e9874afacdb0), CONST64(0xfc513dd8b4906c24), CONST64(0xe07d1dc0a0806020),
+ CONST64(0x3932f98b40f2cbb2), CONST64(0xd94fe44be072ab92), CONST64(0x4e8971ed15b6f8a3), CONST64(0x7a134ebae7275dc0),
+ CONST64(0xc1d61a85490dcc44), CONST64(0x33913751f795a662), CONST64(0x70b0806050403010), CONST64(0x2b08c99f5eeac1b4),
+ CONST64(0xbbc5543fae2a9184), CONST64(0xd4e722975211c543), CONST64(0xde44ec4de576a893), CONST64(0x74055eb6ed2f5bc2),
+ CONST64(0xebb46aa17f35de4a), CONST64(0x145b81a973cedabd), CONST64(0x8a800c0589068c8f), CONST64(0xc30275ee99b4772d),
+ CONST64(0x135089af76cad9bc), CONST64(0xf32d946fd64ab99c), CONST64(0x0bc97761dfb5be6a), CONST64(0xddfa3a9d5d1dc040),
+ CONST64(0x577a3698d41b4ccf), CONST64(0x498279eb10b2fba2), CONST64(0xa7e97427ba3a9d80), CONST64(0xf09342bf6e21d14f),
+ CONST64(0x5dd9f842637c211f), CONST64(0x4c5d1e86c50f43ca), CONST64(0x71da39db3892e3aa), CONST64(0xd3ec2a915715c642),
+};
+
+static const ulong64 c[R + 1] = {
+ CONST64(0xba542f7453d3d24d),
+ CONST64(0x50ac8dbf70529a4c),
+ CONST64(0xead597d133515ba6),
+ CONST64(0xde48a899db32b7fc),
+ CONST64(0xe39e919be2bb416e),
+ CONST64(0xa5cb6b95a1f3b102),
+ CONST64(0xccc41d14c363da5d),
+ CONST64(0x5fdc7dcd7f5a6c5c),
+ CONST64(0xf726ffede89d6f8e),
+};
+
+ /**
+ Initialize the Khazad block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int r;
+ const ulong64 *S;
+ ulong64 K2, K1;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+ if (keylen != 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (num_rounds != 8 && num_rounds != 0) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* use 7th table */
+ S = T7;
+
+ /*
+ * map unsigned char array cipher key to initial key state (mu):
+ */
+ K2 =
+ ((ulong64)key[ 0] << 56) ^
+ ((ulong64)key[ 1] << 48) ^
+ ((ulong64)key[ 2] << 40) ^
+ ((ulong64)key[ 3] << 32) ^
+ ((ulong64)key[ 4] << 24) ^
+ ((ulong64)key[ 5] << 16) ^
+ ((ulong64)key[ 6] << 8) ^
+ ((ulong64)key[ 7] );
+ K1 =
+ ((ulong64)key[ 8] << 56) ^
+ ((ulong64)key[ 9] << 48) ^
+ ((ulong64)key[10] << 40) ^
+ ((ulong64)key[11] << 32) ^
+ ((ulong64)key[12] << 24) ^
+ ((ulong64)key[13] << 16) ^
+ ((ulong64)key[14] << 8) ^
+ ((ulong64)key[15] );
+
+ /*
+ * compute the round keys:
+ */
+ for (r = 0; r <= R; r++) {
+ /*
+ * K[r] = rho(c[r], K1) ^ K2;
+ */
+ skey->khazad.roundKeyEnc[r] =
+ T0[(int)(K1 >> 56) ] ^
+ T1[(int)(K1 >> 48) & 0xff] ^
+ T2[(int)(K1 >> 40) & 0xff] ^
+ T3[(int)(K1 >> 32) & 0xff] ^
+ T4[(int)(K1 >> 24) & 0xff] ^
+ T5[(int)(K1 >> 16) & 0xff] ^
+ T6[(int)(K1 >> 8) & 0xff] ^
+ T7[(int)(K1 ) & 0xff] ^
+ c[r] ^ K2;
+ K2 = K1; K1 = skey->khazad.roundKeyEnc[r];
+ }
+ /*
+ * compute the inverse key schedule:
+ * K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r})
+ */
+ skey->khazad.roundKeyDec[0] = skey->khazad.roundKeyEnc[R];
+ for (r = 1; r < R; r++) {
+ K1 = skey->khazad.roundKeyEnc[R - r];
+ skey->khazad.roundKeyDec[r] =
+ T0[(int)S[(int)(K1 >> 56) ] & 0xff] ^
+ T1[(int)S[(int)(K1 >> 48) & 0xff] & 0xff] ^
+ T2[(int)S[(int)(K1 >> 40) & 0xff] & 0xff] ^
+ T3[(int)S[(int)(K1 >> 32) & 0xff] & 0xff] ^
+ T4[(int)S[(int)(K1 >> 24) & 0xff] & 0xff] ^
+ T5[(int)S[(int)(K1 >> 16) & 0xff] & 0xff] ^
+ T6[(int)S[(int)(K1 >> 8) & 0xff] & 0xff] ^
+ T7[(int)S[(int)(K1 ) & 0xff] & 0xff];
+ }
+ skey->khazad.roundKeyDec[R] = skey->khazad.roundKeyEnc[0];
+
+ return CRYPT_OK;
+}
+
+static void khazad_crypt(const unsigned char *plaintext, unsigned char *ciphertext,
+ const ulong64 *roundKey) {
+ int r;
+ ulong64 state;
+ /*
+ * map plaintext block to cipher state (mu)
+ * and add initial round key (sigma[K^0]):
+ */
+ state =
+ ((ulong64)plaintext[0] << 56) ^
+ ((ulong64)plaintext[1] << 48) ^
+ ((ulong64)plaintext[2] << 40) ^
+ ((ulong64)plaintext[3] << 32) ^
+ ((ulong64)plaintext[4] << 24) ^
+ ((ulong64)plaintext[5] << 16) ^
+ ((ulong64)plaintext[6] << 8) ^
+ ((ulong64)plaintext[7] ) ^
+ roundKey[0];
+
+ /*
+ * R - 1 full rounds:
+ */
+ for (r = 1; r < R; r++) {
+ state =
+ T0[(int)(state >> 56) ] ^
+ T1[(int)(state >> 48) & 0xff] ^
+ T2[(int)(state >> 40) & 0xff] ^
+ T3[(int)(state >> 32) & 0xff] ^
+ T4[(int)(state >> 24) & 0xff] ^
+ T5[(int)(state >> 16) & 0xff] ^
+ T6[(int)(state >> 8) & 0xff] ^
+ T7[(int)(state ) & 0xff] ^
+ roundKey[r];
+ }
+
+ /*
+ * last round:
+ */
+ state =
+ (T0[(int)(state >> 56) ] & CONST64(0xff00000000000000)) ^
+ (T1[(int)(state >> 48) & 0xff] & CONST64(0x00ff000000000000)) ^
+ (T2[(int)(state >> 40) & 0xff] & CONST64(0x0000ff0000000000)) ^
+ (T3[(int)(state >> 32) & 0xff] & CONST64(0x000000ff00000000)) ^
+ (T4[(int)(state >> 24) & 0xff] & CONST64(0x00000000ff000000)) ^
+ (T5[(int)(state >> 16) & 0xff] & CONST64(0x0000000000ff0000)) ^
+ (T6[(int)(state >> 8) & 0xff] & CONST64(0x000000000000ff00)) ^
+ (T7[(int)(state ) & 0xff] & CONST64(0x00000000000000ff)) ^
+ roundKey[R];
+
+ /*
+ * map cipher state to ciphertext block (mu^{-1}):
+ */
+ ciphertext[0] = (unsigned char)(state >> 56);
+ ciphertext[1] = (unsigned char)(state >> 48);
+ ciphertext[2] = (unsigned char)(state >> 40);
+ ciphertext[3] = (unsigned char)(state >> 32);
+ ciphertext[4] = (unsigned char)(state >> 24);
+ ciphertext[5] = (unsigned char)(state >> 16);
+ ciphertext[6] = (unsigned char)(state >> 8);
+ ciphertext[7] = (unsigned char)(state );
+}
+
+/**
+ Encrypts a block of text with Khazad
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ khazad_crypt(pt, ct, skey->khazad.roundKeyEnc);
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with Khazad
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ khazad_crypt(ct, pt, skey->khazad.roundKeyDec);
+ return CRYPT_OK;
+}
+
+/**
+ Performs a self-test of the Khazad block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int khazad_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct test {
+ unsigned char pt[8], ct[8], key[16];
+ } tests[] = {
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x49, 0xA4, 0xCE, 0x32, 0xAC, 0x19, 0x0E, 0x3F },
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x64, 0x5D, 0x77, 0x3E, 0x40, 0xAB, 0xDD, 0x53 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+}, {
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x9E, 0x39, 0x98, 0x64, 0xF7, 0x8E, 0xCA, 0x02 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}, {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0xA9, 0xDF, 0x3D, 0x2C, 0x64, 0xD3, 0xEA, 0x28 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+}
+};
+ int x, y;
+ unsigned char buf[2][8];
+ symmetric_key skey;
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ khazad_setup(tests[x].key, 16, 0, &skey);
+ khazad_ecb_encrypt(tests[x].pt, buf[0], &skey);
+ khazad_ecb_decrypt(buf[0], buf[1], &skey);
+ if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad Encrypt", x) ||
+ compare_testvector(buf[1], 8, tests[x].pt, 8, "Khazad Decrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ for (y = 0; y < 1000; y++) khazad_ecb_encrypt(buf[0], buf[0], &skey);
+ for (y = 0; y < 1000; y++) khazad_ecb_decrypt(buf[0], buf[0], &skey);
+ if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad 1000", 1000)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void khazad_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int khazad_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize >= 16) {
+ *keysize = 16;
+ return CRYPT_OK;
+ }
+ return CRYPT_INVALID_KEYSIZE;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/ciphers/kseed.c b/Sources/libtomcrypt/ciphers/kseed.c
new file mode 100644
index 00000000..1e63aec4
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/kseed.c
@@ -0,0 +1,366 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file kseed.c
+ seed implementation of SEED derived from RFC4269
+ Tom St Denis
+*/
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_KSEED
+
+const struct ltc_cipher_descriptor kseed_desc = {
+ "seed",
+ 20,
+ 16, 16, 16, 16,
+ &kseed_setup,
+ &kseed_ecb_encrypt,
+ &kseed_ecb_decrypt,
+ &kseed_test,
+ &kseed_done,
+ &kseed_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ulong32 SS0[256] = {
+0x2989A1A8UL,0x05858184UL,0x16C6D2D4UL,0x13C3D3D0UL,0x14445054UL,0x1D0D111CUL,0x2C8CA0ACUL,0x25052124UL,
+0x1D4D515CUL,0x03434340UL,0x18081018UL,0x1E0E121CUL,0x11415150UL,0x3CCCF0FCUL,0x0ACAC2C8UL,0x23436360UL,
+0x28082028UL,0x04444044UL,0x20002020UL,0x1D8D919CUL,0x20C0E0E0UL,0x22C2E2E0UL,0x08C8C0C8UL,0x17071314UL,
+0x2585A1A4UL,0x0F8F838CUL,0x03030300UL,0x3B4B7378UL,0x3B8BB3B8UL,0x13031310UL,0x12C2D2D0UL,0x2ECEE2ECUL,
+0x30407070UL,0x0C8C808CUL,0x3F0F333CUL,0x2888A0A8UL,0x32023230UL,0x1DCDD1DCUL,0x36C6F2F4UL,0x34447074UL,
+0x2CCCE0ECUL,0x15859194UL,0x0B0B0308UL,0x17475354UL,0x1C4C505CUL,0x1B4B5358UL,0x3D8DB1BCUL,0x01010100UL,
+0x24042024UL,0x1C0C101CUL,0x33437370UL,0x18889098UL,0x10001010UL,0x0CCCC0CCUL,0x32C2F2F0UL,0x19C9D1D8UL,
+0x2C0C202CUL,0x27C7E3E4UL,0x32427270UL,0x03838380UL,0x1B8B9398UL,0x11C1D1D0UL,0x06868284UL,0x09C9C1C8UL,
+0x20406060UL,0x10405050UL,0x2383A3A0UL,0x2BCBE3E8UL,0x0D0D010CUL,0x3686B2B4UL,0x1E8E929CUL,0x0F4F434CUL,
+0x3787B3B4UL,0x1A4A5258UL,0x06C6C2C4UL,0x38487078UL,0x2686A2A4UL,0x12021210UL,0x2F8FA3ACUL,0x15C5D1D4UL,
+0x21416160UL,0x03C3C3C0UL,0x3484B0B4UL,0x01414140UL,0x12425250UL,0x3D4D717CUL,0x0D8D818CUL,0x08080008UL,
+0x1F0F131CUL,0x19899198UL,0x00000000UL,0x19091118UL,0x04040004UL,0x13435350UL,0x37C7F3F4UL,0x21C1E1E0UL,
+0x3DCDF1FCUL,0x36467274UL,0x2F0F232CUL,0x27072324UL,0x3080B0B0UL,0x0B8B8388UL,0x0E0E020CUL,0x2B8BA3A8UL,
+0x2282A2A0UL,0x2E4E626CUL,0x13839390UL,0x0D4D414CUL,0x29496168UL,0x3C4C707CUL,0x09090108UL,0x0A0A0208UL,
+0x3F8FB3BCUL,0x2FCFE3ECUL,0x33C3F3F0UL,0x05C5C1C4UL,0x07878384UL,0x14041014UL,0x3ECEF2FCUL,0x24446064UL,
+0x1ECED2DCUL,0x2E0E222CUL,0x0B4B4348UL,0x1A0A1218UL,0x06060204UL,0x21012120UL,0x2B4B6368UL,0x26466264UL,
+0x02020200UL,0x35C5F1F4UL,0x12829290UL,0x0A8A8288UL,0x0C0C000CUL,0x3383B3B0UL,0x3E4E727CUL,0x10C0D0D0UL,
+0x3A4A7278UL,0x07474344UL,0x16869294UL,0x25C5E1E4UL,0x26062224UL,0x00808080UL,0x2D8DA1ACUL,0x1FCFD3DCUL,
+0x2181A1A0UL,0x30003030UL,0x37073334UL,0x2E8EA2ACUL,0x36063234UL,0x15051114UL,0x22022220UL,0x38083038UL,
+0x34C4F0F4UL,0x2787A3A4UL,0x05454144UL,0x0C4C404CUL,0x01818180UL,0x29C9E1E8UL,0x04848084UL,0x17879394UL,
+0x35053134UL,0x0BCBC3C8UL,0x0ECEC2CCUL,0x3C0C303CUL,0x31417170UL,0x11011110UL,0x07C7C3C4UL,0x09898188UL,
+0x35457174UL,0x3BCBF3F8UL,0x1ACAD2D8UL,0x38C8F0F8UL,0x14849094UL,0x19495158UL,0x02828280UL,0x04C4C0C4UL,
+0x3FCFF3FCUL,0x09494148UL,0x39093138UL,0x27476364UL,0x00C0C0C0UL,0x0FCFC3CCUL,0x17C7D3D4UL,0x3888B0B8UL,
+0x0F0F030CUL,0x0E8E828CUL,0x02424240UL,0x23032320UL,0x11819190UL,0x2C4C606CUL,0x1BCBD3D8UL,0x2484A0A4UL,
+0x34043034UL,0x31C1F1F0UL,0x08484048UL,0x02C2C2C0UL,0x2F4F636CUL,0x3D0D313CUL,0x2D0D212CUL,0x00404040UL,
+0x3E8EB2BCUL,0x3E0E323CUL,0x3C8CB0BCUL,0x01C1C1C0UL,0x2A8AA2A8UL,0x3A8AB2B8UL,0x0E4E424CUL,0x15455154UL,
+0x3B0B3338UL,0x1CCCD0DCUL,0x28486068UL,0x3F4F737CUL,0x1C8C909CUL,0x18C8D0D8UL,0x0A4A4248UL,0x16465254UL,
+0x37477374UL,0x2080A0A0UL,0x2DCDE1ECUL,0x06464244UL,0x3585B1B4UL,0x2B0B2328UL,0x25456164UL,0x3ACAF2F8UL,
+0x23C3E3E0UL,0x3989B1B8UL,0x3181B1B0UL,0x1F8F939CUL,0x1E4E525CUL,0x39C9F1F8UL,0x26C6E2E4UL,0x3282B2B0UL,
+0x31013130UL,0x2ACAE2E8UL,0x2D4D616CUL,0x1F4F535CUL,0x24C4E0E4UL,0x30C0F0F0UL,0x0DCDC1CCUL,0x08888088UL,
+0x16061214UL,0x3A0A3238UL,0x18485058UL,0x14C4D0D4UL,0x22426260UL,0x29092128UL,0x07070304UL,0x33033330UL,
+0x28C8E0E8UL,0x1B0B1318UL,0x05050104UL,0x39497178UL,0x10809090UL,0x2A4A6268UL,0x2A0A2228UL,0x1A8A9298UL
+};
+
+static const ulong32 SS1[256] = {
+0x38380830UL,0xE828C8E0UL,0x2C2D0D21UL,0xA42686A2UL,0xCC0FCFC3UL,0xDC1ECED2UL,0xB03383B3UL,0xB83888B0UL,
+0xAC2F8FA3UL,0x60204060UL,0x54154551UL,0xC407C7C3UL,0x44044440UL,0x6C2F4F63UL,0x682B4B63UL,0x581B4B53UL,
+0xC003C3C3UL,0x60224262UL,0x30330333UL,0xB43585B1UL,0x28290921UL,0xA02080A0UL,0xE022C2E2UL,0xA42787A3UL,
+0xD013C3D3UL,0x90118191UL,0x10110111UL,0x04060602UL,0x1C1C0C10UL,0xBC3C8CB0UL,0x34360632UL,0x480B4B43UL,
+0xEC2FCFE3UL,0x88088880UL,0x6C2C4C60UL,0xA82888A0UL,0x14170713UL,0xC404C4C0UL,0x14160612UL,0xF434C4F0UL,
+0xC002C2C2UL,0x44054541UL,0xE021C1E1UL,0xD416C6D2UL,0x3C3F0F33UL,0x3C3D0D31UL,0x8C0E8E82UL,0x98188890UL,
+0x28280820UL,0x4C0E4E42UL,0xF436C6F2UL,0x3C3E0E32UL,0xA42585A1UL,0xF839C9F1UL,0x0C0D0D01UL,0xDC1FCFD3UL,
+0xD818C8D0UL,0x282B0B23UL,0x64264662UL,0x783A4A72UL,0x24270723UL,0x2C2F0F23UL,0xF031C1F1UL,0x70324272UL,
+0x40024242UL,0xD414C4D0UL,0x40014141UL,0xC000C0C0UL,0x70334373UL,0x64274763UL,0xAC2C8CA0UL,0x880B8B83UL,
+0xF437C7F3UL,0xAC2D8DA1UL,0x80008080UL,0x1C1F0F13UL,0xC80ACAC2UL,0x2C2C0C20UL,0xA82A8AA2UL,0x34340430UL,
+0xD012C2D2UL,0x080B0B03UL,0xEC2ECEE2UL,0xE829C9E1UL,0x5C1D4D51UL,0x94148490UL,0x18180810UL,0xF838C8F0UL,
+0x54174753UL,0xAC2E8EA2UL,0x08080800UL,0xC405C5C1UL,0x10130313UL,0xCC0DCDC1UL,0x84068682UL,0xB83989B1UL,
+0xFC3FCFF3UL,0x7C3D4D71UL,0xC001C1C1UL,0x30310131UL,0xF435C5F1UL,0x880A8A82UL,0x682A4A62UL,0xB03181B1UL,
+0xD011C1D1UL,0x20200020UL,0xD417C7D3UL,0x00020202UL,0x20220222UL,0x04040400UL,0x68284860UL,0x70314171UL,
+0x04070703UL,0xD81BCBD3UL,0x9C1D8D91UL,0x98198991UL,0x60214161UL,0xBC3E8EB2UL,0xE426C6E2UL,0x58194951UL,
+0xDC1DCDD1UL,0x50114151UL,0x90108090UL,0xDC1CCCD0UL,0x981A8A92UL,0xA02383A3UL,0xA82B8BA3UL,0xD010C0D0UL,
+0x80018181UL,0x0C0F0F03UL,0x44074743UL,0x181A0A12UL,0xE023C3E3UL,0xEC2CCCE0UL,0x8C0D8D81UL,0xBC3F8FB3UL,
+0x94168692UL,0x783B4B73UL,0x5C1C4C50UL,0xA02282A2UL,0xA02181A1UL,0x60234363UL,0x20230323UL,0x4C0D4D41UL,
+0xC808C8C0UL,0x9C1E8E92UL,0x9C1C8C90UL,0x383A0A32UL,0x0C0C0C00UL,0x2C2E0E22UL,0xB83A8AB2UL,0x6C2E4E62UL,
+0x9C1F8F93UL,0x581A4A52UL,0xF032C2F2UL,0x90128292UL,0xF033C3F3UL,0x48094941UL,0x78384870UL,0xCC0CCCC0UL,
+0x14150511UL,0xF83BCBF3UL,0x70304070UL,0x74354571UL,0x7C3F4F73UL,0x34350531UL,0x10100010UL,0x00030303UL,
+0x64244460UL,0x6C2D4D61UL,0xC406C6C2UL,0x74344470UL,0xD415C5D1UL,0xB43484B0UL,0xE82ACAE2UL,0x08090901UL,
+0x74364672UL,0x18190911UL,0xFC3ECEF2UL,0x40004040UL,0x10120212UL,0xE020C0E0UL,0xBC3D8DB1UL,0x04050501UL,
+0xF83ACAF2UL,0x00010101UL,0xF030C0F0UL,0x282A0A22UL,0x5C1E4E52UL,0xA82989A1UL,0x54164652UL,0x40034343UL,
+0x84058581UL,0x14140410UL,0x88098981UL,0x981B8B93UL,0xB03080B0UL,0xE425C5E1UL,0x48084840UL,0x78394971UL,
+0x94178793UL,0xFC3CCCF0UL,0x1C1E0E12UL,0x80028282UL,0x20210121UL,0x8C0C8C80UL,0x181B0B13UL,0x5C1F4F53UL,
+0x74374773UL,0x54144450UL,0xB03282B2UL,0x1C1D0D11UL,0x24250521UL,0x4C0F4F43UL,0x00000000UL,0x44064642UL,
+0xEC2DCDE1UL,0x58184850UL,0x50124252UL,0xE82BCBE3UL,0x7C3E4E72UL,0xD81ACAD2UL,0xC809C9C1UL,0xFC3DCDF1UL,
+0x30300030UL,0x94158591UL,0x64254561UL,0x3C3C0C30UL,0xB43686B2UL,0xE424C4E0UL,0xB83B8BB3UL,0x7C3C4C70UL,
+0x0C0E0E02UL,0x50104050UL,0x38390931UL,0x24260622UL,0x30320232UL,0x84048480UL,0x68294961UL,0x90138393UL,
+0x34370733UL,0xE427C7E3UL,0x24240420UL,0xA42484A0UL,0xC80BCBC3UL,0x50134353UL,0x080A0A02UL,0x84078783UL,
+0xD819C9D1UL,0x4C0C4C40UL,0x80038383UL,0x8C0F8F83UL,0xCC0ECEC2UL,0x383B0B33UL,0x480A4A42UL,0xB43787B3UL
+};
+
+static const ulong32 SS2[256] = {
+0xA1A82989UL,0x81840585UL,0xD2D416C6UL,0xD3D013C3UL,0x50541444UL,0x111C1D0DUL,0xA0AC2C8CUL,0x21242505UL,
+0x515C1D4DUL,0x43400343UL,0x10181808UL,0x121C1E0EUL,0x51501141UL,0xF0FC3CCCUL,0xC2C80ACAUL,0x63602343UL,
+0x20282808UL,0x40440444UL,0x20202000UL,0x919C1D8DUL,0xE0E020C0UL,0xE2E022C2UL,0xC0C808C8UL,0x13141707UL,
+0xA1A42585UL,0x838C0F8FUL,0x03000303UL,0x73783B4BUL,0xB3B83B8BUL,0x13101303UL,0xD2D012C2UL,0xE2EC2ECEUL,
+0x70703040UL,0x808C0C8CUL,0x333C3F0FUL,0xA0A82888UL,0x32303202UL,0xD1DC1DCDUL,0xF2F436C6UL,0x70743444UL,
+0xE0EC2CCCUL,0x91941585UL,0x03080B0BUL,0x53541747UL,0x505C1C4CUL,0x53581B4BUL,0xB1BC3D8DUL,0x01000101UL,
+0x20242404UL,0x101C1C0CUL,0x73703343UL,0x90981888UL,0x10101000UL,0xC0CC0CCCUL,0xF2F032C2UL,0xD1D819C9UL,
+0x202C2C0CUL,0xE3E427C7UL,0x72703242UL,0x83800383UL,0x93981B8BUL,0xD1D011C1UL,0x82840686UL,0xC1C809C9UL,
+0x60602040UL,0x50501040UL,0xA3A02383UL,0xE3E82BCBUL,0x010C0D0DUL,0xB2B43686UL,0x929C1E8EUL,0x434C0F4FUL,
+0xB3B43787UL,0x52581A4AUL,0xC2C406C6UL,0x70783848UL,0xA2A42686UL,0x12101202UL,0xA3AC2F8FUL,0xD1D415C5UL,
+0x61602141UL,0xC3C003C3UL,0xB0B43484UL,0x41400141UL,0x52501242UL,0x717C3D4DUL,0x818C0D8DUL,0x00080808UL,
+0x131C1F0FUL,0x91981989UL,0x00000000UL,0x11181909UL,0x00040404UL,0x53501343UL,0xF3F437C7UL,0xE1E021C1UL,
+0xF1FC3DCDUL,0x72743646UL,0x232C2F0FUL,0x23242707UL,0xB0B03080UL,0x83880B8BUL,0x020C0E0EUL,0xA3A82B8BUL,
+0xA2A02282UL,0x626C2E4EUL,0x93901383UL,0x414C0D4DUL,0x61682949UL,0x707C3C4CUL,0x01080909UL,0x02080A0AUL,
+0xB3BC3F8FUL,0xE3EC2FCFUL,0xF3F033C3UL,0xC1C405C5UL,0x83840787UL,0x10141404UL,0xF2FC3ECEUL,0x60642444UL,
+0xD2DC1ECEUL,0x222C2E0EUL,0x43480B4BUL,0x12181A0AUL,0x02040606UL,0x21202101UL,0x63682B4BUL,0x62642646UL,
+0x02000202UL,0xF1F435C5UL,0x92901282UL,0x82880A8AUL,0x000C0C0CUL,0xB3B03383UL,0x727C3E4EUL,0xD0D010C0UL,
+0x72783A4AUL,0x43440747UL,0x92941686UL,0xE1E425C5UL,0x22242606UL,0x80800080UL,0xA1AC2D8DUL,0xD3DC1FCFUL,
+0xA1A02181UL,0x30303000UL,0x33343707UL,0xA2AC2E8EUL,0x32343606UL,0x11141505UL,0x22202202UL,0x30383808UL,
+0xF0F434C4UL,0xA3A42787UL,0x41440545UL,0x404C0C4CUL,0x81800181UL,0xE1E829C9UL,0x80840484UL,0x93941787UL,
+0x31343505UL,0xC3C80BCBUL,0xC2CC0ECEUL,0x303C3C0CUL,0x71703141UL,0x11101101UL,0xC3C407C7UL,0x81880989UL,
+0x71743545UL,0xF3F83BCBUL,0xD2D81ACAUL,0xF0F838C8UL,0x90941484UL,0x51581949UL,0x82800282UL,0xC0C404C4UL,
+0xF3FC3FCFUL,0x41480949UL,0x31383909UL,0x63642747UL,0xC0C000C0UL,0xC3CC0FCFUL,0xD3D417C7UL,0xB0B83888UL,
+0x030C0F0FUL,0x828C0E8EUL,0x42400242UL,0x23202303UL,0x91901181UL,0x606C2C4CUL,0xD3D81BCBUL,0xA0A42484UL,
+0x30343404UL,0xF1F031C1UL,0x40480848UL,0xC2C002C2UL,0x636C2F4FUL,0x313C3D0DUL,0x212C2D0DUL,0x40400040UL,
+0xB2BC3E8EUL,0x323C3E0EUL,0xB0BC3C8CUL,0xC1C001C1UL,0xA2A82A8AUL,0xB2B83A8AUL,0x424C0E4EUL,0x51541545UL,
+0x33383B0BUL,0xD0DC1CCCUL,0x60682848UL,0x737C3F4FUL,0x909C1C8CUL,0xD0D818C8UL,0x42480A4AUL,0x52541646UL,
+0x73743747UL,0xA0A02080UL,0xE1EC2DCDUL,0x42440646UL,0xB1B43585UL,0x23282B0BUL,0x61642545UL,0xF2F83ACAUL,
+0xE3E023C3UL,0xB1B83989UL,0xB1B03181UL,0x939C1F8FUL,0x525C1E4EUL,0xF1F839C9UL,0xE2E426C6UL,0xB2B03282UL,
+0x31303101UL,0xE2E82ACAUL,0x616C2D4DUL,0x535C1F4FUL,0xE0E424C4UL,0xF0F030C0UL,0xC1CC0DCDUL,0x80880888UL,
+0x12141606UL,0x32383A0AUL,0x50581848UL,0xD0D414C4UL,0x62602242UL,0x21282909UL,0x03040707UL,0x33303303UL,
+0xE0E828C8UL,0x13181B0BUL,0x01040505UL,0x71783949UL,0x90901080UL,0x62682A4AUL,0x22282A0AUL,0x92981A8AUL
+};
+
+static const ulong32 SS3[256] = {
+0x08303838UL,0xC8E0E828UL,0x0D212C2DUL,0x86A2A426UL,0xCFC3CC0FUL,0xCED2DC1EUL,0x83B3B033UL,0x88B0B838UL,
+0x8FA3AC2FUL,0x40606020UL,0x45515415UL,0xC7C3C407UL,0x44404404UL,0x4F636C2FUL,0x4B63682BUL,0x4B53581BUL,
+0xC3C3C003UL,0x42626022UL,0x03333033UL,0x85B1B435UL,0x09212829UL,0x80A0A020UL,0xC2E2E022UL,0x87A3A427UL,
+0xC3D3D013UL,0x81919011UL,0x01111011UL,0x06020406UL,0x0C101C1CUL,0x8CB0BC3CUL,0x06323436UL,0x4B43480BUL,
+0xCFE3EC2FUL,0x88808808UL,0x4C606C2CUL,0x88A0A828UL,0x07131417UL,0xC4C0C404UL,0x06121416UL,0xC4F0F434UL,
+0xC2C2C002UL,0x45414405UL,0xC1E1E021UL,0xC6D2D416UL,0x0F333C3FUL,0x0D313C3DUL,0x8E828C0EUL,0x88909818UL,
+0x08202828UL,0x4E424C0EUL,0xC6F2F436UL,0x0E323C3EUL,0x85A1A425UL,0xC9F1F839UL,0x0D010C0DUL,0xCFD3DC1FUL,
+0xC8D0D818UL,0x0B23282BUL,0x46626426UL,0x4A72783AUL,0x07232427UL,0x0F232C2FUL,0xC1F1F031UL,0x42727032UL,
+0x42424002UL,0xC4D0D414UL,0x41414001UL,0xC0C0C000UL,0x43737033UL,0x47636427UL,0x8CA0AC2CUL,0x8B83880BUL,
+0xC7F3F437UL,0x8DA1AC2DUL,0x80808000UL,0x0F131C1FUL,0xCAC2C80AUL,0x0C202C2CUL,0x8AA2A82AUL,0x04303434UL,
+0xC2D2D012UL,0x0B03080BUL,0xCEE2EC2EUL,0xC9E1E829UL,0x4D515C1DUL,0x84909414UL,0x08101818UL,0xC8F0F838UL,
+0x47535417UL,0x8EA2AC2EUL,0x08000808UL,0xC5C1C405UL,0x03131013UL,0xCDC1CC0DUL,0x86828406UL,0x89B1B839UL,
+0xCFF3FC3FUL,0x4D717C3DUL,0xC1C1C001UL,0x01313031UL,0xC5F1F435UL,0x8A82880AUL,0x4A62682AUL,0x81B1B031UL,
+0xC1D1D011UL,0x00202020UL,0xC7D3D417UL,0x02020002UL,0x02222022UL,0x04000404UL,0x48606828UL,0x41717031UL,
+0x07030407UL,0xCBD3D81BUL,0x8D919C1DUL,0x89919819UL,0x41616021UL,0x8EB2BC3EUL,0xC6E2E426UL,0x49515819UL,
+0xCDD1DC1DUL,0x41515011UL,0x80909010UL,0xCCD0DC1CUL,0x8A92981AUL,0x83A3A023UL,0x8BA3A82BUL,0xC0D0D010UL,
+0x81818001UL,0x0F030C0FUL,0x47434407UL,0x0A12181AUL,0xC3E3E023UL,0xCCE0EC2CUL,0x8D818C0DUL,0x8FB3BC3FUL,
+0x86929416UL,0x4B73783BUL,0x4C505C1CUL,0x82A2A022UL,0x81A1A021UL,0x43636023UL,0x03232023UL,0x4D414C0DUL,
+0xC8C0C808UL,0x8E929C1EUL,0x8C909C1CUL,0x0A32383AUL,0x0C000C0CUL,0x0E222C2EUL,0x8AB2B83AUL,0x4E626C2EUL,
+0x8F939C1FUL,0x4A52581AUL,0xC2F2F032UL,0x82929012UL,0xC3F3F033UL,0x49414809UL,0x48707838UL,0xCCC0CC0CUL,
+0x05111415UL,0xCBF3F83BUL,0x40707030UL,0x45717435UL,0x4F737C3FUL,0x05313435UL,0x00101010UL,0x03030003UL,
+0x44606424UL,0x4D616C2DUL,0xC6C2C406UL,0x44707434UL,0xC5D1D415UL,0x84B0B434UL,0xCAE2E82AUL,0x09010809UL,
+0x46727436UL,0x09111819UL,0xCEF2FC3EUL,0x40404000UL,0x02121012UL,0xC0E0E020UL,0x8DB1BC3DUL,0x05010405UL,
+0xCAF2F83AUL,0x01010001UL,0xC0F0F030UL,0x0A22282AUL,0x4E525C1EUL,0x89A1A829UL,0x46525416UL,0x43434003UL,
+0x85818405UL,0x04101414UL,0x89818809UL,0x8B93981BUL,0x80B0B030UL,0xC5E1E425UL,0x48404808UL,0x49717839UL,
+0x87939417UL,0xCCF0FC3CUL,0x0E121C1EUL,0x82828002UL,0x01212021UL,0x8C808C0CUL,0x0B13181BUL,0x4F535C1FUL,
+0x47737437UL,0x44505414UL,0x82B2B032UL,0x0D111C1DUL,0x05212425UL,0x4F434C0FUL,0x00000000UL,0x46424406UL,
+0xCDE1EC2DUL,0x48505818UL,0x42525012UL,0xCBE3E82BUL,0x4E727C3EUL,0xCAD2D81AUL,0xC9C1C809UL,0xCDF1FC3DUL,
+0x00303030UL,0x85919415UL,0x45616425UL,0x0C303C3CUL,0x86B2B436UL,0xC4E0E424UL,0x8BB3B83BUL,0x4C707C3CUL,
+0x0E020C0EUL,0x40505010UL,0x09313839UL,0x06222426UL,0x02323032UL,0x84808404UL,0x49616829UL,0x83939013UL,
+0x07333437UL,0xC7E3E427UL,0x04202424UL,0x84A0A424UL,0xCBC3C80BUL,0x43535013UL,0x0A02080AUL,0x87838407UL,
+0xC9D1D819UL,0x4C404C0CUL,0x83838003UL,0x8F838C0FUL,0xCEC2CC0EUL,0x0B33383BUL,0x4A42480AUL,0x87B3B437UL
+};
+
+static const ulong32 KCi[16] = {
+0x9E3779B9,0x3C6EF373,
+0x78DDE6E6,0xF1BBCDCC,
+0xE3779B99,0xC6EF3733,
+0x8DDE6E67,0x1BBCDCCF,
+0x3779B99E,0x6EF3733C,
+0xDDE6E678,0xBBCDCCF1,
+0x779B99E3,0xEF3733C6,
+0xDE6E678D,0xBCDCCF1B
+};
+
+#define G(x) (SS3[((x)>>24)&255] ^ SS2[((x)>>16)&255] ^ SS1[((x)>>8)&255] ^ SS0[(x)&255])
+
+#define F(L1, L2, R1, R2, K1, K2) \
+ T2 = G((R1 ^ K1) ^ (R2 ^ K2)); \
+ T = G( G(T2 + (R1 ^ K1)) + T2); \
+ L2 ^= T; \
+ L1 ^= (T + G(T2 + (R1 ^ K1))); \
+
+ /**
+ Initialize the SEED block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int i;
+ ulong32 tmp, k1, k2, k3, k4;
+
+ if (keylen != 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if (num_rounds != 16 && num_rounds != 0) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* load key */
+ LOAD32H(k1, key);
+ LOAD32H(k2, key+4);
+ LOAD32H(k3, key+8);
+ LOAD32H(k4, key+12);
+
+ for (i = 0; i < 16; i++) {
+ skey->kseed.K[2*i+0] = G(k1 + k3 - KCi[i]);
+ skey->kseed.K[2*i+1] = G(k2 - k4 + KCi[i]);
+ if (i&1) {
+ tmp = k3;
+ k3 = ((k3 << 8) | (k4 >> 24)) & 0xFFFFFFFF;
+ k4 = ((k4 << 8) | (tmp >> 24)) & 0xFFFFFFFF;
+ } else {
+ tmp = k1;
+ k1 = ((k1 >> 8) | (k2 << 24)) & 0xFFFFFFFF;
+ k2 = ((k2 >> 8) | (tmp << 24)) & 0xFFFFFFFF;
+ }
+ /* reverse keys for decrypt */
+ skey->kseed.dK[2*(15-i)+0] = skey->kseed.K[2*i+0];
+ skey->kseed.dK[2*(15-i)+1] = skey->kseed.K[2*i+1];
+ }
+
+ return CRYPT_OK;
+}
+
+static void rounds(ulong32 *P, const ulong32 *K)
+{
+ ulong32 T, T2;
+ int i;
+ for (i = 0; i < 16; i += 2) {
+ F(P[0], P[1], P[2], P[3], K[0], K[1]);
+ F(P[2], P[3], P[0], P[1], K[2], K[3]);
+ K += 4;
+ }
+}
+
+/**
+ Encrypts a block of text with SEED
+ @param pt The input plaintext (16 bytes)
+ @param ct The output ciphertext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ ulong32 P[4];
+ LOAD32H(P[0], pt);
+ LOAD32H(P[1], pt+4);
+ LOAD32H(P[2], pt+8);
+ LOAD32H(P[3], pt+12);
+ rounds(P, skey->kseed.K);
+ STORE32H(P[2], ct);
+ STORE32H(P[3], ct+4);
+ STORE32H(P[0], ct+8);
+ STORE32H(P[1], ct+12);
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with SEED
+ @param ct The input ciphertext (16 bytes)
+ @param pt The output plaintext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ ulong32 P[4];
+ LOAD32H(P[0], ct);
+ LOAD32H(P[1], ct+4);
+ LOAD32H(P[2], ct+8);
+ LOAD32H(P[3], ct+12);
+ rounds(P, skey->kseed.dK);
+ STORE32H(P[2], pt);
+ STORE32H(P[3], pt+4);
+ STORE32H(P[0], pt+8);
+ STORE32H(P[1], pt+12);
+ return CRYPT_OK;
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void kseed_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Performs a self-test of the SEED block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int kseed_test(void)
+{
+#if !defined(LTC_TEST)
+ return CRYPT_NOP;
+#else
+ static const struct test {
+ unsigned char pt[16], ct[16], key[16];
+ } tests[] = {
+
+{
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F },
+ { 0x5E,0xBA,0xC6,0xE0,0x05,0x4E,0x16,0x68,0x19,0xAF,0xF1,0xCC,0x6D,0x34,0x6C,0xDB },
+ { 0 },
+},
+
+{
+ { 0 },
+ { 0xC1,0x1F,0x22,0xF2,0x01,0x40,0x50,0x50,0x84,0x48,0x35,0x97,0xE4,0x37,0x0F,0x43 },
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F },
+},
+
+{
+ { 0x83,0xA2,0xF8,0xA2,0x88,0x64,0x1F,0xB9,0xA4,0xE9,0xA5,0xCC,0x2F,0x13,0x1C,0x7D },
+ { 0xEE,0x54,0xD1,0x3E,0xBC,0xAE,0x70,0x6D,0x22,0x6B,0xC3,0x14,0x2C,0xD4,0x0D,0x4A },
+ { 0x47,0x06,0x48,0x08,0x51,0xE6,0x1B,0xE8,0x5D,0x74,0xBF,0xB3,0xFD,0x95,0x61,0x85 },
+},
+
+{
+ { 0xB4,0x1E,0x6B,0xE2,0xEB,0xA8,0x4A,0x14,0x8E,0x2E,0xED,0x84,0x59,0x3C,0x5E,0xC7 },
+ { 0x9B,0x9B,0x7B,0xFC,0xD1,0x81,0x3C,0xB9,0x5D,0x0B,0x36,0x18,0xF4,0x0F,0x51,0x22 },
+ { 0x28,0xDB,0xC3,0xBC,0x49,0xFF,0xD8,0x7D,0xCF,0xA5,0x09,0xB1,0x1D,0x42,0x2B,0xE7 },
+}
+};
+ int x;
+ unsigned char buf[2][16];
+ symmetric_key skey;
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ kseed_setup(tests[x].key, 16, 0, &skey);
+ kseed_ecb_encrypt(tests[x].pt, buf[0], &skey);
+ kseed_ecb_decrypt(buf[0], buf[1], &skey);
+ if (compare_testvector(buf[0], 16, tests[x].ct, 16, "KSEED Encrypt", x) ||
+ compare_testvector(buf[1], 16, tests[x].pt, 16, "KSEED Decrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int kseed_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize >= 16) {
+ *keysize = 16;
+ } else {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/ciphers/multi2.c b/Sources/libtomcrypt/ciphers/multi2.c
new file mode 100644
index 00000000..e1a84acf
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/multi2.c
@@ -0,0 +1,309 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file multi2.c
+ Multi-2 implementation (not public domain, hence the default disable)
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MULTI2
+
+static void s_pi1(ulong32 *p)
+{
+ p[1] ^= p[0];
+}
+
+static void s_pi2(ulong32 *p, const ulong32 *k)
+{
+ ulong32 t;
+ t = (p[1] + k[0]) & 0xFFFFFFFFUL;
+ t = (ROL(t, 1) + t - 1) & 0xFFFFFFFFUL;
+ t = (ROL(t, 4) ^ t) & 0xFFFFFFFFUL;
+ p[0] ^= t;
+}
+
+static void s_pi3(ulong32 *p, const ulong32 *k)
+{
+ ulong32 t;
+ t = p[0] + k[1];
+ t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL;
+ t = (ROL(t, 8) ^ t) & 0xFFFFFFFFUL;
+ t = (t + k[2]) & 0xFFFFFFFFUL;
+ t = (ROL(t, 1) - t) & 0xFFFFFFFFUL;
+ t = ROL(t, 16) ^ (p[0] | t);
+ p[1] ^= t;
+}
+
+static void s_pi4(ulong32 *p, const ulong32 *k)
+{
+ ulong32 t;
+ t = (p[1] + k[3]) & 0xFFFFFFFFUL;
+ t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL;
+ p[0] ^= t;
+}
+
+static void s_setup(const ulong32 *dk, const ulong32 *k, ulong32 *uk)
+{
+ int n, t;
+ ulong32 p[2];
+
+ p[0] = dk[0]; p[1] = dk[1];
+
+ t = 4;
+ n = 0;
+ s_pi1(p);
+ s_pi2(p, k);
+ uk[n++] = p[0];
+ s_pi3(p, k);
+ uk[n++] = p[1];
+ s_pi4(p, k);
+ uk[n++] = p[0];
+ s_pi1(p);
+ uk[n++] = p[1];
+ s_pi2(p, k+t);
+ uk[n++] = p[0];
+ s_pi3(p, k+t);
+ uk[n++] = p[1];
+ s_pi4(p, k+t);
+ uk[n++] = p[0];
+ s_pi1(p);
+ uk[n++] = p[1];
+}
+
+static void s_encrypt(ulong32 *p, int N, const ulong32 *uk)
+{
+ int n, t;
+ for (t = n = 0; ; ) {
+ s_pi1(p); if (++n == N) break;
+ s_pi2(p, uk+t); if (++n == N) break;
+ s_pi3(p, uk+t); if (++n == N) break;
+ s_pi4(p, uk+t); if (++n == N) break;
+ t ^= 4;
+ }
+}
+
+static void s_decrypt(ulong32 *p, int N, const ulong32 *uk)
+{
+ int n, t;
+ for (t = 4*(((N-1)>>2)&1), n = N; ; ) {
+ switch (n<=4 ? n : ((n-1)%4)+1) {
+ case 4: s_pi4(p, uk+t); --n; /* FALLTHROUGH */
+ case 3: s_pi3(p, uk+t); --n; /* FALLTHROUGH */
+ case 2: s_pi2(p, uk+t); --n; /* FALLTHROUGH */
+ case 1: s_pi1(p); --n; break;
+ case 0: return;
+ }
+ t ^= 4;
+ }
+}
+
+const struct ltc_cipher_descriptor multi2_desc = {
+ "multi2",
+ 22,
+ 40, 40, 8, 128,
+ &multi2_setup,
+ &multi2_ecb_encrypt,
+ &multi2_ecb_decrypt,
+ &multi2_test,
+ &multi2_done,
+ &multi2_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ ulong32 sk[8], dk[2];
+ int x;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (keylen != 40) return CRYPT_INVALID_KEYSIZE;
+ if (num_rounds == 0) num_rounds = 128;
+
+ skey->multi2.N = num_rounds;
+ for (x = 0; x < 8; x++) {
+ LOAD32H(sk[x], key + x*4);
+ }
+ LOAD32H(dk[0], key + 32);
+ LOAD32H(dk[1], key + 36);
+ s_setup(dk, sk, skey->multi2.uk);
+
+ zeromem(sk, sizeof(sk));
+ zeromem(dk, sizeof(dk));
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with multi2
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ ulong32 p[2];
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ LOAD32H(p[0], pt);
+ LOAD32H(p[1], pt+4);
+ s_encrypt(p, skey->multi2.N, skey->multi2.uk);
+ STORE32H(p[0], ct);
+ STORE32H(p[1], ct+4);
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with multi2
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ ulong32 p[2];
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ LOAD32H(p[0], ct);
+ LOAD32H(p[1], ct+4);
+ s_decrypt(p, skey->multi2.N, skey->multi2.uk);
+ STORE32H(p[0], pt);
+ STORE32H(p[1], pt+4);
+ return CRYPT_OK;
+}
+
+/**
+ Performs a self-test of the multi2 block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int multi2_test(void)
+{
+ static const struct {
+ unsigned char key[40];
+ unsigned char pt[8], ct[8];
+ int rounds;
+ } tests[] = {
+{
+ {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ 0x01, 0x23, 0x45, 0x67,
+ 0x89, 0xAB, 0xCD, 0xEF
+ },
+ {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01,
+ },
+ {
+ 0xf8, 0x94, 0x40, 0x84,
+ 0x5e, 0x11, 0xcf, 0x89
+ },
+ 128,
+},
+{
+ {
+ 0x35, 0x91, 0x9d, 0x96,
+ 0x07, 0x02, 0xe2, 0xce,
+ 0x8d, 0x0b, 0x58, 0x3c,
+ 0xc9, 0xc8, 0x9d, 0x59,
+ 0xa2, 0xae, 0x96, 0x4e,
+ 0x87, 0x82, 0x45, 0xed,
+ 0x3f, 0x2e, 0x62, 0xd6,
+ 0x36, 0x35, 0xd0, 0x67,
+
+ 0xb1, 0x27, 0xb9, 0x06,
+ 0xe7, 0x56, 0x22, 0x38,
+ },
+ {
+ 0x1f, 0xb4, 0x60, 0x60,
+ 0xd0, 0xb3, 0x4f, 0xa5
+ },
+ {
+ 0xca, 0x84, 0xa9, 0x34,
+ 0x75, 0xc8, 0x60, 0xe5
+ },
+ 216,
+}
+};
+ unsigned char buf[8];
+ symmetric_key skey;
+ int err, x;
+
+ for (x = 1; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ if ((err = multi2_setup(tests[x].key, 40, tests[x].rounds, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = multi2_ecb_encrypt(tests[x].pt, buf, &skey)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (compare_testvector(buf, 8, tests[x].ct, 8, "Multi2 Encrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ if ((err = multi2_ecb_decrypt(buf, buf, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(buf, 8, tests[x].pt, 8, "Multi2 Decrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ for (x = 128; x < 256; ++x) {
+ unsigned char ct[8];
+
+ if ((err = multi2_setup(tests[0].key, 40, x, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = multi2_ecb_encrypt(tests[0].pt, ct, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = multi2_ecb_decrypt(ct, buf, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(buf, 8, tests[0].pt, 8, "Multi2 Rounds", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ return CRYPT_OK;
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void multi2_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int multi2_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize >= 40) {
+ *keysize = 40;
+ } else {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/ciphers/noekeon.c b/Sources/libtomcrypt/ciphers/noekeon.c
new file mode 100644
index 00000000..58d73aec
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/noekeon.c
@@ -0,0 +1,317 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**
+ @file noekeon.c
+ Implementation of the Noekeon block cipher by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_NOEKEON
+
+const struct ltc_cipher_descriptor noekeon_desc =
+{
+ "noekeon",
+ 16,
+ 16, 16, 16, 16,
+ &noekeon_setup,
+ &noekeon_ecb_encrypt,
+ &noekeon_ecb_decrypt,
+ &noekeon_test,
+ &noekeon_done,
+ &noekeon_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ulong32 RC[] = {
+ 0x00000080UL, 0x0000001bUL, 0x00000036UL, 0x0000006cUL,
+ 0x000000d8UL, 0x000000abUL, 0x0000004dUL, 0x0000009aUL,
+ 0x0000002fUL, 0x0000005eUL, 0x000000bcUL, 0x00000063UL,
+ 0x000000c6UL, 0x00000097UL, 0x00000035UL, 0x0000006aUL,
+ 0x000000d4UL
+};
+
+#define kTHETA(a, b, c, d) \
+ temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \
+ b ^= temp; d ^= temp; \
+ temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \
+ a ^= temp; c ^= temp;
+
+#define THETA(k, a, b, c, d) \
+ temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \
+ b ^= temp ^ k[1]; d ^= temp ^ k[3]; \
+ temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \
+ a ^= temp ^ k[0]; c ^= temp ^ k[2];
+
+#define GAMMA(a, b, c, d) \
+ b ^= ~(d|c); \
+ a ^= c&b; \
+ temp = d; d = a; a = temp;\
+ c ^= a ^ b ^ d; \
+ b ^= ~(d|c); \
+ a ^= c&b;
+
+#define PI1(a, b, c, d) \
+ b = ROLc(b, 1); c = ROLc(c, 5); d = ROLc(d, 2);
+
+#define PI2(a, b, c, d) \
+ b = RORc(b, 1); c = RORc(c, 5); d = RORc(d, 2);
+
+ /**
+ Initialize the Noekeon block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ ulong32 temp;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (keylen != 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if (num_rounds != 16 && num_rounds != 0) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ LOAD32H(skey->noekeon.K[0],&key[0]);
+ LOAD32H(skey->noekeon.K[1],&key[4]);
+ LOAD32H(skey->noekeon.K[2],&key[8]);
+ LOAD32H(skey->noekeon.K[3],&key[12]);
+
+ LOAD32H(skey->noekeon.dK[0],&key[0]);
+ LOAD32H(skey->noekeon.dK[1],&key[4]);
+ LOAD32H(skey->noekeon.dK[2],&key[8]);
+ LOAD32H(skey->noekeon.dK[3],&key[12]);
+
+ kTHETA(skey->noekeon.dK[0], skey->noekeon.dK[1], skey->noekeon.dK[2], skey->noekeon.dK[3]);
+
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with Noekeon
+ @param pt The input plaintext (16 bytes)
+ @param ct The output ciphertext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+ ulong32 a,b,c,d,temp;
+ int r;
+
+ LTC_ARGCHK(skey != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ LOAD32H(a,&pt[0]); LOAD32H(b,&pt[4]);
+ LOAD32H(c,&pt[8]); LOAD32H(d,&pt[12]);
+
+#define ROUND(i) \
+ a ^= RC[i]; \
+ THETA(skey->noekeon.K, a,b,c,d); \
+ PI1(a,b,c,d); \
+ GAMMA(a,b,c,d); \
+ PI2(a,b,c,d);
+
+ for (r = 0; r < 16; ++r) {
+ ROUND(r);
+ }
+
+#undef ROUND
+
+ a ^= RC[16];
+ THETA(skey->noekeon.K, a, b, c, d);
+
+ STORE32H(a,&ct[0]); STORE32H(b,&ct[4]);
+ STORE32H(c,&ct[8]); STORE32H(d,&ct[12]);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_noekeon_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(ulong32) * 5 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Decrypts a block of text with Noekeon
+ @param ct The input ciphertext (16 bytes)
+ @param pt The output plaintext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+ ulong32 a,b,c,d, temp;
+ int r;
+
+ LTC_ARGCHK(skey != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ LOAD32H(a,&ct[0]); LOAD32H(b,&ct[4]);
+ LOAD32H(c,&ct[8]); LOAD32H(d,&ct[12]);
+
+
+#define ROUND(i) \
+ THETA(skey->noekeon.dK, a,b,c,d); \
+ a ^= RC[i]; \
+ PI1(a,b,c,d); \
+ GAMMA(a,b,c,d); \
+ PI2(a,b,c,d);
+
+ for (r = 16; r > 0; --r) {
+ ROUND(r);
+ }
+
+#undef ROUND
+
+ THETA(skey->noekeon.dK, a,b,c,d);
+ a ^= RC[0];
+ STORE32H(a,&pt[0]); STORE32H(b, &pt[4]);
+ STORE32H(c,&pt[8]); STORE32H(d, &pt[12]);
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_noekeon_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(ulong32) * 5 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Performs a self-test of the Noekeon block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int noekeon_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ int keylen;
+ unsigned char key[16], pt[16], ct[16];
+ } tests[] = {
+ {
+ 16,
+ { 0xAA, 0x3C, 0x8C, 0x86, 0xD9, 0x8B, 0xF8, 0xBE, 0x21, 0xE0, 0x36, 0x09, 0x78, 0xFB, 0xE4, 0x90 },
+ { 0xE4, 0x96, 0x6C, 0xD3, 0x13, 0xA0, 0x6C, 0xAF, 0xD0, 0x23, 0xC9, 0xFD, 0x45, 0x32, 0x23, 0x16 },
+ { 0xA6, 0xEC, 0xB8, 0xA8, 0x61, 0xFD, 0x62, 0xD9, 0x13, 0x02, 0xFE, 0x9E, 0x47, 0x01, 0x3F, 0xC3 }
+ },
+ {
+ 16,
+ { 0xED, 0x43, 0xD1, 0x87, 0x21, 0x7E, 0xE0, 0x97, 0x3D, 0x76, 0xC3, 0x37, 0x2E, 0x7D, 0xAE, 0xD3 },
+ { 0xE3, 0x38, 0x32, 0xCC, 0xF2, 0x2F, 0x2F, 0x0A, 0x4A, 0x8B, 0x8F, 0x18, 0x12, 0x20, 0x17, 0xD3 },
+ { 0x94, 0xA5, 0xDF, 0xF5, 0xAE, 0x1C, 0xBB, 0x22, 0xAD, 0xEB, 0xA7, 0x0D, 0xB7, 0x82, 0x90, 0xA0 }
+ },
+ {
+ 16,
+ { 0x6F, 0xDC, 0x23, 0x38, 0xF2, 0x10, 0xFB, 0xD3, 0xC1, 0x8C, 0x02, 0xF6, 0xB4, 0x6A, 0xD5, 0xA8 },
+ { 0xDB, 0x29, 0xED, 0xB5, 0x5F, 0xB3, 0x60, 0x3A, 0x92, 0xA8, 0xEB, 0x9C, 0x6D, 0x9D, 0x3E, 0x8F },
+ { 0x78, 0xF3, 0x6F, 0xF8, 0x9E, 0xBB, 0x8C, 0x6A, 0xE8, 0x10, 0xF7, 0x00, 0x22, 0x15, 0x30, 0x3D }
+ },
+ {
+ 16,
+ { 0x2C, 0x0C, 0x02, 0xEF, 0x6B, 0xC4, 0xF2, 0x0B, 0x2E, 0xB9, 0xE0, 0xBF, 0xD9, 0x36, 0xC2, 0x4E },
+ { 0x84, 0xE2, 0xFE, 0x64, 0xB1, 0xB9, 0xFE, 0x76, 0xA8, 0x3F, 0x45, 0xC7, 0x40, 0x7A, 0xAF, 0xEE },
+ { 0x2A, 0x08, 0xD6, 0xA2, 0x1C, 0x63, 0x08, 0xB0, 0xF8, 0xBC, 0xB3, 0xA1, 0x66, 0xF7, 0xAE, 0xCF }
+ },
+ {
+ 16,
+ { 0x6F, 0x30, 0xF8, 0x9F, 0xDA, 0x6E, 0xA0, 0x91, 0x04, 0x0F, 0x6C, 0x8B, 0x7D, 0xF7, 0x2A, 0x4B },
+ { 0x65, 0xB6, 0xA6, 0xD0, 0x42, 0x14, 0x08, 0x60, 0x34, 0x8D, 0x37, 0x2F, 0x01, 0xF0, 0x46, 0xBE },
+ { 0x66, 0xAC, 0x0B, 0x62, 0x1D, 0x68, 0x11, 0xF5, 0x27, 0xB1, 0x13, 0x5D, 0xF3, 0x2A, 0xE9, 0x18 }
+ },
+ {
+ 16,
+ { 0xCA, 0xA4, 0x16, 0xB7, 0x1C, 0x92, 0x2E, 0xAD, 0xEB, 0xA7, 0xDB, 0x69, 0x92, 0xCB, 0x35, 0xEF },
+ { 0x81, 0x6F, 0x8E, 0x4D, 0x96, 0xC6, 0xB3, 0x67, 0x83, 0xF5, 0x63, 0xC7, 0x20, 0x6D, 0x40, 0x23 },
+ { 0x44, 0xF7, 0x63, 0x62, 0xF0, 0x43, 0xBB, 0x67, 0x4A, 0x75, 0x12, 0x42, 0x46, 0x29, 0x28, 0x19 }
+ },
+ {
+ 16,
+ { 0x6B, 0xCF, 0x22, 0x2F, 0xE0, 0x1B, 0xB0, 0xAA, 0xD8, 0x3C, 0x91, 0x99, 0x18, 0xB2, 0x28, 0xE8 },
+ { 0x7C, 0x37, 0xC7, 0xD0, 0xAC, 0x92, 0x29, 0xF1, 0x60, 0x82, 0x93, 0x89, 0xAA, 0x61, 0xAA, 0xA9 },
+ { 0xE5, 0x89, 0x1B, 0xB3, 0xFE, 0x8B, 0x0C, 0xA1, 0xA6, 0xC7, 0xBE, 0x12, 0x73, 0x0F, 0xC1, 0x19 }
+ },
+ {
+ 16,
+ { 0xE6, 0xD0, 0xF1, 0x03, 0x2E, 0xDE, 0x70, 0x8D, 0xD8, 0x9E, 0x36, 0x5C, 0x05, 0x52, 0xE7, 0x0D },
+ { 0xE2, 0x42, 0xE7, 0x92, 0x0E, 0xF7, 0x82, 0xA2, 0xB8, 0x21, 0x8D, 0x26, 0xBA, 0x2D, 0xE6, 0x32 },
+ { 0x1E, 0xDD, 0x75, 0x22, 0xB9, 0x36, 0x8A, 0x0F, 0x32, 0xFD, 0xD4, 0x48, 0x65, 0x12, 0x5A, 0x2F }
+ }
+ };
+ symmetric_key key;
+ unsigned char tmp[2][16];
+ int err, i, y;
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ zeromem(&key, sizeof(key));
+ if ((err = noekeon_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+
+ noekeon_ecb_encrypt(tests[i].pt, tmp[0], &key);
+ noekeon_ecb_decrypt(tmp[0], tmp[1], &key);
+ if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Noekeon Encrypt", i) ||
+ compare_testvector(tmp[1], 16, tests[i].pt, 16, "Noekeon Decrypt", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 16; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) noekeon_ecb_encrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 1000; y++) noekeon_ecb_decrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void noekeon_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int noekeon_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ *keysize = 16;
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/ciphers/rc2.c b/Sources/libtomcrypt/ciphers/rc2.c
new file mode 100644
index 00000000..4832424b
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/rc2.c
@@ -0,0 +1,408 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**********************************************************************\
+* To commemorate the 1996 RSA Data Security Conference, the following *
+* code is released into the public domain by its author. Prost! *
+* *
+* This cipher uses 16-bit words and little-endian byte ordering. *
+* I wonder which processor it was optimized for? *
+* *
+* Thanks to CodeView, SoftIce, and D86 for helping bring this code to *
+* the public. *
+\**********************************************************************/
+#include "tomcrypt_private.h"
+
+/**
+ @file rc2.c
+ Implementation of RC2 with fixed effective key length of 64bits
+*/
+
+#ifdef LTC_RC2
+
+const struct ltc_cipher_descriptor rc2_desc = {
+ "rc2",
+ 12, 8, 128, 8, 16,
+ &rc2_setup,
+ &rc2_ecb_encrypt,
+ &rc2_ecb_decrypt,
+ &rc2_test,
+ &rc2_done,
+ &rc2_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/* 256-entry permutation table, probably derived somehow from pi */
+static const unsigned char permute[256] = {
+ 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157,
+ 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162,
+ 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50,
+ 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130,
+ 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220,
+ 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38,
+ 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3,
+ 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215,
+ 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42,
+ 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236,
+ 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57,
+ 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49,
+ 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201,
+ 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169,
+ 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46,
+ 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173
+};
+
+ /**
+ Initialize the RC2 block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param bits The effective key length in bits
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey)
+{
+ unsigned *xkey = skey->rc2.xkey;
+ unsigned char tmp[128];
+ unsigned T8, TM;
+ int i;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (keylen == 0 || keylen > 128 || bits > 1024) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (bits == 0) {
+ bits = 1024;
+ }
+
+ if (num_rounds != 0 && num_rounds != 16) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ for (i = 0; i < keylen; i++) {
+ tmp[i] = key[i] & 255;
+ }
+
+ /* Phase 1: Expand input key to 128 bytes */
+ if (keylen < 128) {
+ for (i = keylen; i < 128; i++) {
+ tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255];
+ }
+ }
+
+ /* Phase 2 - reduce effective key size to "bits" */
+ T8 = (unsigned)(bits+7)>>3;
+ TM = (255 >> (unsigned)(7 & -bits));
+ tmp[128 - T8] = permute[tmp[128 - T8] & TM];
+ for (i = 127 - T8; i >= 0; i--) {
+ tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]];
+ }
+
+ /* Phase 3 - copy to xkey in little-endian order */
+ for (i = 0; i < 64; i++) {
+ xkey[i] = (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8);
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmp, sizeof(tmp));
+#endif
+
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the RC2 block cipher
+
+ The effective key length is here always keylen * 8
+
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+*/
+int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ return rc2_setup_ex(key, keylen, keylen * 8, num_rounds, skey);
+}
+
+/**********************************************************************\
+* Encrypt an 8-byte block of plaintext using the given key. *
+\**********************************************************************/
+/**
+ Encrypts a block of text with RC2
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_rc2_ecb_encrypt( const unsigned char *pt,
+ unsigned char *ct,
+ const symmetric_key *skey)
+#else
+int rc2_ecb_encrypt( const unsigned char *pt,
+ unsigned char *ct,
+ const symmetric_key *skey)
+#endif
+{
+ const unsigned *xkey;
+ unsigned x76, x54, x32, x10, i;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ xkey = skey->rc2.xkey;
+
+ x76 = ((unsigned)pt[7] << 8) + (unsigned)pt[6];
+ x54 = ((unsigned)pt[5] << 8) + (unsigned)pt[4];
+ x32 = ((unsigned)pt[3] << 8) + (unsigned)pt[2];
+ x10 = ((unsigned)pt[1] << 8) + (unsigned)pt[0];
+
+ for (i = 0; i < 16; i++) {
+ x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF;
+ x10 = ((x10 << 1) | (x10 >> 15));
+
+ x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF;
+ x32 = ((x32 << 2) | (x32 >> 14));
+
+ x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF;
+ x54 = ((x54 << 3) | (x54 >> 13));
+
+ x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF;
+ x76 = ((x76 << 5) | (x76 >> 11));
+
+ if (i == 4 || i == 10) {
+ x10 = (x10 + xkey[x76 & 63]) & 0xFFFF;
+ x32 = (x32 + xkey[x10 & 63]) & 0xFFFF;
+ x54 = (x54 + xkey[x32 & 63]) & 0xFFFF;
+ x76 = (x76 + xkey[x54 & 63]) & 0xFFFF;
+ }
+ }
+
+ ct[0] = (unsigned char)x10;
+ ct[1] = (unsigned char)(x10 >> 8);
+ ct[2] = (unsigned char)x32;
+ ct[3] = (unsigned char)(x32 >> 8);
+ ct[4] = (unsigned char)x54;
+ ct[5] = (unsigned char)(x54 >> 8);
+ ct[6] = (unsigned char)x76;
+ ct[7] = (unsigned char)(x76 >> 8);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int rc2_ecb_encrypt( const unsigned char *pt,
+ unsigned char *ct,
+ const symmetric_key *skey)
+{
+ int err = s_rc2_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 5);
+ return err;
+}
+#endif
+
+/**********************************************************************\
+* Decrypt an 8-byte block of ciphertext using the given key. *
+\**********************************************************************/
+/**
+ Decrypts a block of text with RC2
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_rc2_ecb_decrypt( const unsigned char *ct,
+ unsigned char *pt,
+ const symmetric_key *skey)
+#else
+int rc2_ecb_decrypt( const unsigned char *ct,
+ unsigned char *pt,
+ const symmetric_key *skey)
+#endif
+{
+ unsigned x76, x54, x32, x10;
+ const unsigned *xkey;
+ int i;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ xkey = skey->rc2.xkey;
+
+ x76 = ((unsigned)ct[7] << 8) + (unsigned)ct[6];
+ x54 = ((unsigned)ct[5] << 8) + (unsigned)ct[4];
+ x32 = ((unsigned)ct[3] << 8) + (unsigned)ct[2];
+ x10 = ((unsigned)ct[1] << 8) + (unsigned)ct[0];
+
+ for (i = 15; i >= 0; i--) {
+ if (i == 4 || i == 10) {
+ x76 = (x76 - xkey[x54 & 63]) & 0xFFFF;
+ x54 = (x54 - xkey[x32 & 63]) & 0xFFFF;
+ x32 = (x32 - xkey[x10 & 63]) & 0xFFFF;
+ x10 = (x10 - xkey[x76 & 63]) & 0xFFFF;
+ }
+
+ x76 = ((x76 << 11) | (x76 >> 5));
+ x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF;
+
+ x54 = ((x54 << 13) | (x54 >> 3));
+ x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF;
+
+ x32 = ((x32 << 14) | (x32 >> 2));
+ x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF;
+
+ x10 = ((x10 << 15) | (x10 >> 1));
+ x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF;
+ }
+
+ pt[0] = (unsigned char)x10;
+ pt[1] = (unsigned char)(x10 >> 8);
+ pt[2] = (unsigned char)x32;
+ pt[3] = (unsigned char)(x32 >> 8);
+ pt[4] = (unsigned char)x54;
+ pt[5] = (unsigned char)(x54 >> 8);
+ pt[6] = (unsigned char)x76;
+ pt[7] = (unsigned char)(x76 >> 8);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int rc2_ecb_decrypt( const unsigned char *ct,
+ unsigned char *pt,
+ const symmetric_key *skey)
+{
+ int err = s_rc2_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 4 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Performs a self-test of the RC2 block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int rc2_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ int keylen, bits;
+ unsigned char key[16], pt[8], ct[8];
+ } tests[] = {
+
+ { 8, 63,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff }
+ },
+ { 8, 64,
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0x27, 0x8b, 0x27, 0xe4, 0x2e, 0x2f, 0x0d, 0x49 }
+ },
+ { 8, 64,
+ { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 }
+ },
+ { 1, 64,
+ { 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x61, 0xa8, 0xa2, 0x44, 0xad, 0xac, 0xcc, 0xf0 }
+ },
+ { 7, 64,
+ { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x6c, 0xcf, 0x43, 0x08, 0x97, 0x4c, 0x26, 0x7f }
+ },
+ { 16, 64,
+ { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
+ 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x1a, 0x80, 0x7d, 0x27, 0x2b, 0xbe, 0x5d, 0xb1 }
+ },
+ { 16, 128,
+ { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
+ 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 }
+ }
+ };
+ int x, y, err;
+ symmetric_key skey;
+ unsigned char tmp[2][8];
+
+ for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+ zeromem(tmp, sizeof(tmp));
+ if (tests[x].bits == (tests[x].keylen * 8)) {
+ if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ else {
+ if ((err = rc2_setup_ex(tests[x].key, tests[x].keylen, tests[x].bits, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey);
+ rc2_ecb_decrypt(tmp[0], tmp[1], &skey);
+
+ if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC2 CT", x) ||
+ compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC2 PT", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 8; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) rc2_ecb_encrypt(tmp[0], tmp[0], &skey);
+ for (y = 0; y < 1000; y++) rc2_ecb_decrypt(tmp[0], tmp[0], &skey);
+ for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void rc2_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int rc2_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 1) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize > 128) {
+ *keysize = 128;
+ }
+ return CRYPT_OK;
+}
+
+#endif
+
+
+
diff --git a/Sources/libtomcrypt/ciphers/rc5.c b/Sources/libtomcrypt/ciphers/rc5.c
new file mode 100644
index 00000000..f21ba4f4
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/rc5.c
@@ -0,0 +1,323 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file rc5.c
+ LTC_RC5 code by Tom St Denis
+*/
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RC5
+
+const struct ltc_cipher_descriptor rc5_desc =
+{
+ "rc5",
+ 2,
+ 8, 128, 8, 12,
+ &rc5_setup,
+ &rc5_ecb_encrypt,
+ &rc5_ecb_decrypt,
+ &rc5_test,
+ &rc5_done,
+ &rc5_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ulong32 stab[50] = {
+0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL,
+0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL,
+0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL,
+0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL,
+0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL,
+0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL, 0xe96a3d2fUL, 0x87a1b6e8UL, 0x25d930a1UL, 0xc410aa5aUL,
+0x62482413UL, 0x007f9dccUL
+};
+
+ /**
+ Initialize the LTC_RC5 block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+#ifdef LTC_CLEAN_STACK
+static int s_rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+ ulong32 L[64], *S, A, B, i, j, v, s, t, l;
+
+ LTC_ARGCHK(skey != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* test parameters */
+ if (num_rounds == 0) {
+ num_rounds = rc5_desc.default_rounds;
+ }
+
+ if (num_rounds < 12 || num_rounds > 24) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* key must be between 64 and 1024 bits */
+ if (keylen < 8 || keylen > 128) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ skey->rc5.rounds = num_rounds;
+ S = skey->rc5.K;
+
+ /* copy the key into the L array */
+ for (A = i = j = 0; i < (ulong32)keylen; ) {
+ A = (A << 8) | ((ulong32)(key[i++] & 255));
+ if ((i & 3) == 0) {
+ L[j++] = BSWAP(A);
+ A = 0;
+ }
+ }
+
+ if ((keylen & 3) != 0) {
+ A <<= (ulong32)((8 * (4 - (keylen&3))));
+ L[j++] = BSWAP(A);
+ }
+
+ /* setup the S array */
+ t = (ulong32)(2 * (num_rounds + 1));
+ XMEMCPY(S, stab, t * sizeof(*S));
+
+ /* mix buffer */
+ s = 3 * MAX(t, j);
+ l = j;
+ for (A = B = i = j = v = 0; v < s; v++) {
+ A = S[i] = ROLc(S[i] + A + B, 3);
+ B = L[j] = ROL(L[j] + A + B, (A+B));
+ if (++i == t) { i = 0; }
+ if (++j == l) { j = 0; }
+ }
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int x;
+ x = s_rc5_setup(key, keylen, num_rounds, skey);
+ burn_stack(sizeof(ulong32) * 122 + sizeof(int));
+ return x;
+}
+#endif
+
+/**
+ Encrypts a block of text with LTC_RC5
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+ ulong32 A, B;
+ const ulong32 *K;
+ int r;
+ LTC_ARGCHK(skey != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ LOAD32L(A, &pt[0]);
+ LOAD32L(B, &pt[4]);
+ A += skey->rc5.K[0];
+ B += skey->rc5.K[1];
+ K = skey->rc5.K + 2;
+
+ if ((skey->rc5.rounds & 1) == 0) {
+ for (r = 0; r < skey->rc5.rounds; r += 2) {
+ A = ROL(A ^ B, B) + K[0];
+ B = ROL(B ^ A, A) + K[1];
+ A = ROL(A ^ B, B) + K[2];
+ B = ROL(B ^ A, A) + K[3];
+ K += 4;
+ }
+ } else {
+ for (r = 0; r < skey->rc5.rounds; r++) {
+ A = ROL(A ^ B, B) + K[0];
+ B = ROL(B ^ A, A) + K[1];
+ K += 2;
+ }
+ }
+ STORE32L(A, &ct[0]);
+ STORE32L(B, &ct[4]);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_rc5_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(ulong32) * 2 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Decrypts a block of text with LTC_RC5
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+ ulong32 A, B;
+ const ulong32 *K;
+ int r;
+ LTC_ARGCHK(skey != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ LOAD32L(A, &ct[0]);
+ LOAD32L(B, &ct[4]);
+ K = skey->rc5.K + (skey->rc5.rounds << 1);
+
+ if ((skey->rc5.rounds & 1) == 0) {
+ K -= 2;
+ for (r = skey->rc5.rounds - 1; r >= 0; r -= 2) {
+ B = ROR(B - K[3], A) ^ A;
+ A = ROR(A - K[2], B) ^ B;
+ B = ROR(B - K[1], A) ^ A;
+ A = ROR(A - K[0], B) ^ B;
+ K -= 4;
+ }
+ } else {
+ for (r = skey->rc5.rounds - 1; r >= 0; r--) {
+ B = ROR(B - K[1], A) ^ A;
+ A = ROR(A - K[0], B) ^ B;
+ K -= 2;
+ }
+ }
+ A -= skey->rc5.K[0];
+ B -= skey->rc5.K[1];
+ STORE32L(A, &pt[0]);
+ STORE32L(B, &pt[4]);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_rc5_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(ulong32) * 2 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Performs a self-test of the LTC_RC5 block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int rc5_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ unsigned char key[16], pt[8], ct[8];
+ } tests[] = {
+ {
+ { 0x91, 0x5f, 0x46, 0x19, 0xbe, 0x41, 0xb2, 0x51,
+ 0x63, 0x55, 0xa5, 0x01, 0x10, 0xa9, 0xce, 0x91 },
+ { 0x21, 0xa5, 0xdb, 0xee, 0x15, 0x4b, 0x8f, 0x6d },
+ { 0xf7, 0xc0, 0x13, 0xac, 0x5b, 0x2b, 0x89, 0x52 }
+ },
+ {
+ { 0x78, 0x33, 0x48, 0xe7, 0x5a, 0xeb, 0x0f, 0x2f,
+ 0xd7, 0xb1, 0x69, 0xbb, 0x8d, 0xc1, 0x67, 0x87 },
+ { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 },
+ { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 }
+ },
+ {
+ { 0xDC, 0x49, 0xdb, 0x13, 0x75, 0xa5, 0x58, 0x4f,
+ 0x64, 0x85, 0xb4, 0x13, 0xb5, 0xf1, 0x2b, 0xaf },
+ { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 },
+ { 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc }
+ }
+ };
+ unsigned char tmp[2][8];
+ int x, y, err;
+ symmetric_key key;
+
+ for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+ /* setup key */
+ if ((err = rc5_setup(tests[x].key, 16, 12, &key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* encrypt and decrypt */
+ rc5_ecb_encrypt(tests[x].pt, tmp[0], &key);
+ rc5_ecb_decrypt(tmp[0], tmp[1], &key);
+
+ /* compare */
+ if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC5 Encrypt", x) != 0 ||
+ compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC5 Decrypt", x) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 8; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) rc5_ecb_encrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 1000; y++) rc5_ecb_decrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void rc5_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int rc5_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 8) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize > 128) {
+ *keysize = 128;
+ }
+ return CRYPT_OK;
+}
+
+#endif
+
+
+
diff --git a/Sources/libtomcrypt/ciphers/rc6.c b/Sources/libtomcrypt/ciphers/rc6.c
new file mode 100644
index 00000000..d1341d31
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/rc6.c
@@ -0,0 +1,324 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file rc6.c
+ LTC_RC6 code by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RC6
+
+const struct ltc_cipher_descriptor rc6_desc =
+{
+ "rc6",
+ 3,
+ 8, 128, 16, 20,
+ &rc6_setup,
+ &rc6_ecb_encrypt,
+ &rc6_ecb_decrypt,
+ &rc6_test,
+ &rc6_done,
+ &rc6_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ulong32 stab[44] = {
+0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL,
+0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL,
+0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL,
+0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL,
+0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL,
+0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL };
+
+ /**
+ Initialize the LTC_RC6 block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+#ifdef LTC_CLEAN_STACK
+static int s_rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+ ulong32 L[64], S[50], A, B, i, j, v, s, l;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* test parameters */
+ if (num_rounds != 0 && num_rounds != 20) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* key must be between 64 and 1024 bits */
+ if (keylen < 8 || keylen > 128) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ /* copy the key into the L array */
+ for (A = i = j = 0; i < (ulong32)keylen; ) {
+ A = (A << 8) | ((ulong32)(key[i++] & 255));
+ if (!(i & 3)) {
+ L[j++] = BSWAP(A);
+ A = 0;
+ }
+ }
+
+ /* handle odd sized keys */
+ if (keylen & 3) {
+ A <<= (8 * (4 - (keylen&3)));
+ L[j++] = BSWAP(A);
+ }
+
+ /* setup the S array */
+ XMEMCPY(S, stab, 44 * sizeof(stab[0]));
+
+ /* mix buffer */
+ s = 3 * MAX(44, j);
+ l = j;
+ for (A = B = i = j = v = 0; v < s; v++) {
+ A = S[i] = ROLc(S[i] + A + B, 3);
+ B = L[j] = ROL(L[j] + A + B, (A+B));
+ if (++i == 44) { i = 0; }
+ if (++j == l) { j = 0; }
+ }
+
+ /* copy to key */
+ for (i = 0; i < 44; i++) {
+ skey->rc6.K[i] = S[i];
+ }
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int x;
+ x = s_rc6_setup(key, keylen, num_rounds, skey);
+ burn_stack(sizeof(ulong32) * 122);
+ return x;
+}
+#endif
+
+/**
+ Encrypts a block of text with LTC_RC6
+ @param pt The input plaintext (16 bytes)
+ @param ct The output ciphertext (16 bytes)
+ @param skey The key as scheduled
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+ ulong32 a,b,c,d,t,u;
+ const ulong32 *K;
+ int r;
+
+ LTC_ARGCHK(skey != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LOAD32L(a,&pt[0]);LOAD32L(b,&pt[4]);LOAD32L(c,&pt[8]);LOAD32L(d,&pt[12]);
+
+ b += skey->rc6.K[0];
+ d += skey->rc6.K[1];
+
+#define RND(a,b,c,d) \
+ t = (b * (b + b + 1)); t = ROLc(t, 5); \
+ u = (d * (d + d + 1)); u = ROLc(u, 5); \
+ a = ROL(a^t,u) + K[0]; \
+ c = ROL(c^u,t) + K[1]; K += 2;
+
+ K = skey->rc6.K + 2;
+ for (r = 0; r < 20; r += 4) {
+ RND(a,b,c,d);
+ RND(b,c,d,a);
+ RND(c,d,a,b);
+ RND(d,a,b,c);
+ }
+
+#undef RND
+
+ a += skey->rc6.K[42];
+ c += skey->rc6.K[43];
+ STORE32L(a,&ct[0]);STORE32L(b,&ct[4]);STORE32L(c,&ct[8]);STORE32L(d,&ct[12]);
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_rc6_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(ulong32) * 6 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Decrypts a block of text with LTC_RC6
+ @param ct The input ciphertext (16 bytes)
+ @param pt The output plaintext (16 bytes)
+ @param skey The key as scheduled
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+ ulong32 a,b,c,d,t,u;
+ const ulong32 *K;
+ int r;
+
+ LTC_ARGCHK(skey != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ LOAD32L(a,&ct[0]);LOAD32L(b,&ct[4]);LOAD32L(c,&ct[8]);LOAD32L(d,&ct[12]);
+ a -= skey->rc6.K[42];
+ c -= skey->rc6.K[43];
+
+#define RND(a,b,c,d) \
+ t = (b * (b + b + 1)); t = ROLc(t, 5); \
+ u = (d * (d + d + 1)); u = ROLc(u, 5); \
+ c = ROR(c - K[1], t) ^ u; \
+ a = ROR(a - K[0], u) ^ t; K -= 2;
+
+ K = skey->rc6.K + 40;
+
+ for (r = 0; r < 20; r += 4) {
+ RND(d,a,b,c);
+ RND(c,d,a,b);
+ RND(b,c,d,a);
+ RND(a,b,c,d);
+ }
+
+#undef RND
+
+ b -= skey->rc6.K[0];
+ d -= skey->rc6.K[1];
+ STORE32L(a,&pt[0]);STORE32L(b,&pt[4]);STORE32L(c,&pt[8]);STORE32L(d,&pt[12]);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_rc6_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(ulong32) * 6 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Performs a self-test of the LTC_RC6 block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int rc6_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ int keylen;
+ unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+ {
+ 16,
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
+ 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 },
+ { 0x52, 0x4e, 0x19, 0x2f, 0x47, 0x15, 0xc6, 0x23,
+ 0x1f, 0x51, 0xf6, 0x36, 0x7e, 0xa4, 0x3f, 0x18 }
+ },
+ {
+ 24,
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
+ 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
+ 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 },
+ { 0x68, 0x83, 0x29, 0xd0, 0x19, 0xe5, 0x05, 0x04,
+ 0x1e, 0x52, 0xe9, 0x2a, 0xf9, 0x52, 0x91, 0xd4 }
+ },
+ {
+ 32,
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
+ 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0,
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe },
+ { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
+ 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 },
+ { 0xc8, 0x24, 0x18, 0x16, 0xf0, 0xd7, 0xe4, 0x89,
+ 0x20, 0xad, 0x16, 0xa1, 0x67, 0x4e, 0x5d, 0x48 }
+ }
+ };
+ unsigned char tmp[2][16];
+ int x, y, err;
+ symmetric_key key;
+
+ for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+ /* setup key */
+ if ((err = rc6_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* encrypt and decrypt */
+ rc6_ecb_encrypt(tests[x].pt, tmp[0], &key);
+ rc6_ecb_decrypt(tmp[0], tmp[1], &key);
+
+ /* compare */
+ if (compare_testvector(tmp[0], 16, tests[x].ct, 16, "RC6 Encrypt", x) ||
+ compare_testvector(tmp[1], 16, tests[x].pt, 16, "RC6 Decrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 16; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) rc6_ecb_encrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 1000; y++) rc6_ecb_decrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void rc6_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int rc6_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 8) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize > 128) {
+ *keysize = 128;
+ }
+ return CRYPT_OK;
+}
+
+#endif /*LTC_RC6*/
+
+
diff --git a/Sources/libtomcrypt/ciphers/safer/safer.c b/Sources/libtomcrypt/ciphers/safer/safer.c
new file mode 100644
index 00000000..84cc2d01
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/safer/safer.c
@@ -0,0 +1,484 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/*******************************************************************************
+*
+* FILE: safer.c
+*
+* LTC_DESCRIPTION: block-cipher algorithm LTC_SAFER (Secure And Fast Encryption
+* Routine) in its four versions: LTC_SAFER K-64, LTC_SAFER K-128,
+* LTC_SAFER SK-64 and LTC_SAFER SK-128.
+*
+* AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch)
+* Signal and Information Processing Laboratory
+* Swiss Federal Institute of Technology
+* CH-8092 Zuerich, Switzerland
+*
+* DATE: September 9, 1995
+*
+* CHANGE HISTORY:
+*
+*******************************************************************************/
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SAFER
+
+#define LTC_SAFER_TAB_C
+#include "safer_tab.c"
+
+const struct ltc_cipher_descriptor safer_k64_desc = {
+ "safer-k64",
+ 8, 8, 8, 8, LTC_SAFER_K64_DEFAULT_NOF_ROUNDS,
+ &safer_k64_setup,
+ &safer_ecb_encrypt,
+ &safer_ecb_decrypt,
+ &safer_k64_test,
+ &safer_done,
+ &safer_64_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ },
+
+ safer_sk64_desc = {
+ "safer-sk64",
+ 9, 8, 8, 8, LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS,
+ &safer_sk64_setup,
+ &safer_ecb_encrypt,
+ &safer_ecb_decrypt,
+ &safer_sk64_test,
+ &safer_done,
+ &safer_64_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ },
+
+ safer_k128_desc = {
+ "safer-k128",
+ 10, 16, 16, 8, LTC_SAFER_K128_DEFAULT_NOF_ROUNDS,
+ &safer_k128_setup,
+ &safer_ecb_encrypt,
+ &safer_ecb_decrypt,
+ &safer_sk128_test,
+ &safer_done,
+ &safer_128_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ },
+
+ safer_sk128_desc = {
+ "safer-sk128",
+ 11, 16, 16, 8, LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS,
+ &safer_sk128_setup,
+ &safer_ecb_encrypt,
+ &safer_ecb_decrypt,
+ &safer_sk128_test,
+ &safer_done,
+ &safer_128_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ };
+
+/******************* Constants ************************************************/
+/* #define TAB_LEN 256 */
+
+/******************* Assertions ***********************************************/
+
+/******************* Macros ***************************************************/
+#define ROL8(x, n) ((unsigned char)((unsigned int)(x) << (n)\
+ |(unsigned int)((x) & 0xFF) >> (8 - (n))))
+#define EXP(x) safer_ebox[(x) & 0xFF]
+#define LOG(x) safer_lbox[(x) & 0xFF]
+#define PHT(x, y) { y += x; x += y; }
+#define IPHT(x, y) { x -= y; y -= x; }
+
+/******************* Types ****************************************************/
+
+#ifdef LTC_CLEAN_STACK
+static void s_safer_expand_userkey(const unsigned char *userkey_1,
+ const unsigned char *userkey_2,
+ unsigned int nof_rounds,
+ int strengthened,
+ safer_key_t key)
+#else
+static void safer_expand_userkey(const unsigned char *userkey_1,
+ const unsigned char *userkey_2,
+ unsigned int nof_rounds,
+ int strengthened,
+ safer_key_t key)
+#endif
+{ unsigned int i, j, k;
+ unsigned char ka[LTC_SAFER_BLOCK_LEN + 1];
+ unsigned char kb[LTC_SAFER_BLOCK_LEN + 1];
+
+ if (LTC_SAFER_MAX_NOF_ROUNDS < nof_rounds) {
+ nof_rounds = LTC_SAFER_MAX_NOF_ROUNDS;
+ }
+ *key++ = (unsigned char)nof_rounds;
+ ka[LTC_SAFER_BLOCK_LEN] = (unsigned char)0;
+ kb[LTC_SAFER_BLOCK_LEN] = (unsigned char)0;
+ k = 0;
+ for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) {
+ ka[j] = ROL8(userkey_1[j], 5);
+ ka[LTC_SAFER_BLOCK_LEN] ^= ka[j];
+ kb[j] = *key++ = userkey_2[j];
+ kb[LTC_SAFER_BLOCK_LEN] ^= kb[j];
+ }
+ for (i = 1; i <= nof_rounds; i++) {
+ for (j = 0; j < LTC_SAFER_BLOCK_LEN + 1; j++) {
+ ka[j] = ROL8(ka[j], 6);
+ kb[j] = ROL8(kb[j], 6);
+ }
+ if (strengthened) {
+ k = 2 * i - 1;
+ while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; }
+ }
+ for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) {
+ if (strengthened) {
+ *key++ = (ka[k]
+ + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF;
+ if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; }
+ } else {
+ *key++ = (ka[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF;
+ }
+ }
+ if (strengthened) {
+ k = 2 * i;
+ while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; }
+ }
+ for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) {
+ if (strengthened) {
+ *key++ = (kb[k]
+ + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF;
+ if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; }
+ } else {
+ *key++ = (kb[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF;
+ }
+ }
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(ka, sizeof(ka));
+ zeromem(kb, sizeof(kb));
+#endif
+}
+
+#ifdef LTC_CLEAN_STACK
+static void safer_expand_userkey(const unsigned char *userkey_1,
+ const unsigned char *userkey_2,
+ unsigned int nof_rounds,
+ int strengthened,
+ safer_key_t key)
+{
+ s_safer_expand_userkey(userkey_1, userkey_2, nof_rounds, strengthened, key);
+ burn_stack(sizeof(unsigned char) * (2 * (LTC_SAFER_BLOCK_LEN + 1)) + sizeof(unsigned int)*2);
+}
+#endif
+
+int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (keylen != 8) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K64_DEFAULT_NOF_ROUNDS), 0, skey->safer.key);
+ return CRYPT_OK;
+}
+
+int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (keylen != 8) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS), 1, skey->safer.key);
+ return CRYPT_OK;
+}
+
+int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (keylen != 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K128_DEFAULT_NOF_ROUNDS), 0, skey->safer.key);
+ return CRYPT_OK;
+}
+
+int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (keylen != 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0?num_rounds:LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS), 1, skey->safer.key);
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_safer_ecb_encrypt(const unsigned char *pt,
+ unsigned char *ct,
+ const symmetric_key *skey)
+#else
+int safer_ecb_encrypt(const unsigned char *pt,
+ unsigned char *ct,
+ const symmetric_key *skey)
+#endif
+{ unsigned char a, b, c, d, e, f, g, h, t;
+ unsigned int round;
+ const unsigned char *key;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ key = skey->safer.key;
+ a = pt[0]; b = pt[1]; c = pt[2]; d = pt[3];
+ e = pt[4]; f = pt[5]; g = pt[6]; h = pt[7];
+ if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS;
+ while(round-- > 0)
+ {
+ a ^= *++key; b += *++key; c += *++key; d ^= *++key;
+ e ^= *++key; f += *++key; g += *++key; h ^= *++key;
+ a = EXP(a) + *++key; b = LOG(b) ^ *++key;
+ c = LOG(c) ^ *++key; d = EXP(d) + *++key;
+ e = EXP(e) + *++key; f = LOG(f) ^ *++key;
+ g = LOG(g) ^ *++key; h = EXP(h) + *++key;
+ PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h);
+ PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h);
+ PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h);
+ t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t;
+ }
+ a ^= *++key; b += *++key; c += *++key; d ^= *++key;
+ e ^= *++key; f += *++key; g += *++key; h ^= *++key;
+ ct[0] = a & 0xFF; ct[1] = b & 0xFF;
+ ct[2] = c & 0xFF; ct[3] = d & 0xFF;
+ ct[4] = e & 0xFF; ct[5] = f & 0xFF;
+ ct[6] = g & 0xFF; ct[7] = h & 0xFF;
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int safer_ecb_encrypt(const unsigned char *pt,
+ unsigned char *ct,
+ const symmetric_key *skey)
+{
+ int err = s_safer_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
+ return err;
+}
+#endif
+
+#ifdef LTC_CLEAN_STACK
+static int s_safer_ecb_decrypt(const unsigned char *ct,
+ unsigned char *pt,
+ const symmetric_key *skey)
+#else
+int safer_ecb_decrypt(const unsigned char *ct,
+ unsigned char *pt,
+ const symmetric_key *skey)
+#endif
+{ unsigned char a, b, c, d, e, f, g, h, t;
+ unsigned int round;
+ const unsigned char *key;
+
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ key = skey->safer.key;
+ a = ct[0]; b = ct[1]; c = ct[2]; d = ct[3];
+ e = ct[4]; f = ct[5]; g = ct[6]; h = ct[7];
+ if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS;
+ key += LTC_SAFER_BLOCK_LEN * (1 + 2 * round);
+ h ^= *key; g -= *--key; f -= *--key; e ^= *--key;
+ d ^= *--key; c -= *--key; b -= *--key; a ^= *--key;
+ while (round--)
+ {
+ t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t;
+ IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h);
+ IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h);
+ IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h);
+ h -= *--key; g ^= *--key; f ^= *--key; e -= *--key;
+ d -= *--key; c ^= *--key; b ^= *--key; a -= *--key;
+ h = LOG(h) ^ *--key; g = EXP(g) - *--key;
+ f = EXP(f) - *--key; e = LOG(e) ^ *--key;
+ d = LOG(d) ^ *--key; c = EXP(c) - *--key;
+ b = EXP(b) - *--key; a = LOG(a) ^ *--key;
+ }
+ pt[0] = a & 0xFF; pt[1] = b & 0xFF;
+ pt[2] = c & 0xFF; pt[3] = d & 0xFF;
+ pt[4] = e & 0xFF; pt[5] = f & 0xFF;
+ pt[6] = g & 0xFF; pt[7] = h & 0xFF;
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int safer_ecb_decrypt(const unsigned char *ct,
+ unsigned char *pt,
+ const symmetric_key *skey)
+{
+ int err = s_safer_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
+ return err;
+}
+#endif
+
+int safer_64_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 8) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ *keysize = 8;
+ return CRYPT_OK;
+}
+
+int safer_128_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ *keysize = 16;
+ return CRYPT_OK;
+}
+
+int safer_k64_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const unsigned char k64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
+ k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 },
+ k64_ct[] = { 200, 242, 156, 221, 135, 120, 62, 217 };
+
+ symmetric_key skey;
+ unsigned char buf[2][8];
+ int err;
+
+ /* test K64 */
+ if ((err = safer_k64_setup(k64_key, 8, 6, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ safer_ecb_encrypt(k64_pt, buf[0], &skey);
+ safer_ecb_decrypt(buf[0], buf[1], &skey);
+
+ if (compare_testvector(buf[0], 8, k64_ct, 8, "Safer K64 Encrypt", 0) != 0 ||
+ compare_testvector(buf[1], 8, k64_pt, 8, "Safer K64 Decrypt", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+ #endif
+}
+
+
+int safer_sk64_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const unsigned char sk64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
+ sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
+ sk64_ct[] = { 95, 206, 155, 162, 5, 132, 56, 199 };
+
+ symmetric_key skey;
+ unsigned char buf[2][8];
+ int err, y;
+
+ /* test SK64 */
+ if ((err = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) {
+ return err;
+ }
+
+ safer_ecb_encrypt(sk64_pt, buf[0], &skey);
+ safer_ecb_decrypt(buf[0], buf[1], &skey);
+
+ if (compare_testvector(buf[0], 8, sk64_ct, 8, "Safer SK64 Encrypt", 0) != 0 ||
+ compare_testvector(buf[1], 8, sk64_pt, 8, "Safer SK64 Decrypt", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 8; y++) buf[0][y] = 0;
+ for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
+ for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
+ for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void safer_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+int safer_sk128_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const unsigned char sk128_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
+ sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0 },
+ sk128_ct[] = { 255, 120, 17, 228, 179, 167, 46, 113 };
+
+ symmetric_key skey;
+ unsigned char buf[2][8];
+ int err, y;
+
+ /* test SK128 */
+ if ((err = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ safer_ecb_encrypt(sk128_pt, buf[0], &skey);
+ safer_ecb_decrypt(buf[0], buf[1], &skey);
+
+ if (compare_testvector(buf[0], 8, sk128_ct, 8, "Safer SK128 Encrypt", 0) != 0 ||
+ compare_testvector(buf[1], 8, sk128_pt, 8, "Safer SK128 Decrypt", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 8; y++) buf[0][y] = 0;
+ for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
+ for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
+ for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
+
diff --git a/Sources/libtomcrypt/ciphers/safer/safer_tab.c b/Sources/libtomcrypt/ciphers/safer/safer_tab.c
new file mode 100644
index 00000000..4cc0e476
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/safer/safer_tab.c
@@ -0,0 +1,54 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file safer_tab.c
+ Tables for LTC_SAFER block ciphers
+*/
+
+#ifdef LTC_SAFER_TAB_C
+
+/* This is the box defined by ebox[x] = 45^x mod 257.
+ * Its assumed that the value "256" corresponds to zero. */
+static const unsigned char safer_ebox[256] = {
+ 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63,
+ 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247,
+ 64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177,
+255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131,
+241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20,
+129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160,
+ 4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252,
+ 32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217,
+ 0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194,
+249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10,
+193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80,
+ 2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126,
+ 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237,
+128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97,
+253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5,
+225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40
+};
+
+/* This is the inverse of ebox or the base 45 logarithm */
+static const unsigned char safer_lbox[256] = {
+128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248,
+192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130,
+112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37,
+201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15,
+ 32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198,
+175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84,
+121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188,
+189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217,
+208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158,
+210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42,
+ 95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219,
+164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29,
+ 41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14,
+122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104,
+109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66,
+184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48
+};
+
+#endif /* LTC_SAFER_TAB_C */
+
+
diff --git a/Sources/libtomcrypt/ciphers/safer/saferp.c b/Sources/libtomcrypt/ciphers/safer/saferp.c
new file mode 100644
index 00000000..86cc7089
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/safer/saferp.c
@@ -0,0 +1,567 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file saferp.c
+ LTC_SAFER+ Implementation by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SAFERP
+
+#define LTC_SAFER_TAB_C
+#include "safer_tab.c"
+
+const struct ltc_cipher_descriptor saferp_desc =
+{
+ "safer+",
+ 4,
+ 16, 32, 16, 8,
+ &saferp_setup,
+ &saferp_ecb_encrypt,
+ &saferp_ecb_decrypt,
+ &saferp_test,
+ &saferp_done,
+ &saferp_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/* ROUND(b,i)
+ *
+ * This is one forward key application. Note the basic form is
+ * key addition, substitution, key addition. The safer_ebox and safer_lbox
+ * are the exponentiation box and logarithm boxes respectively.
+ * The value of 'i' is the current round number which allows this
+ * function to be unrolled massively. Most of LTC_SAFER+'s speed
+ * comes from not having to compute indirect accesses into the
+ * array of 16 bytes b[0..15] which is the block of data
+*/
+
+#define ROUND(b, i) do { \
+ b[0] = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255; \
+ b[1] = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1]; \
+ b[2] = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2]; \
+ b[3] = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255; \
+ b[4] = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255; \
+ b[5] = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5]; \
+ b[6] = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6]; \
+ b[7] = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255; \
+ b[8] = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255; \
+ b[9] = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9]; \
+ b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10]; \
+ b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \
+ b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \
+ b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13]; \
+ b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14]; \
+ b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255; \
+} while (0)
+
+/* This is one inverse key application */
+#define iROUND(b, i) do { \
+ b[0] = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0]; \
+ b[1] = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255; \
+ b[2] = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255; \
+ b[3] = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3]; \
+ b[4] = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4]; \
+ b[5] = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255; \
+ b[6] = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255; \
+ b[7] = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7]; \
+ b[8] = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8]; \
+ b[9] = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255; \
+ b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \
+ b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11]; \
+ b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12]; \
+ b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \
+ b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \
+ b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15]; \
+} while (0)
+
+/* This is a forward single layer PHT transform. */
+#define PHT(b) do { \
+ b[0] = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255; \
+ b[2] = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255; \
+ b[4] = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255; \
+ b[6] = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255; \
+ b[8] = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255; \
+ b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \
+ b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \
+ b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255; \
+} while (0)
+
+/* This is an inverse single layer PHT transform */
+#define iPHT(b) do { \
+ b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255; \
+ b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255; \
+ b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255; \
+ b[9] = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255; \
+ b[7] = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255; \
+ b[5] = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255; \
+ b[3] = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255; \
+ b[1] = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255; \
+ } while (0)
+
+/* This is the "Armenian" Shuffle. It takes the input from b and stores it in b2 */
+#define SHUF(b, b2) do { \
+ b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15]; \
+ b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5]; \
+ b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \
+ b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3]; \
+} while (0)
+
+/* This is the inverse shuffle. It takes from b and gives to b2 */
+#define iSHUF(b, b2) do { \
+ b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15]; \
+ b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13]; \
+ b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1]; \
+ b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3]; \
+} while (0)
+
+/* The complete forward Linear Transform layer.
+ * Note that alternating usage of b and b2.
+ * Each round of LT starts in 'b' and ends in 'b2'.
+ */
+#define LT(b, b2) do { \
+ PHT(b); SHUF(b, b2); \
+ PHT(b2); SHUF(b2, b); \
+ PHT(b); SHUF(b, b2); \
+ PHT(b2); \
+} while (0)
+
+/* This is the inverse linear transform layer. */
+#define iLT(b, b2) do { \
+ iPHT(b); \
+ iSHUF(b, b2); iPHT(b2); \
+ iSHUF(b2, b); iPHT(b); \
+ iSHUF(b, b2); iPHT(b2); \
+} while (0)
+
+#ifdef LTC_SMALL_CODE
+
+static void s_round(unsigned char *b, int i, const symmetric_key *skey)
+{
+ ROUND(b, i);
+}
+
+static void s_iround(unsigned char *b, int i, const symmetric_key *skey)
+{
+ iROUND(b, i);
+}
+
+static void s_lt(unsigned char *b, unsigned char *b2)
+{
+ LT(b, b2);
+}
+
+static void s_ilt(unsigned char *b, unsigned char *b2)
+{
+ iLT(b, b2);
+}
+
+#undef ROUND
+#define ROUND(b, i) s_round(b, i, skey)
+
+#undef iROUND
+#define iROUND(b, i) s_iround(b, i, skey)
+
+#undef LT
+#define LT(b, b2) s_lt(b, b2)
+
+#undef iLT
+#define iLT(b, b2) s_ilt(b, b2)
+
+#endif
+
+/* These are the 33, 128-bit bias words for the key schedule */
+static const unsigned char safer_bias[33][16] = {
+{ 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172, 100},
+{ 236, 171, 170, 198, 103, 149, 88, 13, 248, 154, 246, 110, 102, 220, 5, 61},
+{ 138, 195, 216, 137, 106, 233, 54, 73, 67, 191, 235, 212, 150, 155, 104, 160},
+{ 93, 87, 146, 31, 213, 113, 92, 187, 34, 193, 190, 123, 188, 153, 99, 148},
+{ 42, 97, 184, 52, 50, 25, 253, 251, 23, 64, 230, 81, 29, 65, 68, 143},
+{ 221, 4, 128, 222, 231, 49, 214, 127, 1, 162, 247, 57, 218, 111, 35, 202},
+{ 58, 208, 28, 209, 48, 62, 18, 161, 205, 15, 224, 168, 175, 130, 89, 44},
+{ 125, 173, 178, 239, 194, 135, 206, 117, 6, 19, 2, 144, 79, 46, 114, 51},
+{ 192, 141, 207, 169, 129, 226, 196, 39, 47, 108, 122, 159, 82, 225, 21, 56},
+{ 252, 32, 66, 199, 8, 228, 9, 85, 94, 140, 20, 118, 96, 255, 223, 215},
+{ 250, 11, 33, 0, 26, 249, 166, 185, 232, 158, 98, 76, 217, 145, 80, 210},
+{ 24, 180, 7, 132, 234, 91, 164, 200, 14, 203, 72, 105, 75, 78, 156, 53},
+{ 69, 77, 84, 229, 37, 60, 12, 74, 139, 63, 204, 167, 219, 107, 174, 244},
+{ 45, 243, 124, 109, 157, 181, 38, 116, 242, 147, 83, 176, 240, 17, 237, 131},
+{ 182, 3, 22, 115, 59, 30, 142, 112, 189, 134, 27, 71, 126, 36, 86, 241},
+{ 136, 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172},
+{ 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239},
+{ 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202},
+{ 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246},
+{ 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152},
+{ 171, 242, 96, 208, 108, 234, 250, 199, 217, 0, 212, 31, 110, 67, 188, 236},
+{ 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150},
+{ 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30},
+{ 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6},
+{ 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104},
+{ 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175},
+{ 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35},
+{ 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7},
+{ 40, 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207},
+{ 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247},
+{ 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255},
+{ 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51}};
+
+ /**
+ Initialize the LTC_SAFER+ block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ unsigned x, y, z;
+ unsigned char t[33];
+ static const int rounds[3] = { 8, 12, 16 };
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* check arguments */
+ if (keylen != 16 && keylen != 24 && keylen != 32) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ /* Is the number of rounds valid? Either use zero for default or
+ * 8,12,16 rounds for 16,24,32 byte keys
+ */
+ if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* 128 bit key version */
+ if (keylen == 16) {
+ /* copy key into t */
+ for (x = y = 0; x < 16; x++) {
+ t[x] = key[x];
+ y ^= key[x];
+ }
+ t[16] = y;
+
+ /* make round keys */
+ for (x = 0; x < 16; x++) {
+ skey->saferp.K[0][x] = t[x];
+ }
+
+ /* make the 16 other keys as a transformation of the first key */
+ for (x = 1; x < 17; x++) {
+ /* rotate 3 bits each */
+ for (y = 0; y < 17; y++) {
+ t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
+ }
+
+ /* select and add */
+ z = x;
+ for (y = 0; y < 16; y++) {
+ skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
+ if (++z == 17) { z = 0; }
+ }
+ }
+ skey->saferp.rounds = 8;
+ } else if (keylen == 24) {
+ /* copy key into t */
+ for (x = y = 0; x < 24; x++) {
+ t[x] = key[x];
+ y ^= key[x];
+ }
+ t[24] = y;
+
+ /* make round keys */
+ for (x = 0; x < 16; x++) {
+ skey->saferp.K[0][x] = t[x];
+ }
+
+ for (x = 1; x < 25; x++) {
+ /* rotate 3 bits each */
+ for (y = 0; y < 25; y++) {
+ t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
+ }
+
+ /* select and add */
+ z = x;
+ for (y = 0; y < 16; y++) {
+ skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
+ if (++z == 25) { z = 0; }
+ }
+ }
+ skey->saferp.rounds = 12;
+ } else {
+ /* copy key into t */
+ for (x = y = 0; x < 32; x++) {
+ t[x] = key[x];
+ y ^= key[x];
+ }
+ t[32] = y;
+
+ /* make round keys */
+ for (x = 0; x < 16; x++) {
+ skey->saferp.K[0][x] = t[x];
+ }
+
+ for (x = 1; x < 33; x++) {
+ /* rotate 3 bits each */
+ for (y = 0; y < 33; y++) {
+ t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
+ }
+
+ /* select and add */
+ z = x;
+ for (y = 0; y < 16; y++) {
+ skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
+ if (++z == 33) { z = 0; }
+ }
+ }
+ skey->saferp.rounds = 16;
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(t, sizeof(t));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with LTC_SAFER+
+ @param pt The input plaintext (16 bytes)
+ @param ct The output ciphertext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ unsigned char b[16];
+ int x;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* do eight rounds */
+ for (x = 0; x < 16; x++) {
+ b[x] = pt[x];
+ }
+ ROUND(b, 0); LT(b, ct);
+ ROUND(ct, 2); LT(ct, b);
+ ROUND(b, 4); LT(b, ct);
+ ROUND(ct, 6); LT(ct, b);
+ ROUND(b, 8); LT(b, ct);
+ ROUND(ct, 10); LT(ct, b);
+ ROUND(b, 12); LT(b, ct);
+ ROUND(ct, 14); LT(ct, b);
+ /* 192-bit key? */
+ if (skey->saferp.rounds > 8) {
+ ROUND(b, 16); LT(b, ct);
+ ROUND(ct, 18); LT(ct, b);
+ ROUND(b, 20); LT(b, ct);
+ ROUND(ct, 22); LT(ct, b);
+ }
+ /* 256-bit key? */
+ if (skey->saferp.rounds > 12) {
+ ROUND(b, 24); LT(b, ct);
+ ROUND(ct, 26); LT(ct, b);
+ ROUND(b, 28); LT(b, ct);
+ ROUND(ct, 30); LT(ct, b);
+ }
+ ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
+ ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
+ ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
+ ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
+ ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
+ ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
+ ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
+ ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
+ ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
+ ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
+ ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
+ ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
+ ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
+ ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
+ ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
+ ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
+#ifdef LTC_CLEAN_STACK
+ zeromem(b, sizeof(b));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with LTC_SAFER+
+ @param ct The input ciphertext (16 bytes)
+ @param pt The output plaintext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ unsigned char b[16];
+ int x;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* do eight rounds */
+ b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
+ b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
+ b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
+ b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
+ b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
+ b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
+ b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
+ b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
+ b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
+ b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
+ b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
+ b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
+ b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
+ b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
+ b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
+ b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
+ /* 256-bit key? */
+ if (skey->saferp.rounds > 12) {
+ iLT(b, pt); iROUND(pt, 30);
+ iLT(pt, b); iROUND(b, 28);
+ iLT(b, pt); iROUND(pt, 26);
+ iLT(pt, b); iROUND(b, 24);
+ }
+ /* 192-bit key? */
+ if (skey->saferp.rounds > 8) {
+ iLT(b, pt); iROUND(pt, 22);
+ iLT(pt, b); iROUND(b, 20);
+ iLT(b, pt); iROUND(pt, 18);
+ iLT(pt, b); iROUND(b, 16);
+ }
+ iLT(b, pt); iROUND(pt, 14);
+ iLT(pt, b); iROUND(b, 12);
+ iLT(b, pt); iROUND(pt,10);
+ iLT(pt, b); iROUND(b, 8);
+ iLT(b, pt); iROUND(pt,6);
+ iLT(pt, b); iROUND(b, 4);
+ iLT(b, pt); iROUND(pt,2);
+ iLT(pt, b); iROUND(b, 0);
+ for (x = 0; x < 16; x++) {
+ pt[x] = b[x];
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(b, sizeof(b));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Performs a self-test of the LTC_SAFER+ block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int saferp_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ int keylen;
+ unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+ {
+ 16,
+ { 41, 35, 190, 132, 225, 108, 214, 174,
+ 82, 144, 73, 241, 241, 187, 233, 235 },
+ { 179, 166, 219, 60, 135, 12, 62, 153,
+ 36, 94, 13, 28, 6, 183, 71, 222 },
+ { 224, 31, 182, 10, 12, 255, 84, 70,
+ 127, 13, 89, 249, 9, 57, 165, 220 }
+ }, {
+ 24,
+ { 72, 211, 143, 117, 230, 217, 29, 42,
+ 229, 192, 247, 43, 120, 129, 135, 68,
+ 14, 95, 80, 0, 212, 97, 141, 190 },
+ { 123, 5, 21, 7, 59, 51, 130, 31,
+ 24, 112, 146, 218, 100, 84, 206, 177 },
+ { 92, 136, 4, 63, 57, 95, 100, 0,
+ 150, 130, 130, 16, 193, 111, 219, 133 }
+ }, {
+ 32,
+ { 243, 168, 141, 254, 190, 242, 235, 113,
+ 255, 160, 208, 59, 117, 6, 140, 126,
+ 135, 120, 115, 77, 208, 190, 130, 190,
+ 219, 194, 70, 65, 43, 140, 250, 48 },
+ { 127, 112, 240, 167, 84, 134, 50, 149,
+ 170, 91, 104, 19, 11, 230, 252, 245 },
+ { 88, 11, 25, 36, 172, 229, 202, 213,
+ 170, 65, 105, 153, 220, 104, 153, 138 }
+ }
+ };
+
+ unsigned char tmp[2][16];
+ symmetric_key skey;
+ int err, i, y;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey);
+ saferp_ecb_decrypt(tmp[0], tmp[1], &skey);
+
+ /* compare */
+ if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Safer+ Encrypt", i) ||
+ compare_testvector(tmp[1], 16, tests[i].pt, 16, "Safer+ Decrypt", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 16; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey);
+ for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey);
+ for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void saferp_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int saferp_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize < 24) {
+ *keysize = 16;
+ } else if (*keysize < 32) {
+ *keysize = 24;
+ } else {
+ *keysize = 32;
+ }
+ return CRYPT_OK;
+}
+
+#endif
+
+
diff --git a/Sources/libtomcrypt/ciphers/serpent.c b/Sources/libtomcrypt/ciphers/serpent.c
new file mode 100644
index 00000000..dbb999eb
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/serpent.c
@@ -0,0 +1,717 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* Based on serpent.cpp - originally written and placed in the public domain by Wei Dai
+ https://github.com/weidai11/cryptopp/blob/master/serpent.cpp
+
+ On 2017-10-16 wikipedia says:
+ "The Serpent cipher algorithm is in the public domain and has not been patented."
+ https://en.wikipedia.org/wiki/Serpent_(cipher)
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SERPENT
+
+const struct ltc_cipher_descriptor serpent_desc = {
+ "serpent",
+ 25, /* cipher_ID */
+ 16, 32, 16, 32, /* min_key_len, max_key_len, block_len, default_rounds */
+ &serpent_setup,
+ &serpent_ecb_encrypt,
+ &serpent_ecb_decrypt,
+ &serpent_test,
+ &serpent_done,
+ &serpent_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/* linear transformation */
+#define s_lt(i,a,b,c,d,e) { \
+ a = ROLc(a, 13); \
+ c = ROLc(c, 3); \
+ d = ROLc(d ^ c ^ (a << 3), 7); \
+ b = ROLc(b ^ a ^ c, 1); \
+ a = ROLc(a ^ b ^ d, 5); \
+ c = ROLc(c ^ d ^ (b << 7), 22); \
+ }
+
+/* inverse linear transformation */
+#define s_ilt(i,a,b,c,d,e) { \
+ c = RORc(c, 22); \
+ a = RORc(a, 5); \
+ c ^= d ^ (b << 7); \
+ a ^= b ^ d; \
+ b = RORc(b, 1); \
+ d = RORc(d, 7) ^ c ^ (a << 3); \
+ b ^= a ^ c; \
+ c = RORc(c, 3); \
+ a = RORc(a, 13); \
+ }
+
+/* order of output from S-box functions */
+#define s_beforeS0(f) f(0,a,b,c,d,e)
+#define s_afterS0(f) f(1,b,e,c,a,d)
+#define s_afterS1(f) f(2,c,b,a,e,d)
+#define s_afterS2(f) f(3,a,e,b,d,c)
+#define s_afterS3(f) f(4,e,b,d,c,a)
+#define s_afterS4(f) f(5,b,a,e,c,d)
+#define s_afterS5(f) f(6,a,c,b,e,d)
+#define s_afterS6(f) f(7,a,c,d,b,e)
+#define s_afterS7(f) f(8,d,e,b,a,c)
+
+/* order of output from inverse S-box functions */
+#define s_beforeI7(f) f(8,a,b,c,d,e)
+#define s_afterI7(f) f(7,d,a,b,e,c)
+#define s_afterI6(f) f(6,a,b,c,e,d)
+#define s_afterI5(f) f(5,b,d,e,c,a)
+#define s_afterI4(f) f(4,b,c,e,a,d)
+#define s_afterI3(f) f(3,a,b,e,c,d)
+#define s_afterI2(f) f(2,b,d,e,c,a)
+#define s_afterI1(f) f(1,a,b,c,e,d)
+#define s_afterI0(f) f(0,a,d,b,e,c)
+
+/* The instruction sequences for the S-box functions
+ * come from Dag Arne Osvik's paper "Speeding up Serpent".
+ */
+
+#define s_s0(i, r0, r1, r2, r3, r4) { \
+ r3 ^= r0; \
+ r4 = r1; \
+ r1 &= r3; \
+ r4 ^= r2; \
+ r1 ^= r0; \
+ r0 |= r3; \
+ r0 ^= r4; \
+ r4 ^= r3; \
+ r3 ^= r2; \
+ r2 |= r1; \
+ r2 ^= r4; \
+ r4 = ~r4; \
+ r4 |= r1; \
+ r1 ^= r3; \
+ r1 ^= r4; \
+ r3 |= r0; \
+ r1 ^= r3; \
+ r4 ^= r3; \
+}
+
+#define s_i0(i, r0, r1, r2, r3, r4) { \
+ r2 = ~r2; \
+ r4 = r1; \
+ r1 |= r0; \
+ r4 = ~r4; \
+ r1 ^= r2; \
+ r2 |= r4; \
+ r1 ^= r3; \
+ r0 ^= r4; \
+ r2 ^= r0; \
+ r0 &= r3; \
+ r4 ^= r0; \
+ r0 |= r1; \
+ r0 ^= r2; \
+ r3 ^= r4; \
+ r2 ^= r1; \
+ r3 ^= r0; \
+ r3 ^= r1; \
+ r2 &= r3; \
+ r4 ^= r2; \
+}
+
+#define s_s1(i, r0, r1, r2, r3, r4) { \
+ r0 = ~r0; \
+ r2 = ~r2; \
+ r4 = r0; \
+ r0 &= r1; \
+ r2 ^= r0; \
+ r0 |= r3; \
+ r3 ^= r2; \
+ r1 ^= r0; \
+ r0 ^= r4; \
+ r4 |= r1; \
+ r1 ^= r3; \
+ r2 |= r0; \
+ r2 &= r4; \
+ r0 ^= r1; \
+ r1 &= r2; \
+ r1 ^= r0; \
+ r0 &= r2; \
+ r0 ^= r4; \
+}
+
+#define s_i1(i, r0, r1, r2, r3, r4) { \
+ r4 = r1; \
+ r1 ^= r3; \
+ r3 &= r1; \
+ r4 ^= r2; \
+ r3 ^= r0; \
+ r0 |= r1; \
+ r2 ^= r3; \
+ r0 ^= r4; \
+ r0 |= r2; \
+ r1 ^= r3; \
+ r0 ^= r1; \
+ r1 |= r3; \
+ r1 ^= r0; \
+ r4 = ~r4; \
+ r4 ^= r1; \
+ r1 |= r0; \
+ r1 ^= r0; \
+ r1 |= r4; \
+ r3 ^= r1; \
+}
+
+#define s_s2(i, r0, r1, r2, r3, r4) { \
+ r4 = r0; \
+ r0 &= r2; \
+ r0 ^= r3; \
+ r2 ^= r1; \
+ r2 ^= r0; \
+ r3 |= r4; \
+ r3 ^= r1; \
+ r4 ^= r2; \
+ r1 = r3; \
+ r3 |= r4; \
+ r3 ^= r0; \
+ r0 &= r1; \
+ r4 ^= r0; \
+ r1 ^= r3; \
+ r1 ^= r4; \
+ r4 = ~r4; \
+}
+
+#define s_i2(i, r0, r1, r2, r3, r4) { \
+ r2 ^= r3; \
+ r3 ^= r0; \
+ r4 = r3; \
+ r3 &= r2; \
+ r3 ^= r1; \
+ r1 |= r2; \
+ r1 ^= r4; \
+ r4 &= r3; \
+ r2 ^= r3; \
+ r4 &= r0; \
+ r4 ^= r2; \
+ r2 &= r1; \
+ r2 |= r0; \
+ r3 = ~r3; \
+ r2 ^= r3; \
+ r0 ^= r3; \
+ r0 &= r1; \
+ r3 ^= r4; \
+ r3 ^= r0; \
+}
+
+#define s_s3(i, r0, r1, r2, r3, r4) { \
+ r4 = r0; \
+ r0 |= r3; \
+ r3 ^= r1; \
+ r1 &= r4; \
+ r4 ^= r2; \
+ r2 ^= r3; \
+ r3 &= r0; \
+ r4 |= r1; \
+ r3 ^= r4; \
+ r0 ^= r1; \
+ r4 &= r0; \
+ r1 ^= r3; \
+ r4 ^= r2; \
+ r1 |= r0; \
+ r1 ^= r2; \
+ r0 ^= r3; \
+ r2 = r1; \
+ r1 |= r3; \
+ r1 ^= r0; \
+}
+
+#define s_i3(i, r0, r1, r2, r3, r4) { \
+ r4 = r2; \
+ r2 ^= r1; \
+ r1 &= r2; \
+ r1 ^= r0; \
+ r0 &= r4; \
+ r4 ^= r3; \
+ r3 |= r1; \
+ r3 ^= r2; \
+ r0 ^= r4; \
+ r2 ^= r0; \
+ r0 |= r3; \
+ r0 ^= r1; \
+ r4 ^= r2; \
+ r2 &= r3; \
+ r1 |= r3; \
+ r1 ^= r2; \
+ r4 ^= r0; \
+ r2 ^= r4; \
+}
+
+#define s_s4(i, r0, r1, r2, r3, r4) { \
+ r1 ^= r3; \
+ r3 = ~r3; \
+ r2 ^= r3; \
+ r3 ^= r0; \
+ r4 = r1; \
+ r1 &= r3; \
+ r1 ^= r2; \
+ r4 ^= r3; \
+ r0 ^= r4; \
+ r2 &= r4; \
+ r2 ^= r0; \
+ r0 &= r1; \
+ r3 ^= r0; \
+ r4 |= r1; \
+ r4 ^= r0; \
+ r0 |= r3; \
+ r0 ^= r2; \
+ r2 &= r3; \
+ r0 = ~r0; \
+ r4 ^= r2; \
+}
+
+#define s_i4(i, r0, r1, r2, r3, r4) { \
+ r4 = r2; \
+ r2 &= r3; \
+ r2 ^= r1; \
+ r1 |= r3; \
+ r1 &= r0; \
+ r4 ^= r2; \
+ r4 ^= r1; \
+ r1 &= r2; \
+ r0 = ~r0; \
+ r3 ^= r4; \
+ r1 ^= r3; \
+ r3 &= r0; \
+ r3 ^= r2; \
+ r0 ^= r1; \
+ r2 &= r0; \
+ r3 ^= r0; \
+ r2 ^= r4; \
+ r2 |= r3; \
+ r3 ^= r0; \
+ r2 ^= r1; \
+}
+
+#define s_s5(i, r0, r1, r2, r3, r4) { \
+ r0 ^= r1; \
+ r1 ^= r3; \
+ r3 = ~r3; \
+ r4 = r1; \
+ r1 &= r0; \
+ r2 ^= r3; \
+ r1 ^= r2; \
+ r2 |= r4; \
+ r4 ^= r3; \
+ r3 &= r1; \
+ r3 ^= r0; \
+ r4 ^= r1; \
+ r4 ^= r2; \
+ r2 ^= r0; \
+ r0 &= r3; \
+ r2 = ~r2; \
+ r0 ^= r4; \
+ r4 |= r3; \
+ r2 ^= r4; \
+}
+
+#define s_i5(i, r0, r1, r2, r3, r4) { \
+ r1 = ~r1; \
+ r4 = r3; \
+ r2 ^= r1; \
+ r3 |= r0; \
+ r3 ^= r2; \
+ r2 |= r1; \
+ r2 &= r0; \
+ r4 ^= r3; \
+ r2 ^= r4; \
+ r4 |= r0; \
+ r4 ^= r1; \
+ r1 &= r2; \
+ r1 ^= r3; \
+ r4 ^= r2; \
+ r3 &= r4; \
+ r4 ^= r1; \
+ r3 ^= r0; \
+ r3 ^= r4; \
+ r4 = ~r4; \
+}
+
+#define s_s6(i, r0, r1, r2, r3, r4) { \
+ r2 = ~r2; \
+ r4 = r3; \
+ r3 &= r0; \
+ r0 ^= r4; \
+ r3 ^= r2; \
+ r2 |= r4; \
+ r1 ^= r3; \
+ r2 ^= r0; \
+ r0 |= r1; \
+ r2 ^= r1; \
+ r4 ^= r0; \
+ r0 |= r3; \
+ r0 ^= r2; \
+ r4 ^= r3; \
+ r4 ^= r0; \
+ r3 = ~r3; \
+ r2 &= r4; \
+ r2 ^= r3; \
+}
+
+#define s_i6(i, r0, r1, r2, r3, r4) { \
+ r0 ^= r2; \
+ r4 = r2; \
+ r2 &= r0; \
+ r4 ^= r3; \
+ r2 = ~r2; \
+ r3 ^= r1; \
+ r2 ^= r3; \
+ r4 |= r0; \
+ r0 ^= r2; \
+ r3 ^= r4; \
+ r4 ^= r1; \
+ r1 &= r3; \
+ r1 ^= r0; \
+ r0 ^= r3; \
+ r0 |= r2; \
+ r3 ^= r1; \
+ r4 ^= r0; \
+}
+
+#define s_s7(i, r0, r1, r2, r3, r4) { \
+ r4 = r2; \
+ r2 &= r1; \
+ r2 ^= r3; \
+ r3 &= r1; \
+ r4 ^= r2; \
+ r2 ^= r1; \
+ r1 ^= r0; \
+ r0 |= r4; \
+ r0 ^= r2; \
+ r3 ^= r1; \
+ r2 ^= r3; \
+ r3 &= r0; \
+ r3 ^= r4; \
+ r4 ^= r2; \
+ r2 &= r0; \
+ r4 = ~r4; \
+ r2 ^= r4; \
+ r4 &= r0; \
+ r1 ^= r3; \
+ r4 ^= r1; \
+}
+
+#define s_i7(i, r0, r1, r2, r3, r4) { \
+ r4 = r2; \
+ r2 ^= r0; \
+ r0 &= r3; \
+ r2 = ~r2; \
+ r4 |= r3; \
+ r3 ^= r1; \
+ r1 |= r0; \
+ r0 ^= r2; \
+ r2 &= r4; \
+ r1 ^= r2; \
+ r2 ^= r0; \
+ r0 |= r2; \
+ r3 &= r4; \
+ r0 ^= r3; \
+ r4 ^= r1; \
+ r3 ^= r4; \
+ r4 |= r0; \
+ r3 ^= r2; \
+ r4 ^= r2; \
+}
+
+/* key xor */
+#define s_kx(r, a, b, c, d, e) { \
+ a ^= k[4 * r + 0]; \
+ b ^= k[4 * r + 1]; \
+ c ^= k[4 * r + 2]; \
+ d ^= k[4 * r + 3]; \
+}
+
+#define s_lk(r, a, b, c, d, e) { \
+ a = k[(8-r)*4 + 0]; \
+ b = k[(8-r)*4 + 1]; \
+ c = k[(8-r)*4 + 2]; \
+ d = k[(8-r)*4 + 3]; \
+}
+
+#define s_sk(r, a, b, c, d, e) { \
+ k[(8-r)*4 + 4] = a; \
+ k[(8-r)*4 + 5] = b; \
+ k[(8-r)*4 + 6] = c; \
+ k[(8-r)*4 + 7] = d; \
+}
+
+static int s_setup_key(const unsigned char *key, int keylen, int rounds, ulong32 *k)
+{
+ int i;
+ ulong32 t;
+ ulong32 k0[8] = { 0 }; /* zero-initialize */
+ ulong32 a, b, c, d, e;
+
+ for (i = 0; i < 8 && i < keylen/4; ++i) {
+ LOAD32L(k0[i], key + i * 4);
+ }
+ if (keylen < 32) {
+ k0[keylen/4] |= (ulong32)1 << ((keylen%4)*8);
+ }
+
+ t = k0[7];
+ for (i = 0; i < 8; ++i) {
+ k[i] = k0[i] = t = ROLc(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11);
+ }
+ for (i = 8; i < 4*(rounds+1); ++i) {
+ k[i] = t = ROLc(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11);
+ }
+ k -= 20;
+
+ for (i = 0; i < rounds/8; i++) {
+ s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk);
+ s_afterS1(s_lk); s_afterS1(s_s2); s_afterS2(s_sk);
+ s_afterS0(s_lk); s_afterS0(s_s1); s_afterS1(s_sk);
+ s_beforeS0(s_lk); s_beforeS0(s_s0); s_afterS0(s_sk);
+ k += 8*4;
+ s_afterS6(s_lk); s_afterS6(s_s7); s_afterS7(s_sk);
+ s_afterS5(s_lk); s_afterS5(s_s6); s_afterS6(s_sk);
+ s_afterS4(s_lk); s_afterS4(s_s5); s_afterS5(s_sk);
+ s_afterS3(s_lk); s_afterS3(s_s4); s_afterS4(s_sk);
+ }
+ s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk);
+
+ return CRYPT_OK;
+}
+
+static int s_enc_block(const unsigned char *in, unsigned char *out, const ulong32 *k)
+{
+ ulong32 a, b, c, d, e;
+ unsigned int i = 1;
+
+ LOAD32L(a, in + 0);
+ LOAD32L(b, in + 4);
+ LOAD32L(c, in + 8);
+ LOAD32L(d, in + 12);
+
+ do {
+ s_beforeS0(s_kx); s_beforeS0(s_s0); s_afterS0(s_lt);
+ s_afterS0(s_kx); s_afterS0(s_s1); s_afterS1(s_lt);
+ s_afterS1(s_kx); s_afterS1(s_s2); s_afterS2(s_lt);
+ s_afterS2(s_kx); s_afterS2(s_s3); s_afterS3(s_lt);
+ s_afterS3(s_kx); s_afterS3(s_s4); s_afterS4(s_lt);
+ s_afterS4(s_kx); s_afterS4(s_s5); s_afterS5(s_lt);
+ s_afterS5(s_kx); s_afterS5(s_s6); s_afterS6(s_lt);
+ s_afterS6(s_kx); s_afterS6(s_s7);
+
+ if (i == 4) break;
+
+ ++i;
+ c = b;
+ b = e;
+ e = d;
+ d = a;
+ a = e;
+ k += 32;
+ s_beforeS0(s_lt);
+ } while (1);
+
+ s_afterS7(s_kx);
+
+ STORE32L(d, out + 0);
+ STORE32L(e, out + 4);
+ STORE32L(b, out + 8);
+ STORE32L(a, out + 12);
+
+ return CRYPT_OK;
+}
+
+static int s_dec_block(const unsigned char *in, unsigned char *out, const ulong32 *k)
+{
+ ulong32 a, b, c, d, e;
+ unsigned int i;
+
+ LOAD32L(a, in + 0);
+ LOAD32L(b, in + 4);
+ LOAD32L(c, in + 8);
+ LOAD32L(d, in + 12);
+ e = 0; LTC_UNUSED_PARAM(e); /* avoid scan-build warning */
+ i = 4;
+ k += 96;
+
+ s_beforeI7(s_kx);
+ goto start;
+
+ do {
+ c = b;
+ b = d;
+ d = e;
+ k -= 32;
+ s_beforeI7(s_ilt);
+start:
+ s_beforeI7(s_i7); s_afterI7(s_kx);
+ s_afterI7(s_ilt); s_afterI7(s_i6); s_afterI6(s_kx);
+ s_afterI6(s_ilt); s_afterI6(s_i5); s_afterI5(s_kx);
+ s_afterI5(s_ilt); s_afterI5(s_i4); s_afterI4(s_kx);
+ s_afterI4(s_ilt); s_afterI4(s_i3); s_afterI3(s_kx);
+ s_afterI3(s_ilt); s_afterI3(s_i2); s_afterI2(s_kx);
+ s_afterI2(s_ilt); s_afterI2(s_i1); s_afterI1(s_kx);
+ s_afterI1(s_ilt); s_afterI1(s_i0); s_afterI0(s_kx);
+ } while (--i != 0);
+
+ STORE32L(a, out + 0);
+ STORE32L(d, out + 4);
+ STORE32L(b, out + 8);
+ STORE32L(e, out + 12);
+
+ return CRYPT_OK;
+}
+
+int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (num_rounds != 0 && num_rounds != 32) return CRYPT_INVALID_ROUNDS;
+ if (keylen != 16 && keylen != 24 && keylen != 32) return CRYPT_INVALID_KEYSIZE;
+
+ err = s_setup_key(key, keylen, 32, skey->serpent.k);
+#ifdef LTC_CLEAN_STACK
+ burn_stack(sizeof(ulong32) * 14 + sizeof(int));
+#endif
+ return err;
+}
+
+int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_enc_block(pt, ct, skey->serpent.k);
+#ifdef LTC_CLEAN_STACK
+ burn_stack(sizeof(ulong32) * 5 + sizeof(int));
+#endif
+ return err;
+}
+
+int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_dec_block(ct, pt, skey->serpent.k);
+#ifdef LTC_CLEAN_STACK
+ burn_stack(sizeof(ulong32) * 5 + sizeof(int));
+#endif
+ return err;
+}
+
+void serpent_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+int serpent_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+
+ if (*keysize >= 32) { *keysize = 32; }
+ else if (*keysize >= 24) { *keysize = 24; }
+ else if (*keysize >= 16) { *keysize = 16; }
+ else return CRYPT_INVALID_KEYSIZE;
+ return CRYPT_OK;
+}
+
+int serpent_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ unsigned char key[32];
+ int keylen;
+ unsigned char pt[16], ct[16];
+ } tests[] = {
+ {
+ /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* keylen */ 32,
+ /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* ct */ {0xA2,0x23,0xAA,0x12,0x88,0x46,0x3C,0x0E,0x2B,0xE3,0x8E,0xBD,0x82,0x56,0x16,0xC0}
+ },
+ {
+ /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* keylen */ 32,
+ /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* ct */ {0xEA,0xE1,0xD4,0x05,0x57,0x01,0x74,0xDF,0x7D,0xF2,0xF9,0x96,0x6D,0x50,0x91,0x59}
+ },
+ {
+ /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* keylen */ 32,
+ /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* ct */ {0x65,0xF3,0x76,0x84,0x47,0x1E,0x92,0x1D,0xC8,0xA3,0x0F,0x45,0xB4,0x3C,0x44,0x99}
+ },
+ {
+ /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* keylen */ 24,
+ /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* ct */ {0x9E,0x27,0x4E,0xAD,0x9B,0x73,0x7B,0xB2,0x1E,0xFC,0xFC,0xA5,0x48,0x60,0x26,0x89}
+ },
+ {
+ /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* keylen */ 24,
+ /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* ct */ {0x92,0xFC,0x8E,0x51,0x03,0x99,0xE4,0x6A,0x04,0x1B,0xF3,0x65,0xE7,0xB3,0xAE,0x82}
+ },
+ {
+ /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* keylen */ 24,
+ /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* ct */ {0x5E,0x0D,0xA3,0x86,0xC4,0x6A,0xD4,0x93,0xDE,0xA2,0x03,0xFD,0xC6,0xF5,0x7D,0x70}
+ },
+ {
+ /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* keylen */ 16,
+ /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* ct */ {0x26,0x4E,0x54,0x81,0xEF,0xF4,0x2A,0x46,0x06,0xAB,0xDA,0x06,0xC0,0xBF,0xDA,0x3D}
+ },
+ {
+ /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* keylen */ 16,
+ /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* ct */ {0x4A,0x23,0x1B,0x3B,0xC7,0x27,0x99,0x34,0x07,0xAC,0x6E,0xC8,0x35,0x0E,0x85,0x24}
+ },
+ {
+ /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* keylen */ 16,
+ /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ /* ct */ {0xE0,0x32,0x69,0xF9,0xE9,0xFD,0x85,0x3C,0x7D,0x81,0x56,0xDF,0x14,0xB9,0x8D,0x56}
+ }
+ };
+
+ unsigned char buf[2][16];
+ symmetric_key key;
+ int err, x;
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ if ((err = serpent_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = serpent_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(buf[0], 16, tests[x].ct, 16, "SERPENT Encrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ if ((err = serpent_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(buf[1], 16, tests[x].pt, 16, "SERPENT Decrypt", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/ciphers/skipjack.c b/Sources/libtomcrypt/ciphers/skipjack.c
new file mode 100644
index 00000000..0251946a
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/skipjack.c
@@ -0,0 +1,334 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file skipjack.c
+ Skipjack Implementation by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SKIPJACK
+
+const struct ltc_cipher_descriptor skipjack_desc =
+{
+ "skipjack",
+ 17,
+ 10, 10, 8, 32,
+ &skipjack_setup,
+ &skipjack_ecb_encrypt,
+ &skipjack_ecb_decrypt,
+ &skipjack_test,
+ &skipjack_done,
+ &skipjack_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const unsigned char sbox[256] = {
+ 0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9,
+ 0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28,
+ 0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53,
+ 0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2,
+ 0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8,
+ 0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90,
+ 0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76,
+ 0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d,
+ 0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18,
+ 0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4,
+ 0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40,
+ 0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5,
+ 0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2,
+ 0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8,
+ 0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac,
+ 0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46
+};
+
+/* simple x + 1 (mod 10) in one step. */
+static const int keystep[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+
+/* simple x - 1 (mod 10) in one step */
+static const int ikeystep[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ /**
+ Initialize the Skipjack block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int x;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ if (keylen != 10) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if (num_rounds != 32 && num_rounds != 0) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* make sure the key is in range for platforms where CHAR_BIT != 8 */
+ for (x = 0; x < 10; x++) {
+ skey->skipjack.key[x] = key[x] & 255;
+ }
+
+ return CRYPT_OK;
+}
+
+#define RULE_A \
+ tmp = g_func(w1, &kp, skey->skipjack.key); \
+ w1 = tmp ^ w4 ^ x; \
+ w4 = w3; w3 = w2; \
+ w2 = tmp;
+
+#define RULE_B \
+ tmp = g_func(w1, &kp, skey->skipjack.key); \
+ tmp1 = w4; w4 = w3; \
+ w3 = w1 ^ w2 ^ x; \
+ w1 = tmp1; w2 = tmp;
+
+#define RULE_A1 \
+ tmp = w1 ^ w2 ^ x; \
+ w1 = ig_func(w2, &kp, skey->skipjack.key); \
+ w2 = w3; w3 = w4; w4 = tmp;
+
+#define RULE_B1 \
+ tmp = ig_func(w2, &kp, skey->skipjack.key); \
+ w2 = tmp ^ w3 ^ x; \
+ w3 = w4; w4 = w1; w1 = tmp;
+
+static unsigned g_func(unsigned w, int *kp, const unsigned char *key)
+{
+ unsigned char g1,g2;
+
+ g1 = (w >> 8) & 255; g2 = w & 255;
+ g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp];
+ g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp];
+ g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp];
+ g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp];
+ return ((unsigned)g1<<8)|(unsigned)g2;
+}
+
+static unsigned ig_func(unsigned w, int *kp, const unsigned char *key)
+{
+ unsigned char g1,g2;
+
+ g1 = (w >> 8) & 255; g2 = w & 255;
+ *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]];
+ *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]];
+ *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]];
+ *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]];
+ return ((unsigned)g1<<8)|(unsigned)g2;
+}
+
+/**
+ Encrypts a block of text with Skipjack
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+ unsigned w1,w2,w3,w4,tmp,tmp1;
+ int x, kp;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* load block */
+ w1 = ((unsigned)pt[0]<<8)|pt[1];
+ w2 = ((unsigned)pt[2]<<8)|pt[3];
+ w3 = ((unsigned)pt[4]<<8)|pt[5];
+ w4 = ((unsigned)pt[6]<<8)|pt[7];
+
+ /* 8 rounds of RULE A */
+ for (x = 1, kp = 0; x < 9; x++) {
+ RULE_A;
+ }
+
+ /* 8 rounds of RULE B */
+ for (; x < 17; x++) {
+ RULE_B;
+ }
+
+ /* 8 rounds of RULE A */
+ for (; x < 25; x++) {
+ RULE_A;
+ }
+
+ /* 8 rounds of RULE B */
+ for (; x < 33; x++) {
+ RULE_B;
+ }
+
+ /* store block */
+ ct[0] = (w1>>8)&255; ct[1] = w1&255;
+ ct[2] = (w2>>8)&255; ct[3] = w2&255;
+ ct[4] = (w3>>8)&255; ct[5] = w3&255;
+ ct[6] = (w4>>8)&255; ct[7] = w4&255;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_skipjack_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(unsigned) * 8 + sizeof(int) * 2);
+ return err;
+}
+#endif
+
+/**
+ Decrypts a block of text with Skipjack
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+ unsigned w1,w2,w3,w4,tmp;
+ int x, kp;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* load block */
+ w1 = ((unsigned)ct[0]<<8)|ct[1];
+ w2 = ((unsigned)ct[2]<<8)|ct[3];
+ w3 = ((unsigned)ct[4]<<8)|ct[5];
+ w4 = ((unsigned)ct[6]<<8)|ct[7];
+
+ /* 8 rounds of RULE B^-1
+
+ Note the value "kp = 8" comes from "kp = (32 * 4) mod 10" where 32*4 is 128 which mod 10 is 8
+ */
+ for (x = 32, kp = 8; x > 24; x--) {
+ RULE_B1;
+ }
+
+ /* 8 rounds of RULE A^-1 */
+ for (; x > 16; x--) {
+ RULE_A1;
+ }
+
+
+ /* 8 rounds of RULE B^-1 */
+ for (; x > 8; x--) {
+ RULE_B1;
+ }
+
+ /* 8 rounds of RULE A^-1 */
+ for (; x > 0; x--) {
+ RULE_A1;
+ }
+
+ /* store block */
+ pt[0] = (w1>>8)&255; pt[1] = w1&255;
+ pt[2] = (w2>>8)&255; pt[3] = w2&255;
+ pt[4] = (w3>>8)&255; pt[5] = w3&255;
+ pt[6] = (w4>>8)&255; pt[7] = w4&255;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_skipjack_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(unsigned) * 7 + sizeof(int) * 2);
+ return err;
+}
+#endif
+
+/**
+ Performs a self-test of the Skipjack block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int skipjack_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ unsigned char key[10], pt[8], ct[8];
+ } tests[] = {
+ {
+ { 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 },
+ { 0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa },
+ { 0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00 }
+ }
+ };
+ unsigned char buf[2][8];
+ int x, y, err;
+ symmetric_key key;
+
+ for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+ /* setup key */
+ if ((err = skipjack_setup(tests[x].key, 10, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* encrypt and decrypt */
+ skipjack_ecb_encrypt(tests[x].pt, buf[0], &key);
+ skipjack_ecb_decrypt(buf[0], buf[1], &key);
+
+ /* compare */
+ if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Skipjack Encrypt", x) != 0 ||
+ compare_testvector(buf[1], 8, tests[x].pt, 8, "Skipjack Decrypt", x) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 8; y++) buf[0][y] = 0;
+ for (y = 0; y < 1000; y++) skipjack_ecb_encrypt(buf[0], buf[0], &key);
+ for (y = 0; y < 1000; y++) skipjack_ecb_decrypt(buf[0], buf[0], &key);
+ for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void skipjack_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int skipjack_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 10) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize > 10) {
+ *keysize = 10;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/ciphers/sm4.c b/Sources/libtomcrypt/ciphers/sm4.c
new file mode 100644
index 00000000..d21cdce6
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/sm4.c
@@ -0,0 +1,377 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @brief SM4 block cipher algorithm
+ @date Oct 2018
+ @author Chao Wei
+
+ SM4 (formerly SMS4) is a block cipher used in the Chinese National
+ Standard for Wireless LAN WAPI (Wired Authentication and Privacy
+ Infrastructure).
+ --from wikipedia:
+ https://en.wikipedia.org/wiki/SM4_(cipher)
+
+ This implimentation follows Chinese National Standard
+ GM/T 0002-2012
+ */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SM4
+
+/*porting to libtomcrypt*/
+/*char always 8bits long*/
+typedef unsigned char sm4_u8_t;
+typedef ulong32 sm4_u32_t;
+
+/*
+ * S-box defined in section 6.2
+ * (1) Nonlinear transformation
+ */
+static const sm4_u8_t sm4_sbox_table[16][16] = {
+ {0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
+ 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05},
+ {0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
+ 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99},
+ {0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
+ 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62},
+ {0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
+ 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6},
+ {0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
+ 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8},
+ {0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
+ 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35},
+ {0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
+ 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87},
+ {0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
+ 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e},
+ {0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
+ 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1},
+ {0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
+ 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3},
+ {0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
+ 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f},
+ {0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
+ 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51},
+ {0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
+ 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8},
+ {0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
+ 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0},
+ {0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
+ 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84},
+ {0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
+ 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48},
+};
+
+/*
+ * S-box
+ * defined in section 2.6 S-box
+ */
+LTC_INLINE static sm4_u8_t s_sm4_sbox(sm4_u8_t a)
+{
+ return sm4_sbox_table[(a >> 4) & 0x0f][a & 0x0f];
+}
+
+/*
+ * Nonlinear transformation t
+ * defined in section 6.2 (1) Nonelinear transformation t
+ *
+ * Here should be big endian.
+ * But we just convert a 32bit word byte by byte.
+ * So it's OK if we don't convert the endian order
+ */
+LTC_INLINE static sm4_u32_t s_sm4_t(sm4_u32_t A)
+{
+ sm4_u8_t a[4];
+ sm4_u8_t b[4];
+ sm4_u32_t B;
+
+ STORE32H(A, a);
+ b[0] = s_sm4_sbox(a[0]);
+ b[1] = s_sm4_sbox(a[1]);
+ b[2] = s_sm4_sbox(a[2]);
+ b[3] = s_sm4_sbox(a[3]);
+ LOAD32H(B, b);
+ return B;
+}
+
+/*
+ * defined in section 6.2 (2) Linear transformation L
+ */
+LTC_INLINE static sm4_u32_t s_sm4_L62(sm4_u32_t B)
+{
+ return B ^ ROLc(B, 2) ^ ROLc(B, 10) ^ ROLc(B, 18) ^ ROLc(B, 24);
+}
+
+/*
+ * defined in section 6.2 Permutation T
+ */
+LTC_INLINE static sm4_u32_t s_sm4_T62(sm4_u32_t Z)
+{
+ return s_sm4_L62(s_sm4_t(Z));
+}
+
+/*
+ * defined in section 7.3 (2) The system parameter FK
+ */
+static const sm4_u32_t sm4_FK[4] = {
+ 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc
+};
+
+/*
+ * defined in section 7.3 (3) The fixed parameter CK
+ * The fixed parameter CK is used in the key expansion algorithm
+ */
+static const sm4_u32_t sm4_CK[32] =
+{
+ 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
+ 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
+ 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
+ 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
+ 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
+ 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
+ 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
+ 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,
+};
+
+/*
+ * defined in section 7.3 (1) L'
+ */
+LTC_INLINE static sm4_u32_t s_sm4_L73(sm4_u32_t B)
+{
+ return B ^ ROLc(B, 13) ^ ROLc(B, 23);
+}
+
+/*
+ * defined in section 7.3 (1) T'
+ */
+LTC_INLINE static sm4_u32_t s_sm4_T73(sm4_u32_t Z)
+{
+ return s_sm4_L73(s_sm4_t(Z));
+}
+
+/*
+ * defined in section 7.3 Key Expansion
+ */
+LTC_INLINE static void s_sm4_mk2rk(sm4_u32_t rk[32], sm4_u8_t mk[16])
+{
+ sm4_u32_t MK[4] = { 0 };
+ sm4_u32_t K[4+32] = { 0 };
+ int i;
+
+ LOAD32H(MK[0], mk );
+ LOAD32H(MK[1], mk + 4);
+ LOAD32H(MK[2], mk + 8);
+ LOAD32H(MK[3], mk + 12);
+
+ for (i = 0; i < 4; ++i)
+ K[i] = MK[i] ^ sm4_FK[i];
+ for (i = 0; i < 32; ++i)
+ K[i+4] = K[i] ^ s_sm4_T73(K[i+1] ^ K[i+2] ^ K[i+3] ^ sm4_CK[i]);
+ for (i = 0; i < 32; ++i)
+ rk[i] = K[i+4];
+}
+
+/*
+ * defined in section 6 Round Function F
+ */
+LTC_INLINE static sm4_u32_t s_sm4_F(sm4_u32_t X[4], sm4_u32_t rk)
+{
+ return X[0] ^ s_sm4_T62(X[1] ^ X[2] ^ X[3] ^ rk);
+}
+
+/*
+ * defined in section 7.1 (2) The reverse transformation
+ */
+LTC_INLINE static void s_sm4_R(sm4_u32_t Y[4], sm4_u32_t X[32+4])
+{
+ Y[0] = X[35];
+ Y[1] = X[34];
+ Y[2] = X[33];
+ Y[3] = X[32];
+}
+
+/*
+ * defined in section 7.1 (En)cryption
+ */
+LTC_INLINE static void s_sm4_crypt(sm4_u32_t Y[4], sm4_u32_t X[4+32], const sm4_u32_t rk[32])
+{
+ int i;
+
+ for (i = 0; i < 32; ++i)
+ X[i+4] = s_sm4_F(X+i, rk[i]);
+ s_sm4_R(Y, X);
+}
+
+LTC_INLINE static void s_sm4_setkey(struct sm4_key *sm4, const unsigned char *key)
+{
+ int i;
+
+ s_sm4_mk2rk(sm4->ek,(void*)key);
+ /*swap key sequence when decrypt cipher*/
+ for (i = 0; i < 32; ++i)
+ sm4->dk[i] = sm4->ek[32 - 1 - i];
+}
+
+int sm4_setup(const unsigned char *key, int keylen,
+ int num_rounds, symmetric_key *skey)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+ if (num_rounds != 0 && num_rounds != 32)
+ return CRYPT_INVALID_ROUNDS;
+ if (keylen != 16)
+ return CRYPT_INVALID_KEYSIZE;
+ s_sm4_setkey(&(skey->sm4), key);
+ return CRYPT_OK;
+}
+
+/*
+ * SM4 encryption.
+ */
+LTC_INLINE static void s_sm4_do(void *output, const void *input, const sm4_u32_t rk[32])
+{
+ sm4_u32_t Y[4];
+ sm4_u32_t X[32+4];
+
+ LOAD32H(X[0], (sm4_u8_t *)input );
+ LOAD32H(X[1], (sm4_u8_t *)input + 4);
+ LOAD32H(X[2], (sm4_u8_t *)input + 8);
+ LOAD32H(X[3], (sm4_u8_t *)input + 12);
+
+ s_sm4_crypt(Y, X, rk);
+
+ STORE32H(Y[0], (sm4_u8_t *)output );
+ STORE32H(Y[1], (sm4_u8_t *)output + 4);
+ STORE32H(Y[2], (sm4_u8_t *)output + 8);
+ STORE32H(Y[3], (sm4_u8_t *)output + 12);
+}
+
+int sm4_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
+ const symmetric_key *skey)
+{
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ s_sm4_do(ct, pt, skey->sm4.ek);
+ return CRYPT_OK;
+}
+int sm4_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
+ const symmetric_key *skey)
+{
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+ s_sm4_do(pt, ct, skey->sm4.dk);
+ return CRYPT_OK;
+}
+
+void sm4_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+int sm4_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if(*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ *keysize = 16;
+ return CRYPT_OK;
+}
+
+/*
+ * libtomcrypt interface is used
+ */
+
+#ifdef LTC_TEST
+static int sm4_self_test_ltc(void)
+{
+ int result;
+ int i;
+ int keysize;
+ symmetric_key skey;
+
+ sm4_u8_t output[16];
+ sm4_u8_t plaintext[] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ };
+ sm4_u8_t key[] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ };
+ sm4_u8_t ciphertext[] = {
+ 0x68, 0x1E, 0xDF, 0x34, 0xD2, 0x06, 0x96, 0x5E,
+ 0x86, 0xB3, 0xE9, 0x4F, 0x53, 0x6E, 0x42, 0x46,
+ };
+ sm4_u8_t ciphertext_1000000t[] = {
+ 0x59, 0x52, 0x98, 0xC7, 0xC6, 0xFD, 0x27, 0x1F,
+ 0x04, 0x02, 0xF8, 0x04, 0xC3, 0x3D, 0x3F, 0x66,
+ };
+
+ result = CRYPT_OK; /* Assume the best */
+
+ sm4_setup(key, sizeof(key), 32, &skey);
+
+ /*A.1 example 1*/
+ sm4_ecb_encrypt(plaintext, output, &skey);
+ if (compare_testvector(output, 16, ciphertext, 16, "SM4 single encryption", 0) != 0)
+ result = CRYPT_ERROR;
+
+ sm4_ecb_decrypt(ciphertext, output, &skey);
+ if (compare_testvector(output, 16, plaintext, 16, "SM4 single decryption", 0) != 0)
+ result = CRYPT_ERROR;
+
+ /*A.2 example 2*/
+ XMEMCPY(output, plaintext, 16);
+ for (i = 0; i < 1000000; ++i)
+ sm4_ecb_encrypt(output, output, &skey);
+ if (compare_testvector(output, 16, ciphertext_1000000t, 16, "SM4 1000000 times encryption", 0) != 0)
+ result = CRYPT_ERROR;
+
+ XMEMCPY(output, ciphertext_1000000t, 16);
+ for (i = 0; i < 1000000; ++i)
+ sm4_ecb_decrypt(output, output, &skey);
+ if (compare_testvector(output, 16, plaintext, 16, "SM4 1000000 times encryption", 0) != 0)
+ result = CRYPT_ERROR;
+
+ keysize = 128;
+ if (sm4_keysize(&keysize) != CRYPT_OK) {
+ fprintf(stderr, "Getting the max SM4 keysize failed\n");
+ result = CRYPT_ERROR;
+ } else if (keysize != 16) {
+ fprintf(stderr, "SM4 maximum key size is faulty:\nSHOULD be 16\nIS %d\n", keysize);
+ result = CRYPT_ERROR;
+ }
+
+ sm4_done(&skey);
+
+ return result;
+}
+#endif
+
+int sm4_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ return sm4_self_test_ltc();
+#endif
+}
+
+const struct ltc_cipher_descriptor sm4_desc = {
+ "sm4",
+ 28,
+ 16, 16, 16, 32, /* min_key_len, max_key_len, block_len, default_rounds */
+ &sm4_setup,
+ &sm4_ecb_encrypt,
+ &sm4_ecb_decrypt,
+ &sm4_test,
+ &sm4_done,
+ &sm4_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
+#endif /*LTC_SM4*/
diff --git a/Sources/libtomcrypt/ciphers/tea.c b/Sources/libtomcrypt/ciphers/tea.c
new file mode 100644
index 00000000..fc413d42
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/tea.c
@@ -0,0 +1,209 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file tea.c
+ Implementation of TEA, Steffen Jaeckel
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_TEA
+
+const struct ltc_cipher_descriptor tea_desc =
+{
+ "tea",
+ 26,
+ 16, 16, 8, 32,
+ &tea_setup,
+ &tea_ecb_encrypt,
+ &tea_ecb_decrypt,
+ &tea_test,
+ &tea_done,
+ &tea_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#define DELTA 0x9E3779B9uL
+#define SUM 0xC6EF3720uL
+
+int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* check arguments */
+ if (keylen != 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if (num_rounds != 0 && num_rounds != 32) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* load key */
+ LOAD32H(skey->tea.k[0], key+0);
+ LOAD32H(skey->tea.k[1], key+4);
+ LOAD32H(skey->tea.k[2], key+8);
+ LOAD32H(skey->tea.k[3], key+12);
+
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with TEA
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ ulong32 y, z, sum = 0;
+ const ulong32 delta = DELTA;
+ int r;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ LOAD32H(y, &pt[0]);
+ LOAD32H(z, &pt[4]);
+ for (r = 0; r < 32; r++) {
+ sum += delta;
+ y += ((z<<4) + skey->tea.k[0]) ^ (z + sum) ^ ((z>>5) + skey->tea.k[1]);
+ z += ((y<<4) + skey->tea.k[2]) ^ (y + sum) ^ ((y>>5) + skey->tea.k[3]);
+ }
+ STORE32H(y, &ct[0]);
+ STORE32H(z, &ct[4]);
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with TEA
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ ulong32 v0, v1, sum = SUM;
+ const ulong32 delta = DELTA;
+ int r;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ LOAD32H(v0, &ct[0]);
+ LOAD32H(v1, &ct[4]);
+
+ for (r = 0; r < 32; r++) {
+ v1 -= ((v0 << 4) + skey->tea.k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + skey->tea.k[3]);
+ v0 -= ((v1 << 4) + skey->tea.k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + skey->tea.k[1]);
+ sum -= delta;
+ }
+
+ STORE32H(v0, &pt[0]);
+ STORE32H(v1, &pt[4]);
+ return CRYPT_OK;
+}
+
+/**
+ Performs a self-test of the TEA block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int tea_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *key, *pt, *ct;
+ } tests[] = {
+ {
+ "00000000000000000000000000000000",
+ "0000000000000000",
+ "41ea3a0a94baa940"
+ }, {
+ "32a1e65408b63bb9214105744ec5d2e2",
+ "5ada1d89a9c3801a",
+ "dd46249e28aa0b4b"
+ }, {
+ "60388adadf70a1f5d9cb4e097d2c6c57",
+ "7a6adb4d69c53e0f",
+ "44b71215cf25368a"
+ }, {
+ "4368d2249bd0321eb7c56d5b63a1bfac",
+ "5a5d7ca2e186c41a",
+ "91f56dff7281794f"
+ }, {
+ "5c60bff27072d01c4513c5eb8f3a38ab",
+ "80d9c4adcf899635",
+ "2bb0f1b3c023ed11"
+ }
+ };
+ unsigned char ptct[2][8];
+ unsigned char tmp[2][8];
+ unsigned char key[16];
+ unsigned long l;
+ symmetric_key skey;
+ size_t i;
+ int err, y;
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+ zeromem(&skey, sizeof(skey));
+
+ l = sizeof(key);
+ if ((err = base16_decode(tests[i].key, XSTRLEN(tests[i].key), key, &l)) != CRYPT_OK) return err;
+ l = sizeof(ptct[0]);
+ if ((err = base16_decode(tests[i].pt, XSTRLEN(tests[i].pt), ptct[0], &l)) != CRYPT_OK) return err;
+ l = sizeof(ptct[1]);
+ if ((err = base16_decode(tests[i].ct, XSTRLEN(tests[i].ct), ptct[1], &l)) != CRYPT_OK) return err;
+
+ if ((err = tea_setup(key, 16, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ tea_ecb_encrypt(ptct[0], tmp[0], &skey);
+ tea_ecb_decrypt(tmp[0], tmp[1], &skey);
+
+ if (compare_testvector(tmp[0], 8, ptct[1], 8, "TEA Encrypt", i) != 0 ||
+ compare_testvector(tmp[1], 8, ptct[0], 8, "TEA Decrypt", i) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 8; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) tea_ecb_encrypt(tmp[0], tmp[0], &skey);
+ for (y = 0; y < 1000; y++) tea_ecb_decrypt(tmp[0], tmp[0], &skey);
+ for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ } /* for */
+
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void tea_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int tea_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ *keysize = 16;
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/ciphers/twofish/twofish.c b/Sources/libtomcrypt/ciphers/twofish/twofish.c
new file mode 100644
index 00000000..c006361b
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/twofish/twofish.c
@@ -0,0 +1,706 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+ /**
+ @file twofish.c
+ Implementation of Twofish by Tom St Denis
+ */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_TWOFISH
+
+/* first LTC_TWOFISH_ALL_TABLES must ensure LTC_TWOFISH_TABLES is defined */
+#ifdef LTC_TWOFISH_ALL_TABLES
+#ifndef LTC_TWOFISH_TABLES
+#define LTC_TWOFISH_TABLES
+#endif
+#endif
+
+const struct ltc_cipher_descriptor twofish_desc =
+{
+ "twofish",
+ 7,
+ 16, 32, 16, 16,
+ &twofish_setup,
+ &twofish_ecb_encrypt,
+ &twofish_ecb_decrypt,
+ &twofish_test,
+ &twofish_done,
+ &twofish_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/* the two polynomials */
+#ifndef LTC_TWOFISH_TABLES
+#define MDS_POLY 0x169
+#endif
+#ifndef LTC_TWOFISH_ALL_TABLES
+#define RS_POLY 0x14D
+#endif
+
+/* The 4x8 RS Linear Transform */
+static const unsigned char RS[4][8] = {
+ { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E },
+ { 0xA4, 0x56, 0x82, 0xF3, 0X1E, 0XC6, 0X68, 0XE5 },
+ { 0X02, 0XA1, 0XFC, 0XC1, 0X47, 0XAE, 0X3D, 0X19 },
+ { 0XA4, 0X55, 0X87, 0X5A, 0X58, 0XDB, 0X9E, 0X03 }
+};
+
+#ifdef LTC_TWOFISH_SMALL
+/* sbox usage orderings */
+static const unsigned char qord[4][5] = {
+ { 1, 1, 0, 0, 1 },
+ { 0, 1, 1, 0, 0 },
+ { 0, 0, 0, 1, 1 },
+ { 1, 0, 1, 1, 0 }
+};
+#endif /* LTC_TWOFISH_SMALL */
+
+#ifdef LTC_TWOFISH_TABLES
+
+#define LTC_TWOFISH_TAB_C
+#include "twofish_tab.c"
+
+#define sbox(i, x) ((ulong32)SBOX[i][(x)&255])
+
+#else
+
+/* The Q-box tables */
+static const unsigned char qbox[2][4][16] = {
+{
+ { 0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4 },
+ { 0xE, 0XC, 0XB, 0X8, 0X1, 0X2, 0X3, 0X5, 0XF, 0X4, 0XA, 0X6, 0X7, 0X0, 0X9, 0XD },
+ { 0XB, 0XA, 0X5, 0XE, 0X6, 0XD, 0X9, 0X0, 0XC, 0X8, 0XF, 0X3, 0X2, 0X4, 0X7, 0X1 },
+ { 0XD, 0X7, 0XF, 0X4, 0X1, 0X2, 0X6, 0XE, 0X9, 0XB, 0X3, 0X0, 0X8, 0X5, 0XC, 0XA }
+},
+{
+ { 0X2, 0X8, 0XB, 0XD, 0XF, 0X7, 0X6, 0XE, 0X3, 0X1, 0X9, 0X4, 0X0, 0XA, 0XC, 0X5 },
+ { 0X1, 0XE, 0X2, 0XB, 0X4, 0XC, 0X3, 0X7, 0X6, 0XD, 0XA, 0X5, 0XF, 0X9, 0X0, 0X8 },
+ { 0X4, 0XC, 0X7, 0X5, 0X1, 0X6, 0X9, 0XA, 0X0, 0XE, 0XD, 0X8, 0X2, 0XB, 0X3, 0XF },
+ { 0xB, 0X9, 0X5, 0X1, 0XC, 0X3, 0XD, 0XE, 0X6, 0X4, 0X7, 0XF, 0X2, 0X0, 0X8, 0XA }
+}
+};
+
+/* computes S_i[x] */
+#ifdef LTC_CLEAN_STACK
+static ulong32 s_sbox(int i, ulong32 x)
+#else
+static ulong32 sbox(int i, ulong32 x)
+#endif
+{
+ unsigned char a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,y;
+
+ /* a0,b0 = [x/16], x mod 16 */
+ a0 = (unsigned char)((x>>4)&15);
+ b0 = (unsigned char)((x)&15);
+
+ /* a1 = a0 ^ b0 */
+ a1 = a0 ^ b0;
+
+ /* b1 = a0 ^ ROR(b0, 1) ^ 8a0 */
+ b1 = (a0 ^ ((b0<<3)|(b0>>1)) ^ (a0<<3)) & 15;
+
+ /* a2,b2 = t0[a1], t1[b1] */
+ a2 = qbox[i][0][(int)a1];
+ b2 = qbox[i][1][(int)b1];
+
+ /* a3 = a2 ^ b2 */
+ a3 = a2 ^ b2;
+
+ /* b3 = a2 ^ ROR(b2, 1) ^ 8a2 */
+ b3 = (a2 ^ ((b2<<3)|(b2>>1)) ^ (a2<<3)) & 15;
+
+ /* a4,b4 = t2[a3], t3[b3] */
+ a4 = qbox[i][2][(int)a3];
+ b4 = qbox[i][3][(int)b3];
+
+ /* y = 16b4 + a4 */
+ y = (b4 << 4) + a4;
+
+ /* return result */
+ return (ulong32)y;
+}
+
+#ifdef LTC_CLEAN_STACK
+static ulong32 sbox(int i, ulong32 x)
+{
+ ulong32 y;
+ y = s_sbox(i, x);
+ burn_stack(sizeof(unsigned char) * 11);
+ return y;
+}
+#endif /* LTC_CLEAN_STACK */
+
+#endif /* LTC_TWOFISH_TABLES */
+
+/* computes ab mod p */
+static ulong32 gf_mult(ulong32 a, ulong32 b, ulong32 p)
+{
+ ulong32 result, B[2], P[2];
+
+ P[1] = p;
+ B[1] = b;
+ result = P[0] = B[0] = 0;
+
+ /* unrolled branchless GF multiplier */
+ result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1);
+ result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1);
+ result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1);
+ result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1);
+ result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1);
+ result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1);
+ result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1);
+ result ^= B[a&1];
+
+ return result;
+}
+
+/* computes [y0 y1 y2 y3] = MDS . [x0] */
+#ifndef LTC_TWOFISH_TABLES
+static ulong32 mds_column_mult(unsigned char in, int col)
+{
+ ulong32 x01, x5B, xEF;
+
+ x01 = in;
+ x5B = gf_mult(in, 0x5B, MDS_POLY);
+ xEF = gf_mult(in, 0xEF, MDS_POLY);
+
+ switch (col) {
+ case 0:
+ return (x01 << 0 ) |
+ (x5B << 8 ) |
+ (xEF << 16) |
+ (xEF << 24);
+ case 1:
+ return (xEF << 0 ) |
+ (xEF << 8 ) |
+ (x5B << 16) |
+ (x01 << 24);
+ case 2:
+ return (x5B << 0 ) |
+ (xEF << 8 ) |
+ (x01 << 16) |
+ (xEF << 24);
+ case 3:
+ return (x5B << 0 ) |
+ (x01 << 8 ) |
+ (xEF << 16) |
+ (x5B << 24);
+ }
+ /* avoid warnings, we'd never get here normally but just to calm compiler warnings... */
+ return 0;
+}
+
+#else /* !LTC_TWOFISH_TABLES */
+
+#define mds_column_mult(x, i) mds_tab[i][x]
+
+#endif /* LTC_TWOFISH_TABLES */
+
+/* Computes [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] */
+static void mds_mult(const unsigned char *in, unsigned char *out)
+{
+ int x;
+ ulong32 tmp;
+ for (tmp = x = 0; x < 4; x++) {
+ tmp ^= mds_column_mult(in[x], x);
+ }
+ STORE32L(tmp, out);
+}
+
+#ifdef LTC_TWOFISH_ALL_TABLES
+/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */
+static void rs_mult(const unsigned char *in, unsigned char *out)
+{
+ ulong32 tmp;
+ tmp = rs_tab0[in[0]] ^ rs_tab1[in[1]] ^ rs_tab2[in[2]] ^ rs_tab3[in[3]] ^
+ rs_tab4[in[4]] ^ rs_tab5[in[5]] ^ rs_tab6[in[6]] ^ rs_tab7[in[7]];
+ STORE32L(tmp, out);
+}
+
+#else /* !LTC_TWOFISH_ALL_TABLES */
+
+/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */
+static void rs_mult(const unsigned char *in, unsigned char *out)
+{
+ int x, y;
+ for (x = 0; x < 4; x++) {
+ out[x] = 0;
+ for (y = 0; y < 8; y++) {
+ out[x] ^= gf_mult(in[y], RS[x][y], RS_POLY);
+ }
+ }
+}
+
+#endif
+
+/* computes h(x) */
+static void h_func(const unsigned char *in, unsigned char *out, const unsigned char *M, int k, int offset)
+{
+ int x;
+ unsigned char y[4];
+ for (x = 0; x < 4; x++) {
+ y[x] = in[x];
+ }
+ switch (k) {
+ case 4:
+ y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (6 + offset) + 0]);
+ y[1] = (unsigned char)(sbox(0, (ulong32)y[1]) ^ M[4 * (6 + offset) + 1]);
+ y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (6 + offset) + 2]);
+ y[3] = (unsigned char)(sbox(1, (ulong32)y[3]) ^ M[4 * (6 + offset) + 3]);
+ /* FALLTHROUGH */
+ case 3:
+ y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (4 + offset) + 0]);
+ y[1] = (unsigned char)(sbox(1, (ulong32)y[1]) ^ M[4 * (4 + offset) + 1]);
+ y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (4 + offset) + 2]);
+ y[3] = (unsigned char)(sbox(0, (ulong32)y[3]) ^ M[4 * (4 + offset) + 3]);
+ /* FALLTHROUGH */
+ case 2:
+ y[0] = (unsigned char)(sbox(1, sbox(0, sbox(0, (ulong32)y[0]) ^ M[4 * (2 + offset) + 0]) ^ M[4 * (0 + offset) + 0]));
+ y[1] = (unsigned char)(sbox(0, sbox(0, sbox(1, (ulong32)y[1]) ^ M[4 * (2 + offset) + 1]) ^ M[4 * (0 + offset) + 1]));
+ y[2] = (unsigned char)(sbox(1, sbox(1, sbox(0, (ulong32)y[2]) ^ M[4 * (2 + offset) + 2]) ^ M[4 * (0 + offset) + 2]));
+ y[3] = (unsigned char)(sbox(0, sbox(1, sbox(1, (ulong32)y[3]) ^ M[4 * (2 + offset) + 3]) ^ M[4 * (0 + offset) + 3]));
+ /* FALLTHROUGH */
+ }
+ mds_mult(y, out);
+}
+
+#ifndef LTC_TWOFISH_SMALL
+
+/* for GCC we don't use pointer aliases */
+#if defined(__GNUC__)
+ #define S1 skey->twofish.S[0]
+ #define S2 skey->twofish.S[1]
+ #define S3 skey->twofish.S[2]
+ #define S4 skey->twofish.S[3]
+#endif
+
+/* the G function */
+#define g_func(x, dum) (S1[LTC_BYTE(x,0)] ^ S2[LTC_BYTE(x,1)] ^ S3[LTC_BYTE(x,2)] ^ S4[LTC_BYTE(x,3)])
+#define g1_func(x, dum) (S2[LTC_BYTE(x,0)] ^ S3[LTC_BYTE(x,1)] ^ S4[LTC_BYTE(x,2)] ^ S1[LTC_BYTE(x,3)])
+
+#else
+
+#ifdef LTC_CLEAN_STACK
+static ulong32 s_g_func(ulong32 x, const symmetric_key *key)
+#else
+static ulong32 g_func(ulong32 x, const symmetric_key *key)
+#endif
+{
+ unsigned char g, i, y, z;
+ ulong32 res;
+
+ res = 0;
+ for (y = 0; y < 4; y++) {
+ z = key->twofish.start;
+
+ /* do unkeyed substitution */
+ g = sbox(qord[y][z++], (x >> (8*y)) & 255);
+
+ /* first subkey */
+ i = 0;
+
+ /* do key mixing+sbox until z==5 */
+ while (z != 5) {
+ g = g ^ key->twofish.S[4*i++ + y];
+ g = sbox(qord[y][z++], g);
+ }
+
+ /* multiply g by a column of the MDS */
+ res ^= mds_column_mult(g, y);
+ }
+ return res;
+}
+
+#define g1_func(x, key) g_func(ROLc(x, 8), key)
+
+#ifdef LTC_CLEAN_STACK
+static ulong32 g_func(ulong32 x, const symmetric_key *key)
+{
+ ulong32 y;
+ y = s_g_func(x, key);
+ burn_stack(sizeof(unsigned char) * 4 + sizeof(ulong32));
+ return y;
+}
+#endif /* LTC_CLEAN_STACK */
+
+#endif /* LTC_TWOFISH_SMALL */
+
+ /**
+ Initialize the Twofish block cipher
+ @param key The symmetric key you wish to pass
+ @param keylen The key length in bytes
+ @param num_rounds The number of rounds desired (0 for default)
+ @param skey The key in as scheduled by this function.
+ @return CRYPT_OK if successful
+ */
+#ifdef LTC_CLEAN_STACK
+static int s_twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+#ifndef LTC_TWOFISH_SMALL
+ unsigned char S[4*4], tmpx0, tmpx1;
+#endif
+ int k, x, y;
+ unsigned char tmp[4], tmp2[4], M[8*4];
+ ulong32 A, B;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* invalid arguments? */
+ if (num_rounds != 16 && num_rounds != 0) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ if (keylen != 16 && keylen != 24 && keylen != 32) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ /* k = keysize/64 [but since our keysize is in bytes...] */
+ k = keylen / 8;
+
+ /* copy the key into M */
+ for (x = 0; x < keylen; x++) {
+ M[x] = key[x] & 255;
+ }
+
+ /* create the S[..] words */
+#ifndef LTC_TWOFISH_SMALL
+ for (x = 0; x < k; x++) {
+ rs_mult(M+(x*8), S+(x*4));
+ }
+#else
+ for (x = 0; x < k; x++) {
+ rs_mult(M+(x*8), skey->twofish.S+(x*4));
+ }
+#endif
+
+ /* make subkeys */
+ for (x = 0; x < 20; x++) {
+ /* A = h(p * 2x, Me) */
+ for (y = 0; y < 4; y++) {
+ tmp[y] = x+x;
+ }
+ h_func(tmp, tmp2, M, k, 0);
+ LOAD32L(A, tmp2);
+
+ /* B = ROL(h(p * (2x + 1), Mo), 8) */
+ for (y = 0; y < 4; y++) {
+ tmp[y] = (unsigned char)(x+x+1);
+ }
+ h_func(tmp, tmp2, M, k, 1);
+ LOAD32L(B, tmp2);
+ B = ROLc(B, 8);
+
+ /* K[2i] = A + B */
+ skey->twofish.K[x+x] = (A + B) & 0xFFFFFFFFUL;
+
+ /* K[2i+1] = (A + 2B) <<< 9 */
+ skey->twofish.K[x+x+1] = ROLc(B + B + A, 9);
+ }
+
+#ifndef LTC_TWOFISH_SMALL
+ /* make the sboxes (large ram variant) */
+ if (k == 2) {
+ for (x = 0; x < 256; x++) {
+ tmpx0 = (unsigned char)sbox(0, x);
+ tmpx1 = (unsigned char)sbox(1, x);
+ skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, tmpx0 ^ S[0]) ^ S[4])),0);
+ skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, tmpx1 ^ S[1]) ^ S[5])),1);
+ skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, tmpx0 ^ S[2]) ^ S[6])),2);
+ skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, tmpx1 ^ S[3]) ^ S[7])),3);
+ }
+ } else if (k == 3) {
+ for (x = 0; x < 256; x++) {
+ tmpx0 = (unsigned char)sbox(0, x);
+ tmpx1 = (unsigned char)sbox(1, x);
+ skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, tmpx1 ^ S[0]) ^ S[4]) ^ S[8])),0);
+ skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, tmpx1 ^ S[1]) ^ S[5]) ^ S[9])),1);
+ skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10])),2);
+ skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, tmpx0 ^ S[3]) ^ S[7]) ^ S[11])),3);
+ }
+ } else {
+ for (x = 0; x < 256; x++) {
+ tmpx0 = (unsigned char)sbox(0, x);
+ tmpx1 = (unsigned char)sbox(1, x);
+ skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, sbox(1, tmpx1 ^ S[0]) ^ S[4]) ^ S[8]) ^ S[12])),0);
+ skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, sbox(1, tmpx0 ^ S[1]) ^ S[5]) ^ S[9]) ^ S[13])),1);
+ skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10]) ^ S[14])),2);
+ skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, sbox(0, tmpx1 ^ S[3]) ^ S[7]) ^ S[11]) ^ S[15])),3);
+ }
+ }
+#else
+ /* where to start in the sbox layers */
+ /* small ram variant */
+ switch (k) {
+ case 4 : skey->twofish.start = 0; break;
+ case 3 : skey->twofish.start = 1; break;
+ default: skey->twofish.start = 2; break;
+ }
+#endif
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ int x;
+ x = s_twofish_setup(key, keylen, num_rounds, skey);
+ burn_stack(sizeof(int) * 7 + sizeof(unsigned char) * 56 + sizeof(ulong32) * 2);
+ return x;
+}
+#endif
+
+/**
+ Encrypts a block of text with Twofish
+ @param pt The input plaintext (16 bytes)
+ @param ct The output ciphertext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+ ulong32 a,b,c,d,ta,tb,tc,td,t1,t2;
+ const ulong32 *k;
+ int r;
+#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__)
+ const ulong32 *S1, *S2, *S3, *S4;
+#endif
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__)
+ S1 = skey->twofish.S[0];
+ S2 = skey->twofish.S[1];
+ S3 = skey->twofish.S[2];
+ S4 = skey->twofish.S[3];
+#endif
+
+ LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]);
+ LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]);
+ a ^= skey->twofish.K[0];
+ b ^= skey->twofish.K[1];
+ c ^= skey->twofish.K[2];
+ d ^= skey->twofish.K[3];
+
+ k = skey->twofish.K + 8;
+ for (r = 8; r != 0; --r) {
+ t2 = g1_func(b, skey);
+ t1 = g_func(a, skey) + t2;
+ c = RORc(c ^ (t1 + k[0]), 1);
+ d = ROLc(d, 1) ^ (t2 + t1 + k[1]);
+
+ t2 = g1_func(d, skey);
+ t1 = g_func(c, skey) + t2;
+ a = RORc(a ^ (t1 + k[2]), 1);
+ b = ROLc(b, 1) ^ (t2 + t1 + k[3]);
+ k += 4;
+ }
+
+ /* output with "undo last swap" */
+ ta = c ^ skey->twofish.K[4];
+ tb = d ^ skey->twofish.K[5];
+ tc = a ^ skey->twofish.K[6];
+ td = b ^ skey->twofish.K[7];
+
+ /* store output */
+ STORE32L(ta,&ct[0]); STORE32L(tb,&ct[4]);
+ STORE32L(tc,&ct[8]); STORE32L(td,&ct[12]);
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ int err = s_twofish_ecb_encrypt(pt, ct, skey);
+ burn_stack(sizeof(ulong32) * 10 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Decrypts a block of text with Twofish
+ @param ct The input ciphertext (16 bytes)
+ @param pt The output plaintext (16 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+ ulong32 a,b,c,d,ta,tb,tc,td,t1,t2;
+ const ulong32 *k;
+ int r;
+#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__)
+ const ulong32 *S1, *S2, *S3, *S4;
+#endif
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__)
+ S1 = skey->twofish.S[0];
+ S2 = skey->twofish.S[1];
+ S3 = skey->twofish.S[2];
+ S4 = skey->twofish.S[3];
+#endif
+
+ /* load input */
+ LOAD32L(ta,&ct[0]); LOAD32L(tb,&ct[4]);
+ LOAD32L(tc,&ct[8]); LOAD32L(td,&ct[12]);
+
+ /* undo undo final swap */
+ a = tc ^ skey->twofish.K[6];
+ b = td ^ skey->twofish.K[7];
+ c = ta ^ skey->twofish.K[4];
+ d = tb ^ skey->twofish.K[5];
+
+ k = skey->twofish.K + 36;
+ for (r = 8; r != 0; --r) {
+ t2 = g1_func(d, skey);
+ t1 = g_func(c, skey) + t2;
+ a = ROLc(a, 1) ^ (t1 + k[2]);
+ b = RORc(b ^ (t2 + t1 + k[3]), 1);
+
+ t2 = g1_func(b, skey);
+ t1 = g_func(a, skey) + t2;
+ c = ROLc(c, 1) ^ (t1 + k[0]);
+ d = RORc(d ^ (t2 + t1 + k[1]), 1);
+ k -= 4;
+ }
+
+ /* pre-white */
+ a ^= skey->twofish.K[0];
+ b ^= skey->twofish.K[1];
+ c ^= skey->twofish.K[2];
+ d ^= skey->twofish.K[3];
+
+ /* store */
+ STORE32L(a, &pt[0]); STORE32L(b, &pt[4]);
+ STORE32L(c, &pt[8]); STORE32L(d, &pt[12]);
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ int err = s_twofish_ecb_decrypt(ct, pt, skey);
+ burn_stack(sizeof(ulong32) * 10 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Performs a self-test of the Twofish block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int twofish_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ int keylen;
+ unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+ { 16,
+ { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,
+ 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A },
+ { 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E,
+ 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 },
+ { 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85,
+ 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 }
+ }, {
+ 24,
+ { 0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36,
+ 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
+ 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 },
+ { 0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5,
+ 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 },
+ { 0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45,
+ 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 }
+ }, {
+ 32,
+ { 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46,
+ 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
+ 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B,
+ 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F },
+ { 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F,
+ 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 },
+ { 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97,
+ 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA }
+ }
+};
+
+
+ symmetric_key key;
+ unsigned char tmp[2][16];
+ int err, i, y;
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ if ((err = twofish_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+ twofish_ecb_encrypt(tests[i].pt, tmp[0], &key);
+ twofish_ecb_decrypt(tmp[0], tmp[1], &key);
+ if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Twofish Encrypt", i) != 0 ||
+ compare_testvector(tmp[1], 16, tests[i].pt, 16, "Twofish Decrypt", i) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 16; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) twofish_ecb_encrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 1000; y++) twofish_ecb_decrypt(tmp[0], tmp[0], &key);
+ for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void twofish_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int twofish_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize);
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ if (*keysize < 24) {
+ *keysize = 16;
+ return CRYPT_OK;
+ }
+ if (*keysize < 32) {
+ *keysize = 24;
+ return CRYPT_OK;
+ }
+ *keysize = 32;
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/ciphers/twofish/twofish_tab.c b/Sources/libtomcrypt/ciphers/twofish/twofish_tab.c
new file mode 100644
index 00000000..e52d2847
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/twofish/twofish_tab.c
@@ -0,0 +1,486 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+ /**
+ @file twofish_tab.c
+ Twofish tables, Tom St Denis
+ */
+#ifdef LTC_TWOFISH_TABLES
+#ifdef LTC_TWOFISH_TAB_C
+
+/* pre generated 8x8 tables from the four 4x4s */
+static const unsigned char SBOX[2][256] = {
+{
+ 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92,
+ 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98,
+ 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13,
+ 0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23,
+ 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01,
+ 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe,
+ 0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c,
+ 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
+ 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95,
+ 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5,
+ 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9,
+ 0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8,
+ 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d,
+ 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11,
+ 0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c,
+ 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
+ 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87,
+ 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f,
+ 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e,
+ 0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02,
+ 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7,
+ 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12,
+ 0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc,
+ 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
+ 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d,
+ 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0},
+{
+ 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3,
+ 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd,
+ 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa,
+ 0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d,
+ 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84,
+ 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54,
+ 0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60,
+ 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
+ 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3,
+ 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff,
+ 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7,
+ 0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9,
+ 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94,
+ 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c,
+ 0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76,
+ 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
+ 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23,
+ 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e,
+ 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f,
+ 0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5,
+ 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e,
+ 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34,
+ 0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4,
+ 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
+ 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25,
+ 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91}
+};
+
+/* the 4x4 MDS in a nicer format */
+static const ulong32 mds_tab[4][256] = {
+{
+0x00000000UL, 0xefef5b01UL, 0xb7b7b602UL, 0x5858ed03UL, 0x07070504UL, 0xe8e85e05UL, 0xb0b0b306UL, 0x5f5fe807UL,
+0x0e0e0a08UL, 0xe1e15109UL, 0xb9b9bc0aUL, 0x5656e70bUL, 0x09090f0cUL, 0xe6e6540dUL, 0xbebeb90eUL, 0x5151e20fUL,
+0x1c1c1410UL, 0xf3f34f11UL, 0xababa212UL, 0x4444f913UL, 0x1b1b1114UL, 0xf4f44a15UL, 0xacaca716UL, 0x4343fc17UL,
+0x12121e18UL, 0xfdfd4519UL, 0xa5a5a81aUL, 0x4a4af31bUL, 0x15151b1cUL, 0xfafa401dUL, 0xa2a2ad1eUL, 0x4d4df61fUL,
+0x38382820UL, 0xd7d77321UL, 0x8f8f9e22UL, 0x6060c523UL, 0x3f3f2d24UL, 0xd0d07625UL, 0x88889b26UL, 0x6767c027UL,
+0x36362228UL, 0xd9d97929UL, 0x8181942aUL, 0x6e6ecf2bUL, 0x3131272cUL, 0xdede7c2dUL, 0x8686912eUL, 0x6969ca2fUL,
+0x24243c30UL, 0xcbcb6731UL, 0x93938a32UL, 0x7c7cd133UL, 0x23233934UL, 0xcccc6235UL, 0x94948f36UL, 0x7b7bd437UL,
+0x2a2a3638UL, 0xc5c56d39UL, 0x9d9d803aUL, 0x7272db3bUL, 0x2d2d333cUL, 0xc2c2683dUL, 0x9a9a853eUL, 0x7575de3fUL,
+0x70705040UL, 0x9f9f0b41UL, 0xc7c7e642UL, 0x2828bd43UL, 0x77775544UL, 0x98980e45UL, 0xc0c0e346UL, 0x2f2fb847UL,
+0x7e7e5a48UL, 0x91910149UL, 0xc9c9ec4aUL, 0x2626b74bUL, 0x79795f4cUL, 0x9696044dUL, 0xcecee94eUL, 0x2121b24fUL,
+0x6c6c4450UL, 0x83831f51UL, 0xdbdbf252UL, 0x3434a953UL, 0x6b6b4154UL, 0x84841a55UL, 0xdcdcf756UL, 0x3333ac57UL,
+0x62624e58UL, 0x8d8d1559UL, 0xd5d5f85aUL, 0x3a3aa35bUL, 0x65654b5cUL, 0x8a8a105dUL, 0xd2d2fd5eUL, 0x3d3da65fUL,
+0x48487860UL, 0xa7a72361UL, 0xffffce62UL, 0x10109563UL, 0x4f4f7d64UL, 0xa0a02665UL, 0xf8f8cb66UL, 0x17179067UL,
+0x46467268UL, 0xa9a92969UL, 0xf1f1c46aUL, 0x1e1e9f6bUL, 0x4141776cUL, 0xaeae2c6dUL, 0xf6f6c16eUL, 0x19199a6fUL,
+0x54546c70UL, 0xbbbb3771UL, 0xe3e3da72UL, 0x0c0c8173UL, 0x53536974UL, 0xbcbc3275UL, 0xe4e4df76UL, 0x0b0b8477UL,
+0x5a5a6678UL, 0xb5b53d79UL, 0xededd07aUL, 0x02028b7bUL, 0x5d5d637cUL, 0xb2b2387dUL, 0xeaead57eUL, 0x05058e7fUL,
+0xe0e0a080UL, 0x0f0ffb81UL, 0x57571682UL, 0xb8b84d83UL, 0xe7e7a584UL, 0x0808fe85UL, 0x50501386UL, 0xbfbf4887UL,
+0xeeeeaa88UL, 0x0101f189UL, 0x59591c8aUL, 0xb6b6478bUL, 0xe9e9af8cUL, 0x0606f48dUL, 0x5e5e198eUL, 0xb1b1428fUL,
+0xfcfcb490UL, 0x1313ef91UL, 0x4b4b0292UL, 0xa4a45993UL, 0xfbfbb194UL, 0x1414ea95UL, 0x4c4c0796UL, 0xa3a35c97UL,
+0xf2f2be98UL, 0x1d1de599UL, 0x4545089aUL, 0xaaaa539bUL, 0xf5f5bb9cUL, 0x1a1ae09dUL, 0x42420d9eUL, 0xadad569fUL,
+0xd8d888a0UL, 0x3737d3a1UL, 0x6f6f3ea2UL, 0x808065a3UL, 0xdfdf8da4UL, 0x3030d6a5UL, 0x68683ba6UL, 0x878760a7UL,
+0xd6d682a8UL, 0x3939d9a9UL, 0x616134aaUL, 0x8e8e6fabUL, 0xd1d187acUL, 0x3e3edcadUL, 0x666631aeUL, 0x89896aafUL,
+0xc4c49cb0UL, 0x2b2bc7b1UL, 0x73732ab2UL, 0x9c9c71b3UL, 0xc3c399b4UL, 0x2c2cc2b5UL, 0x74742fb6UL, 0x9b9b74b7UL,
+0xcaca96b8UL, 0x2525cdb9UL, 0x7d7d20baUL, 0x92927bbbUL, 0xcdcd93bcUL, 0x2222c8bdUL, 0x7a7a25beUL, 0x95957ebfUL,
+0x9090f0c0UL, 0x7f7fabc1UL, 0x272746c2UL, 0xc8c81dc3UL, 0x9797f5c4UL, 0x7878aec5UL, 0x202043c6UL, 0xcfcf18c7UL,
+0x9e9efac8UL, 0x7171a1c9UL, 0x29294ccaUL, 0xc6c617cbUL, 0x9999ffccUL, 0x7676a4cdUL, 0x2e2e49ceUL, 0xc1c112cfUL,
+0x8c8ce4d0UL, 0x6363bfd1UL, 0x3b3b52d2UL, 0xd4d409d3UL, 0x8b8be1d4UL, 0x6464bad5UL, 0x3c3c57d6UL, 0xd3d30cd7UL,
+0x8282eed8UL, 0x6d6db5d9UL, 0x353558daUL, 0xdada03dbUL, 0x8585ebdcUL, 0x6a6ab0ddUL, 0x32325ddeUL, 0xdddd06dfUL,
+0xa8a8d8e0UL, 0x474783e1UL, 0x1f1f6ee2UL, 0xf0f035e3UL, 0xafafdde4UL, 0x404086e5UL, 0x18186be6UL, 0xf7f730e7UL,
+0xa6a6d2e8UL, 0x494989e9UL, 0x111164eaUL, 0xfefe3febUL, 0xa1a1d7ecUL, 0x4e4e8cedUL, 0x161661eeUL, 0xf9f93aefUL,
+0xb4b4ccf0UL, 0x5b5b97f1UL, 0x03037af2UL, 0xecec21f3UL, 0xb3b3c9f4UL, 0x5c5c92f5UL, 0x04047ff6UL, 0xebeb24f7UL,
+0xbabac6f8UL, 0x55559df9UL, 0x0d0d70faUL, 0xe2e22bfbUL, 0xbdbdc3fcUL, 0x525298fdUL, 0x0a0a75feUL, 0xe5e52effUL
+},
+{
+0x00000000UL, 0x015befefUL, 0x02b6b7b7UL, 0x03ed5858UL, 0x04050707UL, 0x055ee8e8UL, 0x06b3b0b0UL, 0x07e85f5fUL,
+0x080a0e0eUL, 0x0951e1e1UL, 0x0abcb9b9UL, 0x0be75656UL, 0x0c0f0909UL, 0x0d54e6e6UL, 0x0eb9bebeUL, 0x0fe25151UL,
+0x10141c1cUL, 0x114ff3f3UL, 0x12a2ababUL, 0x13f94444UL, 0x14111b1bUL, 0x154af4f4UL, 0x16a7acacUL, 0x17fc4343UL,
+0x181e1212UL, 0x1945fdfdUL, 0x1aa8a5a5UL, 0x1bf34a4aUL, 0x1c1b1515UL, 0x1d40fafaUL, 0x1eada2a2UL, 0x1ff64d4dUL,
+0x20283838UL, 0x2173d7d7UL, 0x229e8f8fUL, 0x23c56060UL, 0x242d3f3fUL, 0x2576d0d0UL, 0x269b8888UL, 0x27c06767UL,
+0x28223636UL, 0x2979d9d9UL, 0x2a948181UL, 0x2bcf6e6eUL, 0x2c273131UL, 0x2d7cdedeUL, 0x2e918686UL, 0x2fca6969UL,
+0x303c2424UL, 0x3167cbcbUL, 0x328a9393UL, 0x33d17c7cUL, 0x34392323UL, 0x3562ccccUL, 0x368f9494UL, 0x37d47b7bUL,
+0x38362a2aUL, 0x396dc5c5UL, 0x3a809d9dUL, 0x3bdb7272UL, 0x3c332d2dUL, 0x3d68c2c2UL, 0x3e859a9aUL, 0x3fde7575UL,
+0x40507070UL, 0x410b9f9fUL, 0x42e6c7c7UL, 0x43bd2828UL, 0x44557777UL, 0x450e9898UL, 0x46e3c0c0UL, 0x47b82f2fUL,
+0x485a7e7eUL, 0x49019191UL, 0x4aecc9c9UL, 0x4bb72626UL, 0x4c5f7979UL, 0x4d049696UL, 0x4ee9ceceUL, 0x4fb22121UL,
+0x50446c6cUL, 0x511f8383UL, 0x52f2dbdbUL, 0x53a93434UL, 0x54416b6bUL, 0x551a8484UL, 0x56f7dcdcUL, 0x57ac3333UL,
+0x584e6262UL, 0x59158d8dUL, 0x5af8d5d5UL, 0x5ba33a3aUL, 0x5c4b6565UL, 0x5d108a8aUL, 0x5efdd2d2UL, 0x5fa63d3dUL,
+0x60784848UL, 0x6123a7a7UL, 0x62ceffffUL, 0x63951010UL, 0x647d4f4fUL, 0x6526a0a0UL, 0x66cbf8f8UL, 0x67901717UL,
+0x68724646UL, 0x6929a9a9UL, 0x6ac4f1f1UL, 0x6b9f1e1eUL, 0x6c774141UL, 0x6d2caeaeUL, 0x6ec1f6f6UL, 0x6f9a1919UL,
+0x706c5454UL, 0x7137bbbbUL, 0x72dae3e3UL, 0x73810c0cUL, 0x74695353UL, 0x7532bcbcUL, 0x76dfe4e4UL, 0x77840b0bUL,
+0x78665a5aUL, 0x793db5b5UL, 0x7ad0ededUL, 0x7b8b0202UL, 0x7c635d5dUL, 0x7d38b2b2UL, 0x7ed5eaeaUL, 0x7f8e0505UL,
+0x80a0e0e0UL, 0x81fb0f0fUL, 0x82165757UL, 0x834db8b8UL, 0x84a5e7e7UL, 0x85fe0808UL, 0x86135050UL, 0x8748bfbfUL,
+0x88aaeeeeUL, 0x89f10101UL, 0x8a1c5959UL, 0x8b47b6b6UL, 0x8cafe9e9UL, 0x8df40606UL, 0x8e195e5eUL, 0x8f42b1b1UL,
+0x90b4fcfcUL, 0x91ef1313UL, 0x92024b4bUL, 0x9359a4a4UL, 0x94b1fbfbUL, 0x95ea1414UL, 0x96074c4cUL, 0x975ca3a3UL,
+0x98bef2f2UL, 0x99e51d1dUL, 0x9a084545UL, 0x9b53aaaaUL, 0x9cbbf5f5UL, 0x9de01a1aUL, 0x9e0d4242UL, 0x9f56adadUL,
+0xa088d8d8UL, 0xa1d33737UL, 0xa23e6f6fUL, 0xa3658080UL, 0xa48ddfdfUL, 0xa5d63030UL, 0xa63b6868UL, 0xa7608787UL,
+0xa882d6d6UL, 0xa9d93939UL, 0xaa346161UL, 0xab6f8e8eUL, 0xac87d1d1UL, 0xaddc3e3eUL, 0xae316666UL, 0xaf6a8989UL,
+0xb09cc4c4UL, 0xb1c72b2bUL, 0xb22a7373UL, 0xb3719c9cUL, 0xb499c3c3UL, 0xb5c22c2cUL, 0xb62f7474UL, 0xb7749b9bUL,
+0xb896cacaUL, 0xb9cd2525UL, 0xba207d7dUL, 0xbb7b9292UL, 0xbc93cdcdUL, 0xbdc82222UL, 0xbe257a7aUL, 0xbf7e9595UL,
+0xc0f09090UL, 0xc1ab7f7fUL, 0xc2462727UL, 0xc31dc8c8UL, 0xc4f59797UL, 0xc5ae7878UL, 0xc6432020UL, 0xc718cfcfUL,
+0xc8fa9e9eUL, 0xc9a17171UL, 0xca4c2929UL, 0xcb17c6c6UL, 0xccff9999UL, 0xcda47676UL, 0xce492e2eUL, 0xcf12c1c1UL,
+0xd0e48c8cUL, 0xd1bf6363UL, 0xd2523b3bUL, 0xd309d4d4UL, 0xd4e18b8bUL, 0xd5ba6464UL, 0xd6573c3cUL, 0xd70cd3d3UL,
+0xd8ee8282UL, 0xd9b56d6dUL, 0xda583535UL, 0xdb03dadaUL, 0xdceb8585UL, 0xddb06a6aUL, 0xde5d3232UL, 0xdf06ddddUL,
+0xe0d8a8a8UL, 0xe1834747UL, 0xe26e1f1fUL, 0xe335f0f0UL, 0xe4ddafafUL, 0xe5864040UL, 0xe66b1818UL, 0xe730f7f7UL,
+0xe8d2a6a6UL, 0xe9894949UL, 0xea641111UL, 0xeb3ffefeUL, 0xecd7a1a1UL, 0xed8c4e4eUL, 0xee611616UL, 0xef3af9f9UL,
+0xf0ccb4b4UL, 0xf1975b5bUL, 0xf27a0303UL, 0xf321ececUL, 0xf4c9b3b3UL, 0xf5925c5cUL, 0xf67f0404UL, 0xf724ebebUL,
+0xf8c6babaUL, 0xf99d5555UL, 0xfa700d0dUL, 0xfb2be2e2UL, 0xfcc3bdbdUL, 0xfd985252UL, 0xfe750a0aUL, 0xff2ee5e5UL
+},
+{
+0x00000000UL, 0xef01ef5bUL, 0xb702b7b6UL, 0x580358edUL, 0x07040705UL, 0xe805e85eUL, 0xb006b0b3UL, 0x5f075fe8UL,
+0x0e080e0aUL, 0xe109e151UL, 0xb90ab9bcUL, 0x560b56e7UL, 0x090c090fUL, 0xe60de654UL, 0xbe0ebeb9UL, 0x510f51e2UL,
+0x1c101c14UL, 0xf311f34fUL, 0xab12aba2UL, 0x441344f9UL, 0x1b141b11UL, 0xf415f44aUL, 0xac16aca7UL, 0x431743fcUL,
+0x1218121eUL, 0xfd19fd45UL, 0xa51aa5a8UL, 0x4a1b4af3UL, 0x151c151bUL, 0xfa1dfa40UL, 0xa21ea2adUL, 0x4d1f4df6UL,
+0x38203828UL, 0xd721d773UL, 0x8f228f9eUL, 0x602360c5UL, 0x3f243f2dUL, 0xd025d076UL, 0x8826889bUL, 0x672767c0UL,
+0x36283622UL, 0xd929d979UL, 0x812a8194UL, 0x6e2b6ecfUL, 0x312c3127UL, 0xde2dde7cUL, 0x862e8691UL, 0x692f69caUL,
+0x2430243cUL, 0xcb31cb67UL, 0x9332938aUL, 0x7c337cd1UL, 0x23342339UL, 0xcc35cc62UL, 0x9436948fUL, 0x7b377bd4UL,
+0x2a382a36UL, 0xc539c56dUL, 0x9d3a9d80UL, 0x723b72dbUL, 0x2d3c2d33UL, 0xc23dc268UL, 0x9a3e9a85UL, 0x753f75deUL,
+0x70407050UL, 0x9f419f0bUL, 0xc742c7e6UL, 0x284328bdUL, 0x77447755UL, 0x9845980eUL, 0xc046c0e3UL, 0x2f472fb8UL,
+0x7e487e5aUL, 0x91499101UL, 0xc94ac9ecUL, 0x264b26b7UL, 0x794c795fUL, 0x964d9604UL, 0xce4ecee9UL, 0x214f21b2UL,
+0x6c506c44UL, 0x8351831fUL, 0xdb52dbf2UL, 0x345334a9UL, 0x6b546b41UL, 0x8455841aUL, 0xdc56dcf7UL, 0x335733acUL,
+0x6258624eUL, 0x8d598d15UL, 0xd55ad5f8UL, 0x3a5b3aa3UL, 0x655c654bUL, 0x8a5d8a10UL, 0xd25ed2fdUL, 0x3d5f3da6UL,
+0x48604878UL, 0xa761a723UL, 0xff62ffceUL, 0x10631095UL, 0x4f644f7dUL, 0xa065a026UL, 0xf866f8cbUL, 0x17671790UL,
+0x46684672UL, 0xa969a929UL, 0xf16af1c4UL, 0x1e6b1e9fUL, 0x416c4177UL, 0xae6dae2cUL, 0xf66ef6c1UL, 0x196f199aUL,
+0x5470546cUL, 0xbb71bb37UL, 0xe372e3daUL, 0x0c730c81UL, 0x53745369UL, 0xbc75bc32UL, 0xe476e4dfUL, 0x0b770b84UL,
+0x5a785a66UL, 0xb579b53dUL, 0xed7aedd0UL, 0x027b028bUL, 0x5d7c5d63UL, 0xb27db238UL, 0xea7eead5UL, 0x057f058eUL,
+0xe080e0a0UL, 0x0f810ffbUL, 0x57825716UL, 0xb883b84dUL, 0xe784e7a5UL, 0x088508feUL, 0x50865013UL, 0xbf87bf48UL,
+0xee88eeaaUL, 0x018901f1UL, 0x598a591cUL, 0xb68bb647UL, 0xe98ce9afUL, 0x068d06f4UL, 0x5e8e5e19UL, 0xb18fb142UL,
+0xfc90fcb4UL, 0x139113efUL, 0x4b924b02UL, 0xa493a459UL, 0xfb94fbb1UL, 0x149514eaUL, 0x4c964c07UL, 0xa397a35cUL,
+0xf298f2beUL, 0x1d991de5UL, 0x459a4508UL, 0xaa9baa53UL, 0xf59cf5bbUL, 0x1a9d1ae0UL, 0x429e420dUL, 0xad9fad56UL,
+0xd8a0d888UL, 0x37a137d3UL, 0x6fa26f3eUL, 0x80a38065UL, 0xdfa4df8dUL, 0x30a530d6UL, 0x68a6683bUL, 0x87a78760UL,
+0xd6a8d682UL, 0x39a939d9UL, 0x61aa6134UL, 0x8eab8e6fUL, 0xd1acd187UL, 0x3ead3edcUL, 0x66ae6631UL, 0x89af896aUL,
+0xc4b0c49cUL, 0x2bb12bc7UL, 0x73b2732aUL, 0x9cb39c71UL, 0xc3b4c399UL, 0x2cb52cc2UL, 0x74b6742fUL, 0x9bb79b74UL,
+0xcab8ca96UL, 0x25b925cdUL, 0x7dba7d20UL, 0x92bb927bUL, 0xcdbccd93UL, 0x22bd22c8UL, 0x7abe7a25UL, 0x95bf957eUL,
+0x90c090f0UL, 0x7fc17fabUL, 0x27c22746UL, 0xc8c3c81dUL, 0x97c497f5UL, 0x78c578aeUL, 0x20c62043UL, 0xcfc7cf18UL,
+0x9ec89efaUL, 0x71c971a1UL, 0x29ca294cUL, 0xc6cbc617UL, 0x99cc99ffUL, 0x76cd76a4UL, 0x2ece2e49UL, 0xc1cfc112UL,
+0x8cd08ce4UL, 0x63d163bfUL, 0x3bd23b52UL, 0xd4d3d409UL, 0x8bd48be1UL, 0x64d564baUL, 0x3cd63c57UL, 0xd3d7d30cUL,
+0x82d882eeUL, 0x6dd96db5UL, 0x35da3558UL, 0xdadbda03UL, 0x85dc85ebUL, 0x6add6ab0UL, 0x32de325dUL, 0xdddfdd06UL,
+0xa8e0a8d8UL, 0x47e14783UL, 0x1fe21f6eUL, 0xf0e3f035UL, 0xafe4afddUL, 0x40e54086UL, 0x18e6186bUL, 0xf7e7f730UL,
+0xa6e8a6d2UL, 0x49e94989UL, 0x11ea1164UL, 0xfeebfe3fUL, 0xa1eca1d7UL, 0x4eed4e8cUL, 0x16ee1661UL, 0xf9eff93aUL,
+0xb4f0b4ccUL, 0x5bf15b97UL, 0x03f2037aUL, 0xecf3ec21UL, 0xb3f4b3c9UL, 0x5cf55c92UL, 0x04f6047fUL, 0xebf7eb24UL,
+0xbaf8bac6UL, 0x55f9559dUL, 0x0dfa0d70UL, 0xe2fbe22bUL, 0xbdfcbdc3UL, 0x52fd5298UL, 0x0afe0a75UL, 0xe5ffe52eUL
+},
+{
+0x00000000UL, 0x5bef015bUL, 0xb6b702b6UL, 0xed5803edUL, 0x05070405UL, 0x5ee8055eUL, 0xb3b006b3UL, 0xe85f07e8UL,
+0x0a0e080aUL, 0x51e10951UL, 0xbcb90abcUL, 0xe7560be7UL, 0x0f090c0fUL, 0x54e60d54UL, 0xb9be0eb9UL, 0xe2510fe2UL,
+0x141c1014UL, 0x4ff3114fUL, 0xa2ab12a2UL, 0xf94413f9UL, 0x111b1411UL, 0x4af4154aUL, 0xa7ac16a7UL, 0xfc4317fcUL,
+0x1e12181eUL, 0x45fd1945UL, 0xa8a51aa8UL, 0xf34a1bf3UL, 0x1b151c1bUL, 0x40fa1d40UL, 0xada21eadUL, 0xf64d1ff6UL,
+0x28382028UL, 0x73d72173UL, 0x9e8f229eUL, 0xc56023c5UL, 0x2d3f242dUL, 0x76d02576UL, 0x9b88269bUL, 0xc06727c0UL,
+0x22362822UL, 0x79d92979UL, 0x94812a94UL, 0xcf6e2bcfUL, 0x27312c27UL, 0x7cde2d7cUL, 0x91862e91UL, 0xca692fcaUL,
+0x3c24303cUL, 0x67cb3167UL, 0x8a93328aUL, 0xd17c33d1UL, 0x39233439UL, 0x62cc3562UL, 0x8f94368fUL, 0xd47b37d4UL,
+0x362a3836UL, 0x6dc5396dUL, 0x809d3a80UL, 0xdb723bdbUL, 0x332d3c33UL, 0x68c23d68UL, 0x859a3e85UL, 0xde753fdeUL,
+0x50704050UL, 0x0b9f410bUL, 0xe6c742e6UL, 0xbd2843bdUL, 0x55774455UL, 0x0e98450eUL, 0xe3c046e3UL, 0xb82f47b8UL,
+0x5a7e485aUL, 0x01914901UL, 0xecc94aecUL, 0xb7264bb7UL, 0x5f794c5fUL, 0x04964d04UL, 0xe9ce4ee9UL, 0xb2214fb2UL,
+0x446c5044UL, 0x1f83511fUL, 0xf2db52f2UL, 0xa93453a9UL, 0x416b5441UL, 0x1a84551aUL, 0xf7dc56f7UL, 0xac3357acUL,
+0x4e62584eUL, 0x158d5915UL, 0xf8d55af8UL, 0xa33a5ba3UL, 0x4b655c4bUL, 0x108a5d10UL, 0xfdd25efdUL, 0xa63d5fa6UL,
+0x78486078UL, 0x23a76123UL, 0xceff62ceUL, 0x95106395UL, 0x7d4f647dUL, 0x26a06526UL, 0xcbf866cbUL, 0x90176790UL,
+0x72466872UL, 0x29a96929UL, 0xc4f16ac4UL, 0x9f1e6b9fUL, 0x77416c77UL, 0x2cae6d2cUL, 0xc1f66ec1UL, 0x9a196f9aUL,
+0x6c54706cUL, 0x37bb7137UL, 0xdae372daUL, 0x810c7381UL, 0x69537469UL, 0x32bc7532UL, 0xdfe476dfUL, 0x840b7784UL,
+0x665a7866UL, 0x3db5793dUL, 0xd0ed7ad0UL, 0x8b027b8bUL, 0x635d7c63UL, 0x38b27d38UL, 0xd5ea7ed5UL, 0x8e057f8eUL,
+0xa0e080a0UL, 0xfb0f81fbUL, 0x16578216UL, 0x4db8834dUL, 0xa5e784a5UL, 0xfe0885feUL, 0x13508613UL, 0x48bf8748UL,
+0xaaee88aaUL, 0xf10189f1UL, 0x1c598a1cUL, 0x47b68b47UL, 0xafe98cafUL, 0xf4068df4UL, 0x195e8e19UL, 0x42b18f42UL,
+0xb4fc90b4UL, 0xef1391efUL, 0x024b9202UL, 0x59a49359UL, 0xb1fb94b1UL, 0xea1495eaUL, 0x074c9607UL, 0x5ca3975cUL,
+0xbef298beUL, 0xe51d99e5UL, 0x08459a08UL, 0x53aa9b53UL, 0xbbf59cbbUL, 0xe01a9de0UL, 0x0d429e0dUL, 0x56ad9f56UL,
+0x88d8a088UL, 0xd337a1d3UL, 0x3e6fa23eUL, 0x6580a365UL, 0x8ddfa48dUL, 0xd630a5d6UL, 0x3b68a63bUL, 0x6087a760UL,
+0x82d6a882UL, 0xd939a9d9UL, 0x3461aa34UL, 0x6f8eab6fUL, 0x87d1ac87UL, 0xdc3eaddcUL, 0x3166ae31UL, 0x6a89af6aUL,
+0x9cc4b09cUL, 0xc72bb1c7UL, 0x2a73b22aUL, 0x719cb371UL, 0x99c3b499UL, 0xc22cb5c2UL, 0x2f74b62fUL, 0x749bb774UL,
+0x96cab896UL, 0xcd25b9cdUL, 0x207dba20UL, 0x7b92bb7bUL, 0x93cdbc93UL, 0xc822bdc8UL, 0x257abe25UL, 0x7e95bf7eUL,
+0xf090c0f0UL, 0xab7fc1abUL, 0x4627c246UL, 0x1dc8c31dUL, 0xf597c4f5UL, 0xae78c5aeUL, 0x4320c643UL, 0x18cfc718UL,
+0xfa9ec8faUL, 0xa171c9a1UL, 0x4c29ca4cUL, 0x17c6cb17UL, 0xff99ccffUL, 0xa476cda4UL, 0x492ece49UL, 0x12c1cf12UL,
+0xe48cd0e4UL, 0xbf63d1bfUL, 0x523bd252UL, 0x09d4d309UL, 0xe18bd4e1UL, 0xba64d5baUL, 0x573cd657UL, 0x0cd3d70cUL,
+0xee82d8eeUL, 0xb56dd9b5UL, 0x5835da58UL, 0x03dadb03UL, 0xeb85dcebUL, 0xb06addb0UL, 0x5d32de5dUL, 0x06dddf06UL,
+0xd8a8e0d8UL, 0x8347e183UL, 0x6e1fe26eUL, 0x35f0e335UL, 0xddafe4ddUL, 0x8640e586UL, 0x6b18e66bUL, 0x30f7e730UL,
+0xd2a6e8d2UL, 0x8949e989UL, 0x6411ea64UL, 0x3ffeeb3fUL, 0xd7a1ecd7UL, 0x8c4eed8cUL, 0x6116ee61UL, 0x3af9ef3aUL,
+0xccb4f0ccUL, 0x975bf197UL, 0x7a03f27aUL, 0x21ecf321UL, 0xc9b3f4c9UL, 0x925cf592UL, 0x7f04f67fUL, 0x24ebf724UL,
+0xc6baf8c6UL, 0x9d55f99dUL, 0x700dfa70UL, 0x2be2fb2bUL, 0xc3bdfcc3UL, 0x9852fd98UL, 0x750afe75UL, 0x2ee5ff2eUL
+}};
+
+#ifdef LTC_TWOFISH_ALL_TABLES
+
+/* the 4x8 RS transform */
+static const ulong32 rs_tab0[256] = {
+0x00000000LU, 0xa402a401LU, 0x05040502LU, 0xa106a103LU, 0x0a080a04LU, 0xae0aae05LU, 0x0f0c0f06LU, 0xab0eab07LU,
+0x14101408LU, 0xb012b009LU, 0x1114110aLU, 0xb516b50bLU, 0x1e181e0cLU, 0xba1aba0dLU, 0x1b1c1b0eLU, 0xbf1ebf0fLU,
+0x28202810LU, 0x8c228c11LU, 0x2d242d12LU, 0x89268913LU, 0x22282214LU, 0x862a8615LU, 0x272c2716LU, 0x832e8317LU,
+0x3c303c18LU, 0x98329819LU, 0x3934391aLU, 0x9d369d1bLU, 0x3638361cLU, 0x923a921dLU, 0x333c331eLU, 0x973e971fLU,
+0x50405020LU, 0xf442f421LU, 0x55445522LU, 0xf146f123LU, 0x5a485a24LU, 0xfe4afe25LU, 0x5f4c5f26LU, 0xfb4efb27LU,
+0x44504428LU, 0xe052e029LU, 0x4154412aLU, 0xe556e52bLU, 0x4e584e2cLU, 0xea5aea2dLU, 0x4b5c4b2eLU, 0xef5eef2fLU,
+0x78607830LU, 0xdc62dc31LU, 0x7d647d32LU, 0xd966d933LU, 0x72687234LU, 0xd66ad635LU, 0x776c7736LU, 0xd36ed337LU,
+0x6c706c38LU, 0xc872c839LU, 0x6974693aLU, 0xcd76cd3bLU, 0x6678663cLU, 0xc27ac23dLU, 0x637c633eLU, 0xc77ec73fLU,
+0xa080a040LU, 0x04820441LU, 0xa584a542LU, 0x01860143LU, 0xaa88aa44LU, 0x0e8a0e45LU, 0xaf8caf46LU, 0x0b8e0b47LU,
+0xb490b448LU, 0x10921049LU, 0xb194b14aLU, 0x1596154bLU, 0xbe98be4cLU, 0x1a9a1a4dLU, 0xbb9cbb4eLU, 0x1f9e1f4fLU,
+0x88a08850LU, 0x2ca22c51LU, 0x8da48d52LU, 0x29a62953LU, 0x82a88254LU, 0x26aa2655LU, 0x87ac8756LU, 0x23ae2357LU,
+0x9cb09c58LU, 0x38b23859LU, 0x99b4995aLU, 0x3db63d5bLU, 0x96b8965cLU, 0x32ba325dLU, 0x93bc935eLU, 0x37be375fLU,
+0xf0c0f060LU, 0x54c25461LU, 0xf5c4f562LU, 0x51c65163LU, 0xfac8fa64LU, 0x5eca5e65LU, 0xffccff66LU, 0x5bce5b67LU,
+0xe4d0e468LU, 0x40d24069LU, 0xe1d4e16aLU, 0x45d6456bLU, 0xeed8ee6cLU, 0x4ada4a6dLU, 0xebdceb6eLU, 0x4fde4f6fLU,
+0xd8e0d870LU, 0x7ce27c71LU, 0xdde4dd72LU, 0x79e67973LU, 0xd2e8d274LU, 0x76ea7675LU, 0xd7ecd776LU, 0x73ee7377LU,
+0xccf0cc78LU, 0x68f26879LU, 0xc9f4c97aLU, 0x6df66d7bLU, 0xc6f8c67cLU, 0x62fa627dLU, 0xc3fcc37eLU, 0x67fe677fLU,
+0x0d4d0d80LU, 0xa94fa981LU, 0x08490882LU, 0xac4bac83LU, 0x07450784LU, 0xa347a385LU, 0x02410286LU, 0xa643a687LU,
+0x195d1988LU, 0xbd5fbd89LU, 0x1c591c8aLU, 0xb85bb88bLU, 0x1355138cLU, 0xb757b78dLU, 0x1651168eLU, 0xb253b28fLU,
+0x256d2590LU, 0x816f8191LU, 0x20692092LU, 0x846b8493LU, 0x2f652f94LU, 0x8b678b95LU, 0x2a612a96LU, 0x8e638e97LU,
+0x317d3198LU, 0x957f9599LU, 0x3479349aLU, 0x907b909bLU, 0x3b753b9cLU, 0x9f779f9dLU, 0x3e713e9eLU, 0x9a739a9fLU,
+0x5d0d5da0LU, 0xf90ff9a1LU, 0x580958a2LU, 0xfc0bfca3LU, 0x570557a4LU, 0xf307f3a5LU, 0x520152a6LU, 0xf603f6a7LU,
+0x491d49a8LU, 0xed1feda9LU, 0x4c194caaLU, 0xe81be8abLU, 0x431543acLU, 0xe717e7adLU, 0x461146aeLU, 0xe213e2afLU,
+0x752d75b0LU, 0xd12fd1b1LU, 0x702970b2LU, 0xd42bd4b3LU, 0x7f257fb4LU, 0xdb27dbb5LU, 0x7a217ab6LU, 0xde23deb7LU,
+0x613d61b8LU, 0xc53fc5b9LU, 0x643964baLU, 0xc03bc0bbLU, 0x6b356bbcLU, 0xcf37cfbdLU, 0x6e316ebeLU, 0xca33cabfLU,
+0xadcdadc0LU, 0x09cf09c1LU, 0xa8c9a8c2LU, 0x0ccb0cc3LU, 0xa7c5a7c4LU, 0x03c703c5LU, 0xa2c1a2c6LU, 0x06c306c7LU,
+0xb9ddb9c8LU, 0x1ddf1dc9LU, 0xbcd9bccaLU, 0x18db18cbLU, 0xb3d5b3ccLU, 0x17d717cdLU, 0xb6d1b6ceLU, 0x12d312cfLU,
+0x85ed85d0LU, 0x21ef21d1LU, 0x80e980d2LU, 0x24eb24d3LU, 0x8fe58fd4LU, 0x2be72bd5LU, 0x8ae18ad6LU, 0x2ee32ed7LU,
+0x91fd91d8LU, 0x35ff35d9LU, 0x94f994daLU, 0x30fb30dbLU, 0x9bf59bdcLU, 0x3ff73fddLU, 0x9ef19edeLU, 0x3af33adfLU,
+0xfd8dfde0LU, 0x598f59e1LU, 0xf889f8e2LU, 0x5c8b5ce3LU, 0xf785f7e4LU, 0x538753e5LU, 0xf281f2e6LU, 0x568356e7LU,
+0xe99de9e8LU, 0x4d9f4de9LU, 0xec99eceaLU, 0x489b48ebLU, 0xe395e3ecLU, 0x479747edLU, 0xe691e6eeLU, 0x429342efLU,
+0xd5add5f0LU, 0x71af71f1LU, 0xd0a9d0f2LU, 0x74ab74f3LU, 0xdfa5dff4LU, 0x7ba77bf5LU, 0xdaa1daf6LU, 0x7ea37ef7LU,
+0xc1bdc1f8LU, 0x65bf65f9LU, 0xc4b9c4faLU, 0x60bb60fbLU, 0xcbb5cbfcLU, 0x6fb76ffdLU, 0xceb1cefeLU, 0x6ab36affLU };
+
+static const ulong32 rs_tab1[256] = {
+0x00000000LU, 0x55a156a4LU, 0xaa0fac05LU, 0xffaefaa1LU, 0x191e150aLU, 0x4cbf43aeLU, 0xb311b90fLU, 0xe6b0efabLU,
+0x323c2a14LU, 0x679d7cb0LU, 0x98338611LU, 0xcd92d0b5LU, 0x2b223f1eLU, 0x7e8369baLU, 0x812d931bLU, 0xd48cc5bfLU,
+0x64785428LU, 0x31d9028cLU, 0xce77f82dLU, 0x9bd6ae89LU, 0x7d664122LU, 0x28c71786LU, 0xd769ed27LU, 0x82c8bb83LU,
+0x56447e3cLU, 0x03e52898LU, 0xfc4bd239LU, 0xa9ea849dLU, 0x4f5a6b36LU, 0x1afb3d92LU, 0xe555c733LU, 0xb0f49197LU,
+0xc8f0a850LU, 0x9d51fef4LU, 0x62ff0455LU, 0x375e52f1LU, 0xd1eebd5aLU, 0x844febfeLU, 0x7be1115fLU, 0x2e4047fbLU,
+0xfacc8244LU, 0xaf6dd4e0LU, 0x50c32e41LU, 0x056278e5LU, 0xe3d2974eLU, 0xb673c1eaLU, 0x49dd3b4bLU, 0x1c7c6defLU,
+0xac88fc78LU, 0xf929aadcLU, 0x0687507dLU, 0x532606d9LU, 0xb596e972LU, 0xe037bfd6LU, 0x1f994577LU, 0x4a3813d3LU,
+0x9eb4d66cLU, 0xcb1580c8LU, 0x34bb7a69LU, 0x611a2ccdLU, 0x87aac366LU, 0xd20b95c2LU, 0x2da56f63LU, 0x780439c7LU,
+0xddad1da0LU, 0x880c4b04LU, 0x77a2b1a5LU, 0x2203e701LU, 0xc4b308aaLU, 0x91125e0eLU, 0x6ebca4afLU, 0x3b1df20bLU,
+0xef9137b4LU, 0xba306110LU, 0x459e9bb1LU, 0x103fcd15LU, 0xf68f22beLU, 0xa32e741aLU, 0x5c808ebbLU, 0x0921d81fLU,
+0xb9d54988LU, 0xec741f2cLU, 0x13dae58dLU, 0x467bb329LU, 0xa0cb5c82LU, 0xf56a0a26LU, 0x0ac4f087LU, 0x5f65a623LU,
+0x8be9639cLU, 0xde483538LU, 0x21e6cf99LU, 0x7447993dLU, 0x92f77696LU, 0xc7562032LU, 0x38f8da93LU, 0x6d598c37LU,
+0x155db5f0LU, 0x40fce354LU, 0xbf5219f5LU, 0xeaf34f51LU, 0x0c43a0faLU, 0x59e2f65eLU, 0xa64c0cffLU, 0xf3ed5a5bLU,
+0x27619fe4LU, 0x72c0c940LU, 0x8d6e33e1LU, 0xd8cf6545LU, 0x3e7f8aeeLU, 0x6bdedc4aLU, 0x947026ebLU, 0xc1d1704fLU,
+0x7125e1d8LU, 0x2484b77cLU, 0xdb2a4dddLU, 0x8e8b1b79LU, 0x683bf4d2LU, 0x3d9aa276LU, 0xc23458d7LU, 0x97950e73LU,
+0x4319cbccLU, 0x16b89d68LU, 0xe91667c9LU, 0xbcb7316dLU, 0x5a07dec6LU, 0x0fa68862LU, 0xf00872c3LU, 0xa5a92467LU,
+0xf7173a0dLU, 0xa2b66ca9LU, 0x5d189608LU, 0x08b9c0acLU, 0xee092f07LU, 0xbba879a3LU, 0x44068302LU, 0x11a7d5a6LU,
+0xc52b1019LU, 0x908a46bdLU, 0x6f24bc1cLU, 0x3a85eab8LU, 0xdc350513LU, 0x899453b7LU, 0x763aa916LU, 0x239bffb2LU,
+0x936f6e25LU, 0xc6ce3881LU, 0x3960c220LU, 0x6cc19484LU, 0x8a717b2fLU, 0xdfd02d8bLU, 0x207ed72aLU, 0x75df818eLU,
+0xa1534431LU, 0xf4f21295LU, 0x0b5ce834LU, 0x5efdbe90LU, 0xb84d513bLU, 0xedec079fLU, 0x1242fd3eLU, 0x47e3ab9aLU,
+0x3fe7925dLU, 0x6a46c4f9LU, 0x95e83e58LU, 0xc04968fcLU, 0x26f98757LU, 0x7358d1f3LU, 0x8cf62b52LU, 0xd9577df6LU,
+0x0ddbb849LU, 0x587aeeedLU, 0xa7d4144cLU, 0xf27542e8LU, 0x14c5ad43LU, 0x4164fbe7LU, 0xbeca0146LU, 0xeb6b57e2LU,
+0x5b9fc675LU, 0x0e3e90d1LU, 0xf1906a70LU, 0xa4313cd4LU, 0x4281d37fLU, 0x172085dbLU, 0xe88e7f7aLU, 0xbd2f29deLU,
+0x69a3ec61LU, 0x3c02bac5LU, 0xc3ac4064LU, 0x960d16c0LU, 0x70bdf96bLU, 0x251cafcfLU, 0xdab2556eLU, 0x8f1303caLU,
+0x2aba27adLU, 0x7f1b7109LU, 0x80b58ba8LU, 0xd514dd0cLU, 0x33a432a7LU, 0x66056403LU, 0x99ab9ea2LU, 0xcc0ac806LU,
+0x18860db9LU, 0x4d275b1dLU, 0xb289a1bcLU, 0xe728f718LU, 0x019818b3LU, 0x54394e17LU, 0xab97b4b6LU, 0xfe36e212LU,
+0x4ec27385LU, 0x1b632521LU, 0xe4cddf80LU, 0xb16c8924LU, 0x57dc668fLU, 0x027d302bLU, 0xfdd3ca8aLU, 0xa8729c2eLU,
+0x7cfe5991LU, 0x295f0f35LU, 0xd6f1f594LU, 0x8350a330LU, 0x65e04c9bLU, 0x30411a3fLU, 0xcfefe09eLU, 0x9a4eb63aLU,
+0xe24a8ffdLU, 0xb7ebd959LU, 0x484523f8LU, 0x1de4755cLU, 0xfb549af7LU, 0xaef5cc53LU, 0x515b36f2LU, 0x04fa6056LU,
+0xd076a5e9LU, 0x85d7f34dLU, 0x7a7909ecLU, 0x2fd85f48LU, 0xc968b0e3LU, 0x9cc9e647LU, 0x63671ce6LU, 0x36c64a42LU,
+0x8632dbd5LU, 0xd3938d71LU, 0x2c3d77d0LU, 0x799c2174LU, 0x9f2ccedfLU, 0xca8d987bLU, 0x352362daLU, 0x6082347eLU,
+0xb40ef1c1LU, 0xe1afa765LU, 0x1e015dc4LU, 0x4ba00b60LU, 0xad10e4cbLU, 0xf8b1b26fLU, 0x071f48ceLU, 0x52be1e6aLU };
+
+static const ulong32 rs_tab2[256] = {
+0x00000000LU, 0x87fc8255LU, 0x43b549aaLU, 0xc449cbffLU, 0x86279219LU, 0x01db104cLU, 0xc592dbb3LU, 0x426e59e6LU,
+0x414e6932LU, 0xc6b2eb67LU, 0x02fb2098LU, 0x8507a2cdLU, 0xc769fb2bLU, 0x4095797eLU, 0x84dcb281LU, 0x032030d4LU,
+0x829cd264LU, 0x05605031LU, 0xc1299bceLU, 0x46d5199bLU, 0x04bb407dLU, 0x8347c228LU, 0x470e09d7LU, 0xc0f28b82LU,
+0xc3d2bb56LU, 0x442e3903LU, 0x8067f2fcLU, 0x079b70a9LU, 0x45f5294fLU, 0xc209ab1aLU, 0x064060e5LU, 0x81bce2b0LU,
+0x4975e9c8LU, 0xce896b9dLU, 0x0ac0a062LU, 0x8d3c2237LU, 0xcf527bd1LU, 0x48aef984LU, 0x8ce7327bLU, 0x0b1bb02eLU,
+0x083b80faLU, 0x8fc702afLU, 0x4b8ec950LU, 0xcc724b05LU, 0x8e1c12e3LU, 0x09e090b6LU, 0xcda95b49LU, 0x4a55d91cLU,
+0xcbe93bacLU, 0x4c15b9f9LU, 0x885c7206LU, 0x0fa0f053LU, 0x4dcea9b5LU, 0xca322be0LU, 0x0e7be01fLU, 0x8987624aLU,
+0x8aa7529eLU, 0x0d5bd0cbLU, 0xc9121b34LU, 0x4eee9961LU, 0x0c80c087LU, 0x8b7c42d2LU, 0x4f35892dLU, 0xc8c90b78LU,
+0x92ea9fddLU, 0x15161d88LU, 0xd15fd677LU, 0x56a35422LU, 0x14cd0dc4LU, 0x93318f91LU, 0x5778446eLU, 0xd084c63bLU,
+0xd3a4f6efLU, 0x545874baLU, 0x9011bf45LU, 0x17ed3d10LU, 0x558364f6LU, 0xd27fe6a3LU, 0x16362d5cLU, 0x91caaf09LU,
+0x10764db9LU, 0x978acfecLU, 0x53c30413LU, 0xd43f8646LU, 0x9651dfa0LU, 0x11ad5df5LU, 0xd5e4960aLU, 0x5218145fLU,
+0x5138248bLU, 0xd6c4a6deLU, 0x128d6d21LU, 0x9571ef74LU, 0xd71fb692LU, 0x50e334c7LU, 0x94aaff38LU, 0x13567d6dLU,
+0xdb9f7615LU, 0x5c63f440LU, 0x982a3fbfLU, 0x1fd6bdeaLU, 0x5db8e40cLU, 0xda446659LU, 0x1e0dada6LU, 0x99f12ff3LU,
+0x9ad11f27LU, 0x1d2d9d72LU, 0xd964568dLU, 0x5e98d4d8LU, 0x1cf68d3eLU, 0x9b0a0f6bLU, 0x5f43c494LU, 0xd8bf46c1LU,
+0x5903a471LU, 0xdeff2624LU, 0x1ab6eddbLU, 0x9d4a6f8eLU, 0xdf243668LU, 0x58d8b43dLU, 0x9c917fc2LU, 0x1b6dfd97LU,
+0x184dcd43LU, 0x9fb14f16LU, 0x5bf884e9LU, 0xdc0406bcLU, 0x9e6a5f5aLU, 0x1996dd0fLU, 0xdddf16f0LU, 0x5a2394a5LU,
+0x699973f7LU, 0xee65f1a2LU, 0x2a2c3a5dLU, 0xadd0b808LU, 0xefbee1eeLU, 0x684263bbLU, 0xac0ba844LU, 0x2bf72a11LU,
+0x28d71ac5LU, 0xaf2b9890LU, 0x6b62536fLU, 0xec9ed13aLU, 0xaef088dcLU, 0x290c0a89LU, 0xed45c176LU, 0x6ab94323LU,
+0xeb05a193LU, 0x6cf923c6LU, 0xa8b0e839LU, 0x2f4c6a6cLU, 0x6d22338aLU, 0xeadeb1dfLU, 0x2e977a20LU, 0xa96bf875LU,
+0xaa4bc8a1LU, 0x2db74af4LU, 0xe9fe810bLU, 0x6e02035eLU, 0x2c6c5ab8LU, 0xab90d8edLU, 0x6fd91312LU, 0xe8259147LU,
+0x20ec9a3fLU, 0xa710186aLU, 0x6359d395LU, 0xe4a551c0LU, 0xa6cb0826LU, 0x21378a73LU, 0xe57e418cLU, 0x6282c3d9LU,
+0x61a2f30dLU, 0xe65e7158LU, 0x2217baa7LU, 0xa5eb38f2LU, 0xe7856114LU, 0x6079e341LU, 0xa43028beLU, 0x23ccaaebLU,
+0xa270485bLU, 0x258cca0eLU, 0xe1c501f1LU, 0x663983a4LU, 0x2457da42LU, 0xa3ab5817LU, 0x67e293e8LU, 0xe01e11bdLU,
+0xe33e2169LU, 0x64c2a33cLU, 0xa08b68c3LU, 0x2777ea96LU, 0x6519b370LU, 0xe2e53125LU, 0x26acfadaLU, 0xa150788fLU,
+0xfb73ec2aLU, 0x7c8f6e7fLU, 0xb8c6a580LU, 0x3f3a27d5LU, 0x7d547e33LU, 0xfaa8fc66LU, 0x3ee13799LU, 0xb91db5ccLU,
+0xba3d8518LU, 0x3dc1074dLU, 0xf988ccb2LU, 0x7e744ee7LU, 0x3c1a1701LU, 0xbbe69554LU, 0x7faf5eabLU, 0xf853dcfeLU,
+0x79ef3e4eLU, 0xfe13bc1bLU, 0x3a5a77e4LU, 0xbda6f5b1LU, 0xffc8ac57LU, 0x78342e02LU, 0xbc7de5fdLU, 0x3b8167a8LU,
+0x38a1577cLU, 0xbf5dd529LU, 0x7b141ed6LU, 0xfce89c83LU, 0xbe86c565LU, 0x397a4730LU, 0xfd338ccfLU, 0x7acf0e9aLU,
+0xb20605e2LU, 0x35fa87b7LU, 0xf1b34c48LU, 0x764fce1dLU, 0x342197fbLU, 0xb3dd15aeLU, 0x7794de51LU, 0xf0685c04LU,
+0xf3486cd0LU, 0x74b4ee85LU, 0xb0fd257aLU, 0x3701a72fLU, 0x756ffec9LU, 0xf2937c9cLU, 0x36dab763LU, 0xb1263536LU,
+0x309ad786LU, 0xb76655d3LU, 0x732f9e2cLU, 0xf4d31c79LU, 0xb6bd459fLU, 0x3141c7caLU, 0xf5080c35LU, 0x72f48e60LU,
+0x71d4beb4LU, 0xf6283ce1LU, 0x3261f71eLU, 0xb59d754bLU, 0xf7f32cadLU, 0x700faef8LU, 0xb4466507LU, 0x33bae752LU };
+
+static const ulong32 rs_tab3[256] = {
+0x00000000LU, 0x5ac1f387LU, 0xb4cfab43LU, 0xee0e58c4LU, 0x25d31b86LU, 0x7f12e801LU, 0x911cb0c5LU, 0xcbdd4342LU,
+0x4aeb3641LU, 0x102ac5c6LU, 0xfe249d02LU, 0xa4e56e85LU, 0x6f382dc7LU, 0x35f9de40LU, 0xdbf78684LU, 0x81367503LU,
+0x949b6c82LU, 0xce5a9f05LU, 0x2054c7c1LU, 0x7a953446LU, 0xb1487704LU, 0xeb898483LU, 0x0587dc47LU, 0x5f462fc0LU,
+0xde705ac3LU, 0x84b1a944LU, 0x6abff180LU, 0x307e0207LU, 0xfba34145LU, 0xa162b2c2LU, 0x4f6cea06LU, 0x15ad1981LU,
+0x657bd849LU, 0x3fba2bceLU, 0xd1b4730aLU, 0x8b75808dLU, 0x40a8c3cfLU, 0x1a693048LU, 0xf467688cLU, 0xaea69b0bLU,
+0x2f90ee08LU, 0x75511d8fLU, 0x9b5f454bLU, 0xc19eb6ccLU, 0x0a43f58eLU, 0x50820609LU, 0xbe8c5ecdLU, 0xe44dad4aLU,
+0xf1e0b4cbLU, 0xab21474cLU, 0x452f1f88LU, 0x1feeec0fLU, 0xd433af4dLU, 0x8ef25ccaLU, 0x60fc040eLU, 0x3a3df789LU,
+0xbb0b828aLU, 0xe1ca710dLU, 0x0fc429c9LU, 0x5505da4eLU, 0x9ed8990cLU, 0xc4196a8bLU, 0x2a17324fLU, 0x70d6c1c8LU,
+0xcaf6fd92LU, 0x90370e15LU, 0x7e3956d1LU, 0x24f8a556LU, 0xef25e614LU, 0xb5e41593LU, 0x5bea4d57LU, 0x012bbed0LU,
+0x801dcbd3LU, 0xdadc3854LU, 0x34d26090LU, 0x6e139317LU, 0xa5ced055LU, 0xff0f23d2LU, 0x11017b16LU, 0x4bc08891LU,
+0x5e6d9110LU, 0x04ac6297LU, 0xeaa23a53LU, 0xb063c9d4LU, 0x7bbe8a96LU, 0x217f7911LU, 0xcf7121d5LU, 0x95b0d252LU,
+0x1486a751LU, 0x4e4754d6LU, 0xa0490c12LU, 0xfa88ff95LU, 0x3155bcd7LU, 0x6b944f50LU, 0x859a1794LU, 0xdf5be413LU,
+0xaf8d25dbLU, 0xf54cd65cLU, 0x1b428e98LU, 0x41837d1fLU, 0x8a5e3e5dLU, 0xd09fcddaLU, 0x3e91951eLU, 0x64506699LU,
+0xe566139aLU, 0xbfa7e01dLU, 0x51a9b8d9LU, 0x0b684b5eLU, 0xc0b5081cLU, 0x9a74fb9bLU, 0x747aa35fLU, 0x2ebb50d8LU,
+0x3b164959LU, 0x61d7badeLU, 0x8fd9e21aLU, 0xd518119dLU, 0x1ec552dfLU, 0x4404a158LU, 0xaa0af99cLU, 0xf0cb0a1bLU,
+0x71fd7f18LU, 0x2b3c8c9fLU, 0xc532d45bLU, 0x9ff327dcLU, 0x542e649eLU, 0x0eef9719LU, 0xe0e1cfddLU, 0xba203c5aLU,
+0xd9a1b769LU, 0x836044eeLU, 0x6d6e1c2aLU, 0x37afefadLU, 0xfc72acefLU, 0xa6b35f68LU, 0x48bd07acLU, 0x127cf42bLU,
+0x934a8128LU, 0xc98b72afLU, 0x27852a6bLU, 0x7d44d9ecLU, 0xb6999aaeLU, 0xec586929LU, 0x025631edLU, 0x5897c26aLU,
+0x4d3adbebLU, 0x17fb286cLU, 0xf9f570a8LU, 0xa334832fLU, 0x68e9c06dLU, 0x322833eaLU, 0xdc266b2eLU, 0x86e798a9LU,
+0x07d1edaaLU, 0x5d101e2dLU, 0xb31e46e9LU, 0xe9dfb56eLU, 0x2202f62cLU, 0x78c305abLU, 0x96cd5d6fLU, 0xcc0caee8LU,
+0xbcda6f20LU, 0xe61b9ca7LU, 0x0815c463LU, 0x52d437e4LU, 0x990974a6LU, 0xc3c88721LU, 0x2dc6dfe5LU, 0x77072c62LU,
+0xf6315961LU, 0xacf0aae6LU, 0x42fef222LU, 0x183f01a5LU, 0xd3e242e7LU, 0x8923b160LU, 0x672de9a4LU, 0x3dec1a23LU,
+0x284103a2LU, 0x7280f025LU, 0x9c8ea8e1LU, 0xc64f5b66LU, 0x0d921824LU, 0x5753eba3LU, 0xb95db367LU, 0xe39c40e0LU,
+0x62aa35e3LU, 0x386bc664LU, 0xd6659ea0LU, 0x8ca46d27LU, 0x47792e65LU, 0x1db8dde2LU, 0xf3b68526LU, 0xa97776a1LU,
+0x13574afbLU, 0x4996b97cLU, 0xa798e1b8LU, 0xfd59123fLU, 0x3684517dLU, 0x6c45a2faLU, 0x824bfa3eLU, 0xd88a09b9LU,
+0x59bc7cbaLU, 0x037d8f3dLU, 0xed73d7f9LU, 0xb7b2247eLU, 0x7c6f673cLU, 0x26ae94bbLU, 0xc8a0cc7fLU, 0x92613ff8LU,
+0x87cc2679LU, 0xdd0dd5feLU, 0x33038d3aLU, 0x69c27ebdLU, 0xa21f3dffLU, 0xf8dece78LU, 0x16d096bcLU, 0x4c11653bLU,
+0xcd271038LU, 0x97e6e3bfLU, 0x79e8bb7bLU, 0x232948fcLU, 0xe8f40bbeLU, 0xb235f839LU, 0x5c3ba0fdLU, 0x06fa537aLU,
+0x762c92b2LU, 0x2ced6135LU, 0xc2e339f1LU, 0x9822ca76LU, 0x53ff8934LU, 0x093e7ab3LU, 0xe7302277LU, 0xbdf1d1f0LU,
+0x3cc7a4f3LU, 0x66065774LU, 0x88080fb0LU, 0xd2c9fc37LU, 0x1914bf75LU, 0x43d54cf2LU, 0xaddb1436LU, 0xf71ae7b1LU,
+0xe2b7fe30LU, 0xb8760db7LU, 0x56785573LU, 0x0cb9a6f4LU, 0xc764e5b6LU, 0x9da51631LU, 0x73ab4ef5LU, 0x296abd72LU,
+0xa85cc871LU, 0xf29d3bf6LU, 0x1c936332LU, 0x465290b5LU, 0x8d8fd3f7LU, 0xd74e2070LU, 0x394078b4LU, 0x63818b33LU };
+
+static const ulong32 rs_tab4[256] = {
+0x00000000LU, 0x58471e5aLU, 0xb08e3cb4LU, 0xe8c922eeLU, 0x2d517825LU, 0x7516667fLU, 0x9ddf4491LU, 0xc5985acbLU,
+0x5aa2f04aLU, 0x02e5ee10LU, 0xea2cccfeLU, 0xb26bd2a4LU, 0x77f3886fLU, 0x2fb49635LU, 0xc77db4dbLU, 0x9f3aaa81LU,
+0xb409ad94LU, 0xec4eb3ceLU, 0x04879120LU, 0x5cc08f7aLU, 0x9958d5b1LU, 0xc11fcbebLU, 0x29d6e905LU, 0x7191f75fLU,
+0xeeab5ddeLU, 0xb6ec4384LU, 0x5e25616aLU, 0x06627f30LU, 0xc3fa25fbLU, 0x9bbd3ba1LU, 0x7374194fLU, 0x2b330715LU,
+0x25121765LU, 0x7d55093fLU, 0x959c2bd1LU, 0xcddb358bLU, 0x08436f40LU, 0x5004711aLU, 0xb8cd53f4LU, 0xe08a4daeLU,
+0x7fb0e72fLU, 0x27f7f975LU, 0xcf3edb9bLU, 0x9779c5c1LU, 0x52e19f0aLU, 0x0aa68150LU, 0xe26fa3beLU, 0xba28bde4LU,
+0x911bbaf1LU, 0xc95ca4abLU, 0x21958645LU, 0x79d2981fLU, 0xbc4ac2d4LU, 0xe40ddc8eLU, 0x0cc4fe60LU, 0x5483e03aLU,
+0xcbb94abbLU, 0x93fe54e1LU, 0x7b37760fLU, 0x23706855LU, 0xe6e8329eLU, 0xbeaf2cc4LU, 0x56660e2aLU, 0x0e211070LU,
+0x4a242ecaLU, 0x12633090LU, 0xfaaa127eLU, 0xa2ed0c24LU, 0x677556efLU, 0x3f3248b5LU, 0xd7fb6a5bLU, 0x8fbc7401LU,
+0x1086de80LU, 0x48c1c0daLU, 0xa008e234LU, 0xf84ffc6eLU, 0x3dd7a6a5LU, 0x6590b8ffLU, 0x8d599a11LU, 0xd51e844bLU,
+0xfe2d835eLU, 0xa66a9d04LU, 0x4ea3bfeaLU, 0x16e4a1b0LU, 0xd37cfb7bLU, 0x8b3be521LU, 0x63f2c7cfLU, 0x3bb5d995LU,
+0xa48f7314LU, 0xfcc86d4eLU, 0x14014fa0LU, 0x4c4651faLU, 0x89de0b31LU, 0xd199156bLU, 0x39503785LU, 0x611729dfLU,
+0x6f3639afLU, 0x377127f5LU, 0xdfb8051bLU, 0x87ff1b41LU, 0x4267418aLU, 0x1a205fd0LU, 0xf2e97d3eLU, 0xaaae6364LU,
+0x3594c9e5LU, 0x6dd3d7bfLU, 0x851af551LU, 0xdd5deb0bLU, 0x18c5b1c0LU, 0x4082af9aLU, 0xa84b8d74LU, 0xf00c932eLU,
+0xdb3f943bLU, 0x83788a61LU, 0x6bb1a88fLU, 0x33f6b6d5LU, 0xf66eec1eLU, 0xae29f244LU, 0x46e0d0aaLU, 0x1ea7cef0LU,
+0x819d6471LU, 0xd9da7a2bLU, 0x311358c5LU, 0x6954469fLU, 0xaccc1c54LU, 0xf48b020eLU, 0x1c4220e0LU, 0x44053ebaLU,
+0x94485cd9LU, 0xcc0f4283LU, 0x24c6606dLU, 0x7c817e37LU, 0xb91924fcLU, 0xe15e3aa6LU, 0x09971848LU, 0x51d00612LU,
+0xceeaac93LU, 0x96adb2c9LU, 0x7e649027LU, 0x26238e7dLU, 0xe3bbd4b6LU, 0xbbfccaecLU, 0x5335e802LU, 0x0b72f658LU,
+0x2041f14dLU, 0x7806ef17LU, 0x90cfcdf9LU, 0xc888d3a3LU, 0x0d108968LU, 0x55579732LU, 0xbd9eb5dcLU, 0xe5d9ab86LU,
+0x7ae30107LU, 0x22a41f5dLU, 0xca6d3db3LU, 0x922a23e9LU, 0x57b27922LU, 0x0ff56778LU, 0xe73c4596LU, 0xbf7b5bccLU,
+0xb15a4bbcLU, 0xe91d55e6LU, 0x01d47708LU, 0x59936952LU, 0x9c0b3399LU, 0xc44c2dc3LU, 0x2c850f2dLU, 0x74c21177LU,
+0xebf8bbf6LU, 0xb3bfa5acLU, 0x5b768742LU, 0x03319918LU, 0xc6a9c3d3LU, 0x9eeedd89LU, 0x7627ff67LU, 0x2e60e13dLU,
+0x0553e628LU, 0x5d14f872LU, 0xb5ddda9cLU, 0xed9ac4c6LU, 0x28029e0dLU, 0x70458057LU, 0x988ca2b9LU, 0xc0cbbce3LU,
+0x5ff11662LU, 0x07b60838LU, 0xef7f2ad6LU, 0xb738348cLU, 0x72a06e47LU, 0x2ae7701dLU, 0xc22e52f3LU, 0x9a694ca9LU,
+0xde6c7213LU, 0x862b6c49LU, 0x6ee24ea7LU, 0x36a550fdLU, 0xf33d0a36LU, 0xab7a146cLU, 0x43b33682LU, 0x1bf428d8LU,
+0x84ce8259LU, 0xdc899c03LU, 0x3440beedLU, 0x6c07a0b7LU, 0xa99ffa7cLU, 0xf1d8e426LU, 0x1911c6c8LU, 0x4156d892LU,
+0x6a65df87LU, 0x3222c1ddLU, 0xdaebe333LU, 0x82acfd69LU, 0x4734a7a2LU, 0x1f73b9f8LU, 0xf7ba9b16LU, 0xaffd854cLU,
+0x30c72fcdLU, 0x68803197LU, 0x80491379LU, 0xd80e0d23LU, 0x1d9657e8LU, 0x45d149b2LU, 0xad186b5cLU, 0xf55f7506LU,
+0xfb7e6576LU, 0xa3397b2cLU, 0x4bf059c2LU, 0x13b74798LU, 0xd62f1d53LU, 0x8e680309LU, 0x66a121e7LU, 0x3ee63fbdLU,
+0xa1dc953cLU, 0xf99b8b66LU, 0x1152a988LU, 0x4915b7d2LU, 0x8c8ded19LU, 0xd4caf343LU, 0x3c03d1adLU, 0x6444cff7LU,
+0x4f77c8e2LU, 0x1730d6b8LU, 0xfff9f456LU, 0xa7beea0cLU, 0x6226b0c7LU, 0x3a61ae9dLU, 0xd2a88c73LU, 0x8aef9229LU,
+0x15d538a8LU, 0x4d9226f2LU, 0xa55b041cLU, 0xfd1c1a46LU, 0x3884408dLU, 0x60c35ed7LU, 0x880a7c39LU, 0xd04d6263LU };
+
+static const ulong32 rs_tab5[256] = {
+0x00000000LU, 0xdbaec658LU, 0xfb11c1b0LU, 0x20bf07e8LU, 0xbb22cf2dLU, 0x608c0975LU, 0x40330e9dLU, 0x9b9dc8c5LU,
+0x3b44d35aLU, 0xe0ea1502LU, 0xc05512eaLU, 0x1bfbd4b2LU, 0x80661c77LU, 0x5bc8da2fLU, 0x7b77ddc7LU, 0xa0d91b9fLU,
+0x7688ebb4LU, 0xad262decLU, 0x8d992a04LU, 0x5637ec5cLU, 0xcdaa2499LU, 0x1604e2c1LU, 0x36bbe529LU, 0xed152371LU,
+0x4dcc38eeLU, 0x9662feb6LU, 0xb6ddf95eLU, 0x6d733f06LU, 0xf6eef7c3LU, 0x2d40319bLU, 0x0dff3673LU, 0xd651f02bLU,
+0xec5d9b25LU, 0x37f35d7dLU, 0x174c5a95LU, 0xcce29ccdLU, 0x577f5408LU, 0x8cd19250LU, 0xac6e95b8LU, 0x77c053e0LU,
+0xd719487fLU, 0x0cb78e27LU, 0x2c0889cfLU, 0xf7a64f97LU, 0x6c3b8752LU, 0xb795410aLU, 0x972a46e2LU, 0x4c8480baLU,
+0x9ad57091LU, 0x417bb6c9LU, 0x61c4b121LU, 0xba6a7779LU, 0x21f7bfbcLU, 0xfa5979e4LU, 0xdae67e0cLU, 0x0148b854LU,
+0xa191a3cbLU, 0x7a3f6593LU, 0x5a80627bLU, 0x812ea423LU, 0x1ab36ce6LU, 0xc11daabeLU, 0xe1a2ad56LU, 0x3a0c6b0eLU,
+0x95ba7b4aLU, 0x4e14bd12LU, 0x6eabbafaLU, 0xb5057ca2LU, 0x2e98b467LU, 0xf536723fLU, 0xd58975d7LU, 0x0e27b38fLU,
+0xaefea810LU, 0x75506e48LU, 0x55ef69a0LU, 0x8e41aff8LU, 0x15dc673dLU, 0xce72a165LU, 0xeecda68dLU, 0x356360d5LU,
+0xe33290feLU, 0x389c56a6LU, 0x1823514eLU, 0xc38d9716LU, 0x58105fd3LU, 0x83be998bLU, 0xa3019e63LU, 0x78af583bLU,
+0xd87643a4LU, 0x03d885fcLU, 0x23678214LU, 0xf8c9444cLU, 0x63548c89LU, 0xb8fa4ad1LU, 0x98454d39LU, 0x43eb8b61LU,
+0x79e7e06fLU, 0xa2492637LU, 0x82f621dfLU, 0x5958e787LU, 0xc2c52f42LU, 0x196be91aLU, 0x39d4eef2LU, 0xe27a28aaLU,
+0x42a33335LU, 0x990df56dLU, 0xb9b2f285LU, 0x621c34ddLU, 0xf981fc18LU, 0x222f3a40LU, 0x02903da8LU, 0xd93efbf0LU,
+0x0f6f0bdbLU, 0xd4c1cd83LU, 0xf47eca6bLU, 0x2fd00c33LU, 0xb44dc4f6LU, 0x6fe302aeLU, 0x4f5c0546LU, 0x94f2c31eLU,
+0x342bd881LU, 0xef851ed9LU, 0xcf3a1931LU, 0x1494df69LU, 0x8f0917acLU, 0x54a7d1f4LU, 0x7418d61cLU, 0xafb61044LU,
+0x6739f694LU, 0xbc9730ccLU, 0x9c283724LU, 0x4786f17cLU, 0xdc1b39b9LU, 0x07b5ffe1LU, 0x270af809LU, 0xfca43e51LU,
+0x5c7d25ceLU, 0x87d3e396LU, 0xa76ce47eLU, 0x7cc22226LU, 0xe75feae3LU, 0x3cf12cbbLU, 0x1c4e2b53LU, 0xc7e0ed0bLU,
+0x11b11d20LU, 0xca1fdb78LU, 0xeaa0dc90LU, 0x310e1ac8LU, 0xaa93d20dLU, 0x713d1455LU, 0x518213bdLU, 0x8a2cd5e5LU,
+0x2af5ce7aLU, 0xf15b0822LU, 0xd1e40fcaLU, 0x0a4ac992LU, 0x91d70157LU, 0x4a79c70fLU, 0x6ac6c0e7LU, 0xb16806bfLU,
+0x8b646db1LU, 0x50caabe9LU, 0x7075ac01LU, 0xabdb6a59LU, 0x3046a29cLU, 0xebe864c4LU, 0xcb57632cLU, 0x10f9a574LU,
+0xb020beebLU, 0x6b8e78b3LU, 0x4b317f5bLU, 0x909fb903LU, 0x0b0271c6LU, 0xd0acb79eLU, 0xf013b076LU, 0x2bbd762eLU,
+0xfdec8605LU, 0x2642405dLU, 0x06fd47b5LU, 0xdd5381edLU, 0x46ce4928LU, 0x9d608f70LU, 0xbddf8898LU, 0x66714ec0LU,
+0xc6a8555fLU, 0x1d069307LU, 0x3db994efLU, 0xe61752b7LU, 0x7d8a9a72LU, 0xa6245c2aLU, 0x869b5bc2LU, 0x5d359d9aLU,
+0xf2838ddeLU, 0x292d4b86LU, 0x09924c6eLU, 0xd23c8a36LU, 0x49a142f3LU, 0x920f84abLU, 0xb2b08343LU, 0x691e451bLU,
+0xc9c75e84LU, 0x126998dcLU, 0x32d69f34LU, 0xe978596cLU, 0x72e591a9LU, 0xa94b57f1LU, 0x89f45019LU, 0x525a9641LU,
+0x840b666aLU, 0x5fa5a032LU, 0x7f1aa7daLU, 0xa4b46182LU, 0x3f29a947LU, 0xe4876f1fLU, 0xc43868f7LU, 0x1f96aeafLU,
+0xbf4fb530LU, 0x64e17368LU, 0x445e7480LU, 0x9ff0b2d8LU, 0x046d7a1dLU, 0xdfc3bc45LU, 0xff7cbbadLU, 0x24d27df5LU,
+0x1ede16fbLU, 0xc570d0a3LU, 0xe5cfd74bLU, 0x3e611113LU, 0xa5fcd9d6LU, 0x7e521f8eLU, 0x5eed1866LU, 0x8543de3eLU,
+0x259ac5a1LU, 0xfe3403f9LU, 0xde8b0411LU, 0x0525c249LU, 0x9eb80a8cLU, 0x4516ccd4LU, 0x65a9cb3cLU, 0xbe070d64LU,
+0x6856fd4fLU, 0xb3f83b17LU, 0x93473cffLU, 0x48e9faa7LU, 0xd3743262LU, 0x08daf43aLU, 0x2865f3d2LU, 0xf3cb358aLU,
+0x53122e15LU, 0x88bce84dLU, 0xa803efa5LU, 0x73ad29fdLU, 0xe830e138LU, 0x339e2760LU, 0x13212088LU, 0xc88fe6d0LU };
+
+static const ulong32 rs_tab6[256] = {
+0x00000000LU, 0x9e3d68dbLU, 0x717ad0fbLU, 0xef47b820LU, 0xe2f4edbbLU, 0x7cc98560LU, 0x938e3d40LU, 0x0db3559bLU,
+0x89a5973bLU, 0x1798ffe0LU, 0xf8df47c0LU, 0x66e22f1bLU, 0x6b517a80LU, 0xf56c125bLU, 0x1a2baa7bLU, 0x8416c2a0LU,
+0x5f076376LU, 0xc13a0badLU, 0x2e7db38dLU, 0xb040db56LU, 0xbdf38ecdLU, 0x23cee616LU, 0xcc895e36LU, 0x52b436edLU,
+0xd6a2f44dLU, 0x489f9c96LU, 0xa7d824b6LU, 0x39e54c6dLU, 0x345619f6LU, 0xaa6b712dLU, 0x452cc90dLU, 0xdb11a1d6LU,
+0xbe0ec6ecLU, 0x2033ae37LU, 0xcf741617LU, 0x51497eccLU, 0x5cfa2b57LU, 0xc2c7438cLU, 0x2d80fbacLU, 0xb3bd9377LU,
+0x37ab51d7LU, 0xa996390cLU, 0x46d1812cLU, 0xd8ece9f7LU, 0xd55fbc6cLU, 0x4b62d4b7LU, 0xa4256c97LU, 0x3a18044cLU,
+0xe109a59aLU, 0x7f34cd41LU, 0x90737561LU, 0x0e4e1dbaLU, 0x03fd4821LU, 0x9dc020faLU, 0x728798daLU, 0xecbaf001LU,
+0x68ac32a1LU, 0xf6915a7aLU, 0x19d6e25aLU, 0x87eb8a81LU, 0x8a58df1aLU, 0x1465b7c1LU, 0xfb220fe1LU, 0x651f673aLU,
+0x311cc195LU, 0xaf21a94eLU, 0x4066116eLU, 0xde5b79b5LU, 0xd3e82c2eLU, 0x4dd544f5LU, 0xa292fcd5LU, 0x3caf940eLU,
+0xb8b956aeLU, 0x26843e75LU, 0xc9c38655LU, 0x57feee8eLU, 0x5a4dbb15LU, 0xc470d3ceLU, 0x2b376beeLU, 0xb50a0335LU,
+0x6e1ba2e3LU, 0xf026ca38LU, 0x1f617218LU, 0x815c1ac3LU, 0x8cef4f58LU, 0x12d22783LU, 0xfd959fa3LU, 0x63a8f778LU,
+0xe7be35d8LU, 0x79835d03LU, 0x96c4e523LU, 0x08f98df8LU, 0x054ad863LU, 0x9b77b0b8LU, 0x74300898LU, 0xea0d6043LU,
+0x8f120779LU, 0x112f6fa2LU, 0xfe68d782LU, 0x6055bf59LU, 0x6de6eac2LU, 0xf3db8219LU, 0x1c9c3a39LU, 0x82a152e2LU,
+0x06b79042LU, 0x988af899LU, 0x77cd40b9LU, 0xe9f02862LU, 0xe4437df9LU, 0x7a7e1522LU, 0x9539ad02LU, 0x0b04c5d9LU,
+0xd015640fLU, 0x4e280cd4LU, 0xa16fb4f4LU, 0x3f52dc2fLU, 0x32e189b4LU, 0xacdce16fLU, 0x439b594fLU, 0xdda63194LU,
+0x59b0f334LU, 0xc78d9befLU, 0x28ca23cfLU, 0xb6f74b14LU, 0xbb441e8fLU, 0x25797654LU, 0xca3ece74LU, 0x5403a6afLU,
+0x6238cf67LU, 0xfc05a7bcLU, 0x13421f9cLU, 0x8d7f7747LU, 0x80cc22dcLU, 0x1ef14a07LU, 0xf1b6f227LU, 0x6f8b9afcLU,
+0xeb9d585cLU, 0x75a03087LU, 0x9ae788a7LU, 0x04dae07cLU, 0x0969b5e7LU, 0x9754dd3cLU, 0x7813651cLU, 0xe62e0dc7LU,
+0x3d3fac11LU, 0xa302c4caLU, 0x4c457ceaLU, 0xd2781431LU, 0xdfcb41aaLU, 0x41f62971LU, 0xaeb19151LU, 0x308cf98aLU,
+0xb49a3b2aLU, 0x2aa753f1LU, 0xc5e0ebd1LU, 0x5bdd830aLU, 0x566ed691LU, 0xc853be4aLU, 0x2714066aLU, 0xb9296eb1LU,
+0xdc36098bLU, 0x420b6150LU, 0xad4cd970LU, 0x3371b1abLU, 0x3ec2e430LU, 0xa0ff8cebLU, 0x4fb834cbLU, 0xd1855c10LU,
+0x55939eb0LU, 0xcbaef66bLU, 0x24e94e4bLU, 0xbad42690LU, 0xb767730bLU, 0x295a1bd0LU, 0xc61da3f0LU, 0x5820cb2bLU,
+0x83316afdLU, 0x1d0c0226LU, 0xf24bba06LU, 0x6c76d2ddLU, 0x61c58746LU, 0xfff8ef9dLU, 0x10bf57bdLU, 0x8e823f66LU,
+0x0a94fdc6LU, 0x94a9951dLU, 0x7bee2d3dLU, 0xe5d345e6LU, 0xe860107dLU, 0x765d78a6LU, 0x991ac086LU, 0x0727a85dLU,
+0x53240ef2LU, 0xcd196629LU, 0x225ede09LU, 0xbc63b6d2LU, 0xb1d0e349LU, 0x2fed8b92LU, 0xc0aa33b2LU, 0x5e975b69LU,
+0xda8199c9LU, 0x44bcf112LU, 0xabfb4932LU, 0x35c621e9LU, 0x38757472LU, 0xa6481ca9LU, 0x490fa489LU, 0xd732cc52LU,
+0x0c236d84LU, 0x921e055fLU, 0x7d59bd7fLU, 0xe364d5a4LU, 0xeed7803fLU, 0x70eae8e4LU, 0x9fad50c4LU, 0x0190381fLU,
+0x8586fabfLU, 0x1bbb9264LU, 0xf4fc2a44LU, 0x6ac1429fLU, 0x67721704LU, 0xf94f7fdfLU, 0x1608c7ffLU, 0x8835af24LU,
+0xed2ac81eLU, 0x7317a0c5LU, 0x9c5018e5LU, 0x026d703eLU, 0x0fde25a5LU, 0x91e34d7eLU, 0x7ea4f55eLU, 0xe0999d85LU,
+0x648f5f25LU, 0xfab237feLU, 0x15f58fdeLU, 0x8bc8e705LU, 0x867bb29eLU, 0x1846da45LU, 0xf7016265LU, 0x693c0abeLU,
+0xb22dab68LU, 0x2c10c3b3LU, 0xc3577b93LU, 0x5d6a1348LU, 0x50d946d3LU, 0xcee42e08LU, 0x21a39628LU, 0xbf9efef3LU,
+0x3b883c53LU, 0xa5b55488LU, 0x4af2eca8LU, 0xd4cf8473LU, 0xd97cd1e8LU, 0x4741b933LU, 0xa8060113LU, 0x363b69c8LU };
+
+static const ulong32 rs_tab7[256] = {
+0x00000000LU, 0x0319e59eLU, 0x06328771LU, 0x052b62efLU, 0x0c6443e2LU, 0x0f7da67cLU, 0x0a56c493LU, 0x094f210dLU,
+0x18c88689LU, 0x1bd16317LU, 0x1efa01f8LU, 0x1de3e466LU, 0x14acc56bLU, 0x17b520f5LU, 0x129e421aLU, 0x1187a784LU,
+0x30dd415fLU, 0x33c4a4c1LU, 0x36efc62eLU, 0x35f623b0LU, 0x3cb902bdLU, 0x3fa0e723LU, 0x3a8b85ccLU, 0x39926052LU,
+0x2815c7d6LU, 0x2b0c2248LU, 0x2e2740a7LU, 0x2d3ea539LU, 0x24718434LU, 0x276861aaLU, 0x22430345LU, 0x215ae6dbLU,
+0x60f782beLU, 0x63ee6720LU, 0x66c505cfLU, 0x65dce051LU, 0x6c93c15cLU, 0x6f8a24c2LU, 0x6aa1462dLU, 0x69b8a3b3LU,
+0x783f0437LU, 0x7b26e1a9LU, 0x7e0d8346LU, 0x7d1466d8LU, 0x745b47d5LU, 0x7742a24bLU, 0x7269c0a4LU, 0x7170253aLU,
+0x502ac3e1LU, 0x5333267fLU, 0x56184490LU, 0x5501a10eLU, 0x5c4e8003LU, 0x5f57659dLU, 0x5a7c0772LU, 0x5965e2ecLU,
+0x48e24568LU, 0x4bfba0f6LU, 0x4ed0c219LU, 0x4dc92787LU, 0x4486068aLU, 0x479fe314LU, 0x42b481fbLU, 0x41ad6465LU,
+0xc0a34931LU, 0xc3baacafLU, 0xc691ce40LU, 0xc5882bdeLU, 0xccc70ad3LU, 0xcfdeef4dLU, 0xcaf58da2LU, 0xc9ec683cLU,
+0xd86bcfb8LU, 0xdb722a26LU, 0xde5948c9LU, 0xdd40ad57LU, 0xd40f8c5aLU, 0xd71669c4LU, 0xd23d0b2bLU, 0xd124eeb5LU,
+0xf07e086eLU, 0xf367edf0LU, 0xf64c8f1fLU, 0xf5556a81LU, 0xfc1a4b8cLU, 0xff03ae12LU, 0xfa28ccfdLU, 0xf9312963LU,
+0xe8b68ee7LU, 0xebaf6b79LU, 0xee840996LU, 0xed9dec08LU, 0xe4d2cd05LU, 0xe7cb289bLU, 0xe2e04a74LU, 0xe1f9afeaLU,
+0xa054cb8fLU, 0xa34d2e11LU, 0xa6664cfeLU, 0xa57fa960LU, 0xac30886dLU, 0xaf296df3LU, 0xaa020f1cLU, 0xa91bea82LU,
+0xb89c4d06LU, 0xbb85a898LU, 0xbeaeca77LU, 0xbdb72fe9LU, 0xb4f80ee4LU, 0xb7e1eb7aLU, 0xb2ca8995LU, 0xb1d36c0bLU,
+0x90898ad0LU, 0x93906f4eLU, 0x96bb0da1LU, 0x95a2e83fLU, 0x9cedc932LU, 0x9ff42cacLU, 0x9adf4e43LU, 0x99c6abddLU,
+0x88410c59LU, 0x8b58e9c7LU, 0x8e738b28LU, 0x8d6a6eb6LU, 0x84254fbbLU, 0x873caa25LU, 0x8217c8caLU, 0x810e2d54LU,
+0xcd0b9262LU, 0xce1277fcLU, 0xcb391513LU, 0xc820f08dLU, 0xc16fd180LU, 0xc276341eLU, 0xc75d56f1LU, 0xc444b36fLU,
+0xd5c314ebLU, 0xd6daf175LU, 0xd3f1939aLU, 0xd0e87604LU, 0xd9a75709LU, 0xdabeb297LU, 0xdf95d078LU, 0xdc8c35e6LU,
+0xfdd6d33dLU, 0xfecf36a3LU, 0xfbe4544cLU, 0xf8fdb1d2LU, 0xf1b290dfLU, 0xf2ab7541LU, 0xf78017aeLU, 0xf499f230LU,
+0xe51e55b4LU, 0xe607b02aLU, 0xe32cd2c5LU, 0xe035375bLU, 0xe97a1656LU, 0xea63f3c8LU, 0xef489127LU, 0xec5174b9LU,
+0xadfc10dcLU, 0xaee5f542LU, 0xabce97adLU, 0xa8d77233LU, 0xa198533eLU, 0xa281b6a0LU, 0xa7aad44fLU, 0xa4b331d1LU,
+0xb5349655LU, 0xb62d73cbLU, 0xb3061124LU, 0xb01ff4baLU, 0xb950d5b7LU, 0xba493029LU, 0xbf6252c6LU, 0xbc7bb758LU,
+0x9d215183LU, 0x9e38b41dLU, 0x9b13d6f2LU, 0x980a336cLU, 0x91451261LU, 0x925cf7ffLU, 0x97779510LU, 0x946e708eLU,
+0x85e9d70aLU, 0x86f03294LU, 0x83db507bLU, 0x80c2b5e5LU, 0x898d94e8LU, 0x8a947176LU, 0x8fbf1399LU, 0x8ca6f607LU,
+0x0da8db53LU, 0x0eb13ecdLU, 0x0b9a5c22LU, 0x0883b9bcLU, 0x01cc98b1LU, 0x02d57d2fLU, 0x07fe1fc0LU, 0x04e7fa5eLU,
+0x15605ddaLU, 0x1679b844LU, 0x1352daabLU, 0x104b3f35LU, 0x19041e38LU, 0x1a1dfba6LU, 0x1f369949LU, 0x1c2f7cd7LU,
+0x3d759a0cLU, 0x3e6c7f92LU, 0x3b471d7dLU, 0x385ef8e3LU, 0x3111d9eeLU, 0x32083c70LU, 0x37235e9fLU, 0x343abb01LU,
+0x25bd1c85LU, 0x26a4f91bLU, 0x238f9bf4LU, 0x20967e6aLU, 0x29d95f67LU, 0x2ac0baf9LU, 0x2febd816LU, 0x2cf23d88LU,
+0x6d5f59edLU, 0x6e46bc73LU, 0x6b6dde9cLU, 0x68743b02LU, 0x613b1a0fLU, 0x6222ff91LU, 0x67099d7eLU, 0x641078e0LU,
+0x7597df64LU, 0x768e3afaLU, 0x73a55815LU, 0x70bcbd8bLU, 0x79f39c86LU, 0x7aea7918LU, 0x7fc11bf7LU, 0x7cd8fe69LU,
+0x5d8218b2LU, 0x5e9bfd2cLU, 0x5bb09fc3LU, 0x58a97a5dLU, 0x51e65b50LU, 0x52ffbeceLU, 0x57d4dc21LU, 0x54cd39bfLU,
+0x454a9e3bLU, 0x46537ba5LU, 0x4378194aLU, 0x4061fcd4LU, 0x492eddd9LU, 0x4a373847LU, 0x4f1c5aa8LU, 0x4c05bf36LU };
+
+#endif /* LTC_TWOFISH_ALL_TABLES */
+
+#endif /* LTC_TWOFISH_TAB_C */
+#endif
diff --git a/Sources/libtomcrypt/ciphers/xtea.c b/Sources/libtomcrypt/ciphers/xtea.c
new file mode 100644
index 00000000..95aaa1a9
--- /dev/null
+++ b/Sources/libtomcrypt/ciphers/xtea.c
@@ -0,0 +1,251 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file xtea.c
+ Implementation of eXtended TEA, Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_XTEA
+
+const struct ltc_cipher_descriptor xtea_desc =
+{
+ "xtea",
+ 1,
+ 16, 16, 8, 32,
+ &xtea_setup,
+ &xtea_ecb_encrypt,
+ &xtea_ecb_decrypt,
+ &xtea_test,
+ &xtea_done,
+ &xtea_keysize,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+ ulong32 x, sum, K[4];
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ /* check arguments */
+ if (keylen != 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if (num_rounds != 0 && num_rounds != 32) {
+ return CRYPT_INVALID_ROUNDS;
+ }
+
+ /* load key */
+ LOAD32H(K[0], key+0);
+ LOAD32H(K[1], key+4);
+ LOAD32H(K[2], key+8);
+ LOAD32H(K[3], key+12);
+
+ for (x = sum = 0; x < 32; x++) {
+ skey->xtea.A[x] = (sum + K[sum&3]) & 0xFFFFFFFFUL;
+ sum = (sum + 0x9E3779B9UL) & 0xFFFFFFFFUL;
+ skey->xtea.B[x] = (sum + K[(sum>>11)&3]) & 0xFFFFFFFFUL;
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(&K, sizeof(K));
+#endif
+
+ return CRYPT_OK;
+}
+
+/**
+ Encrypts a block of text with LTC_XTEA
+ @param pt The input plaintext (8 bytes)
+ @param ct The output ciphertext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+ ulong32 y, z;
+ int r;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ LOAD32H(y, &pt[0]);
+ LOAD32H(z, &pt[4]);
+ for (r = 0; r < 32; r += 4) {
+ y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL;
+ z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL;
+
+ y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+1])) & 0xFFFFFFFFUL;
+ z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+1])) & 0xFFFFFFFFUL;
+
+ y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+2])) & 0xFFFFFFFFUL;
+ z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+2])) & 0xFFFFFFFFUL;
+
+ y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+3])) & 0xFFFFFFFFUL;
+ z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+3])) & 0xFFFFFFFFUL;
+ }
+ STORE32H(y, &ct[0]);
+ STORE32H(z, &ct[4]);
+ return CRYPT_OK;
+}
+
+/**
+ Decrypts a block of text with LTC_XTEA
+ @param ct The input ciphertext (8 bytes)
+ @param pt The output plaintext (8 bytes)
+ @param skey The key as scheduled
+ @return CRYPT_OK if successful
+*/
+int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+ ulong32 y, z;
+ int r;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(skey != NULL);
+
+ LOAD32H(y, &ct[0]);
+ LOAD32H(z, &ct[4]);
+ for (r = 31; r >= 0; r -= 4) {
+ z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL;
+ y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL;
+
+ z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-1])) & 0xFFFFFFFFUL;
+ y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-1])) & 0xFFFFFFFFUL;
+
+ z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-2])) & 0xFFFFFFFFUL;
+ y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-2])) & 0xFFFFFFFFUL;
+
+ z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-3])) & 0xFFFFFFFFUL;
+ y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-3])) & 0xFFFFFFFFUL;
+ }
+ STORE32H(y, &pt[0]);
+ STORE32H(z, &pt[4]);
+ return CRYPT_OK;
+}
+
+/**
+ Performs a self-test of the LTC_XTEA block cipher
+ @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int xtea_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ unsigned char key[16], pt[8], ct[8];
+ } tests[] = {
+ {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xde, 0xe9, 0xd4, 0xd8, 0xf7, 0x13, 0x1e, 0xd9 }
+ }, {
+ { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xa5, 0x97, 0xab, 0x41, 0x76, 0x01, 0x4d, 0x72 }
+ }, {
+ { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06 },
+ { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 },
+ { 0xb1, 0xfd, 0x5d, 0xa9, 0xcc, 0x6d, 0xc9, 0xdc }
+ }, {
+ { 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+ 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+ { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+ { 0x70, 0x4b, 0x31, 0x34, 0x47, 0x44, 0xdf, 0xab }
+ }, {
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+ { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }
+ }, {
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+ { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }
+ }, {
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
+ }, {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+ { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }
+ }, {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+ { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }
+ }, {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
+ }
+ };
+ unsigned char tmp[2][8];
+ symmetric_key skey;
+ int i, err, y;
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ zeromem(&skey, sizeof(skey));
+ if ((err = xtea_setup(tests[i].key, 16, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+ xtea_ecb_encrypt(tests[i].pt, tmp[0], &skey);
+ xtea_ecb_decrypt(tmp[0], tmp[1], &skey);
+
+ if (compare_testvector(tmp[0], 8, tests[i].ct, 8, "XTEA Encrypt", i) != 0 ||
+ compare_testvector(tmp[1], 8, tests[i].pt, 8, "XTEA Decrypt", i) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+ for (y = 0; y < 8; y++) tmp[0][y] = 0;
+ for (y = 0; y < 1000; y++) xtea_ecb_encrypt(tmp[0], tmp[0], &skey);
+ for (y = 0; y < 1000; y++) xtea_ecb_decrypt(tmp[0], tmp[0], &skey);
+ for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ } /* for */
+
+ return CRYPT_OK;
+ #endif
+}
+
+/** Terminate the context
+ @param skey The scheduled key
+*/
+void xtea_done(symmetric_key *skey)
+{
+ LTC_UNUSED_PARAM(skey);
+}
+
+/**
+ Gets suitable key size
+ @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
+ @return CRYPT_OK if the input key size is acceptable.
+*/
+int xtea_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize != NULL);
+ if (*keysize < 16) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ *keysize = 16;
+ return CRYPT_OK;
+}
+
+
+#endif
+
+
+
diff --git a/Sources/libtomcrypt/encauth/ccm/ccm_add_aad.c b/Sources/libtomcrypt/encauth/ccm/ccm_add_aad.c
new file mode 100644
index 00000000..130d3041
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ccm/ccm_add_aad.c
@@ -0,0 +1,53 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CCM_MODE
+
+/**
+ Add AAD to the CCM state
+ @param ccm The CCM state
+ @param adata The additional authentication data to add to the CCM state
+ @param adatalen The length of the AAD data.
+ @return CRYPT_OK on success
+ */
+int ccm_add_aad(ccm_state *ccm,
+ const unsigned char *adata, unsigned long adatalen)
+{
+ unsigned long y;
+ int err;
+
+ LTC_ARGCHK(ccm != NULL);
+ LTC_ARGCHK(adata != NULL);
+
+ if (ccm->aadlen < ccm->current_aadlen + adatalen) {
+ return CRYPT_INVALID_ARG;
+ }
+ ccm->current_aadlen += adatalen;
+
+ /* now add the data */
+ for (y = 0; y < adatalen; y++) {
+ if (ccm->x == 16) {
+ /* full block so let's encrypt it */
+ if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) {
+ return err;
+ }
+ ccm->x = 0;
+ }
+ ccm->PAD[ccm->x++] ^= adata[y];
+ }
+
+ /* remainder? */
+ if (ccm->aadlen == ccm->current_aadlen) {
+ if (ccm->x != 0) {
+ if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ ccm->x = 0;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ccm/ccm_add_nonce.c b/Sources/libtomcrypt/encauth/ccm/ccm_add_nonce.c
new file mode 100644
index 00000000..a56a43a5
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ccm/ccm_add_nonce.c
@@ -0,0 +1,109 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CCM_MODE
+
+/**
+ Add nonce data to the CCM state
+ @param ccm The CCM state
+ @param nonce The nonce data to add
+ @param noncelen The length of the nonce
+ @return CRYPT_OK on success
+ */
+int ccm_add_nonce(ccm_state *ccm,
+ const unsigned char *nonce, unsigned long noncelen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(ccm != NULL);
+ LTC_ARGCHK(nonce != NULL);
+
+ /* increase L to match the nonce len */
+ ccm->noncelen = (noncelen > 13) ? 13 : noncelen;
+ if ((15 - ccm->noncelen) > ccm->L) {
+ ccm->L = 15 - ccm->noncelen;
+ }
+ if (ccm->L > 8) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* decrease noncelen to match L */
+ if ((ccm->noncelen + ccm->L) > 15) {
+ ccm->noncelen = 15 - ccm->L;
+ }
+
+ /* form B_0 == flags | Nonce N | l(m) */
+ x = 0;
+ ccm->PAD[x++] = (unsigned char)(((ccm->aadlen > 0) ? (1<<6) : 0) |
+ (((ccm->taglen - 2)>>1)<<3) |
+ (ccm->L-1));
+
+ /* nonce */
+ for (y = 0; y < 15 - ccm->L; y++) {
+ ccm->PAD[x++] = nonce[y];
+ }
+
+ /* store len */
+ len = ccm->ptlen;
+
+ /* shift len so the upper bytes of len are the contents of the length */
+ for (y = ccm->L; y < 4; y++) {
+ len <<= 8;
+ }
+
+ /* store l(m) (only store 32-bits) */
+ for (y = 0; ccm->L > 4 && (ccm->L-y)>4; y++) {
+ ccm->PAD[x++] = 0;
+ }
+ for (; y < ccm->L; y++) {
+ if (x >= sizeof(ccm->PAD)) {
+ return CRYPT_INVALID_ARG;
+ }
+ ccm->PAD[x++] = (unsigned char)((len >> 24) & 255);
+ len <<= 8;
+ }
+
+ /* encrypt PAD */
+ if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* handle header */
+ ccm->x = 0;
+ if (ccm->aadlen > 0) {
+ /* store length */
+ if (ccm->aadlen < ((1UL<<16) - (1UL<<8))) {
+ ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255;
+ ccm->PAD[ccm->x++] ^= ccm->aadlen & 255;
+ } else {
+ ccm->PAD[ccm->x++] ^= 0xFF;
+ ccm->PAD[ccm->x++] ^= 0xFE;
+ ccm->PAD[ccm->x++] ^= (ccm->aadlen>>24) & 255;
+ ccm->PAD[ccm->x++] ^= (ccm->aadlen>>16) & 255;
+ ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255;
+ ccm->PAD[ccm->x++] ^= ccm->aadlen & 255;
+ }
+ }
+
+ /* setup the ctr counter */
+ x = 0;
+
+ /* flags */
+ ccm->ctr[x++] = (unsigned char)ccm->L-1;
+
+ /* nonce */
+ for (y = 0; y < (16 - (ccm->L+1)); ++y) {
+ ccm->ctr[x++] = nonce[y];
+ }
+ /* offset */
+ while (x < 16) {
+ ccm->ctr[x++] = 0;
+ }
+
+ ccm->CTRlen = 16;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ccm/ccm_done.c b/Sources/libtomcrypt/encauth/ccm/ccm_done.c
new file mode 100644
index 00000000..965121d7
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ccm/ccm_done.c
@@ -0,0 +1,55 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CCM_MODE
+
+/**
+ Terminate a CCM stream
+ @param ccm The CCM state
+ @param tag [out] The destination for the MAC tag
+ @param taglen [in/out] The length of the MAC tag
+ @return CRYPT_OK on success
+ */
+int ccm_done(ccm_state *ccm,
+ unsigned char *tag, unsigned long *taglen)
+{
+ unsigned long x, y;
+ int err;
+
+ LTC_ARGCHK(ccm != NULL);
+
+ /* Check all data have been processed */
+ if (ccm->ptlen != ccm->current_ptlen) {
+ return CRYPT_ERROR;
+ }
+
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+
+ if (ccm->x != 0) {
+ if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* setup CTR for the TAG (zero the count) */
+ for (y = 15; y > 15 - ccm->L; y--) {
+ ccm->ctr[y] = 0x00;
+ }
+ if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) {
+ return err;
+ }
+
+ cipher_descriptor[ccm->cipher].done(&ccm->K);
+
+ /* store the TAG */
+ for (x = 0; x < 16 && x < *taglen; x++) {
+ tag[x] = ccm->PAD[x] ^ ccm->CTRPAD[x];
+ }
+ *taglen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ccm/ccm_init.c b/Sources/libtomcrypt/encauth/ccm/ccm_init.c
new file mode 100644
index 00000000..527c6af7
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ccm/ccm_init.c
@@ -0,0 +1,64 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CCM_MODE
+
+/**
+ Initialize a CCM state
+ @param ccm The CCM state to initialize
+ @param cipher The index of the cipher to use
+ @param key The secret key
+ @param keylen The length of the secret key
+ @param ptlen The length of the plain/cipher text that will be processed
+ @param taglen The max length of the MAC tag
+ @param aadlen The length of the AAD
+
+ @return CRYPT_OK on success
+ */
+int ccm_init(ccm_state *ccm, int cipher,
+ const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen)
+{
+ int err;
+
+ LTC_ARGCHK(ccm != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ XMEMSET(ccm, 0, sizeof(ccm_state));
+
+ /* check cipher input */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (cipher_descriptor[cipher].block_length != 16) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ /* make sure the taglen is valid */
+ if (taglen < 4 || taglen > 16 || (taglen % 2) == 1 || aadlen < 0 || ptlen < 0) {
+ return CRYPT_INVALID_ARG;
+ }
+ ccm->taglen = taglen;
+
+ /* schedule key */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ccm->K)) != CRYPT_OK) {
+ return err;
+ }
+ ccm->cipher = cipher;
+
+ /* let's get the L value */
+ ccm->ptlen = ptlen;
+ ccm->L = 0;
+ while (ptlen) {
+ ++ccm->L;
+ ptlen >>= 8;
+ }
+ if (ccm->L <= 1) {
+ ccm->L = 2;
+ }
+
+ ccm->aadlen = aadlen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ccm/ccm_memory.c b/Sources/libtomcrypt/encauth/ccm/ccm_memory.c
new file mode 100644
index 00000000..c0ffa781
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ccm/ccm_memory.c
@@ -0,0 +1,376 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ccm_memory.c
+ CCM support, process a block of memory, Tom St Denis
+*/
+
+#ifdef LTC_CCM_MODE
+
+/**
+ CCM encrypt/decrypt and produce an authentication tag
+
+ *1 'pt', 'ct' and 'tag' can both be 'in' or 'out', depending on 'direction'
+
+ @param cipher The index of the cipher desired
+ @param key The secret key to use
+ @param keylen The length of the secret key (octets)
+ @param uskey A previously scheduled key [optional can be NULL]
+ @param nonce The session nonce [use once]
+ @param noncelen The length of the nonce
+ @param header The header for the session
+ @param headerlen The length of the header (octets)
+ @param pt [*1] The plaintext
+ @param ptlen The length of the plaintext (octets)
+ @param ct [*1] The ciphertext
+ @param tag [*1] The destination tag
+ @param taglen The max size and resulting size of the authentication tag
+ @param direction Encrypt or Decrypt direction (0 or 1)
+ @return CRYPT_OK if successful
+*/
+int ccm_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ symmetric_key *uskey,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction)
+{
+ unsigned char PAD[16], ctr[16], CTRPAD[16], ptTag[16], b, *pt_real;
+ unsigned char *pt_work = NULL;
+ symmetric_key *skey;
+ int err;
+ unsigned long len, L, x, y, z, CTRlen;
+
+ if (uskey == NULL) {
+ LTC_ARGCHK(key != NULL);
+ }
+ LTC_ARGCHK(nonce != NULL);
+ if (headerlen > 0) {
+ LTC_ARGCHK(header != NULL);
+ }
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+
+ pt_real = pt;
+
+#ifdef LTC_FAST
+ if (16 % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ /* check cipher input */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (cipher_descriptor[cipher].block_length != 16) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ /* make sure the taglen is valid */
+ if (*taglen < 4 || *taglen > 16 || (*taglen % 2) == 1 || headerlen > 0x7fffffffu) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* is there an accelerator? */
+ if (cipher_descriptor[cipher].accel_ccm_memory != NULL) {
+ return cipher_descriptor[cipher].accel_ccm_memory(
+ key, keylen,
+ uskey,
+ nonce, noncelen,
+ header, headerlen,
+ pt, ptlen,
+ ct,
+ tag, taglen,
+ direction);
+ }
+
+ /* let's get the L value */
+ len = ptlen;
+ L = 0;
+ while (len) {
+ ++L;
+ len >>= 8;
+ }
+ if (L <= 1) {
+ L = 2;
+ }
+
+ /* increase L to match the nonce len */
+ noncelen = (noncelen > 13) ? 13 : noncelen;
+ if ((15 - noncelen) > L) {
+ L = 15 - noncelen;
+ }
+ if (L > 8) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* allocate mem for the symmetric key */
+ if (uskey == NULL) {
+ skey = XMALLOC(sizeof(*skey));
+ if (skey == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* initialize the cipher */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) {
+ XFREE(skey);
+ return err;
+ }
+ } else {
+ skey = uskey;
+ }
+
+ /* initialize buffer for pt */
+ if (direction == CCM_DECRYPT && ptlen > 0) {
+ pt_work = XMALLOC(ptlen);
+ if (pt_work == NULL) {
+ goto error;
+ }
+ pt = pt_work;
+ }
+
+ /* form B_0 == flags | Nonce N | l(m) */
+ x = 0;
+ PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) |
+ (((*taglen - 2)>>1)<<3) |
+ (L-1));
+
+ /* nonce */
+ for (y = 0; y < 15 - L; y++) {
+ PAD[x++] = nonce[y];
+ }
+
+ /* store len */
+ len = ptlen;
+
+ /* shift len so the upper bytes of len are the contents of the length */
+ for (y = L; y < 4; y++) {
+ len <<= 8;
+ }
+
+ /* store l(m) (only store 32-bits) */
+ for (y = 0; L > 4 && (L-y)>4; y++) {
+ PAD[x++] = 0;
+ }
+ for (; y < L; y++) {
+ if (x >= sizeof(PAD)) {
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+ PAD[x++] = (unsigned char)((len >> 24) & 255);
+ len <<= 8;
+ }
+
+ /* encrypt PAD */
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* handle header */
+ if (headerlen > 0) {
+ x = 0;
+
+ /* store length */
+ if (headerlen < ((1UL<<16) - (1UL<<8))) {
+ PAD[x++] ^= (headerlen>>8) & 255;
+ PAD[x++] ^= headerlen & 255;
+ } else {
+ PAD[x++] ^= 0xFF;
+ PAD[x++] ^= 0xFE;
+ PAD[x++] ^= (headerlen>>24) & 255;
+ PAD[x++] ^= (headerlen>>16) & 255;
+ PAD[x++] ^= (headerlen>>8) & 255;
+ PAD[x++] ^= headerlen & 255;
+ }
+
+ /* now add the data */
+ for (y = 0; y < headerlen; y++) {
+ if (x == 16) {
+ /* full block so let's encrypt it */
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+ x = 0;
+ }
+ PAD[x++] ^= header[y];
+ }
+
+ /* remainder */
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+ }
+
+ /* setup the ctr counter */
+ x = 0;
+
+ /* flags */
+ ctr[x++] = (unsigned char)L-1;
+
+ /* nonce */
+ for (y = 0; y < (16 - (L+1)); ++y) {
+ ctr[x++] = nonce[y];
+ }
+ /* offset */
+ while (x < 16) {
+ ctr[x++] = 0;
+ }
+
+ x = 0;
+ CTRlen = 16;
+
+ /* now handle the PT */
+ if (ptlen > 0) {
+ y = 0;
+#ifdef LTC_FAST
+ if (ptlen & ~15) {
+ if (direction == CCM_ENCRYPT) {
+ for (; y < (ptlen & ~15); y += 16) {
+ /* increment the ctr? */
+ for (z = 15; z > 15-L; z--) {
+ ctr[z] = (ctr[z] + 1) & 255;
+ if (ctr[z]) break;
+ }
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* xor the PT against the pad first */
+ for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z]));
+ *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z]));
+ }
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+ }
+ } else { /* direction == CCM_DECRYPT */
+ for (; y < (ptlen & ~15); y += 16) {
+ /* increment the ctr? */
+ for (z = 15; z > 15-L; z--) {
+ ctr[z] = (ctr[z] + 1) & 255;
+ if (ctr[z]) break;
+ }
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* xor the PT against the pad last */
+ for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z]));
+ *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z]));
+ }
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+ }
+ }
+ }
+#endif
+
+ for (; y < ptlen; y++) {
+ /* increment the ctr? */
+ if (CTRlen == 16) {
+ for (z = 15; z > 15-L; z--) {
+ ctr[z] = (ctr[z] + 1) & 255;
+ if (ctr[z]) break;
+ }
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+ CTRlen = 0;
+ }
+
+ /* if we encrypt we add the bytes to the MAC first */
+ if (direction == CCM_ENCRYPT) {
+ b = pt[y];
+ ct[y] = b ^ CTRPAD[CTRlen++];
+ } else {
+ b = ct[y] ^ CTRPAD[CTRlen++];
+ pt[y] = b;
+ }
+
+ if (x == 16) {
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+ x = 0;
+ }
+ PAD[x++] ^= b;
+ }
+
+ if (x != 0) {
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+ }
+ }
+
+ /* setup CTR for the TAG (zero the count) */
+ for (y = 15; y > 15 - L; y--) {
+ ctr[y] = 0x00;
+ }
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if (skey != uskey) {
+ cipher_descriptor[cipher].done(skey);
+#ifdef LTC_CLEAN_STACK
+ zeromem(skey, sizeof(*skey));
+#endif
+ }
+
+ if (direction == CCM_ENCRYPT) {
+ /* store the TAG */
+ for (x = 0; x < 16 && x < *taglen; x++) {
+ tag[x] = PAD[x] ^ CTRPAD[x];
+ }
+ *taglen = x;
+ } else { /* direction == CCM_DECRYPT */
+ /* decrypt the tag */
+ for (x = 0; x < 16 && x < *taglen; x++) {
+ ptTag[x] = tag[x] ^ CTRPAD[x];
+ }
+ *taglen = x;
+
+ /* check validity of the decrypted tag against the computed PAD (in constant time) */
+ /* HACK: the boolean value of XMEM_NEQ becomes either 0 (CRYPT_OK) or 1 (CRYPT_ERR).
+ * there should be a better way of setting the correct error code in constant
+ * time.
+ */
+ err = XMEM_NEQ(ptTag, PAD, *taglen);
+
+ /* Zero the plaintext if the tag was invalid (in constant time) */
+ if (ptlen > 0) {
+ copy_or_zeromem(pt, pt_real, ptlen, err);
+ }
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(PAD, sizeof(PAD));
+ zeromem(CTRPAD, sizeof(CTRPAD));
+ if (pt_work != NULL) {
+ zeromem(pt_work, ptlen);
+ }
+#endif
+error:
+ if (pt_work) {
+ XFREE(pt_work);
+ }
+ if (skey != uskey) {
+ XFREE(skey);
+ }
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ccm/ccm_process.c b/Sources/libtomcrypt/encauth/ccm/ccm_process.c
new file mode 100644
index 00000000..3d224809
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ccm/ccm_process.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CCM_MODE
+
+/**
+ Process plaintext/ciphertext through CCM
+ @param ccm The CCM state
+ @param pt The plaintext
+ @param ptlen The plaintext length (ciphertext length is the same)
+ @param ct The ciphertext
+ @param direction Encrypt or Decrypt mode (CCM_ENCRYPT or CCM_DECRYPT)
+ @return CRYPT_OK on success
+ */
+int ccm_process(ccm_state *ccm,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ int direction)
+{
+ unsigned char z, b;
+ unsigned long y;
+ int err;
+
+ LTC_ARGCHK(ccm != NULL);
+
+ /* Check aad has been correctly added */
+ if (ccm->aadlen != ccm->current_aadlen) {
+ return CRYPT_ERROR;
+ }
+
+ /* Check we do not process too much data */
+ if (ccm->ptlen < ccm->current_ptlen + ptlen) {
+ return CRYPT_ERROR;
+ }
+ ccm->current_ptlen += ptlen;
+
+ /* now handle the PT */
+ if (ptlen > 0) {
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ for (y = 0; y < ptlen; y++) {
+ /* increment the ctr? */
+ if (ccm->CTRlen == 16) {
+ for (z = 15; z > 15-ccm->L; z--) {
+ ccm->ctr[z] = (ccm->ctr[z] + 1) & 255;
+ if (ccm->ctr[z]) break;
+ }
+ if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) {
+ return err;
+ }
+ ccm->CTRlen = 0;
+ }
+
+ /* if we encrypt we add the bytes to the MAC first */
+ if (direction == CCM_ENCRYPT) {
+ b = pt[y];
+ ct[y] = b ^ ccm->CTRPAD[ccm->CTRlen++];
+ } else {
+ b = ct[y] ^ ccm->CTRPAD[ccm->CTRlen++];
+ pt[y] = b;
+ }
+
+ if (ccm->x == 16) {
+ if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) {
+ return err;
+ }
+ ccm->x = 0;
+ }
+ ccm->PAD[ccm->x++] ^= b;
+ }
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ccm/ccm_reset.c b/Sources/libtomcrypt/encauth/ccm/ccm_reset.c
new file mode 100644
index 00000000..93b8fecc
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ccm/ccm_reset.c
@@ -0,0 +1,25 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CCM_MODE
+
+/**
+ Reset a CCM state to as if you just called ccm_init(). This saves the initialization time.
+ @param ccm The CCM state to reset
+ @return CRYPT_OK on success
+*/
+int ccm_reset(ccm_state *ccm)
+{
+ LTC_ARGCHK(ccm != NULL);
+ zeromem(ccm->PAD, sizeof(ccm->PAD));
+ zeromem(ccm->ctr, sizeof(ccm->ctr));
+ zeromem(ccm->CTRPAD, sizeof(ccm->CTRPAD));
+ ccm->CTRlen = 0;
+ ccm->current_ptlen = 0;
+ ccm->current_aadlen = 0;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ccm/ccm_test.c b/Sources/libtomcrypt/encauth/ccm/ccm_test.c
new file mode 100644
index 00000000..bd71da96
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ccm/ccm_test.c
@@ -0,0 +1,274 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ccm_test.c
+ CCM support, process a block of memory, Tom St Denis
+*/
+
+#ifdef LTC_CCM_MODE
+
+int ccm_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ unsigned char key[16];
+ unsigned char nonce[16];
+ int noncelen;
+ unsigned char header[64];
+ int headerlen;
+ unsigned char pt[64];
+ int ptlen;
+ unsigned char ct[64];
+ unsigned char tag[16];
+ unsigned long taglen;
+ } tests[] = {
+
+/* 13 byte nonce, 8 byte auth, 23 byte pt */
+{
+ { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF },
+ { 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 },
+ 13,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
+ 8,
+ { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E },
+ 23,
+ { 0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2,
+ 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80,
+ 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84 },
+ { 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
+ 8
+},
+
+/* 13 byte nonce, 12 byte header, 19 byte pt */
+{
+ { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF },
+ { 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x03, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 },
+ 13,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B },
+ 12,
+ { 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E },
+ 19,
+ { 0xA2, 0x8C, 0x68, 0x65, 0x93, 0x9A, 0x9A, 0x79,
+ 0xFA, 0xAA, 0x5C, 0x4C, 0x2A, 0x9D, 0x4A, 0x91,
+ 0xCD, 0xAC, 0x8C },
+ { 0x96, 0xC8, 0x61, 0xB9, 0xC9, 0xE6, 0x1E, 0xF1 },
+ 8
+},
+
+/* supplied by Brian Gladman */
+{
+ { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f },
+ { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 },
+ 7,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
+ 8,
+ { 0x20, 0x21, 0x22, 0x23 },
+ 4,
+ { 0x71, 0x62, 0x01, 0x5b },
+ { 0x4d, 0xac, 0x25, 0x5d },
+ 4
+},
+
+{
+ { 0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85,
+ 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f },
+ { 0x00, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xb5,
+ 0x03, 0x97, 0x76, 0xe7, 0x0c },
+ 13,
+ { 0x08, 0x40, 0x0f, 0xd2, 0xe1, 0x28, 0xa5, 0x7c,
+ 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xab, 0xae,
+ 0xa5, 0xb8, 0xfc, 0xba, 0x00, 0x00 },
+ 22,
+ { 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,
+ 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb,
+ 0x7e, 0x78, 0xa0, 0x50 },
+ 20,
+ { 0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23,
+ 0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c,
+ 0x3c, 0x04, 0xd0, 0x19 },
+ { 0x78, 0x45, 0xce, 0x0b, 0x16, 0xf9, 0x76, 0x23 },
+ 8
+},
+
+};
+ unsigned long taglen, x, y;
+ unsigned char buf[64], buf2[64], tag[16], tag2[16], tag3[16], zero[64];
+ int err, idx;
+ symmetric_key skey;
+ ccm_state ccm;
+
+ zeromem(zero, 64);
+
+ idx = find_cipher("aes");
+ if (idx == -1) {
+ idx = find_cipher("rijndael");
+ if (idx == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ for (x = 0; x < (sizeof(tests)/sizeof(tests[0])); x++) {
+ for (y = 0; y < 2; y++) {
+ taglen = tests[x].taglen;
+ if (y == 0) {
+ if ((err = cipher_descriptor[idx].setup(tests[x].key, 16, 0, &skey)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = ccm_memory(idx,
+ tests[x].key, 16,
+ &skey,
+ tests[x].nonce, tests[x].noncelen,
+ tests[x].header, tests[x].headerlen,
+ (unsigned char*)tests[x].pt, tests[x].ptlen,
+ buf,
+ tag, &taglen, 0)) != CRYPT_OK) {
+ return err;
+ }
+ /* run a second time to make sure skey is not touched */
+ if ((err = ccm_memory(idx,
+ tests[x].key, 16,
+ &skey,
+ tests[x].nonce, tests[x].noncelen,
+ tests[x].header, tests[x].headerlen,
+ (unsigned char*)tests[x].pt, tests[x].ptlen,
+ buf,
+ tag, &taglen, 0)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = ccm_process(&ccm, (unsigned char*)tests[x].pt, tests[x].ptlen, buf, CCM_ENCRYPT)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = ccm_done(&ccm, tag, &taglen)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ if (compare_testvector(buf, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "CCM encrypt data", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ if (compare_testvector(tag, taglen, tests[x].tag, tests[x].taglen, "CCM encrypt tag", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ if (y == 0) {
+ XMEMCPY(tag3, tests[x].tag, tests[x].taglen);
+ taglen = tests[x].taglen;
+ if ((err = ccm_memory(idx,
+ tests[x].key, 16,
+ NULL,
+ tests[x].nonce, tests[x].noncelen,
+ tests[x].header, tests[x].headerlen,
+ buf2, tests[x].ptlen,
+ buf,
+ tag3, &taglen, 1 )) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = ccm_process(&ccm, buf2, tests[x].ptlen, buf, CCM_DECRYPT)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = ccm_done(&ccm, tag2, &taglen)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+
+ if (compare_testvector(buf2, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "CCM decrypt data", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ if (y == 0) {
+ /* check if decryption with the wrong tag does not reveal the plaintext */
+ XMEMCPY(tag3, tests[x].tag, tests[x].taglen);
+ tag3[0] ^= 0xff; /* set the tag to the wrong value */
+ taglen = tests[x].taglen;
+ if (ccm_memory(idx,
+ tests[x].key, 16,
+ NULL,
+ tests[x].nonce, tests[x].noncelen,
+ tests[x].header, tests[x].headerlen,
+ buf2, tests[x].ptlen,
+ buf,
+ tag3, &taglen, 1 ) != CRYPT_ERROR) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ if (compare_testvector(buf2, tests[x].ptlen, zero, tests[x].ptlen, "CCM decrypt wrong tag", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ } else {
+ if (compare_testvector(tag2, taglen, tests[x].tag, tests[x].taglen, "CCM decrypt tag", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ if (y == 0) {
+ cipher_descriptor[idx].done(&skey);
+ }
+ }
+ }
+
+ /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/452 */
+ {
+ unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
+ unsigned char iv[] = { 0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51 };
+ unsigned char valid_tag[] = { 0x23,0x1a,0x2d,0x8f };
+ unsigned char invalid_tag[] = { 0x23,0x1a,0x2d,0x8f,0x6a };
+ unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f };
+ unsigned char ct[] = { 0xd3,0xda,0xb1,0xee,0x49,0x4c,0xc2,0x29,0x09,0x9d,0x6c,0xac,0x7d,0xf1,0x4a,0xdd };
+ unsigned char pt[20] = { 0 };
+
+ /* VALID tag */
+ taglen = sizeof(valid_tag);
+ err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0,
+ pt, sizeof(ct), ct, valid_tag, &taglen, CCM_DECRYPT);
+ if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* INVALID tag */
+ taglen = sizeof(invalid_tag);
+ err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0,
+ pt, sizeof(ct), ct, invalid_tag, &taglen, CCM_DECRYPT);
+ if (err == CRYPT_OK) {
+ return CRYPT_FAIL_TESTVECTOR; /* should fail */
+ }
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_add_aad.c b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_add_aad.c
new file mode 100644
index 00000000..dc6b5bb9
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_add_aad.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+/**
+ Add AAD to the ChaCha20Poly1305 state
+ @param st The ChaCha20Poly1305 state
+ @param in The additional authentication data to add to the ChaCha20Poly1305 state
+ @param inlen The length of the ChaCha20Poly1305 data.
+ @return CRYPT_OK on success
+ */
+int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen)
+{
+ int err;
+
+ if (inlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(st != NULL);
+
+ if (st->aadflg == 0) return CRYPT_ERROR;
+ if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err;
+ st->aadlen += (ulong64)inlen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_decrypt.c b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_decrypt.c
new file mode 100644
index 00000000..e51322a5
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_decrypt.c
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+/**
+ Decrypt bytes of ciphertext with ChaCha20Poly1305
+ @param st The ChaCha20Poly1305 state
+ @param in The ciphertext
+ @param inlen The length of the input (octets)
+ @param out [out] The plaintext (length inlen)
+ @return CRYPT_OK if successful
+*/
+int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out)
+{
+ unsigned char padzero[16] = { 0 };
+ unsigned long padlen;
+ int err;
+
+ LTC_ARGCHK(st != NULL);
+
+ if (st->aadflg) {
+ padlen = 16 - (unsigned long)(st->aadlen % 16);
+ if (padlen < 16) {
+ if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err;
+ }
+ st->aadflg = 0; /* no more AAD */
+ }
+ if (st->aadflg) st->aadflg = 0; /* no more AAD */
+ if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err;
+ if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err;
+ st->ctlen += (ulong64)inlen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_done.c b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_done.c
new file mode 100644
index 00000000..b27ae661
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_done.c
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+/**
+ Terminate a ChaCha20Poly1305 stream
+ @param st The ChaCha20Poly1305 state
+ @param tag [out] The destination for the MAC tag
+ @param taglen [in/out] The length of the MAC tag
+ @return CRYPT_OK on success
+ */
+int chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen)
+{
+ unsigned char padzero[16] = { 0 };
+ unsigned long padlen;
+ unsigned char buf[16];
+ int err;
+
+ LTC_ARGCHK(st != NULL);
+
+ if (!st->openssh_compat) {
+ padlen = 16 - (unsigned long)(st->ctlen % 16);
+ if (padlen < 16) {
+ if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err;
+ }
+ STORE64L(st->aadlen, buf);
+ STORE64L(st->ctlen, buf + 8);
+ if ((err = poly1305_process(&st->poly, buf, 16)) != CRYPT_OK) return err;
+ }
+ if ((err = poly1305_done(&st->poly, tag, taglen)) != CRYPT_OK) return err;
+ if ((err = chacha_done(&st->chacha)) != CRYPT_OK) return err;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_encrypt.c b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_encrypt.c
new file mode 100644
index 00000000..2a4208e3
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_encrypt.c
@@ -0,0 +1,37 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+/**
+ Encrypt bytes of ciphertext with ChaCha20Poly1305
+ @param st The ChaCha20Poly1305 state
+ @param in The plaintext
+ @param inlen The length of the input (octets)
+ @param out [out] The ciphertext (length inlen)
+ @return CRYPT_OK if successful
+*/
+int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out)
+{
+ unsigned char padzero[16] = { 0 };
+ unsigned long padlen;
+ int err;
+
+ LTC_ARGCHK(st != NULL);
+
+ if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err;
+ if (st->aadflg) {
+ padlen = 16 - (unsigned long)(st->aadlen % 16);
+ if (padlen < 16) {
+ if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err;
+ }
+ st->aadflg = 0; /* no more AAD */
+ }
+ if ((err = poly1305_process(&st->poly, out, inlen)) != CRYPT_OK) return err;
+ st->ctlen += (ulong64)inlen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_init.c b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_init.c
new file mode 100644
index 00000000..14ddb6c1
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_init.c
@@ -0,0 +1,21 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+/**
+ Initialize an ChaCha20Poly1305 context (only the key)
+ @param st [out] The destination of the ChaCha20Poly1305 state
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @return CRYPT_OK if successful
+*/
+int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen)
+{
+ XMEMSET(st, 0, sizeof(*st));
+ return chacha_setup(&st->chacha, key, keylen, 20);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_memory.c b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_memory.c
new file mode 100644
index 00000000..5adca427
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_memory.c
@@ -0,0 +1,76 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+/**
+ Process an entire GCM packet in one call.
+ @param key The secret key
+ @param keylen The length of the secret key
+ @param iv The initialization vector
+ @param ivlen The length of the initialization vector
+ @param aad The additional authentication data (header)
+ @param aadlen The length of the aad
+ @param in The plaintext
+ @param inlen The length of the plaintext (ciphertext length is the same)
+ @param out The ciphertext
+ @param tag [out] The MAC tag
+ @param taglen [in/out] The MAC tag length
+ @param direction Encrypt or Decrypt mode (CHACHA20POLY1305_ENCRYPT or CHACHA20POLY1305_DECRYPT)
+ @return CRYPT_OK on success
+ */
+int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *aad, unsigned long aadlen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out,
+ unsigned char *tag, unsigned long *taglen,
+ int direction)
+{
+ chacha20poly1305_state st;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(iv != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+
+ if ((err = chacha20poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; }
+
+ st.openssh_compat = (direction & CHACHA20POLY1305_OPENSSH_COMPAT) ? 1 : 0;
+ direction &= ~(CHACHA20POLY1305_OPENSSH_COMPAT);
+
+ if ((err = chacha20poly1305_setiv(&st, iv, ivlen)) != CRYPT_OK) { goto LBL_ERR; }
+ if (aad && aadlen > 0) {
+ if ((err = chacha20poly1305_add_aad(&st, aad, aadlen)) != CRYPT_OK) { goto LBL_ERR; }
+ }
+ if (direction == CHACHA20POLY1305_ENCRYPT) {
+ if ((err = chacha20poly1305_encrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = chacha20poly1305_done(&st, tag, taglen)) != CRYPT_OK) { goto LBL_ERR; }
+ }
+ else if (direction == CHACHA20POLY1305_DECRYPT) {
+ unsigned char buf[MAXBLOCKSIZE];
+ unsigned long buflen = sizeof(buf);
+ if ((err = chacha20poly1305_decrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = chacha20poly1305_done(&st, buf, &buflen)) != CRYPT_OK) { goto LBL_ERR; }
+ if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) {
+ err = CRYPT_ERROR;
+ goto LBL_ERR;
+ }
+ }
+ else {
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(chacha20poly1305_state));
+#endif
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv.c b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv.c
new file mode 100644
index 00000000..d5ec3e69
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv.c
@@ -0,0 +1,58 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+/**
+ Set IV + counter data to the ChaCha20Poly1305 state and reset the context
+ @param st The ChaCha20Poly1305 state
+ @param iv The IV data to add
+ @param ivlen The length of the IV (must be 12 or 8)
+ @return CRYPT_OK on success
+ */
+int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen)
+{
+ chacha_state tmp_st;
+ int i, err;
+ unsigned char polykey[32];
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(iv != NULL);
+ LTC_ARGCHK(ivlen == 12 || ivlen == 8);
+
+ /* set IV for chacha20 */
+ if (ivlen == 12) {
+ /* IV 96bit */
+ if ((err = chacha_ivctr32(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err;
+ }
+ else {
+ /* IV 64bit */
+ if ((err = chacha_ivctr64(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err;
+ }
+
+ /* copy chacha20 key to temporary state */
+ for(i = 0; i < 12; i++) tmp_st.input[i] = st->chacha.input[i];
+ tmp_st.rounds = 20;
+ /* set IV */
+ if (ivlen == 12) {
+ /* IV 32bit */
+ if ((err = chacha_ivctr32(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err;
+ }
+ else {
+ /* IV 64bit */
+ if ((err = chacha_ivctr64(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err;
+ }
+ /* (re)generate new poly1305 key */
+ if ((err = chacha_keystream(&tmp_st, polykey, 32)) != CRYPT_OK) return err;
+ /* (re)initialise poly1305 */
+ if ((err = poly1305_init(&st->poly, polykey, 32)) != CRYPT_OK) return err;
+ st->ctlen = 0;
+ st->aadlen = 0;
+ st->aadflg = 1;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c
new file mode 100644
index 00000000..75da634f
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+/**
+ Set IV + counter data (with RFC7905-magic) to the ChaCha20Poly1305 state and reset the context
+ @param st The ChaCha20Poly1305 state
+ @param iv The IV data to add
+ @param ivlen The length of the IV (must be 12 or 8)
+ @param sequence_number 64bit sequence number which is incorporated into IV as described in RFC7905
+ @return CRYPT_OK on success
+ */
+int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number)
+{
+ int i;
+ unsigned char combined_iv[12] = { 0 };
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(iv != NULL);
+ LTC_ARGCHK(ivlen == 12);
+
+ STORE64L(sequence_number, combined_iv + 4);
+ for (i = 0; i < 12; i++) combined_iv[i] = iv[i] ^ combined_iv[i];
+ return chacha20poly1305_setiv(st, combined_iv, 12);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_test.c b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_test.c
new file mode 100644
index 00000000..30d49731
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/chachapoly/chacha20poly1305_test.c
@@ -0,0 +1,159 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+int chacha20poly1305_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ chacha20poly1305_state st1, st2;
+ unsigned char k[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f };
+ unsigned char i12[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 };
+ unsigned char i8[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43 };
+ unsigned char aad[] = { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 };
+ unsigned char enc[] = { 0xD3, 0x1A, 0x8D, 0x34, 0x64, 0x8E, 0x60, 0xDB, 0x7B, 0x86, 0xAF, 0xBC, 0x53, 0xEF, 0x7E, 0xC2,
+ 0xA4, 0xAD, 0xED, 0x51, 0x29, 0x6E, 0x08, 0xFE, 0xA9, 0xE2, 0xB5, 0xA7, 0x36, 0xEE, 0x62, 0xD6,
+ 0x3D, 0xBE, 0xA4, 0x5E, 0x8C, 0xA9, 0x67, 0x12, 0x82, 0xFA, 0xFB, 0x69, 0xDA, 0x92, 0x72, 0x8B,
+ 0x1A, 0x71, 0xDE, 0x0A, 0x9E, 0x06, 0x0B, 0x29, 0x05, 0xD6, 0xA5, 0xB6, 0x7E, 0xCD, 0x3B, 0x36,
+ 0x92, 0xDD, 0xBD, 0x7F, 0x2D, 0x77, 0x8B, 0x8C, 0x98, 0x03, 0xAE, 0xE3, 0x28, 0x09, 0x1B, 0x58,
+ 0xFA, 0xB3, 0x24, 0xE4, 0xFA, 0xD6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8B, 0x48, 0x31, 0xD7, 0xBC,
+ 0x3F, 0xF4, 0xDE, 0xF0, 0x8E, 0x4B, 0x7A, 0x9D, 0xE5, 0x76, 0xD2, 0x65, 0x86, 0xCE, 0xC6, 0x4B,
+ 0x61, 0x16 };
+ unsigned char tag[] = { 0x1A, 0xE1, 0x0B, 0x59, 0x4F, 0x09, 0xE2, 0x6A, 0x7E, 0x90, 0x2E, 0xCB, 0xD0, 0x60, 0x06, 0x91 };
+ char m[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
+ unsigned long mlen = XSTRLEN(m);
+ unsigned long len;
+ unsigned char rfc7905_pt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ unsigned char rfc7905_enc[] = { 0xE4, 0x62, 0x85, 0xB4, 0x29, 0x95, 0x34, 0x96, 0xAB, 0xFB, 0x67, 0xCD, 0xAE, 0xAC, 0x94, 0x1E };
+ unsigned char rfc7905_tag[] = { 0x16, 0x2C, 0x92, 0x48, 0x2A, 0xDB, 0xD3, 0x5D, 0x48, 0xBE, 0xC6, 0xFF, 0x10, 0x9C, 0xBA, 0xE4 };
+ unsigned char ct[1000], pt[1000], emac[16], dmac[16];
+ int err;
+
+ /* encrypt IV 96bit */
+ if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_setiv(&st1, i12, sizeof(i12))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err;
+ /* encrypt piece by piece */
+ if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, 25, ct)) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 25, 10, ct + 25)) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 35, 35, ct + 35)) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 70, 5, ct + 70)) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 75, 5, ct + 75)) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 80, mlen - 80, ct + 80)) != CRYPT_OK) return err;
+ len = sizeof(emac);
+ if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err;
+
+ if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+ if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG", 2) != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ /* decrypt IV 96bit */
+ if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_setiv(&st2, i12, sizeof(i12))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_decrypt(&st2, ct, 21, pt)) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_decrypt(&st2, ct + 21, mlen - 21, pt + 21)) != CRYPT_OK) return err;
+ len = sizeof(dmac);
+ if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err;
+
+ if (compare_testvector(pt, mlen, m, mlen, "DEC-PT", 3) != 0) return CRYPT_FAIL_TESTVECTOR;
+ if (compare_testvector(dmac, len, tag, sizeof(tag), "DEC-TAG", 4) != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ /* chacha20poly1305_memory - encrypt */
+ len = sizeof(emac);
+ if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad), (unsigned char *)m,
+ mlen, ct, emac, &len, CHACHA20POLY1305_ENCRYPT)) != CRYPT_OK) return err;
+ if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT2", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+ if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG2", 2) != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ /* chacha20poly1305_memory - decrypt */
+ len = sizeof(dmac);
+ XMEMCPY(dmac, tag, sizeof(tag));
+ if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad),
+ ct, mlen, pt, dmac, &len, CHACHA20POLY1305_DECRYPT)) != CRYPT_OK) return err;
+ if (compare_testvector(pt, mlen, m, mlen, "DEC-PT2", 3) != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ /* encrypt - rfc7905 */
+ if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_encrypt(&st1, rfc7905_pt, 16, ct)) != CRYPT_OK) return err;
+ len = sizeof(emac);
+ if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err;
+
+ if (compare_testvector(ct, 16, rfc7905_enc, 16, "ENC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+ if (compare_testvector(emac, len, rfc7905_tag, 16, "ENC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ /* decrypt - rfc7905 */
+ if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_decrypt(&st1, ct, 16, pt)) != CRYPT_OK) return err;
+ len = sizeof(dmac);
+ if ((err = chacha20poly1305_done(&st1, dmac, &len)) != CRYPT_OK) return err;
+
+ if (compare_testvector(pt, 16, rfc7905_pt, 16, "DEC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+ if (compare_testvector(dmac, len, rfc7905_tag, 16, "DEC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ /* encrypt IV 64bit */
+ if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_setiv(&st1, i8, sizeof(i8))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, mlen, ct)) != CRYPT_OK) return err;
+ len = sizeof(emac);
+ if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err;
+
+ /* decrypt IV 64bit */
+ if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_setiv(&st2, i8, sizeof(i8))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err;
+ if ((err = chacha20poly1305_decrypt(&st2, ct, mlen, pt)) != CRYPT_OK) return err;
+ len = sizeof(dmac);
+ if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err;
+
+ if (compare_testvector(pt, mlen, m, mlen, "DEC-PT4", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+ if (compare_testvector(dmac, len, emac, len, "DEC-TAG4", 2) != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */
+ {
+ unsigned char key[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,
+ 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff };
+ unsigned char iv[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b };
+ unsigned char valid_tag[] = { 0xa3,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 };
+ unsigned char invalid_tag[] = { 0xa2,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 };
+ unsigned char waad[] = { 0x61,0x61,0x64 };
+ unsigned char wct[] = { 0x00 };
+ unsigned char wpt[20] = { 0 };
+ unsigned char wtag[20] = { 0 };
+ unsigned long taglen;
+
+ /* encrypt */
+ taglen = sizeof(wtag);
+ err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad),
+ wpt, 0, wct, wtag, &taglen, CHACHA20POLY1305_ENCRYPT);
+ if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR;
+ if (compare_testvector(wtag, taglen, valid_tag, sizeof(valid_tag), "WYCH", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+
+ /* VALID tag */
+ taglen = sizeof(valid_tag);
+ err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad),
+ wpt, 0, wct, valid_tag, &taglen, CHACHA20POLY1305_DECRYPT);
+ if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR;
+
+ /* INVALID tag */
+ taglen = sizeof(invalid_tag);
+ err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad),
+ wpt, 0, wct, invalid_tag, &taglen, CHACHA20POLY1305_DECRYPT);
+ if (err == CRYPT_OK) {
+ return CRYPT_FAIL_TESTVECTOR; /* should fail */
+ }
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/eax/eax_addheader.c b/Sources/libtomcrypt/encauth/eax/eax_addheader.c
new file mode 100644
index 00000000..a6b8f76c
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/eax/eax_addheader.c
@@ -0,0 +1,26 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**
+ @file eax_addheader.c
+ EAX implementation, add meta-data, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_EAX_MODE
+
+/**
+ add header (metadata) to the stream
+ @param eax The current EAX state
+ @param header The header (meta-data) data you wish to add to the state
+ @param length The length of the header data
+ @return CRYPT_OK if successful
+*/
+int eax_addheader(eax_state *eax, const unsigned char *header,
+ unsigned long length)
+{
+ LTC_ARGCHK(eax != NULL);
+ LTC_ARGCHK(header != NULL);
+ return omac_process(&eax->headeromac, header, length);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/eax/eax_decrypt.c b/Sources/libtomcrypt/encauth/eax/eax_decrypt.c
new file mode 100644
index 00000000..cc03c5c5
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/eax/eax_decrypt.c
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file eax_decrypt.c
+ EAX implementation, decrypt block, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_EAX_MODE
+
+/**
+ Decrypt data with the EAX protocol
+ @param eax The EAX state
+ @param ct The ciphertext
+ @param pt [out] The plaintext
+ @param length The length (octets) of the ciphertext
+ @return CRYPT_OK if successful
+*/
+int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt,
+ unsigned long length)
+{
+ int err;
+
+ LTC_ARGCHK(eax != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ /* omac ciphertext */
+ if ((err = omac_process(&eax->ctomac, ct, length)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* decrypt */
+ return ctr_decrypt(ct, pt, length, &eax->ctr);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/eax/eax_decrypt_verify_memory.c b/Sources/libtomcrypt/encauth/eax/eax_decrypt_verify_memory.c
new file mode 100644
index 00000000..5429d4ae
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/eax/eax_decrypt_verify_memory.c
@@ -0,0 +1,99 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file eax_decrypt_verify_memory.c
+ EAX implementation, decrypt block of memory, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_EAX_MODE
+
+/**
+ Decrypt a block of memory and verify the provided MAC tag with EAX
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the key (octets)
+ @param nonce The nonce data (use once) for the session
+ @param noncelen The length of the nonce data.
+ @param header The session header data
+ @param headerlen The length of the header (octets)
+ @param ct The ciphertext
+ @param ctlen The length of the ciphertext (octets)
+ @param pt [out] The plaintext
+ @param tag The authentication tag provided by the encoder
+ @param taglen [in/out] The length of the tag (octets)
+ @param stat [out] The result of the decryption (1==valid tag, 0==invalid)
+ @return CRYPT_OK if successful regardless of the resulting tag comparison
+*/
+int eax_decrypt_verify_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen,
+ int *stat)
+{
+ int err;
+ eax_state *eax;
+ unsigned char *buf;
+ unsigned long buflen;
+
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tag != NULL);
+
+ /* default to zero */
+ *stat = 0;
+
+ /* limit taglen */
+ taglen = MIN(taglen, MAXBLOCKSIZE);
+
+ /* allocate ram */
+ buf = XMALLOC(taglen);
+ eax = XMALLOC(sizeof(*eax));
+ if (eax == NULL || buf == NULL) {
+ if (eax != NULL) {
+ XFREE(eax);
+ }
+ if (buf != NULL) {
+ XFREE(buf);
+ }
+ return CRYPT_MEM;
+ }
+
+ if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if ((err = eax_decrypt(eax, ct, pt, ctlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ buflen = taglen;
+ if ((err = eax_done(eax, buf, &buflen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* compare tags */
+ if (buflen >= taglen && XMEM_NEQ(buf, tag, taglen) == 0) {
+ *stat = 1;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, taglen);
+ zeromem(eax, sizeof(*eax));
+#endif
+
+ XFREE(eax);
+ XFREE(buf);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/eax/eax_done.c b/Sources/libtomcrypt/encauth/eax/eax_done.c
new file mode 100644
index 00000000..f2362cf5
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/eax/eax_done.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file eax_done.c
+ EAX implementation, terminate session, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_EAX_MODE
+
+/**
+ Terminate an EAX session and get the tag.
+ @param eax The EAX state
+ @param tag [out] The destination of the authentication tag
+ @param taglen [in/out] The max length and resulting length of the authentication tag
+ @return CRYPT_OK if successful
+*/
+int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen)
+{
+ int err;
+ unsigned char *headermac, *ctmac;
+ unsigned long x, len;
+
+ LTC_ARGCHK(eax != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+
+ /* allocate ram */
+ headermac = XMALLOC(MAXBLOCKSIZE);
+ ctmac = XMALLOC(MAXBLOCKSIZE);
+
+ if (headermac == NULL || ctmac == NULL) {
+ if (headermac != NULL) {
+ XFREE(headermac);
+ }
+ if (ctmac != NULL) {
+ XFREE(ctmac);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* finish ctomac */
+ len = MAXBLOCKSIZE;
+ if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* finish headeromac */
+
+ /* note we specifically don't reset len so the two lens are minimal */
+
+ if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* terminate the CTR chain */
+ if ((err = ctr_done(&eax->ctr)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* compute N xor H xor C */
+ for (x = 0; x < len && x < *taglen; x++) {
+ tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x];
+ }
+ *taglen = x;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(ctmac, MAXBLOCKSIZE);
+ zeromem(headermac, MAXBLOCKSIZE);
+ zeromem(eax, sizeof(*eax));
+#endif
+
+ XFREE(ctmac);
+ XFREE(headermac);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/eax/eax_encrypt.c b/Sources/libtomcrypt/encauth/eax/eax_encrypt.c
new file mode 100644
index 00000000..dba32390
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/eax/eax_encrypt.c
@@ -0,0 +1,39 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file eax_encrypt.c
+ EAX implementation, encrypt block by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_EAX_MODE
+
+/**
+ Encrypt with EAX a block of data.
+ @param eax The EAX state
+ @param pt The plaintext to encrypt
+ @param ct [out] The ciphertext as encrypted
+ @param length The length of the plaintext (octets)
+ @return CRYPT_OK if successful
+*/
+int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct,
+ unsigned long length)
+{
+ int err;
+
+ LTC_ARGCHK(eax != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ /* encrypt */
+ if ((err = ctr_encrypt(pt, ct, length, &eax->ctr)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* omac ciphertext */
+ return omac_process(&eax->ctomac, ct, length);
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/eax/eax_encrypt_authenticate_memory.c b/Sources/libtomcrypt/encauth/eax/eax_encrypt_authenticate_memory.c
new file mode 100644
index 00000000..76aeec2b
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/eax/eax_encrypt_authenticate_memory.c
@@ -0,0 +1,70 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file eax_encrypt_authenticate_memory.c
+ EAX implementation, encrypt a block of memory, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_EAX_MODE
+
+/**
+ EAX encrypt and produce an authentication tag
+ @param cipher The index of the cipher desired
+ @param key The secret key to use
+ @param keylen The length of the secret key (octets)
+ @param nonce The session nonce [use once]
+ @param noncelen The length of the nonce
+ @param header The header for the session
+ @param headerlen The length of the header (octets)
+ @param pt The plaintext
+ @param ptlen The length of the plaintext (octets)
+ @param ct [out] The ciphertext
+ @param tag [out] The destination tag
+ @param taglen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful
+*/
+int eax_encrypt_authenticate_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen)
+{
+ int err;
+ eax_state *eax;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+
+ eax = XMALLOC(sizeof(*eax));
+
+ if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if ((err = eax_encrypt(eax, pt, ct, ptlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if ((err = eax_done(eax, tag, taglen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(eax, sizeof(*eax));
+#endif
+
+ XFREE(eax);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/eax/eax_init.c b/Sources/libtomcrypt/encauth/eax/eax_init.c
new file mode 100644
index 00000000..153c4273
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/eax/eax_init.c
@@ -0,0 +1,132 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file eax_init.c
+ EAX implementation, initialized EAX state, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_EAX_MODE
+
+/**
+ Initialized an EAX state
+ @param eax [out] The EAX state to initialize
+ @param cipher The index of the desired cipher
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param nonce The use-once nonce for the session
+ @param noncelen The length of the nonce (octets)
+ @param header The header for the EAX state
+ @param headerlen The header length (octets)
+ @return CRYPT_OK if successful
+*/
+int eax_init(eax_state *eax, int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen)
+{
+ unsigned char *buf;
+ int err, blklen;
+ omac_state *omac;
+ unsigned long len;
+
+
+ LTC_ARGCHK(eax != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(nonce != NULL);
+ if (headerlen > 0) {
+ LTC_ARGCHK(header != NULL);
+ }
+
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+ blklen = cipher_descriptor[cipher].block_length;
+
+ /* allocate ram */
+ buf = XMALLOC(MAXBLOCKSIZE);
+ omac = XMALLOC(sizeof(*omac));
+
+ if (buf == NULL || omac == NULL) {
+ if (buf != NULL) {
+ XFREE(buf);
+ }
+ if (omac != NULL) {
+ XFREE(omac);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* N = LTC_OMAC_0K(nonce) */
+ zeromem(buf, MAXBLOCKSIZE);
+ if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* omac the [0]_n */
+ if ((err = omac_process(omac, buf, blklen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* omac the nonce */
+ if ((err = omac_process(omac, nonce, noncelen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* store result */
+ len = sizeof(eax->N);
+ if ((err = omac_done(omac, eax->N, &len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* H = LTC_OMAC_1K(header) */
+ zeromem(buf, MAXBLOCKSIZE);
+ buf[blklen - 1] = 1;
+
+ if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* omac the [1]_n */
+ if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* omac the header */
+ if (headerlen != 0) {
+ if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* note we don't finish the headeromac, this allows us to add more header later */
+
+ /* setup the CTR mode */
+ if ((err = ctr_start(cipher, eax->N, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &eax->ctr)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* setup the LTC_OMAC for the ciphertext */
+ if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* omac [2]_n */
+ zeromem(buf, MAXBLOCKSIZE);
+ buf[blklen-1] = 2;
+ if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, MAXBLOCKSIZE);
+ zeromem(omac, sizeof(*omac));
+#endif
+
+ XFREE(omac);
+ XFREE(buf);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/eax/eax_test.c b/Sources/libtomcrypt/encauth/eax/eax_test.c
new file mode 100644
index 00000000..c613e0d2
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/eax/eax_test.c
@@ -0,0 +1,249 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file eax_test.c
+ EAX implementation, self-test, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_EAX_MODE
+
+/**
+ Test the EAX implementation
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+*/
+int eax_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ int keylen,
+ noncelen,
+ headerlen,
+ msglen;
+
+ unsigned char key[MAXBLOCKSIZE],
+ nonce[MAXBLOCKSIZE],
+ header[MAXBLOCKSIZE],
+ plaintext[MAXBLOCKSIZE],
+ ciphertext[MAXBLOCKSIZE],
+ tag[MAXBLOCKSIZE];
+ } tests[] = {
+
+/* NULL message */
+{
+ 16, 0, 0, 0,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0 },
+ /* header */
+ { 0 },
+ /* plaintext */
+ { 0 },
+ /* ciphertext */
+ { 0 },
+ /* tag */
+ { 0x9a, 0xd0, 0x7e, 0x7d, 0xbf, 0xf3, 0x01, 0xf5,
+ 0x05, 0xde, 0x59, 0x6b, 0x96, 0x15, 0xdf, 0xff }
+},
+
+/* test with nonce */
+{
+ 16, 16, 0, 0,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* header */
+ { 0 },
+ /* plaintext */
+ { 0 },
+ /* ciphertext */
+ { 0 },
+ /* tag */
+ { 0x1c, 0xe1, 0x0d, 0x3e, 0xff, 0xd4, 0xca, 0xdb,
+ 0xe2, 0xe4, 0x4b, 0x58, 0xd6, 0x0a, 0xb9, 0xec }
+},
+
+/* test with header [no nonce] */
+{
+ 16, 0, 16, 0,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0 },
+ /* header */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* plaintext */
+ { 0 },
+ /* ciphertext */
+ { 0 },
+ /* tag */
+ { 0x3a, 0x69, 0x8f, 0x7a, 0x27, 0x0e, 0x51, 0xb0,
+ 0xf6, 0x5b, 0x3d, 0x3e, 0x47, 0x19, 0x3c, 0xff }
+},
+
+/* test with header + nonce + plaintext */
+{
+ 16, 16, 16, 32,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* header */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* plaintext */
+ { 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 },
+ /* ciphertext */
+ { 0x29, 0xd8, 0x78, 0xd1, 0xa3, 0xbe, 0x85, 0x7b,
+ 0x6f, 0xb8, 0xc8, 0xea, 0x59, 0x50, 0xa7, 0x78,
+ 0x33, 0x1f, 0xbf, 0x2c, 0xcf, 0x33, 0x98, 0x6f,
+ 0x35, 0xe8, 0xcf, 0x12, 0x1d, 0xcb, 0x30, 0xbc },
+ /* tag */
+ { 0x4f, 0xbe, 0x03, 0x38, 0xbe, 0x1c, 0x8c, 0x7e,
+ 0x1d, 0x7a, 0xe7, 0xe4, 0x5b, 0x92, 0xc5, 0x87 }
+},
+
+/* test with header + nonce + plaintext [not even sizes!] */
+{
+ 16, 15, 14, 29,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e },
+ /* header */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d },
+ /* plaintext */
+ { 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 },
+ /* ciphertext */
+ { 0xdd, 0x25, 0xc7, 0x54, 0xc5, 0xb1, 0x7c, 0x59,
+ 0x28, 0xb6, 0x9b, 0x73, 0x15, 0x5f, 0x7b, 0xb8,
+ 0x88, 0x8f, 0xaf, 0x37, 0x09, 0x1a, 0xd9, 0x2c,
+ 0x8a, 0x24, 0xdb, 0x86, 0x8b },
+ /* tag */
+ { 0x0d, 0x1a, 0x14, 0xe5, 0x22, 0x24, 0xff, 0xd2,
+ 0x3a, 0x05, 0xfa, 0x02, 0xcd, 0xef, 0x52, 0xda }
+},
+
+/* Vectors from Brian Gladman */
+
+{
+ 16, 16, 8, 0,
+ /* key */
+ { 0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f,
+ 0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78 },
+ /* nonce */
+ { 0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07,
+ 0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3 },
+ /* header */
+ { 0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b },
+ /* PT */
+ { 0x00 },
+ /* CT */
+ { 0x00 },
+ /* tag */
+ { 0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2, 0x7b,
+ 0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01 }
+},
+
+{
+ 16, 16, 8, 2,
+ /* key */
+ { 0x91, 0x94, 0x5d, 0x3f, 0x4d, 0xcb, 0xee, 0x0b,
+ 0xf4, 0x5e, 0xf5, 0x22, 0x55, 0xf0, 0x95, 0xa4 },
+ /* nonce */
+ { 0xbe, 0xca, 0xf0, 0x43, 0xb0, 0xa2, 0x3d, 0x84,
+ 0x31, 0x94, 0xba, 0x97, 0x2c, 0x66, 0xde, 0xbd },
+ /* header */
+ { 0xfa, 0x3b, 0xfd, 0x48, 0x06, 0xeb, 0x53, 0xfa },
+ /* PT */
+ { 0xf7, 0xfb },
+ /* CT */
+ { 0x19, 0xdd },
+ /* tag */
+ { 0x5c, 0x4c, 0x93, 0x31, 0x04, 0x9d, 0x0b, 0xda,
+ 0xb0, 0x27, 0x74, 0x08, 0xf6, 0x79, 0x67, 0xe5 }
+},
+
+{
+ 16, 16, 8, 5,
+ /* key */
+ { 0x01, 0xf7, 0x4a, 0xd6, 0x40, 0x77, 0xf2, 0xe7,
+ 0x04, 0xc0, 0xf6, 0x0a, 0xda, 0x3d, 0xd5, 0x23 },
+ /* nonce */
+ { 0x70, 0xc3, 0xdb, 0x4f, 0x0d, 0x26, 0x36, 0x84,
+ 0x00, 0xa1, 0x0e, 0xd0, 0x5d, 0x2b, 0xff, 0x5e },
+ /* header */
+ { 0x23, 0x4a, 0x34, 0x63, 0xc1, 0x26, 0x4a, 0xc6 },
+ /* PT */
+ { 0x1a, 0x47, 0xcb, 0x49, 0x33 },
+ /* CT */
+ { 0xd8, 0x51, 0xd5, 0xba, 0xe0 },
+ /* Tag */
+ { 0x3a, 0x59, 0xf2, 0x38, 0xa2, 0x3e, 0x39, 0x19,
+ 0x9d, 0xc9, 0x26, 0x66, 0x26, 0xc4, 0x0f, 0x80 }
+}
+
+};
+ int err, x, idx, res;
+ unsigned long len;
+ unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE];
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((idx = find_cipher("aes")) == -1) {
+ if ((idx = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ len = sizeof(outtag);
+ if ((err = eax_encrypt_authenticate_memory(idx, tests[x].key, tests[x].keylen,
+ tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen,
+ tests[x].plaintext, tests[x].msglen, outct, outtag, &len)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(outtag, len, tests[x].tag, len, "EAX Tag", x) ||
+ compare_testvector(outct, tests[x].msglen, tests[x].ciphertext, tests[x].msglen, "EAX CT", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* test decrypt */
+ if ((err = eax_decrypt_verify_memory(idx, tests[x].key, tests[x].keylen,
+ tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen,
+ outct, tests[x].msglen, outct, outtag, len, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if ((res != 1) || compare_testvector(outct, tests[x].msglen, tests[x].plaintext, tests[x].msglen, "EAX", x)) {
+#ifdef LTC_TEST_DBG
+ printf("\n\nEAX: Failure-decrypt - res = %d\n", res);
+#endif
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ }
+ return CRYPT_OK;
+#endif /* LTC_TEST */
+}
+
+#endif /* LTC_EAX_MODE */
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_add_aad.c b/Sources/libtomcrypt/encauth/gcm/gcm_add_aad.c
new file mode 100644
index 00000000..5c3793eb
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_add_aad.c
@@ -0,0 +1,114 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_add_aad.c
+ GCM implementation, Add AAD data to the stream, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_GCM_MODE
+
+/**
+ Add AAD to the GCM state
+ @param gcm The GCM state
+ @param adata The additional authentication data to add to the GCM state
+ @param adatalen The length of the AAD data.
+ @return CRYPT_OK on success
+ */
+int gcm_add_aad(gcm_state *gcm,
+ const unsigned char *adata, unsigned long adatalen)
+{
+ unsigned long x;
+ int err;
+#ifdef LTC_FAST
+ unsigned long y;
+#endif
+
+ LTC_ARGCHK(gcm != NULL);
+ if (adatalen > 0) {
+ LTC_ARGCHK(adata != NULL);
+ }
+
+ if (gcm->buflen > 16 || gcm->buflen < 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* in IV mode? */
+ if (gcm->mode == LTC_GCM_MODE_IV) {
+ /* IV length must be > 0 */
+ if (gcm->buflen == 0 && gcm->totlen == 0) return CRYPT_ERROR;
+ /* let's process the IV */
+ if (gcm->ivmode || gcm->buflen != 12) {
+ for (x = 0; x < (unsigned long)gcm->buflen; x++) {
+ gcm->X[x] ^= gcm->buf[x];
+ }
+ if (gcm->buflen) {
+ gcm->totlen += gcm->buflen * CONST64(8);
+ gcm_mult_h(gcm, gcm->X);
+ }
+
+ /* mix in the length */
+ zeromem(gcm->buf, 8);
+ STORE64H(gcm->totlen, gcm->buf+8);
+ for (x = 0; x < 16; x++) {
+ gcm->X[x] ^= gcm->buf[x];
+ }
+ gcm_mult_h(gcm, gcm->X);
+
+ /* copy counter out */
+ XMEMCPY(gcm->Y, gcm->X, 16);
+ zeromem(gcm->X, 16);
+ } else {
+ XMEMCPY(gcm->Y, gcm->buf, 12);
+ gcm->Y[12] = 0;
+ gcm->Y[13] = 0;
+ gcm->Y[14] = 0;
+ gcm->Y[15] = 1;
+ }
+ XMEMCPY(gcm->Y_0, gcm->Y, 16);
+ zeromem(gcm->buf, 16);
+ gcm->buflen = 0;
+ gcm->totlen = 0;
+ gcm->mode = LTC_GCM_MODE_AAD;
+ }
+
+ if (gcm->mode != LTC_GCM_MODE_AAD || gcm->buflen >= 16) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ x = 0;
+#ifdef LTC_FAST
+ if (gcm->buflen == 0 && adatalen > 15) {
+ for (x = 0; x < (adatalen & ~15); x += 16) {
+ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&adata[x + y]));
+ }
+ gcm_mult_h(gcm, gcm->X);
+ gcm->totlen += 128;
+ }
+ adata += x;
+ }
+#endif
+
+
+ /* start adding AAD data to the state */
+ for (; x < adatalen; x++) {
+ gcm->X[gcm->buflen++] ^= *adata++;
+
+ if (gcm->buflen == 16) {
+ /* GF mult it */
+ gcm_mult_h(gcm, gcm->X);
+ gcm->buflen = 0;
+ gcm->totlen += 128;
+ }
+ }
+
+ return CRYPT_OK;
+}
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_add_iv.c b/Sources/libtomcrypt/encauth/gcm/gcm_add_iv.c
new file mode 100644
index 00000000..33a24445
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_add_iv.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_add_iv.c
+ GCM implementation, add IV data to the state, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_GCM_MODE
+
+/**
+ Add IV data to the GCM state
+ @param gcm The GCM state
+ @param IV The initial value data to add
+ @param IVlen The length of the IV
+ @return CRYPT_OK on success
+ */
+int gcm_add_iv(gcm_state *gcm,
+ const unsigned char *IV, unsigned long IVlen)
+{
+ unsigned long x, y;
+ int err;
+
+ LTC_ARGCHK(gcm != NULL);
+ if (IVlen > 0) {
+ LTC_ARGCHK(IV != NULL);
+ }
+
+ /* must be in IV mode */
+ if (gcm->mode != LTC_GCM_MODE_IV) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (gcm->buflen >= 16 || gcm->buflen < 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+
+ /* trip the ivmode flag */
+ if (IVlen + gcm->buflen > 12) {
+ gcm->ivmode |= 1;
+ }
+
+ x = 0;
+#ifdef LTC_FAST
+ if (gcm->buflen == 0) {
+ for (x = 0; x < (IVlen & ~15); x += 16) {
+ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&IV[x + y]));
+ }
+ gcm_mult_h(gcm, gcm->X);
+ gcm->totlen += 128;
+ }
+ IV += x;
+ }
+#endif
+
+ /* start adding IV data to the state */
+ for (; x < IVlen; x++) {
+ gcm->buf[gcm->buflen++] = *IV++;
+
+ if (gcm->buflen == 16) {
+ /* GF mult it */
+ for (y = 0; y < 16; y++) {
+ gcm->X[y] ^= gcm->buf[y];
+ }
+ gcm_mult_h(gcm, gcm->X);
+ gcm->buflen = 0;
+ gcm->totlen += 128;
+ }
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_done.c b/Sources/libtomcrypt/encauth/gcm/gcm_done.c
new file mode 100644
index 00000000..464f87ad
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_done.c
@@ -0,0 +1,80 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_done.c
+ GCM implementation, Terminate the stream, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_GCM_MODE
+
+/**
+ Terminate a GCM stream
+ @param gcm The GCM state
+ @param tag [out] The destination for the MAC tag
+ @param taglen [in/out] The length of the MAC tag
+ @return CRYPT_OK on success
+ */
+int gcm_done(gcm_state *gcm,
+ unsigned char *tag, unsigned long *taglen)
+{
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(gcm != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+
+ if (gcm->buflen > 16 || gcm->buflen < 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (gcm->mode == LTC_GCM_MODE_IV) {
+ /* let's process the IV */
+ if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err;
+ }
+
+ if (gcm->mode == LTC_GCM_MODE_AAD) {
+ /* let's process the AAD */
+ if ((err = gcm_process(gcm, NULL, 0, NULL, 0)) != CRYPT_OK) return err;
+ }
+
+ if (gcm->mode != LTC_GCM_MODE_TEXT) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* handle remaining ciphertext */
+ if (gcm->buflen) {
+ gcm->pttotlen += gcm->buflen * CONST64(8);
+ gcm_mult_h(gcm, gcm->X);
+ }
+
+ /* length */
+ STORE64H(gcm->totlen, gcm->buf);
+ STORE64H(gcm->pttotlen, gcm->buf+8);
+ for (x = 0; x < 16; x++) {
+ gcm->X[x] ^= gcm->buf[x];
+ }
+ gcm_mult_h(gcm, gcm->X);
+
+ /* encrypt original counter */
+ if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) {
+ return err;
+ }
+ for (x = 0; x < 16 && x < *taglen; x++) {
+ tag[x] = gcm->buf[x] ^ gcm->X[x];
+ }
+ *taglen = x;
+
+ cipher_descriptor[gcm->cipher].done(&gcm->K);
+
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_gf_mult.c b/Sources/libtomcrypt/encauth/gcm/gcm_gf_mult.c
new file mode 100644
index 00000000..10cd3c95
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_gf_mult.c
@@ -0,0 +1,209 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_gf_mult.c
+ GCM implementation, do the GF mult, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || (defined(LTC_GCM_MODE) && defined(LTC_FAST))
+
+/* this is x*2^128 mod p(x) ... the results are 16 bytes each stored in a packed format. Since only the
+ * lower 16 bits are not zero'ed I removed the upper 14 bytes */
+const unsigned char gcm_shift_table[256*2] = {
+0x00, 0x00, 0x01, 0xc2, 0x03, 0x84, 0x02, 0x46, 0x07, 0x08, 0x06, 0xca, 0x04, 0x8c, 0x05, 0x4e,
+0x0e, 0x10, 0x0f, 0xd2, 0x0d, 0x94, 0x0c, 0x56, 0x09, 0x18, 0x08, 0xda, 0x0a, 0x9c, 0x0b, 0x5e,
+0x1c, 0x20, 0x1d, 0xe2, 0x1f, 0xa4, 0x1e, 0x66, 0x1b, 0x28, 0x1a, 0xea, 0x18, 0xac, 0x19, 0x6e,
+0x12, 0x30, 0x13, 0xf2, 0x11, 0xb4, 0x10, 0x76, 0x15, 0x38, 0x14, 0xfa, 0x16, 0xbc, 0x17, 0x7e,
+0x38, 0x40, 0x39, 0x82, 0x3b, 0xc4, 0x3a, 0x06, 0x3f, 0x48, 0x3e, 0x8a, 0x3c, 0xcc, 0x3d, 0x0e,
+0x36, 0x50, 0x37, 0x92, 0x35, 0xd4, 0x34, 0x16, 0x31, 0x58, 0x30, 0x9a, 0x32, 0xdc, 0x33, 0x1e,
+0x24, 0x60, 0x25, 0xa2, 0x27, 0xe4, 0x26, 0x26, 0x23, 0x68, 0x22, 0xaa, 0x20, 0xec, 0x21, 0x2e,
+0x2a, 0x70, 0x2b, 0xb2, 0x29, 0xf4, 0x28, 0x36, 0x2d, 0x78, 0x2c, 0xba, 0x2e, 0xfc, 0x2f, 0x3e,
+0x70, 0x80, 0x71, 0x42, 0x73, 0x04, 0x72, 0xc6, 0x77, 0x88, 0x76, 0x4a, 0x74, 0x0c, 0x75, 0xce,
+0x7e, 0x90, 0x7f, 0x52, 0x7d, 0x14, 0x7c, 0xd6, 0x79, 0x98, 0x78, 0x5a, 0x7a, 0x1c, 0x7b, 0xde,
+0x6c, 0xa0, 0x6d, 0x62, 0x6f, 0x24, 0x6e, 0xe6, 0x6b, 0xa8, 0x6a, 0x6a, 0x68, 0x2c, 0x69, 0xee,
+0x62, 0xb0, 0x63, 0x72, 0x61, 0x34, 0x60, 0xf6, 0x65, 0xb8, 0x64, 0x7a, 0x66, 0x3c, 0x67, 0xfe,
+0x48, 0xc0, 0x49, 0x02, 0x4b, 0x44, 0x4a, 0x86, 0x4f, 0xc8, 0x4e, 0x0a, 0x4c, 0x4c, 0x4d, 0x8e,
+0x46, 0xd0, 0x47, 0x12, 0x45, 0x54, 0x44, 0x96, 0x41, 0xd8, 0x40, 0x1a, 0x42, 0x5c, 0x43, 0x9e,
+0x54, 0xe0, 0x55, 0x22, 0x57, 0x64, 0x56, 0xa6, 0x53, 0xe8, 0x52, 0x2a, 0x50, 0x6c, 0x51, 0xae,
+0x5a, 0xf0, 0x5b, 0x32, 0x59, 0x74, 0x58, 0xb6, 0x5d, 0xf8, 0x5c, 0x3a, 0x5e, 0x7c, 0x5f, 0xbe,
+0xe1, 0x00, 0xe0, 0xc2, 0xe2, 0x84, 0xe3, 0x46, 0xe6, 0x08, 0xe7, 0xca, 0xe5, 0x8c, 0xe4, 0x4e,
+0xef, 0x10, 0xee, 0xd2, 0xec, 0x94, 0xed, 0x56, 0xe8, 0x18, 0xe9, 0xda, 0xeb, 0x9c, 0xea, 0x5e,
+0xfd, 0x20, 0xfc, 0xe2, 0xfe, 0xa4, 0xff, 0x66, 0xfa, 0x28, 0xfb, 0xea, 0xf9, 0xac, 0xf8, 0x6e,
+0xf3, 0x30, 0xf2, 0xf2, 0xf0, 0xb4, 0xf1, 0x76, 0xf4, 0x38, 0xf5, 0xfa, 0xf7, 0xbc, 0xf6, 0x7e,
+0xd9, 0x40, 0xd8, 0x82, 0xda, 0xc4, 0xdb, 0x06, 0xde, 0x48, 0xdf, 0x8a, 0xdd, 0xcc, 0xdc, 0x0e,
+0xd7, 0x50, 0xd6, 0x92, 0xd4, 0xd4, 0xd5, 0x16, 0xd0, 0x58, 0xd1, 0x9a, 0xd3, 0xdc, 0xd2, 0x1e,
+0xc5, 0x60, 0xc4, 0xa2, 0xc6, 0xe4, 0xc7, 0x26, 0xc2, 0x68, 0xc3, 0xaa, 0xc1, 0xec, 0xc0, 0x2e,
+0xcb, 0x70, 0xca, 0xb2, 0xc8, 0xf4, 0xc9, 0x36, 0xcc, 0x78, 0xcd, 0xba, 0xcf, 0xfc, 0xce, 0x3e,
+0x91, 0x80, 0x90, 0x42, 0x92, 0x04, 0x93, 0xc6, 0x96, 0x88, 0x97, 0x4a, 0x95, 0x0c, 0x94, 0xce,
+0x9f, 0x90, 0x9e, 0x52, 0x9c, 0x14, 0x9d, 0xd6, 0x98, 0x98, 0x99, 0x5a, 0x9b, 0x1c, 0x9a, 0xde,
+0x8d, 0xa0, 0x8c, 0x62, 0x8e, 0x24, 0x8f, 0xe6, 0x8a, 0xa8, 0x8b, 0x6a, 0x89, 0x2c, 0x88, 0xee,
+0x83, 0xb0, 0x82, 0x72, 0x80, 0x34, 0x81, 0xf6, 0x84, 0xb8, 0x85, 0x7a, 0x87, 0x3c, 0x86, 0xfe,
+0xa9, 0xc0, 0xa8, 0x02, 0xaa, 0x44, 0xab, 0x86, 0xae, 0xc8, 0xaf, 0x0a, 0xad, 0x4c, 0xac, 0x8e,
+0xa7, 0xd0, 0xa6, 0x12, 0xa4, 0x54, 0xa5, 0x96, 0xa0, 0xd8, 0xa1, 0x1a, 0xa3, 0x5c, 0xa2, 0x9e,
+0xb5, 0xe0, 0xb4, 0x22, 0xb6, 0x64, 0xb7, 0xa6, 0xb2, 0xe8, 0xb3, 0x2a, 0xb1, 0x6c, 0xb0, 0xae,
+0xbb, 0xf0, 0xba, 0x32, 0xb8, 0x74, 0xb9, 0xb6, 0xbc, 0xf8, 0xbd, 0x3a, 0xbf, 0x7c, 0xbe, 0xbe };
+
+#endif
+
+
+#if defined(LTC_GCM_MODE) || defined(LRW_MODE)
+
+#ifndef LTC_FAST
+/* right shift */
+static void s_gcm_rightshift(unsigned char *a)
+{
+ int x;
+ for (x = 15; x > 0; x--) {
+ a[x] = (a[x]>>1) | ((a[x-1]<<7)&0x80);
+ }
+ a[0] >>= 1;
+}
+
+/* c = b*a */
+static const unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+static const unsigned char poly[] = { 0x00, 0xE1 };
+
+
+/**
+ GCM GF multiplier (internal use only) bitserial
+ @param a First value
+ @param b Second value
+ @param c Destination for a * b
+ */
+void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c)
+{
+ unsigned char Z[16], V[16];
+ unsigned char x, y, z;
+
+ zeromem(Z, 16);
+ XMEMCPY(V, a, 16);
+ for (x = 0; x < 128; x++) {
+ if (b[x>>3] & mask[x&7]) {
+ for (y = 0; y < 16; y++) {
+ Z[y] ^= V[y];
+ }
+ }
+ z = V[15] & 0x01;
+ s_gcm_rightshift(V);
+ V[0] ^= poly[z];
+ }
+ XMEMCPY(c, Z, 16);
+}
+
+#else
+
+/* map normal numbers to "ieee" way ... e.g. bit reversed */
+#define M(x) ( ((x&8)>>3) | ((x&4)>>1) | ((x&2)<<1) | ((x&1)<<3) )
+
+#define BPD (sizeof(LTC_FAST_TYPE) * 8)
+#define WPV (1 + (16 / sizeof(LTC_FAST_TYPE)))
+
+/**
+ GCM GF multiplier (internal use only) word oriented
+ @param a First value
+ @param b Second value
+ @param c Destination for a * b
+ */
+void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c)
+{
+ int i, j, k, u;
+ LTC_FAST_TYPE B[16][WPV], tmp[32 / sizeof(LTC_FAST_TYPE)], pB[16 / sizeof(LTC_FAST_TYPE)], zz, z;
+ unsigned char pTmp[32];
+
+ /* create simple tables */
+ zeromem(B[0], sizeof(B[0]));
+ zeromem(B[M(1)], sizeof(B[M(1)]));
+
+#ifdef ENDIAN_32BITWORD
+ for (i = 0; i < 4; i++) {
+ LOAD32H(B[M(1)][i], a + (i<<2));
+ LOAD32L(pB[i], b + (i<<2));
+ }
+#else
+ for (i = 0; i < 2; i++) {
+ LOAD64H(B[M(1)][i], a + (i<<3));
+ LOAD64L(pB[i], b + (i<<3));
+ }
+#endif
+
+ /* now create 2, 4 and 8 */
+ B[M(2)][0] = B[M(1)][0] >> 1;
+ B[M(4)][0] = B[M(1)][0] >> 2;
+ B[M(8)][0] = B[M(1)][0] >> 3;
+ for (i = 1; i < (int)WPV; i++) {
+ B[M(2)][i] = (B[M(1)][i-1] << (BPD-1)) | (B[M(1)][i] >> 1);
+ B[M(4)][i] = (B[M(1)][i-1] << (BPD-2)) | (B[M(1)][i] >> 2);
+ B[M(8)][i] = (B[M(1)][i-1] << (BPD-3)) | (B[M(1)][i] >> 3);
+ }
+
+ /* now all values with two bits which are 3, 5, 6, 9, 10, 12 */
+ for (i = 0; i < (int)WPV; i++) {
+ B[M(3)][i] = B[M(1)][i] ^ B[M(2)][i];
+ B[M(5)][i] = B[M(1)][i] ^ B[M(4)][i];
+ B[M(6)][i] = B[M(2)][i] ^ B[M(4)][i];
+ B[M(9)][i] = B[M(1)][i] ^ B[M(8)][i];
+ B[M(10)][i] = B[M(2)][i] ^ B[M(8)][i];
+ B[M(12)][i] = B[M(8)][i] ^ B[M(4)][i];
+
+ /* now all 3 bit values and the only 4 bit value: 7, 11, 13, 14, 15 */
+ B[M(7)][i] = B[M(3)][i] ^ B[M(4)][i];
+ B[M(11)][i] = B[M(3)][i] ^ B[M(8)][i];
+ B[M(13)][i] = B[M(1)][i] ^ B[M(12)][i];
+ B[M(14)][i] = B[M(6)][i] ^ B[M(8)][i];
+ B[M(15)][i] = B[M(7)][i] ^ B[M(8)][i];
+ }
+
+ zeromem(tmp, sizeof(tmp));
+
+ /* compute product four bits of each word at a time */
+ /* for each nibble */
+ for (i = (BPD/4)-1; i >= 0; i--) {
+ /* for each word */
+ for (j = 0; j < (int)(WPV-1); j++) {
+ /* grab the 4 bits recall the nibbles are backwards so it's a shift by (i^1)*4 */
+ u = (pB[j] >> ((i^1)<<2)) & 15;
+
+ /* add offset by the word count the table looked up value to the result */
+ for (k = 0; k < (int)WPV; k++) {
+ tmp[k+j] ^= B[u][k];
+ }
+ }
+ /* shift result up by 4 bits */
+ if (i != 0) {
+ for (z = j = 0; j < (int)(32 / sizeof(LTC_FAST_TYPE)); j++) {
+ zz = tmp[j] << (BPD-4);
+ tmp[j] = (tmp[j] >> 4) | z;
+ z = zz;
+ }
+ }
+ }
+
+ /* store product */
+#ifdef ENDIAN_32BITWORD
+ for (i = 0; i < 8; i++) {
+ STORE32H(tmp[i], pTmp + (i<<2));
+ }
+#else
+ for (i = 0; i < 4; i++) {
+ STORE64H(tmp[i], pTmp + (i<<3));
+ }
+#endif
+
+ /* reduce by taking most significant byte and adding the appropriate two byte sequence 16 bytes down */
+ for (i = 31; i >= 16; i--) {
+ pTmp[i-16] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)];
+ pTmp[i-15] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)+1];
+ }
+
+ for (i = 0; i < 16; i++) {
+ c[i] = pTmp[i];
+ }
+
+}
+
+#endif
+
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_init.c b/Sources/libtomcrypt/encauth/gcm/gcm_init.c
new file mode 100644
index 00000000..1822bdcc
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_init.c
@@ -0,0 +1,95 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_init.c
+ GCM implementation, initialize state, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_GCM_MODE
+
+/**
+ Initialize a GCM state
+ @param gcm The GCM state to initialize
+ @param cipher The index of the cipher to use
+ @param key The secret key
+ @param keylen The length of the secret key
+ @return CRYPT_OK on success
+ */
+int gcm_init(gcm_state *gcm, int cipher,
+ const unsigned char *key, int keylen)
+{
+ int err;
+ unsigned char B[16];
+#ifdef LTC_GCM_TABLES
+ int x, y, z, t;
+#endif
+
+ LTC_ARGCHK(gcm != NULL);
+ LTC_ARGCHK(key != NULL);
+
+#ifdef LTC_FAST
+ if (16 % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ /* is cipher valid? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (cipher_descriptor[cipher].block_length != 16) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ /* schedule key */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &gcm->K)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* H = E(0) */
+ zeromem(B, 16);
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(B, gcm->H, &gcm->K)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* setup state */
+ zeromem(gcm->buf, sizeof(gcm->buf));
+ zeromem(gcm->X, sizeof(gcm->X));
+ gcm->cipher = cipher;
+ gcm->mode = LTC_GCM_MODE_IV;
+ gcm->ivmode = 0;
+ gcm->buflen = 0;
+ gcm->totlen = 0;
+ gcm->pttotlen = 0;
+
+#ifdef LTC_GCM_TABLES
+ /* setup tables */
+
+ /* generate the first table as it has no shifting (from which we make the other tables) */
+ zeromem(B, 16);
+ for (y = 0; y < 256; y++) {
+ B[0] = y;
+ gcm_gf_mult(gcm->H, B, &gcm->PC[0][y][0]);
+ }
+
+ /* now generate the rest of the tables based the previous table */
+ for (x = 1; x < 16; x++) {
+ for (y = 0; y < 256; y++) {
+ /* now shift it right by 8 bits */
+ t = gcm->PC[x-1][y][15];
+ for (z = 15; z > 0; z--) {
+ gcm->PC[x][y][z] = gcm->PC[x-1][y][z-1];
+ }
+ gcm->PC[x][y][0] = gcm_shift_table[t<<1];
+ gcm->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1];
+ }
+ }
+
+#endif
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_memory.c b/Sources/libtomcrypt/encauth/gcm/gcm_memory.c
new file mode 100644
index 00000000..6de0b309
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_memory.c
@@ -0,0 +1,112 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_memory.c
+ GCM implementation, process a packet, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_GCM_MODE
+
+/**
+ Process an entire GCM packet in one call.
+ @param cipher Index of cipher to use
+ @param key The secret key
+ @param keylen The length of the secret key
+ @param IV The initialization vector
+ @param IVlen The length of the initialization vector
+ @param adata The additional authentication data (header)
+ @param adatalen The length of the adata
+ @param pt The plaintext
+ @param ptlen The length of the plaintext (ciphertext length is the same)
+ @param ct The ciphertext
+ @param tag [out] The MAC tag
+ @param taglen [in/out] The MAC tag length
+ @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
+ @return CRYPT_OK on success
+ */
+int gcm_memory( int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *IV, unsigned long IVlen,
+ const unsigned char *adata, unsigned long adatalen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction)
+{
+ void *orig;
+ gcm_state *gcm;
+ int err;
+
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (cipher_descriptor[cipher].accel_gcm_memory != NULL) {
+ return cipher_descriptor[cipher].accel_gcm_memory
+ (key, keylen,
+ IV, IVlen,
+ adata, adatalen,
+ pt, ptlen,
+ ct,
+ tag, taglen,
+ direction);
+ }
+
+
+
+#ifndef LTC_GCM_TABLES_SSE2
+ orig = gcm = XMALLOC(sizeof(*gcm));
+#else
+ orig = gcm = XMALLOC(sizeof(*gcm) + 16);
+#endif
+ if (gcm == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* Force GCM to be on a multiple of 16 so we can use 128-bit aligned operations
+ * note that we only modify gcm and keep orig intact. This code is not portable
+ * but again it's only for SSE2 anyways, so who cares?
+ */
+#ifdef LTC_GCM_TABLES_SSE2
+ gcm = LTC_ALIGN_BUF(gcm, 16);
+#endif
+
+ if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) {
+ goto LTC_ERR;
+ }
+ if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) {
+ goto LTC_ERR;
+ }
+ if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) {
+ goto LTC_ERR;
+ }
+ if ((err = gcm_process(gcm, pt, ptlen, ct, direction)) != CRYPT_OK) {
+ goto LTC_ERR;
+ }
+ if (direction == GCM_ENCRYPT) {
+ if ((err = gcm_done(gcm, tag, taglen)) != CRYPT_OK) {
+ goto LTC_ERR;
+ }
+ }
+ else if (direction == GCM_DECRYPT) {
+ unsigned char buf[MAXBLOCKSIZE];
+ unsigned long buflen = sizeof(buf);
+ if ((err = gcm_done(gcm, buf, &buflen)) != CRYPT_OK) {
+ goto LTC_ERR;
+ }
+ if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) {
+ err = CRYPT_ERROR;
+ }
+ }
+ else {
+ err = CRYPT_INVALID_ARG;
+ }
+LTC_ERR:
+ gcm_reset(gcm);
+ XFREE(orig);
+ return err;
+}
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_mult_h.c b/Sources/libtomcrypt/encauth/gcm/gcm_mult_h.c
new file mode 100644
index 00000000..c0fd9c56
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_mult_h.c
@@ -0,0 +1,47 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_mult_h.c
+ GCM implementation, do the GF mult, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#if defined(LTC_GCM_MODE)
+/**
+ GCM multiply by H
+ @param gcm The GCM state which holds the H value
+ @param I The value to multiply H by
+ */
+void gcm_mult_h(const gcm_state *gcm, unsigned char *I)
+{
+ unsigned char T[16];
+#ifdef LTC_GCM_TABLES
+ int x;
+#ifdef LTC_GCM_TABLES_SSE2
+ __asm__("movdqa (%0),%%xmm0"::"r"(&gcm->PC[0][I[0]][0]));
+ for (x = 1; x < 16; x++) {
+ __asm__("pxor (%0),%%xmm0"::"r"(&gcm->PC[x][I[x]][0]));
+ }
+ __asm__("movdqa %%xmm0,(%0)"::"r"(&T));
+#else
+ int y;
+ XMEMCPY(T, &gcm->PC[0][I[0]][0], 16);
+ for (x = 1; x < 16; x++) {
+#ifdef LTC_FAST
+ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&gcm->PC[x][I[x]][y]));
+ }
+#else
+ for (y = 0; y < 16; y++) {
+ T[y] ^= gcm->PC[x][I[x]][y];
+ }
+#endif /* LTC_FAST */
+ }
+#endif /* LTC_GCM_TABLES_SSE2 */
+#else
+ gcm_gf_mult(gcm->H, I, T);
+#endif
+ XMEMCPY(I, T, 16);
+}
+#endif
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_process.c b/Sources/libtomcrypt/encauth/gcm/gcm_process.c
new file mode 100644
index 00000000..e3c956c6
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_process.c
@@ -0,0 +1,150 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_process.c
+ GCM implementation, process message data, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_GCM_MODE
+
+/**
+ Process plaintext/ciphertext through GCM
+ @param gcm The GCM state
+ @param pt The plaintext
+ @param ptlen The plaintext length (ciphertext length is the same)
+ @param ct The ciphertext
+ @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
+ @return CRYPT_OK on success
+ */
+int gcm_process(gcm_state *gcm,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ int direction)
+{
+ unsigned long x;
+ int y, err;
+ unsigned char b;
+
+ LTC_ARGCHK(gcm != NULL);
+ if (ptlen > 0) {
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ }
+
+ if (gcm->buflen > 16 || gcm->buflen < 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* 0xFFFFFFFE0 = ((2^39)-256)/8 */
+ if (gcm->pttotlen / 8 + (ulong64)gcm->buflen + (ulong64)ptlen >= CONST64(0xFFFFFFFE0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (gcm->mode == LTC_GCM_MODE_IV) {
+ /* let's process the IV */
+ if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err;
+ }
+
+ /* in AAD mode? */
+ if (gcm->mode == LTC_GCM_MODE_AAD) {
+ /* let's process the AAD */
+ if (gcm->buflen) {
+ gcm->totlen += gcm->buflen * CONST64(8);
+ gcm_mult_h(gcm, gcm->X);
+ }
+
+ /* increment counter */
+ for (y = 15; y >= 12; y--) {
+ if (++gcm->Y[y] & 255) { break; }
+ }
+ /* encrypt the counter */
+ if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
+ return err;
+ }
+
+ gcm->buflen = 0;
+ gcm->mode = LTC_GCM_MODE_TEXT;
+ }
+
+ if (gcm->mode != LTC_GCM_MODE_TEXT) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ x = 0;
+#ifdef LTC_FAST
+ if (gcm->buflen == 0) {
+ if (direction == GCM_ENCRYPT) {
+ for (x = 0; x < (ptlen & ~15); x += 16) {
+ /* ctr encrypt */
+ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&ct[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&gcm->buf[y]));
+ *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y]));
+ }
+ /* GMAC it */
+ gcm->pttotlen += 128;
+ gcm_mult_h(gcm, gcm->X);
+ /* increment counter */
+ for (y = 15; y >= 12; y--) {
+ if (++gcm->Y[y] & 255) { break; }
+ }
+ if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ } else {
+ for (x = 0; x < (ptlen & ~15); x += 16) {
+ /* ctr encrypt */
+ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y]));
+ *(LTC_FAST_TYPE_PTR_CAST(&pt[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&gcm->buf[y]));
+ }
+ /* GMAC it */
+ gcm->pttotlen += 128;
+ gcm_mult_h(gcm, gcm->X);
+ /* increment counter */
+ for (y = 15; y >= 12; y--) {
+ if (++gcm->Y[y] & 255) { break; }
+ }
+ if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ }
+ }
+#endif
+
+ /* process text */
+ for (; x < ptlen; x++) {
+ if (gcm->buflen == 16) {
+ gcm->pttotlen += 128;
+ gcm_mult_h(gcm, gcm->X);
+
+ /* increment counter */
+ for (y = 15; y >= 12; y--) {
+ if (++gcm->Y[y] & 255) { break; }
+ }
+ if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
+ return err;
+ }
+ gcm->buflen = 0;
+ }
+
+ if (direction == GCM_ENCRYPT) {
+ b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen];
+ } else {
+ b = ct[x];
+ pt[x] = ct[x] ^ gcm->buf[gcm->buflen];
+ }
+ gcm->X[gcm->buflen++] ^= b;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_reset.c b/Sources/libtomcrypt/encauth/gcm/gcm_reset.c
new file mode 100644
index 00000000..a071dcd8
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_reset.c
@@ -0,0 +1,32 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_reset.c
+ GCM implementation, reset a used state so it can accept IV data, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_GCM_MODE
+
+/**
+ Reset a GCM state to as if you just called gcm_init(). This saves the initialization time.
+ @param gcm The GCM state to reset
+ @return CRYPT_OK on success
+*/
+int gcm_reset(gcm_state *gcm)
+{
+ LTC_ARGCHK(gcm != NULL);
+
+ zeromem(gcm->buf, sizeof(gcm->buf));
+ zeromem(gcm->X, sizeof(gcm->X));
+ gcm->mode = LTC_GCM_MODE_IV;
+ gcm->ivmode = 0;
+ gcm->buflen = 0;
+ gcm->totlen = 0;
+ gcm->pttotlen = 0;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/gcm/gcm_test.c b/Sources/libtomcrypt/encauth/gcm/gcm_test.c
new file mode 100644
index 00000000..228db57d
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/gcm/gcm_test.c
@@ -0,0 +1,407 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file gcm_test.c
+ GCM implementation, testing, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_GCM_MODE
+
+/**
+ Test the GCM code
+ @return CRYPT_OK on success
+ */
+int gcm_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ unsigned char K[32];
+ int keylen;
+ unsigned char P[128];
+ unsigned long ptlen;
+ unsigned char A[128];
+ unsigned long alen;
+ unsigned char IV[128];
+ unsigned long IVlen;
+ unsigned char C[128];
+ unsigned char T[16];
+ } tests[] = {
+
+/* test case #1 */
+{
+ /* key */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ 16,
+
+ /* plaintext */
+ { 0 },
+ 0,
+
+ /* AAD data */
+ { 0 },
+ 0,
+
+ /* IV */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ 12,
+
+ /* ciphertext */
+ { 0 },
+
+ /* tag */
+ { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+ 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }
+},
+
+/* test case #2 */
+{
+ /* key */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ 16,
+
+ /* PT */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ 16,
+
+ /* ADATA */
+ { 0 },
+ 0,
+
+ /* IV */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ 12,
+
+ /* CT */
+ { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+ 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
+
+ /* TAG */
+ { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+ 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }
+},
+
+/* test case #3 */
+{
+ /* key */
+ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, },
+ 16,
+
+ /* PT */
+ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, },
+ 64,
+
+ /* ADATA */
+ { 0 },
+ 0,
+
+ /* IV */
+ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88, },
+ 12,
+
+ /* CT */
+ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, },
+
+ /* TAG */
+ { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4, }
+},
+
+/* test case #4 */
+{
+ /* key */
+ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, },
+ 16,
+
+ /* PT */
+ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, },
+ 60,
+
+ /* ADATA */
+ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2, },
+ 20,
+
+ /* IV */
+ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88, },
+ 12,
+
+ /* CT */
+ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, },
+
+ /* TAG */
+ { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+ 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, }
+
+},
+
+/* test case #5 */
+{
+ /* key */
+ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, },
+ 16,
+
+ /* PT */
+ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, },
+ 60,
+
+ /* ADATA */
+ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2, },
+ 20,
+
+ /* IV */
+ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, },
+ 8,
+
+ /* CT */
+ { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
+ 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
+ 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
+ 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
+ 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
+ 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
+ 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
+ 0xc2, 0x3f, 0x45, 0x98, },
+
+ /* TAG */
+ { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
+ 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb, }
+},
+
+/* test case #6 */
+{
+ /* key */
+ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, },
+ 16,
+
+ /* PT */
+ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, },
+ 60,
+
+ /* ADATA */
+ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2, },
+ 20,
+
+ /* IV */
+ { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
+ 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
+ 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
+ 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
+ 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
+ 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
+ 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
+ 0xa6, 0x37, 0xb3, 0x9b, },
+ 60,
+
+ /* CT */
+ { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
+ 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
+ 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
+ 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
+ 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
+ 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
+ 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
+ 0x4c, 0x34, 0xae, 0xe5, },
+
+ /* TAG */
+ { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
+ 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50, }
+},
+
+/* test case #46 from BG (catches the LTC bug of v1.15) */
+{
+ /* key */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ 16,
+
+ /* PT */
+ { 0xa2, 0xaa, 0xb3, 0xad, 0x8b, 0x17, 0xac, 0xdd,
+ 0xa2, 0x88, 0x42, 0x6c, 0xd7, 0xc4, 0x29, 0xb7,
+ 0xca, 0x86, 0xb7, 0xac, 0xa0, 0x58, 0x09, 0xc7,
+ 0x0c, 0xe8, 0x2d, 0xb2, 0x57, 0x11, 0xcb, 0x53,
+ 0x02, 0xeb, 0x27, 0x43, 0xb0, 0x36, 0xf3, 0xd7,
+ 0x50, 0xd6, 0xcf, 0x0d, 0xc0, 0xac, 0xb9, 0x29,
+ 0x50, 0xd5, 0x46, 0xdb, 0x30, 0x8f, 0x93, 0xb4,
+ 0xff, 0x24, 0x4a, 0xfa, 0x9d, 0xc7, 0x2b, 0xcd,
+ 0x75, 0x8d, 0x2c },
+ 67,
+
+ /* ADATA */
+ { 0x68, 0x8e, 0x1a, 0xa9, 0x84, 0xde, 0x92, 0x6d,
+ 0xc7, 0xb4, 0xc4, 0x7f, 0x44 },
+ 13,
+
+ /* IV */
+ { 0xb7, 0x21, 0x38, 0xb5, 0xa0, 0x5f, 0xf5, 0x07,
+ 0x0e, 0x8c, 0xd9, 0x41, 0x83, 0xf7, 0x61, 0xd8 },
+ 16,
+
+ /* CT */
+ { 0xcb, 0xc8, 0xd2, 0xf1, 0x54, 0x81, 0xa4, 0xcc,
+ 0x7d, 0xd1, 0xe1, 0x9a, 0xaa, 0x83, 0xde, 0x56,
+ 0x78, 0x48, 0x3e, 0xc3, 0x59, 0xae, 0x7d, 0xec,
+ 0x2a, 0xb8, 0xd5, 0x34, 0xe0, 0x90, 0x6f, 0x4b,
+ 0x46, 0x63, 0xfa, 0xff, 0x58, 0xa8, 0xb2, 0xd7,
+ 0x33, 0xb8, 0x45, 0xee, 0xf7, 0xc9, 0xb3, 0x31,
+ 0xe9, 0xe1, 0x0e, 0xb2, 0x61, 0x2c, 0x99, 0x5f,
+ 0xeb, 0x1a, 0xc1, 0x5a, 0x62, 0x86, 0xcc, 0xe8,
+ 0xb2, 0x97, 0xa8 },
+
+ /* TAG */
+ { 0x8d, 0x2d, 0x2a, 0x93, 0x72, 0x62, 0x6f, 0x6b,
+ 0xee, 0x85, 0x80, 0x27, 0x6a, 0x63, 0x66, 0xbf }
+}
+
+/* rest of test cases are the same except AES key size changes... ignored... */
+};
+ int idx, err;
+ unsigned long x, y;
+ unsigned char out[2][128], T[2][16];
+ gcm_state gcm;
+
+ /* find aes */
+ idx = find_cipher("aes");
+ if (idx == -1) {
+ idx = find_cipher("rijndael");
+ if (idx == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ /* Special test case for empty AAD + empty PT */
+ y = sizeof(T[0]);
+ if ((err = gcm_init(&gcm, idx, tests[0].K, tests[0].keylen)) != CRYPT_OK) return err;
+ if ((err = gcm_add_iv(&gcm, tests[0].IV, tests[0].IVlen)) != CRYPT_OK) return err;
+ /* intentionally skip gcm_add_aad + gcm_process */
+ if ((err = gcm_done(&gcm, T[0], &y)) != CRYPT_OK) return err;
+ if (compare_testvector(T[0], y, tests[0].T, 16, "GCM Encrypt Tag-special", 0)) return CRYPT_FAIL_TESTVECTOR;
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ y = sizeof(T[0]);
+ if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen,
+ tests[x].IV, tests[x].IVlen,
+ tests[x].A, tests[x].alen,
+ (unsigned char*)tests[x].P, tests[x].ptlen,
+ out[0], T[0], &y, GCM_ENCRYPT)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (compare_testvector(out[0], tests[x].ptlen, tests[x].C, tests[x].ptlen, "GCM CT", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ if (compare_testvector(T[0], y, tests[x].T, 16, "GCM Encrypt Tag", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ y = sizeof(T[1]);
+ XMEMCPY(T[1], tests[x].T, 16);
+ if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen,
+ tests[x].IV, tests[x].IVlen,
+ tests[x].A, tests[x].alen,
+ out[1], tests[x].ptlen,
+ out[0], T[1], &y, GCM_DECRYPT)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (compare_testvector(out[1], tests[x].ptlen, tests[x].P, tests[x].ptlen, "GCM PT", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */
+ {
+ unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
+ unsigned char iv[] = { 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b };
+ unsigned char valid_tag[] = { 0xd8,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 };
+ unsigned char invalid_tag[] = { 0xd9,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 };
+ unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f };
+ unsigned char ct[] = { 0xeb,0x15,0x6d,0x08,0x1e,0xd6,0xb6,0xb5,0x5f,0x46,0x12,0xf0,0x21,0xd8,0x7b,0x39 };
+ unsigned char pt[20] = { 0 };
+ unsigned long taglen;
+
+ /* VALID tag */
+ taglen = sizeof(valid_tag);
+ err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0,
+ pt, sizeof(ct), ct, valid_tag, &taglen, GCM_DECRYPT);
+ if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* INVALID tag */
+ taglen = sizeof(invalid_tag);
+ err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0,
+ pt, sizeof(ct), ct, invalid_tag, &taglen, GCM_DECRYPT);
+ if (err == CRYPT_OK) {
+ return CRYPT_FAIL_TESTVECTOR; /* should fail */
+ }
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_decrypt.c b/Sources/libtomcrypt/encauth/ocb/ocb_decrypt.c
new file mode 100644
index 00000000..dd512ce2
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_decrypt.c
@@ -0,0 +1,67 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_decrypt.c
+ OCB implementation, decrypt data, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/**
+ Decrypt a block with OCB.
+ @param ocb The OCB state
+ @param ct The ciphertext (length of the block size of the block cipher)
+ @param pt [out] The plaintext (length of ct)
+ @return CRYPT_OK if successful
+*/
+int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt)
+{
+ unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE];
+ int err, x;
+
+ LTC_ARGCHK(ocb != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ /* check if valid cipher */
+ if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ LTC_ARGCHK(cipher_descriptor[ocb->cipher].ecb_decrypt != NULL);
+
+ /* check length */
+ if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* Get Z[i] value */
+ ocb_shift_xor(ocb, Z);
+
+ /* xor ct in, encrypt, xor Z out */
+ for (x = 0; x < ocb->block_len; x++) {
+ tmp[x] = ct[x] ^ Z[x];
+ }
+ if ((err = cipher_descriptor[ocb->cipher].ecb_decrypt(tmp, pt, &ocb->key)) != CRYPT_OK) {
+ return err;
+ }
+ for (x = 0; x < ocb->block_len; x++) {
+ pt[x] ^= Z[x];
+ }
+
+ /* compute checksum */
+ for (x = 0; x < ocb->block_len; x++) {
+ ocb->checksum[x] ^= pt[x];
+ }
+
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(Z, sizeof(Z));
+ zeromem(tmp, sizeof(tmp));
+#endif
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_decrypt_verify_memory.c b/Sources/libtomcrypt/encauth/ocb/ocb_decrypt_verify_memory.c
new file mode 100644
index 00000000..0f4dcb78
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_decrypt_verify_memory.c
@@ -0,0 +1,74 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_decrypt_verify_memory.c
+ OCB implementation, helper to decrypt block of memory, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/**
+ Decrypt and compare the tag with OCB.
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param nonce The session nonce (length of the block size of the block cipher)
+ @param ct The ciphertext
+ @param ctlen The length of the ciphertext (octets)
+ @param pt [out] The plaintext
+ @param tag The tag to compare against
+ @param taglen The length of the tag (octets)
+ @param stat [out] The result of the tag comparison (1==valid, 0==invalid)
+ @return CRYPT_OK if successful regardless of the tag comparison
+*/
+int ocb_decrypt_verify_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen,
+ int *stat)
+{
+ int err;
+ ocb_state *ocb;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(nonce != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* allocate memory */
+ ocb = XMALLOC(sizeof(ocb_state));
+ if (ocb == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ while (ctlen > (unsigned long)ocb->block_len) {
+ if ((err = ocb_decrypt(ocb, ct, pt)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ ctlen -= ocb->block_len;
+ pt += ocb->block_len;
+ ct += ocb->block_len;
+ }
+
+ err = ocb_done_decrypt(ocb, ct, ctlen, pt, tag, taglen, stat);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(ocb, sizeof(ocb_state));
+#endif
+
+ XFREE(ocb);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_done_decrypt.c b/Sources/libtomcrypt/encauth/ocb/ocb_done_decrypt.c
new file mode 100644
index 00000000..3d516c9b
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_done_decrypt.c
@@ -0,0 +1,68 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_done_decrypt.c
+ OCB implementation, terminate decryption, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/**
+ Terminate a decrypting OCB state
+ @param ocb The OCB state
+ @param ct The ciphertext (if any)
+ @param ctlen The length of the ciphertext (octets)
+ @param pt [out] The plaintext
+ @param tag The authentication tag (to compare against)
+ @param taglen The length of the authentication tag provided
+ @param stat [out] The result of the tag comparison
+ @return CRYPT_OK if the process was successful regardless if the tag is valid
+*/
+int ocb_done_decrypt(ocb_state *ocb,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen, int *stat)
+{
+ int err;
+ unsigned char *tagbuf;
+ unsigned long tagbuflen;
+
+ LTC_ARGCHK(ocb != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to failed */
+ *stat = 0;
+
+ /* allocate memory */
+ tagbuf = XMALLOC(MAXBLOCKSIZE);
+ if (tagbuf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ tagbuflen = MAXBLOCKSIZE;
+ if ((err = s_ocb_done(ocb, ct, ctlen, pt, tagbuf, &tagbuflen, 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if (taglen <= tagbuflen && XMEM_NEQ(tagbuf, tag, taglen) == 0) {
+ *stat = 1;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tagbuf, MAXBLOCKSIZE);
+#endif
+
+ XFREE(tagbuf);
+
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_done_encrypt.c b/Sources/libtomcrypt/encauth/ocb/ocb_done_encrypt.c
new file mode 100644
index 00000000..5cd39adc
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_done_encrypt.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_done_encrypt.c
+ OCB implementation, terminate encryption, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/**
+ Terminate an encryption OCB state
+ @param ocb The OCB state
+ @param pt Remaining plaintext (if any)
+ @param ptlen The length of the plaintext (octets)
+ @param ct [out] The ciphertext (if any)
+ @param tag [out] The tag for the OCB stream
+ @param taglen [in/out] The max size and resulting size of the tag
+ @return CRYPT_OK if successful
+*/
+int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct, unsigned char *tag, unsigned long *taglen)
+{
+ LTC_ARGCHK(ocb != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+ return s_ocb_done(ocb, pt, ptlen, ct, tag, taglen, 0);
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_encrypt.c b/Sources/libtomcrypt/encauth/ocb/ocb_encrypt.c
new file mode 100644
index 00000000..ad6260f4
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_encrypt.c
@@ -0,0 +1,60 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_encrypt.c
+ OCB implementation, encrypt data, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/**
+ Encrypt a block of data with OCB.
+ @param ocb The OCB state
+ @param pt The plaintext (length of the block size of the block cipher)
+ @param ct [out] The ciphertext (same size as the pt)
+ @return CRYPT_OK if successful
+*/
+int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct)
+{
+ unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE];
+ int err, x;
+
+ LTC_ARGCHK(ocb != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* compute checksum */
+ for (x = 0; x < ocb->block_len; x++) {
+ ocb->checksum[x] ^= pt[x];
+ }
+
+ /* Get Z[i] value */
+ ocb_shift_xor(ocb, Z);
+
+ /* xor pt in, encrypt, xor Z out */
+ for (x = 0; x < ocb->block_len; x++) {
+ tmp[x] = pt[x] ^ Z[x];
+ }
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, ct, &ocb->key)) != CRYPT_OK) {
+ return err;
+ }
+ for (x = 0; x < ocb->block_len; x++) {
+ ct[x] ^= Z[x];
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(Z, sizeof(Z));
+ zeromem(tmp, sizeof(tmp));
+#endif
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_encrypt_authenticate_memory.c b/Sources/libtomcrypt/encauth/ocb/ocb_encrypt_authenticate_memory.c
new file mode 100644
index 00000000..7560a6e7
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_encrypt_authenticate_memory.c
@@ -0,0 +1,72 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_encrypt_authenticate_memory.c
+ OCB implementation, encrypt block of memory, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/**
+ Encrypt and generate an authentication code for a buffer of memory
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param nonce The session nonce (length of the block ciphers block size)
+ @param pt The plaintext
+ @param ptlen The length of the plaintext (octets)
+ @param ct [out] The ciphertext
+ @param tag [out] The authentication tag
+ @param taglen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful
+*/
+int ocb_encrypt_authenticate_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen)
+{
+ int err;
+ ocb_state *ocb;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(nonce != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+
+ /* allocate ram */
+ ocb = XMALLOC(sizeof(ocb_state));
+ if (ocb == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ while (ptlen > (unsigned long)ocb->block_len) {
+ if ((err = ocb_encrypt(ocb, pt, ct)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ ptlen -= ocb->block_len;
+ pt += ocb->block_len;
+ ct += ocb->block_len;
+ }
+
+ err = ocb_done_encrypt(ocb, pt, ptlen, ct, tag, taglen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(ocb, sizeof(ocb_state));
+#endif
+
+ XFREE(ocb);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_init.c b/Sources/libtomcrypt/encauth/ocb/ocb_init.c
new file mode 100644
index 00000000..1ae58b6c
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_init.c
@@ -0,0 +1,129 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_init.c
+ OCB implementation, initialize state, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+static const struct {
+ int len;
+ unsigned char poly_div[MAXBLOCKSIZE],
+ poly_mul[MAXBLOCKSIZE];
+} polys[] = {
+{
+ 8,
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }
+}, {
+ 16,
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }
+}
+};
+
+/**
+ Initialize an OCB context.
+ @param ocb [out] The destination of the OCB state
+ @param cipher The index of the desired cipher
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param nonce The session nonce (length of the block size of the cipher)
+ @return CRYPT_OK if successful
+*/
+int ocb_init(ocb_state *ocb, int cipher,
+ const unsigned char *key, unsigned long keylen, const unsigned char *nonce)
+{
+ int poly, x, y, m, err;
+
+ LTC_ARGCHK(ocb != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(nonce != NULL);
+
+ /* valid cipher? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* determine which polys to use */
+ ocb->block_len = cipher_descriptor[cipher].block_length;
+ x = (int)(sizeof(polys)/sizeof(polys[0]));
+ for (poly = 0; poly < x; poly++) {
+ if (polys[poly].len == ocb->block_len) {
+ break;
+ }
+ }
+ if (poly == x) {
+ return CRYPT_INVALID_ARG; /* block_len not found in polys */
+ }
+ if (polys[poly].len != ocb->block_len) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* schedule the key */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* find L = E[0] */
+ zeromem(ocb->L, ocb->block_len);
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->L, ocb->L, &ocb->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* find R = E[N xor L] */
+ for (x = 0; x < ocb->block_len; x++) {
+ ocb->R[x] = ocb->L[x] ^ nonce[x];
+ }
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->R, ocb->R, &ocb->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* find Ls[i] = L << i for i == 0..31 */
+ XMEMCPY(ocb->Ls[0], ocb->L, ocb->block_len);
+ for (x = 1; x < 32; x++) {
+ m = ocb->Ls[x-1][0] >> 7;
+ for (y = 0; y < ocb->block_len-1; y++) {
+ ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255;
+ }
+ ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255;
+
+ if (m == 1) {
+ for (y = 0; y < ocb->block_len; y++) {
+ ocb->Ls[x][y] ^= polys[poly].poly_mul[y];
+ }
+ }
+ }
+
+ /* find Lr = L / x */
+ m = ocb->L[ocb->block_len-1] & 1;
+
+ /* shift right */
+ for (x = ocb->block_len - 1; x > 0; x--) {
+ ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255;
+ }
+ ocb->Lr[0] = ocb->L[0] >> 1;
+
+ if (m == 1) {
+ for (x = 0; x < ocb->block_len; x++) {
+ ocb->Lr[x] ^= polys[poly].poly_div[x];
+ }
+ }
+
+ /* set Li, checksum */
+ zeromem(ocb->Li, ocb->block_len);
+ zeromem(ocb->checksum, ocb->block_len);
+
+ /* set other params */
+ ocb->block_index = 1;
+ ocb->cipher = cipher;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_ntz.c b/Sources/libtomcrypt/encauth/ocb/ocb_ntz.c
new file mode 100644
index 00000000..b0f5570d
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_ntz.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_ntz.c
+ OCB implementation, internal function, by Tom St Denis
+*/
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/**
+ Returns the number of leading zero bits [from lsb up]
+ @param x The 32-bit value to observe
+ @return The number of bits [from the lsb up] that are zero
+*/
+int ocb_ntz(unsigned long x)
+{
+ int c;
+ x &= 0xFFFFFFFFUL;
+ c = 0;
+ while ((x & 1) == 0) {
+ ++c;
+ x >>= 1;
+ }
+ return c;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_shift_xor.c b/Sources/libtomcrypt/encauth/ocb/ocb_shift_xor.c
new file mode 100644
index 00000000..2f7bb3b8
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_shift_xor.c
@@ -0,0 +1,27 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_shift_xor.c
+ OCB implementation, internal function, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/**
+ Compute the shift/xor for OCB (internal function)
+ @param ocb The OCB state
+ @param Z The destination of the shift
+*/
+void ocb_shift_xor(ocb_state *ocb, unsigned char *Z)
+{
+ int x, y;
+ y = ocb_ntz(ocb->block_index++);
+ for (x = 0; x < ocb->block_len; x++) {
+ ocb->Li[x] ^= ocb->Ls[y][x];
+ Z[x] = ocb->Li[x] ^ ocb->R[x];
+ }
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb/ocb_test.c b/Sources/libtomcrypt/encauth/ocb/ocb_test.c
new file mode 100644
index 00000000..b03c2fd3
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/ocb_test.c
@@ -0,0 +1,205 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb_test.c
+ OCB implementation, self-test by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/**
+ Test the OCB protocol
+ @return CRYPT_OK if successful
+*/
+int ocb_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ int ptlen;
+ unsigned char key[16], nonce[16], pt[34], ct[34], tag[16];
+ } tests[] = {
+
+ /* OCB-AES-128-0B */
+{
+ 0,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ /* pt */
+ { 0 },
+ /* ct */
+ { 0 },
+ /* tag */
+ { 0x15, 0xd3, 0x7d, 0xd7, 0xc8, 0x90, 0xd5, 0xd6,
+ 0xac, 0xab, 0x92, 0x7b, 0xc0, 0xdc, 0x60, 0xee },
+},
+
+
+ /* OCB-AES-128-3B */
+{
+ 3,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ /* pt */
+ { 0x00, 0x01, 0x02 },
+ /* ct */
+ { 0xfc, 0xd3, 0x7d },
+ /* tag */
+ { 0x02, 0x25, 0x47, 0x39, 0xa5, 0xe3, 0x56, 0x5a,
+ 0xe2, 0xdc, 0xd6, 0x2c, 0x65, 0x97, 0x46, 0xba },
+},
+
+ /* OCB-AES-128-16B */
+{
+ 16,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ /* pt */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* ct */
+ { 0x37, 0xdf, 0x8c, 0xe1, 0x5b, 0x48, 0x9b, 0xf3,
+ 0x1d, 0x0f, 0xc4, 0x4d, 0xa1, 0xfa, 0xf6, 0xd6 },
+ /* tag */
+ { 0xdf, 0xb7, 0x63, 0xeb, 0xdb, 0x5f, 0x0e, 0x71,
+ 0x9c, 0x7b, 0x41, 0x61, 0x80, 0x80, 0x04, 0xdf },
+},
+
+ /* OCB-AES-128-20B */
+{
+ 20,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ /* pt */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13 },
+ /* ct */
+ { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4,
+ 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb,
+ 0x70, 0x03, 0xeb, 0x55},
+ /* tag */
+ { 0x75, 0x30, 0x84, 0x14, 0x4e, 0xb6, 0x3b, 0x77,
+ 0x0b, 0x06, 0x3c, 0x2e, 0x23, 0xcd, 0xa0, 0xbb },
+},
+
+ /* OCB-AES-128-32B */
+{
+ 32,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ /* pt */
+ { 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 },
+ /* ct */
+ { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4,
+ 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb,
+ 0x4a, 0xfc, 0xbb, 0x7f, 0xed, 0xc0, 0x8c, 0xa8,
+ 0x65, 0x4c, 0x6d, 0x30, 0x4d, 0x16, 0x12, 0xfa },
+
+ /* tag */
+ { 0xc1, 0x4c, 0xbf, 0x2c, 0x1a, 0x1f, 0x1c, 0x3c,
+ 0x13, 0x7e, 0xad, 0xea, 0x1f, 0x2f, 0x2f, 0xcf },
+},
+
+ /* OCB-AES-128-34B */
+{
+ 34,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* nonce */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ /* pt */
+ { 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,
+ 0x20, 0x21 },
+ /* ct */
+ { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4,
+ 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb,
+ 0xd4, 0x90, 0x3d, 0xd0, 0x02, 0x5b, 0xa4, 0xaa,
+ 0x83, 0x7c, 0x74, 0xf1, 0x21, 0xb0, 0x26, 0x0f,
+ 0xa9, 0x5d },
+
+ /* tag */
+ { 0xcf, 0x83, 0x41, 0xbb, 0x10, 0x82, 0x0c, 0xcf,
+ 0x14, 0xbd, 0xec, 0x56, 0xb8, 0xd7, 0xd6, 0xab },
+},
+
+};
+
+ int err, x, idx, res;
+ unsigned long len;
+ unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE];
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((idx = find_cipher("aes")) == -1) {
+ if ((idx = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ len = sizeof(outtag);
+ if ((err = ocb_encrypt_authenticate_memory(idx, tests[x].key, 16,
+ tests[x].nonce, tests[x].pt, tests[x].ptlen, outct, outtag, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB Tag", x) ||
+ compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB CT", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ if ((err = ocb_decrypt_verify_memory(idx, tests[x].key, 16, tests[x].nonce, outct, tests[x].ptlen,
+ outct, tests[x].tag, len, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if ((res != 1) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB", x)) {
+#ifdef LTC_TEST_DBG
+ printf("\n\nOCB: Failure-decrypt - res = %d\n", res);
+#endif
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif /* LTC_TEST */
+}
+
+#endif /* LTC_OCB_MODE */
+
+
+/* some comments
+
+ -- it's hard to seek
+ -- hard to stream [you can't emit ciphertext until full block]
+ -- The setup is somewhat complicated...
+*/
diff --git a/Sources/libtomcrypt/encauth/ocb/s_ocb_done.c b/Sources/libtomcrypt/encauth/ocb/s_ocb_done.c
new file mode 100644
index 00000000..c5987b9b
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb/s_ocb_done.c
@@ -0,0 +1,136 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file s_ocb_done.c
+ OCB implementation, internal helper, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB_MODE
+
+/* Since the last block is encrypted in CTR mode the same code can
+ * be used to finish a decrypt or encrypt stream. The only difference
+ * is we XOR the final ciphertext into the checksum so we have to xor it
+ * before we CTR [decrypt] or after [encrypt]
+ *
+ * the names pt/ptlen/ct really just mean in/inlen/out but this is the way I wrote it...
+ */
+
+/**
+ Shared code to finish an OCB stream
+ @param ocb The OCB state
+ @param pt The remaining plaintext [or input]
+ @param ptlen The length of the input (octets)
+ @param ct [out] The output buffer
+ @param tag [out] The destination for the authentication tag
+ @param taglen [in/out] The max size and resulting size of the authentication tag
+ @param mode The mode we are terminating, 0==encrypt, 1==decrypt
+ @return CRYPT_OK if successful
+*/
+int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode)
+
+{
+ unsigned char *Z, *Y, *X;
+ int err, x;
+
+ LTC_ARGCHK(ocb != NULL);
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+ if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length ||
+ (int)ptlen > ocb->block_len || (int)ptlen < 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* allocate ram */
+ Z = XMALLOC(MAXBLOCKSIZE);
+ Y = XMALLOC(MAXBLOCKSIZE);
+ X = XMALLOC(MAXBLOCKSIZE);
+ if (X == NULL || Y == NULL || Z == NULL) {
+ if (X != NULL) {
+ XFREE(X);
+ }
+ if (Y != NULL) {
+ XFREE(Y);
+ }
+ if (Z != NULL) {
+ XFREE(Z);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */
+ ocb_shift_xor(ocb, X);
+ XMEMCPY(Z, X, ocb->block_len);
+
+ X[ocb->block_len-1] ^= (ptlen*8)&255;
+ X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255;
+ for (x = 0; x < ocb->block_len; x++) {
+ X[x] ^= ocb->Lr[x];
+ }
+
+ /* Y[m] = E(X[m])) */
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(X, Y, &ocb->key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if (mode == 1) {
+ /* decrypt mode, so let's xor it first */
+ /* xor C[m] into checksum */
+ for (x = 0; x < (int)ptlen; x++) {
+ ocb->checksum[x] ^= ct[x];
+ }
+ }
+
+ /* C[m] = P[m] xor Y[m] */
+ for (x = 0; x < (int)ptlen; x++) {
+ ct[x] = pt[x] ^ Y[x];
+ }
+
+ if (mode == 0) {
+ /* encrypt mode */
+ /* xor C[m] into checksum */
+ for (x = 0; x < (int)ptlen; x++) {
+ ocb->checksum[x] ^= ct[x];
+ }
+ }
+
+ /* xor Y[m] and Z[m] into checksum */
+ for (x = 0; x < ocb->block_len; x++) {
+ ocb->checksum[x] ^= Y[x] ^ Z[x];
+ }
+
+ /* encrypt checksum, er... tag!! */
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->checksum, X, &ocb->key)) != CRYPT_OK) {
+ goto error;
+ }
+ cipher_descriptor[ocb->cipher].done(&ocb->key);
+
+ /* now store it */
+ for (x = 0; x < ocb->block_len && x < (int)*taglen; x++) {
+ tag[x] = X[x];
+ }
+ *taglen = x;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(X, MAXBLOCKSIZE);
+ zeromem(Y, MAXBLOCKSIZE);
+ zeromem(Z, MAXBLOCKSIZE);
+ zeromem(ocb, sizeof(*ocb));
+#endif
+error:
+ XFREE(X);
+ XFREE(Y);
+ XFREE(Z);
+
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_add_aad.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_add_aad.c
new file mode 100644
index 00000000..fd09abaa
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_add_aad.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_add_aad.c
+ OCB implementation, add AAD data, by Karel Miko
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Add one block of AAD data (internal function)
+ @param ocb The OCB state
+ @param aad_block [in] AAD data (block_len size)
+ @return CRYPT_OK if successful
+*/
+static int s_ocb3_int_aad_add_block(ocb3_state *ocb, const unsigned char *aad_block)
+{
+ unsigned char tmp[MAXBLOCKSIZE];
+ int err;
+
+ /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+ ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_[ocb3_int_ntz(ocb->ablock_index)], ocb->block_len);
+
+ /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */
+ ocb3_int_xor_blocks(tmp, aad_block, ocb->aOffset_current, ocb->block_len);
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) {
+ return err;
+ }
+ ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len);
+
+ ocb->ablock_index++;
+
+ return CRYPT_OK;
+}
+
+/**
+ Add AAD - additional associated data
+ @param ocb The OCB state
+ @param aad The AAD data
+ @param aadlen The size of AAD data (octets)
+ @return CRYPT_OK if successful
+*/
+int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen)
+{
+ int err, x, full_blocks, full_blocks_len, last_block_len;
+ unsigned char *data;
+ unsigned long datalen, l;
+
+ LTC_ARGCHK(ocb != NULL);
+ if (aadlen == 0) return CRYPT_OK;
+ LTC_ARGCHK(aad != NULL);
+
+ if (ocb->adata_buffer_bytes > 0) {
+ l = ocb->block_len - ocb->adata_buffer_bytes;
+ if (l > aadlen) l = aadlen;
+ XMEMCPY(ocb->adata_buffer+ocb->adata_buffer_bytes, aad, l);
+ ocb->adata_buffer_bytes += l;
+
+ if (ocb->adata_buffer_bytes == ocb->block_len) {
+ if ((err = s_ocb3_int_aad_add_block(ocb, ocb->adata_buffer)) != CRYPT_OK) {
+ return err;
+ }
+ ocb->adata_buffer_bytes = 0;
+ }
+
+ data = (unsigned char *)aad + l;
+ datalen = aadlen - l;
+ }
+ else {
+ data = (unsigned char *)aad;
+ datalen = aadlen;
+ }
+
+ if (datalen == 0) return CRYPT_OK;
+
+ full_blocks = datalen/ocb->block_len;
+ full_blocks_len = full_blocks * ocb->block_len;
+ last_block_len = datalen - full_blocks_len;
+
+ for (x=0; xblock_len)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ if (last_block_len>0) {
+ XMEMCPY(ocb->adata_buffer, data+full_blocks_len, last_block_len);
+ ocb->adata_buffer_bytes = last_block_len;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_decrypt.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_decrypt.c
new file mode 100644
index 00000000..5261518f
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_decrypt.c
@@ -0,0 +1,76 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_decrypt.c
+ OCB implementation, decrypt data, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Decrypt blocks of ciphertext with OCB
+ @param ocb The OCB state
+ @param ct The ciphertext (length multiple of the block size of the block cipher)
+ @param ctlen The length of the input (octets)
+ @param pt [out] The plaintext (length of ct)
+ @return CRYPT_OK if successful
+*/
+int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt)
+{
+ unsigned char tmp[MAXBLOCKSIZE];
+ int err, i, full_blocks;
+ unsigned char *pt_b, *ct_b;
+
+ LTC_ARGCHK(ocb != NULL);
+ if (ctlen == 0) return CRYPT_OK; /* no data, nothing to do */
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(pt != NULL);
+
+ if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (ctlen % ocb->block_len) { /* ctlen has to bu multiple of block_len */
+ return CRYPT_INVALID_ARG;
+ }
+
+ full_blocks = ctlen/ocb->block_len;
+ for(i=0; iblock_len;
+ ct_b = (unsigned char *)ct+i*ocb->block_len;
+
+ /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */
+ ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len);
+
+ /* tmp[] = ct[] XOR ocb->Offset_current[] */
+ ocb3_int_xor_blocks(tmp, ct_b, ocb->Offset_current, ocb->block_len);
+
+ /* decrypt */
+ if ((err = cipher_descriptor[ocb->cipher].ecb_decrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* pt[] = tmp[] XOR ocb->Offset_current[] */
+ ocb3_int_xor_blocks(pt_b, tmp, ocb->Offset_current, ocb->block_len);
+
+ /* ocb->checksum[] = ocb->checksum[] XOR pt[] */
+ ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len);
+
+ ocb->block_index++;
+ }
+
+ err = CRYPT_OK;
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmp, sizeof(tmp));
+#endif
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_decrypt_last.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_decrypt_last.c
new file mode 100644
index 00000000..f69e34b7
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_decrypt_last.c
@@ -0,0 +1,101 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_decrypt_last.c
+ OCB implementation, internal helper, by Karel Miko
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Finish an OCB (decryption) stream
+ @param ocb The OCB state
+ @param ct The remaining ciphertext
+ @param ctlen The length of the ciphertext (octets)
+ @param pt [out] The output buffer
+ @return CRYPT_OK if successful
+*/
+int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt)
+{
+ unsigned char iOffset_star[MAXBLOCKSIZE];
+ unsigned char iPad[MAXBLOCKSIZE];
+ int err, x, full_blocks, full_blocks_len, last_block_len;
+
+ LTC_ARGCHK(ocb != NULL);
+ if (ct == NULL) LTC_ARGCHK(ctlen == 0);
+ if (ctlen != 0) {
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(pt != NULL);
+ }
+
+ if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ full_blocks = ctlen/ocb->block_len;
+ full_blocks_len = full_blocks * ocb->block_len;
+ last_block_len = ctlen - full_blocks_len;
+
+ /* process full blocks first */
+ if (full_blocks>0) {
+ if ((err = ocb3_decrypt(ocb, ct, full_blocks_len, pt)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ if (last_block_len>0) {
+ /* Offset_* = Offset_m xor L_* */
+ ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len);
+
+ /* Pad = ENCIPHER(K, Offset_*) */
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* P_* = C_* xor Pad[1..bitlen(C_*)] */
+ ocb3_int_xor_blocks(pt+full_blocks_len, (unsigned char *)ct+full_blocks_len, iPad, last_block_len);
+
+ /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
+ ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len);
+ for(x=last_block_len; xblock_len; x++) {
+ if (x == last_block_len) {
+ ocb->checksum[x] ^= 0x80;
+ } else {
+ ocb->checksum[x] ^= 0x00;
+ }
+ }
+
+ /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */
+ /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */
+ for(x=0; xblock_len; x++) {
+ ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x];
+ }
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+ else {
+ /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */
+ /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */
+ for(x=0; xblock_len; x++) {
+ ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x];
+ }
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ err = CRYPT_OK;
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(iOffset_star, MAXBLOCKSIZE);
+ zeromem(iPad, MAXBLOCKSIZE);
+#endif
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_decrypt_verify_memory.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_decrypt_verify_memory.c
new file mode 100644
index 00000000..03d33b20
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_decrypt_verify_memory.c
@@ -0,0 +1,100 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_decrypt_verify_memory.c
+ OCB implementation, helper to decrypt block of memory, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Decrypt and compare the tag with OCB
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param nonce The session nonce (length of the block size of the block cipher)
+ @param noncelen The length of the nonce (octets)
+ @param adata The AAD - additional associated data
+ @param adatalen The length of AAD (octets)
+ @param ct The ciphertext
+ @param ctlen The length of the ciphertext (octets)
+ @param pt [out] The plaintext
+ @param tag The tag to compare against
+ @param taglen The length of the tag (octets)
+ @param stat [out] The result of the tag comparison (1==valid, 0==invalid)
+ @return CRYPT_OK if successful regardless of the tag comparison
+*/
+int ocb3_decrypt_verify_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *adata, unsigned long adatalen,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen,
+ int *stat)
+{
+ int err;
+ ocb3_state *ocb;
+ unsigned char *buf;
+ unsigned long buflen;
+
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to zero */
+ *stat = 0;
+
+ /* limit taglen */
+ taglen = MIN(taglen, MAXBLOCKSIZE);
+
+ /* allocate memory */
+ buf = XMALLOC(taglen);
+ ocb = XMALLOC(sizeof(ocb3_state));
+ if (ocb == NULL || buf == NULL) {
+ if (ocb != NULL) {
+ XFREE(ocb);
+ }
+ if (buf != NULL) {
+ XFREE(buf);
+ }
+ return CRYPT_MEM;
+ }
+
+ if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, taglen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if (adata != NULL || adatalen != 0) {
+ if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ if ((err = ocb3_decrypt_last(ocb, ct, ctlen, pt)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ buflen = taglen;
+ if ((err = ocb3_done(ocb, buf, &buflen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* compare tags */
+ if (buflen >= taglen && XMEM_NEQ(buf, tag, taglen) == 0) {
+ *stat = 1;
+ }
+
+ err = CRYPT_OK;
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(ocb, sizeof(ocb3_state));
+#endif
+
+ XFREE(ocb);
+ XFREE(buf);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_done.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_done.c
new file mode 100644
index 00000000..688aa80e
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_done.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_done.c
+ OCB implementation, INTERNAL ONLY helper, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Finish OCB processing and compute the tag
+ @param ocb The OCB state
+ @param tag [out] The destination for the authentication tag
+ @param taglen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful
+*/
+int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen)
+{
+ unsigned char tmp[MAXBLOCKSIZE];
+ int err, x;
+
+ LTC_ARGCHK(ocb != NULL);
+ LTC_ARGCHK(tag != NULL);
+ LTC_ARGCHK(taglen != NULL);
+ if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* check taglen */
+ if ((int)*taglen < ocb->tag_len) {
+ *taglen = (unsigned long)ocb->tag_len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* finalize AAD processing */
+
+ if (ocb->adata_buffer_bytes>0) {
+ /* Offset_* = Offset_m xor L_* */
+ ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_star, ocb->block_len);
+
+ /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */
+ ocb3_int_xor_blocks(tmp, ocb->adata_buffer, ocb->aOffset_current, ocb->adata_buffer_bytes);
+ for(x=ocb->adata_buffer_bytes; xblock_len; x++) {
+ if (x == ocb->adata_buffer_bytes) {
+ tmp[x] = 0x80 ^ ocb->aOffset_current[x];
+ }
+ else {
+ tmp[x] = 0x00 ^ ocb->aOffset_current[x];
+ }
+ }
+
+ /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len);
+ }
+
+ /* finalize TAG computing */
+
+ /* at this point ocb->aSum_current = HASH(K, A) */
+ /* tag = tag ^ HASH(K, A) */
+ ocb3_int_xor_blocks(tmp, ocb->tag_part, ocb->aSum_current, ocb->block_len);
+
+ /* copy tag bytes */
+ for(x = 0; x < ocb->tag_len; x++) tag[x] = tmp[x];
+ *taglen = (unsigned long)ocb->tag_len;
+
+ err = CRYPT_OK;
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmp, MAXBLOCKSIZE);
+ zeromem(ocb, sizeof(*ocb));
+#endif
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_encrypt.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_encrypt.c
new file mode 100644
index 00000000..45ba8a97
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_encrypt.c
@@ -0,0 +1,76 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_encrypt.c
+ OCB implementation, encrypt data, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Encrypt blocks of data with OCB
+ @param ocb The OCB state
+ @param pt The plaintext (length multiple of the block size of the block cipher)
+ @param ptlen The length of the input (octets)
+ @param ct [out] The ciphertext (same size as the pt)
+ @return CRYPT_OK if successful
+*/
+int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct)
+{
+ unsigned char tmp[MAXBLOCKSIZE];
+ int err, i, full_blocks;
+ unsigned char *pt_b, *ct_b;
+
+ LTC_ARGCHK(ocb != NULL);
+ if (ptlen == 0) return CRYPT_OK; /* no data, nothing to do */
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+
+ if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (ptlen % ocb->block_len) { /* ptlen has to bu multiple of block_len */
+ return CRYPT_INVALID_ARG;
+ }
+
+ full_blocks = ptlen/ocb->block_len;
+ for(i=0; iblock_len;
+ ct_b = (unsigned char *)ct+i*ocb->block_len;
+
+ /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */
+ ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len);
+
+ /* tmp[] = pt[] XOR ocb->Offset_current[] */
+ ocb3_int_xor_blocks(tmp, pt_b, ocb->Offset_current, ocb->block_len);
+
+ /* encrypt */
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* ct[] = tmp[] XOR ocb->Offset_current[] */
+ ocb3_int_xor_blocks(ct_b, tmp, ocb->Offset_current, ocb->block_len);
+
+ /* ocb->checksum[] = ocb->checksum[] XOR pt[] */
+ ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len);
+
+ ocb->block_index++;
+ }
+
+ err = CRYPT_OK;
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmp, sizeof(tmp));
+#endif
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_encrypt_authenticate_memory.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_encrypt_authenticate_memory.c
new file mode 100644
index 00000000..b1189252
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_encrypt_authenticate_memory.c
@@ -0,0 +1,72 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_encrypt_authenticate_memory.c
+ OCB implementation, encrypt block of memory, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Encrypt and generate an authentication code for a buffer of memory
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param nonce The session nonce (length of the block ciphers block size)
+ @param noncelen The length of the nonce (octets)
+ @param adata The AAD - additional associated data
+ @param adatalen The length of AAD (octets)
+ @param pt The plaintext
+ @param ptlen The length of the plaintext (octets)
+ @param ct [out] The ciphertext
+ @param tag [out] The authentication tag
+ @param taglen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful
+*/
+int ocb3_encrypt_authenticate_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *adata, unsigned long adatalen,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen)
+{
+ int err;
+ ocb3_state *ocb;
+
+ LTC_ARGCHK(taglen != NULL);
+
+ /* allocate memory */
+ ocb = XMALLOC(sizeof(ocb3_state));
+ if (ocb == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, *taglen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if (adata != NULL || adatalen != 0) {
+ if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ if ((err = ocb3_encrypt_last(ocb, pt, ptlen, ct)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ err = ocb3_done(ocb, tag, taglen);
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(ocb, sizeof(ocb3_state));
+#endif
+
+ XFREE(ocb);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_encrypt_last.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_encrypt_last.c
new file mode 100644
index 00000000..76bd1ede
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_encrypt_last.c
@@ -0,0 +1,102 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_encrypt_last.c
+ OCB implementation, internal helper, by Karel Miko
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Finish an OCB (encryption) stream
+ @param ocb The OCB state
+ @param pt The remaining plaintext
+ @param ptlen The length of the plaintext (octets)
+ @param ct [out] The output buffer
+ @return CRYPT_OK if successful
+*/
+int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct)
+{
+ unsigned char iOffset_star[MAXBLOCKSIZE];
+ unsigned char iPad[MAXBLOCKSIZE];
+ int err, x, full_blocks, full_blocks_len, last_block_len;
+
+ LTC_ARGCHK(ocb != NULL);
+ if (pt == NULL) LTC_ARGCHK(ptlen == 0);
+ if (ptlen != 0) {
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ }
+
+ if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ full_blocks = ptlen/ocb->block_len;
+ full_blocks_len = full_blocks * ocb->block_len;
+ last_block_len = ptlen - full_blocks_len;
+
+ /* process full blocks first */
+ if (full_blocks>0) {
+ if ((err = ocb3_encrypt(ocb, pt, full_blocks_len, ct)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* at this point: m = ocb->block_index (last block index), Offset_m = ocb->Offset_current */
+
+ if (last_block_len>0) {
+ /* Offset_* = Offset_m xor L_* */
+ ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len);
+
+ /* Pad = ENCIPHER(K, Offset_*) */
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* C_* = P_* xor Pad[1..bitlen(P_*)] */
+ ocb3_int_xor_blocks(ct+full_blocks_len, pt+full_blocks_len, iPad, last_block_len);
+
+ /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
+ ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len);
+ for(x=last_block_len; xblock_len; x++) {
+ if (x == last_block_len) {
+ ocb->checksum[x] ^= 0x80;
+ } else {
+ ocb->checksum[x] ^= 0x00;
+ }
+ }
+
+ /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */
+ /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */
+ for(x=0; xblock_len; x++) {
+ ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x];
+ }
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */
+ /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */
+ for(x=0; xblock_len; x++) {
+ ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x];
+ }
+ if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ err = CRYPT_OK;
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(iOffset_star, MAXBLOCKSIZE);
+ zeromem(iPad, MAXBLOCKSIZE);
+#endif
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_init.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_init.c
new file mode 100644
index 00000000..09493acc
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_init.c
@@ -0,0 +1,186 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_init.c
+ OCB implementation, initialize state, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+static void s_ocb3_int_calc_offset_zero(ocb3_state *ocb, const unsigned char *nonce, unsigned long noncelen, unsigned long taglen)
+{
+ int x, y, bottom;
+ int idx, shift;
+ unsigned char iNonce[MAXBLOCKSIZE];
+ unsigned char iKtop[MAXBLOCKSIZE];
+ unsigned char iStretch[MAXBLOCKSIZE+8];
+
+ /* Nonce = zeros(127-bitlen(N)) || 1 || N */
+ zeromem(iNonce, sizeof(iNonce));
+ for (x = ocb->block_len-1, y=0; y<(int)noncelen; x--, y++) {
+ iNonce[x] = nonce[noncelen-y-1];
+ }
+ iNonce[x] = 0x01;
+ iNonce[0] |= ((taglen*8) % 128) << 1;
+
+ /* bottom = str2num(Nonce[123..128]) */
+ bottom = iNonce[ocb->block_len-1] & 0x3F;
+
+ /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */
+ iNonce[ocb->block_len-1] = iNonce[ocb->block_len-1] & 0xC0;
+ if ((cipher_descriptor[ocb->cipher].ecb_encrypt(iNonce, iKtop, &ocb->key)) != CRYPT_OK) {
+ zeromem(ocb->Offset_current, ocb->block_len);
+ return;
+ }
+
+ /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */
+ for (x = 0; x < ocb->block_len; x++) {
+ iStretch[x] = iKtop[x];
+ }
+ for (y = 0; y < 8; y++) {
+ iStretch[x+y] = iKtop[y] ^ iKtop[y+1];
+ }
+
+ /* Offset_0 = Stretch[1+bottom..128+bottom] */
+ idx = bottom / 8;
+ shift = (bottom % 8);
+ for (x = 0; x < ocb->block_len; x++) {
+ ocb->Offset_current[x] = iStretch[idx+x] << shift;
+ if (shift > 0) {
+ ocb->Offset_current[x] |= iStretch[idx+x+1] >> (8-shift);
+ }
+ }
+}
+
+static const struct {
+ int len;
+ unsigned char poly_mul[MAXBLOCKSIZE];
+} polys[] = {
+{
+ 8,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }
+}, {
+ 16,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }
+}
+};
+
+/**
+ Initialize an OCB context
+ @param ocb [out] The destination of the OCB state
+ @param cipher The index of the desired cipher
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param nonce The session nonce
+ @param noncelen The length of the session nonce (octets, up to 15)
+ @param taglen The length of the tag (octets, up to 16)
+ @return CRYPT_OK if successful
+*/
+int ocb3_init(ocb3_state *ocb, int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ unsigned long taglen)
+{
+ int poly, x, y, m, err;
+ unsigned char *previous, *current;
+
+ LTC_ARGCHK(ocb != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(nonce != NULL);
+
+ /* valid cipher? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+ ocb->cipher = cipher;
+
+ /* Valid Nonce?
+ * As of RFC7253: "string of no more than 120 bits" */
+ if (noncelen > (120/8)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* The blockcipher must have a 128-bit blocksize */
+ if (cipher_descriptor[cipher].block_length != 16) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* The TAGLEN may be any value up to 128 (bits) */
+ if (taglen > 16) {
+ return CRYPT_INVALID_ARG;
+ }
+ ocb->tag_len = taglen;
+
+ /* determine which polys to use */
+ ocb->block_len = cipher_descriptor[cipher].block_length;
+ x = (int)(sizeof(polys)/sizeof(polys[0]));
+ for (poly = 0; poly < x; poly++) {
+ if (polys[poly].len == ocb->block_len) {
+ break;
+ }
+ }
+ if (poly == x) {
+ return CRYPT_INVALID_ARG; /* block_len not found in polys */
+ }
+ if (polys[poly].len != ocb->block_len) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* schedule the key */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* L_* = ENCIPHER(K, zeros(128)) */
+ zeromem(ocb->L_star, ocb->block_len);
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->L_star, ocb->L_star, &ocb->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* compute L_$, L_0, L_1, ... */
+ for (x = -1; x < 32; x++) {
+ if (x == -1) { /* gonna compute: L_$ = double(L_*) */
+ current = ocb->L_dollar;
+ previous = ocb->L_star;
+ }
+ else if (x == 0) { /* gonna compute: L_0 = double(L_$) */
+ current = ocb->L_[0];
+ previous = ocb->L_dollar;
+ }
+ else { /* gonna compute: L_i = double(L_{i-1}) for every integer i > 0 */
+ current = ocb->L_[x];
+ previous = ocb->L_[x-1];
+ }
+ m = previous[0] >> 7;
+ for (y = 0; y < ocb->block_len-1; y++) {
+ current[y] = ((previous[y] << 1) | (previous[y+1] >> 7)) & 255;
+ }
+ current[ocb->block_len-1] = (previous[ocb->block_len-1] << 1) & 255;
+ if (m == 1) {
+ /* current[] = current[] XOR polys[poly].poly_mul[]*/
+ ocb3_int_xor_blocks(current, current, polys[poly].poly_mul, ocb->block_len);
+ }
+ }
+
+ /* initialize ocb->Offset_current = Offset_0 */
+ s_ocb3_int_calc_offset_zero(ocb, nonce, noncelen, taglen);
+
+ /* initialize checksum to all zeros */
+ zeromem(ocb->checksum, ocb->block_len);
+
+ /* set block index */
+ ocb->block_index = 1;
+
+ /* initialize AAD related stuff */
+ ocb->ablock_index = 1;
+ ocb->adata_buffer_bytes = 0;
+ zeromem(ocb->aOffset_current, ocb->block_len);
+ zeromem(ocb->aSum_current, ocb->block_len);
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_int_ntz.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_int_ntz.c
new file mode 100644
index 00000000..86942ced
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_int_ntz.c
@@ -0,0 +1,29 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_int_ntz.c
+ OCB implementation, INTERNAL ONLY helper, by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Returns the number of leading zero bits [from lsb up] (internal function)
+ @param x The 32-bit value to observe
+ @return The number of bits [from the lsb up] that are zero
+*/
+int ocb3_int_ntz(unsigned long x)
+{
+ int c;
+ x &= 0xFFFFFFFFUL;
+ c = 0;
+ while ((x & 1) == 0) {
+ ++c;
+ x >>= 1;
+ }
+ return c;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_int_xor_blocks.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_int_xor_blocks.c
new file mode 100644
index 00000000..f9f342aa
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_int_xor_blocks.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_int_xor_blocks.c
+ OCB implementation, INTERNAL ONLY helper, by Karel Miko
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Compute xor for two blocks of bytes 'out = block_a XOR block_b' (internal function)
+ @param out The block of bytes (output)
+ @param block_a The block of bytes (input)
+ @param block_b The block of bytes (input)
+ @param block_len The size of block_a, block_b, out
+*/
+void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len)
+{
+ int x;
+ if (out == block_a) {
+ for (x = 0; x < (int)block_len; x++) out[x] ^= block_b[x];
+ }
+ else {
+ for (x = 0; x < (int)block_len; x++) out[x] = block_a[x] ^ block_b[x];
+ }
+}
+
+#endif
diff --git a/Sources/libtomcrypt/encauth/ocb3/ocb3_test.c b/Sources/libtomcrypt/encauth/ocb3/ocb3_test.c
new file mode 100644
index 00000000..3a9816e6
--- /dev/null
+++ b/Sources/libtomcrypt/encauth/ocb3/ocb3_test.c
@@ -0,0 +1,299 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file ocb3_test.c
+ OCB implementation, self-test by Tom St Denis
+*/
+#include "tomcrypt_private.h"
+
+#ifdef LTC_OCB3_MODE
+
+/**
+ Test the OCB protocol
+ @return CRYPT_OK if successful
+*/
+int ocb3_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ /* test vectors from: http://tools.ietf.org/html/draft-krovetz-ocb-03 */
+ unsigned char key[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F };
+ unsigned char nonce[12] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B };
+ const struct {
+ int ptlen;
+ int aadlen;
+ unsigned char pt[64], aad[64], ct[64], tag[16];
+ } tests[] = {
+
+ { /* index:0 */
+ 0, /* PLAINTEXT length */
+ 0, /* AAD length */
+ { 0 }, /* PLAINTEXT */
+ { 0 }, /* AAD */
+ { 0 }, /* CIPHERTEXT */
+ { 0x19,0x7b,0x9c,0x3c,0x44,0x1d,0x3c,0x83,0xea,0xfb,0x2b,0xef,0x63,0x3b,0x91,0x82 }, /* TAG */
+ },
+ { /* index:1 */
+ 8, /* PLAINTEXT length */
+ 8, /* AAD length */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */
+ { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */
+ { 0x16,0xdc,0x76,0xa4,0x6d,0x47,0xe1,0xea,0xd5,0x37,0x20,0x9e,0x8a,0x96,0xd1,0x4e }, /* TAG */
+ },
+ { /* index:2 */
+ 0, /* PLAINTEXT length */
+ 8, /* AAD length */
+ { 0 }, /* PLAINTEXT */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */
+ { 0 }, /* CIPHERTEXT */
+ { 0x98,0xb9,0x15,0x52,0xc8,0xc0,0x09,0x18,0x50,0x44,0xe3,0x0a,0x6e,0xb2,0xfe,0x21 }, /* TAG */
+ },
+ { /* index:3 */
+ 8, /* PLAINTEXT length */
+ 0, /* AAD length */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */
+ { 0 }, /* AAD */
+ { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */
+ { 0x97,0x1e,0xff,0xca,0xe1,0x9a,0xd4,0x71,0x6f,0x88,0xe8,0x7b,0x87,0x1f,0xbe,0xed }, /* TAG */
+ },
+ { /* index:4 */
+ 16, /* PLAINTEXT length */
+ 16, /* AAD length */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* PLAINTEXT */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* AAD */
+ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */
+ { 0x77,0x6c,0x99,0x24,0xd6,0x72,0x3a,0x1f,0xc4,0x52,0x45,0x32,0xac,0x3e,0x5b,0xeb }, /* TAG */
+ },
+ { /* index:5 */
+ 0, /* PLAINTEXT length */
+ 16, /* AAD length */
+ { 0 }, /* PLAINTEXT */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* AAD */
+ { 0 }, /* CIPHERTEXT */
+ { 0x7d,0xdb,0x8e,0x6c,0xea,0x68,0x14,0x86,0x62,0x12,0x50,0x96,0x19,0xb1,0x9c,0xc6 }, /* TAG */
+ },
+ { /* index:6 */
+ 16, /* PLAINTEXT length */
+ 0, /* AAD length */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* PLAINTEXT */
+ { 0 }, /* AAD */
+ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */
+ { 0x13,0xcc,0x8b,0x74,0x78,0x07,0x12,0x1a,0x4c,0xbb,0x3e,0x4b,0xd6,0xb4,0x56,0xaf }, /* TAG */
+ },
+ { /* index:7 */
+ 24, /* PLAINTEXT length */
+ 24, /* AAD length */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* PLAINTEXT */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* AAD */
+ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */
+ { 0x5f,0xa9,0x4f,0xc3,0xf3,0x88,0x20,0xf1,0xdc,0x3f,0x3d,0x1f,0xd4,0xe5,0x5e,0x1c }, /* TAG */
+ },
+ { /* index:8 */
+ 0, /* PLAINTEXT length */
+ 24, /* AAD length */
+ { 0 }, /* PLAINTEXT */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* AAD */
+ { 0 }, /* CIPHERTEXT */
+ { 0x28,0x20,0x26,0xda,0x30,0x68,0xbc,0x9f,0xa1,0x18,0x68,0x1d,0x55,0x9f,0x10,0xf6 }, /* TAG */
+ },
+ { /* index:9 */
+ 24, /* PLAINTEXT length */
+ 0, /* AAD length */
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* PLAINTEXT */
+ { 0 }, /* AAD */
+ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */
+ { 0x6e,0xf2,0xf5,0x25,0x87,0xfd,0xa0,0xed,0x97,0xdc,0x7e,0xed,0xe2,0x41,0xdf,0x68 }, /* TAG */
+ },
+ { /* index:10 */
+ 32, /* PLAINTEXT length */
+ 32, /* AAD length */
+ { 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 }, /* PLAINTEXT */
+ { 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 }, /* AAD */
+ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */
+ { 0xb2,0xa0,0x40,0xdd,0x3b,0xd5,0x16,0x43,0x72,0xd7,0x6d,0x7b,0xb6,0x82,0x42,0x40 }, /* TAG */
+ },
+ { /* index:11 */
+ 0, /* PLAINTEXT length */
+ 32, /* AAD length */
+ { 0 }, /* PLAINTEXT */
+ { 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 }, /* AAD */
+ { 0 }, /* CIPHERTEXT */
+ { 0xe1,0xe0,0x72,0x63,0x3b,0xad,0xe5,0x1a,0x60,0xe8,0x59,0x51,0xd9,0xc4,0x2a,0x1b }, /* TAG */
+ },
+ { /* index:12 */
+ 32, /* PLAINTEXT length */
+ 0, /* AAD length */
+ { 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 }, /* PLAINTEXT */
+ { 0 }, /* AAD */
+ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */
+ { 0x4a,0x3b,0xae,0x82,0x44,0x65,0xcf,0xda,0xf8,0xc4,0x1f,0xc5,0x0c,0x7d,0xf9,0xd9 }, /* TAG */
+ },
+ { /* index:13 */
+ 40, /* PLAINTEXT length */
+ 40, /* AAD length */
+ { 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,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* PLAINTEXT */
+ { 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,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */
+ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */
+ { 0x65,0x9c,0x62,0x32,0x11,0xde,0xea,0x0d,0xe3,0x0d,0x2c,0x38,0x18,0x79,0xf4,0xc8 }, /* TAG */
+ },
+ { /* index:14 */
+ 0, /* PLAINTEXT length */
+ 40, /* AAD length */
+ { 0 }, /* PLAINTEXT */
+ { 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,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */
+ { 0 }, /* CIPHERTEXT */
+ { 0x7a,0xeb,0x7a,0x69,0xa1,0x68,0x7d,0xd0,0x82,0xca,0x27,0xb0,0xd9,0xa3,0x70,0x96 }, /* TAG */
+ },
+ { /* index:15 */
+ 40, /* PLAINTEXT length */
+ 0, /* AAD length */
+ { 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,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* PLAINTEXT */
+ { 0 }, /* AAD */
+ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */
+ { 0x06,0x0c,0x84,0x67,0xf4,0xab,0xab,0x5e,0x8b,0x3c,0x20,0x67,0xa2,0xe1,0x15,0xdc }, /* TAG */
+ },
+
+};
+ /* As of RFC 7253 - 'Appendix A. Sample Results'
+ * The next tuple shows a result with a tag length of 96 bits and a
+ different key.
+
+ K: 0F0E0D0C0B0A09080706050403020100
+
+ N: BBAA9988776655443322110D
+ A: 000102030405060708090A0B0C0D0E0F1011121314151617
+ 18191A1B1C1D1E1F2021222324252627
+ P: 000102030405060708090A0B0C0D0E0F1011121314151617
+ 18191A1B1C1D1E1F2021222324252627
+ C: 1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1
+ A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD
+ AC4F02AA
+
+ The C has been split up in C and T (tag)
+ */
+ const unsigned char K[] = { 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08,
+ 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 };
+ const unsigned char N[] = { 0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44,
+ 0x33,0x22,0x11,0x0D };
+ const unsigned char A[] = { 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,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 };
+ const unsigned char P[] = { 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,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 };
+ const unsigned char C[] = { 0x17,0x92,0xA4,0xE3,0x1E,0x07,0x55,0xFB,
+ 0x03,0xE3,0x1B,0x22,0x11,0x6E,0x6C,0x2D,
+ 0xDF,0x9E,0xFD,0x6E,0x33,0xD5,0x36,0xF1,
+ 0xA0,0x12,0x4B,0x0A,0x55,0xBA,0xE8,0x84,
+ 0xED,0x93,0x48,0x15,0x29,0xC7,0x6B,0x6A };
+ const unsigned char T[] = { 0xD0,0xC5,0x15,0xF4,0xD1,0xCD,0xD4,0xFD,
+ 0xAC,0x4F,0x02,0xAA };
+
+ int err, x, idx, res;
+ unsigned long len;
+ unsigned char outct[MAXBLOCKSIZE] = { 0 };
+ unsigned char outtag[MAXBLOCKSIZE] = { 0 };
+ ocb3_state ocb;
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((idx = find_cipher("aes")) == -1) {
+ if ((idx = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ len = 16; /* must be the same as the required taglen */
+ if ((err = ocb3_encrypt_authenticate_memory(idx,
+ key, sizeof(key),
+ nonce, sizeof(nonce),
+ tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen,
+ tests[x].ptlen != 0 ? tests[x].pt : NULL, tests[x].ptlen,
+ tests[x].ptlen != 0 ? outct : NULL, outtag, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB3 Tag", x) ||
+ compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB3 CT", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ if ((err = ocb3_decrypt_verify_memory(idx,
+ key, sizeof(key),
+ nonce, sizeof(nonce),
+ tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen,
+ tests[x].ptlen != 0 ? outct : NULL, tests[x].ptlen,
+ tests[x].ptlen != 0 ? outct : NULL, tests[x].tag, len, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if ((res != 1) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB3", x)) {
+#ifdef LTC_TEST_DBG
+ printf("\n\nOCB3: Failure-decrypt - res = %d\n", res);
+#endif
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ /* RFC 7253 - test vector with a tag length of 96 bits - part 1 */
+ x = 99;
+ len = 12;
+ if ((err = ocb3_encrypt_authenticate_memory(idx,
+ K, sizeof(K),
+ N, sizeof(N),
+ A, sizeof(A),
+ P, sizeof(P),
+ outct, outtag, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag", x) ||
+ compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ if ((err = ocb3_decrypt_verify_memory(idx,
+ K, sizeof(K),
+ N, sizeof(N),
+ A, sizeof(A),
+ C, sizeof(C),
+ outct, T, sizeof(T), &res)) != CRYPT_OK) {
+ return err;
+ }
+ if ((res != 1) || compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3", x)) {
+#ifdef LTC_TEST_DBG
+ printf("\n\nOCB3: Failure-decrypt - res = %d\n", res);
+#endif
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* RFC 7253 - test vector with a tag length of 96 bits - part 2 */
+ x = 100;
+ if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err;
+ if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err;
+ if ((err = ocb3_encrypt(&ocb, P, 32, outct)) != CRYPT_OK) return err;
+ if ((err = ocb3_encrypt_last(&ocb, P+32, sizeof(P)-32, outct+32)) != CRYPT_OK) return err;
+ len = sizeof(outtag); /* intentionally more than 12 */
+ if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err;
+ if (compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) return CRYPT_FAIL_TESTVECTOR;
+ if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.enc", x)) return CRYPT_FAIL_TESTVECTOR;
+ if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err;
+ if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err;
+ if ((err = ocb3_decrypt(&ocb, C, 32, outct)) != CRYPT_OK) return err;
+ if ((err = ocb3_decrypt_last(&ocb, C+32, sizeof(C)-32, outct+32)) != CRYPT_OK) return err;
+ len = sizeof(outtag); /* intentionally more than 12 */
+ if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err;
+ if (compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3 PT", x)) return CRYPT_FAIL_TESTVECTOR;
+ if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.dec", x)) return CRYPT_FAIL_TESTVECTOR;
+
+ return CRYPT_OK;
+#endif /* LTC_TEST */
+}
+
+#endif /* LTC_OCB3_MODE */
diff --git a/Sources/libtomcrypt/hashes/blake2b.c b/Sources/libtomcrypt/hashes/blake2b.c
new file mode 100644
index 00000000..8cbeac21
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/blake2b.c
@@ -0,0 +1,628 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/*
+ BLAKE2 reference source code package - reference C implementations
+
+ Copyright 2012, Samuel Neves . You may use this under the
+ terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
+ your option. The terms of these licenses can be found at:
+
+ - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ - OpenSSL license : https://www.openssl.org/source/license.html
+ - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
+
+ More information about the BLAKE2 hash function can be found at
+ https://blake2.net.
+*/
+/* see also https://www.ietf.org/rfc/rfc7693.txt */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2B
+
+enum blake2b_constant {
+ BLAKE2B_BLOCKBYTES = 128,
+ BLAKE2B_OUTBYTES = 64,
+ BLAKE2B_KEYBYTES = 64,
+ BLAKE2B_SALTBYTES = 16,
+ BLAKE2B_PERSONALBYTES = 16,
+ BLAKE2B_PARAM_SIZE = 64
+};
+
+/* param offsets */
+enum {
+ O_DIGEST_LENGTH = 0,
+ O_KEY_LENGTH = 1,
+ O_FANOUT = 2,
+ O_DEPTH = 3,
+ O_LEAF_LENGTH = 4,
+ O_NODE_OFFSET = 8,
+ O_XOF_LENGTH = 12,
+ O_NODE_DEPTH = 16,
+ O_INNER_LENGTH = 17,
+ O_RESERVED = 18,
+ O_SALT = 32,
+ O_PERSONAL = 48
+};
+
+/*
+struct blake2b_param {
+ unsigned char digest_length;
+ unsigned char key_length;
+ unsigned char fanout;
+ unsigned char depth;
+ ulong32 leaf_length;
+ ulong32 node_offset;
+ ulong32 xof_length;
+ unsigned char node_depth;
+ unsigned char inner_length;
+ unsigned char reserved[14];
+ unsigned char salt[BLAKE2B_SALTBYTES];
+ unsigned char personal[BLAKE2B_PERSONALBYTES];
+};
+*/
+
+const struct ltc_hash_descriptor blake2b_160_desc =
+{
+ "blake2b-160",
+ 25,
+ 20,
+ 128,
+ { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 5 },
+ 11,
+ &blake2b_160_init,
+ &blake2b_process,
+ &blake2b_done,
+ &blake2b_160_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor blake2b_256_desc =
+{
+ "blake2b-256",
+ 26,
+ 32,
+ 128,
+ { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 8 },
+ 11,
+ &blake2b_256_init,
+ &blake2b_process,
+ &blake2b_done,
+ &blake2b_256_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor blake2b_384_desc =
+{
+ "blake2b-384",
+ 27,
+ 48,
+ 128,
+ { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 12 },
+ 11,
+ &blake2b_384_init,
+ &blake2b_process,
+ &blake2b_done,
+ &blake2b_384_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor blake2b_512_desc =
+{
+ "blake2b-512",
+ 28,
+ 64,
+ 128,
+ { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 16 },
+ 11,
+ &blake2b_512_init,
+ &blake2b_process,
+ &blake2b_done,
+ &blake2b_512_test,
+ NULL
+};
+
+static const ulong64 blake2b_IV[8] =
+{
+ CONST64(0x6a09e667f3bcc908), CONST64(0xbb67ae8584caa73b),
+ CONST64(0x3c6ef372fe94f82b), CONST64(0xa54ff53a5f1d36f1),
+ CONST64(0x510e527fade682d1), CONST64(0x9b05688c2b3e6c1f),
+ CONST64(0x1f83d9abfb41bd6b), CONST64(0x5be0cd19137e2179)
+};
+
+static const unsigned char blake2b_sigma[12][16] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
+};
+
+static void s_blake2b_set_lastnode(hash_state *md) { md->blake2b.f[1] = CONST64(0xffffffffffffffff); }
+
+/* Some helper functions, not necessarily useful */
+static int s_blake2b_is_lastblock(const hash_state *md) { return md->blake2b.f[0] != 0; }
+
+static void s_blake2b_set_lastblock(hash_state *md)
+{
+ if (md->blake2b.last_node) {
+ s_blake2b_set_lastnode(md);
+ }
+ md->blake2b.f[0] = CONST64(0xffffffffffffffff);
+}
+
+static void s_blake2b_increment_counter(hash_state *md, ulong64 inc)
+{
+ md->blake2b.t[0] += inc;
+ if (md->blake2b.t[0] < inc) md->blake2b.t[1]++;
+}
+
+static void s_blake2b_init0(hash_state *md)
+{
+ unsigned long i;
+ XMEMSET(&md->blake2b, 0, sizeof(md->blake2b));
+
+ for (i = 0; i < 8; ++i) {
+ md->blake2b.h[i] = blake2b_IV[i];
+ }
+}
+
+/* init xors IV with input parameter block */
+static int s_blake2b_init_param(hash_state *md, const unsigned char *P)
+{
+ unsigned long i;
+
+ s_blake2b_init0(md);
+
+ /* IV XOR ParamBlock */
+ for (i = 0; i < 8; ++i) {
+ ulong64 tmp;
+ LOAD64L(tmp, P + i * 8);
+ md->blake2b.h[i] ^= tmp;
+ }
+
+ md->blake2b.outlen = P[O_DIGEST_LENGTH];
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the hash/MAC state
+
+ Use this function to init for arbitrary sizes.
+
+ Give a key and keylen to init for MAC mode.
+
+ @param md The hash state you wish to initialize
+ @param outlen The desired output-length
+ @param key The key of the MAC
+ @param keylen The length of the key
+ @return CRYPT_OK if successful
+*/
+int blake2b_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen)
+{
+ unsigned char P[BLAKE2B_PARAM_SIZE];
+ int err;
+
+ LTC_ARGCHK(md != NULL);
+
+ if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
+ return CRYPT_INVALID_ARG;
+ }
+ if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2B_KEYBYTES)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ XMEMSET(P, 0, sizeof(P));
+
+ P[O_DIGEST_LENGTH] = (unsigned char)outlen;
+ P[O_KEY_LENGTH] = (unsigned char)keylen;
+ P[O_FANOUT] = 1;
+ P[O_DEPTH] = 1;
+
+ err = s_blake2b_init_param(md, P);
+ if (err != CRYPT_OK) return err;
+
+ if (key) {
+ unsigned char block[BLAKE2B_BLOCKBYTES];
+
+ XMEMSET(block, 0, BLAKE2B_BLOCKBYTES);
+ XMEMCPY(block, key, keylen);
+ blake2b_process(md, block, BLAKE2B_BLOCKBYTES);
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(block, sizeof(block));
+#endif
+ }
+
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int blake2b_160_init(hash_state *md) { return blake2b_init(md, 20, NULL, 0); }
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int blake2b_256_init(hash_state *md) { return blake2b_init(md, 32, NULL, 0); }
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int blake2b_384_init(hash_state *md) { return blake2b_init(md, 48, NULL, 0); }
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int blake2b_512_init(hash_state *md) { return blake2b_init(md, 64, NULL, 0); }
+
+#define G(r, i, a, b, c, d) \
+ do { \
+ a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
+ d = ROR64(d ^ a, 32); \
+ c = c + d; \
+ b = ROR64(b ^ c, 24); \
+ a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
+ d = ROR64(d ^ a, 16); \
+ c = c + d; \
+ b = ROR64(b ^ c, 63); \
+ } while (0)
+
+#define ROUND(r) \
+ do { \
+ G(r, 0, v[0], v[4], v[8], v[12]); \
+ G(r, 1, v[1], v[5], v[9], v[13]); \
+ G(r, 2, v[2], v[6], v[10], v[14]); \
+ G(r, 3, v[3], v[7], v[11], v[15]); \
+ G(r, 4, v[0], v[5], v[10], v[15]); \
+ G(r, 5, v[1], v[6], v[11], v[12]); \
+ G(r, 6, v[2], v[7], v[8], v[13]); \
+ G(r, 7, v[3], v[4], v[9], v[14]); \
+ } while (0)
+
+#ifdef LTC_CLEAN_STACK
+static int ss_blake2b_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_blake2b_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong64 m[16];
+ ulong64 v[16];
+ unsigned long i;
+
+ for (i = 0; i < 16; ++i) {
+ LOAD64L(m[i], buf + i * sizeof(m[i]));
+ }
+
+ for (i = 0; i < 8; ++i) {
+ v[i] = md->blake2b.h[i];
+ }
+
+ v[8] = blake2b_IV[0];
+ v[9] = blake2b_IV[1];
+ v[10] = blake2b_IV[2];
+ v[11] = blake2b_IV[3];
+ v[12] = blake2b_IV[4] ^ md->blake2b.t[0];
+ v[13] = blake2b_IV[5] ^ md->blake2b.t[1];
+ v[14] = blake2b_IV[6] ^ md->blake2b.f[0];
+ v[15] = blake2b_IV[7] ^ md->blake2b.f[1];
+
+ ROUND(0);
+ ROUND(1);
+ ROUND(2);
+ ROUND(3);
+ ROUND(4);
+ ROUND(5);
+ ROUND(6);
+ ROUND(7);
+ ROUND(8);
+ ROUND(9);
+ ROUND(10);
+ ROUND(11);
+
+ for (i = 0; i < 8; ++i) {
+ md->blake2b.h[i] = md->blake2b.h[i] ^ v[i] ^ v[i + 8];
+ }
+ return CRYPT_OK;
+}
+
+#undef G
+#undef ROUND
+
+#ifdef LTC_CLEAN_STACK
+static int s_blake2b_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_blake2b_compress(md, buf);
+ burn_stack(sizeof(ulong64) * 32 + sizeof(unsigned long));
+ return err;
+}
+#endif
+
+/**
+ Process a block of memory through the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+int blake2b_process(hash_state *md, const unsigned char *in, unsigned long inlen)
+{
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ if (md->blake2b.curlen > sizeof(md->blake2b.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (inlen > 0) {
+ unsigned long left = md->blake2b.curlen;
+ unsigned long fill = BLAKE2B_BLOCKBYTES - left;
+ if (inlen > fill) {
+ md->blake2b.curlen = 0;
+ XMEMCPY(md->blake2b.buf + (left % sizeof(md->blake2b.buf)), in, fill); /* Fill buffer */
+ s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES);
+ s_blake2b_compress(md, md->blake2b.buf); /* Compress */
+ in += fill;
+ inlen -= fill;
+ while (inlen > BLAKE2B_BLOCKBYTES) {
+ s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES);
+ s_blake2b_compress(md, in);
+ in += BLAKE2B_BLOCKBYTES;
+ inlen -= BLAKE2B_BLOCKBYTES;
+ }
+ }
+ XMEMCPY(md->blake2b.buf + md->blake2b.curlen, in, inlen);
+ md->blake2b.curlen += inlen;
+ }
+ return CRYPT_OK;
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (size depending on the length used on init)
+ @return CRYPT_OK if successful
+*/
+int blake2b_done(hash_state *md, unsigned char *out)
+{
+ unsigned char buffer[BLAKE2B_OUTBYTES] = { 0 };
+ unsigned long i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* if(md->blakebs.outlen != outlen) return CRYPT_INVALID_ARG; */
+
+ if (s_blake2b_is_lastblock(md)) {
+ return CRYPT_ERROR;
+ }
+
+ s_blake2b_increment_counter(md, md->blake2b.curlen);
+ s_blake2b_set_lastblock(md);
+ XMEMSET(md->blake2b.buf + md->blake2b.curlen, 0, BLAKE2B_BLOCKBYTES - md->blake2b.curlen); /* Padding */
+ s_blake2b_compress(md, md->blake2b.buf);
+
+ for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
+ STORE64L(md->blake2b.h[i], buffer + i * 8);
+ }
+
+ XMEMCPY(out, buffer, md->blake2b.outlen);
+ zeromem(md, sizeof(hash_state));
+#ifdef LTC_CLEAN_STACK
+ zeromem(buffer, sizeof(buffer));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int blake2b_512_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[64];
+ } tests[] = {
+ { "",
+ { 0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03,
+ 0xc6, 0xc6, 0xfd, 0x85, 0x25, 0x52, 0xd2, 0x72,
+ 0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, 0x47, 0x61,
+ 0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19,
+ 0xd2, 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53,
+ 0x13, 0x89, 0x64, 0x44, 0x93, 0x4e, 0xb0, 0x4b,
+ 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55,
+ 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce } },
+ { "abc",
+ { 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d,
+ 0x6a, 0x27, 0x97, 0xb6, 0x9f, 0x12, 0xf6, 0xe9,
+ 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, 0xc4, 0xb7,
+ 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1,
+ 0x7d, 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d,
+ 0xc2, 0x52, 0xd5, 0xde, 0x45, 0x33, 0xcc, 0x95,
+ 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 0x5a,
+ 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23 } },
+
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[64];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ blake2b_512_init(&md);
+ blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ blake2b_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_512", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int blake2b_384_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[48];
+ } tests[] = {
+ { "",
+ { 0xb3, 0x28, 0x11, 0x42, 0x33, 0x77, 0xf5, 0x2d,
+ 0x78, 0x62, 0x28, 0x6e, 0xe1, 0xa7, 0x2e, 0xe5,
+ 0x40, 0x52, 0x43, 0x80, 0xfd, 0xa1, 0x72, 0x4a,
+ 0x6f, 0x25, 0xd7, 0x97, 0x8c, 0x6f, 0xd3, 0x24,
+ 0x4a, 0x6c, 0xaf, 0x04, 0x98, 0x81, 0x26, 0x73,
+ 0xc5, 0xe0, 0x5e, 0xf5, 0x83, 0x82, 0x51, 0x00 } },
+ { "abc",
+ { 0x6f, 0x56, 0xa8, 0x2c, 0x8e, 0x7e, 0xf5, 0x26,
+ 0xdf, 0xe1, 0x82, 0xeb, 0x52, 0x12, 0xf7, 0xdb,
+ 0x9d, 0xf1, 0x31, 0x7e, 0x57, 0x81, 0x5d, 0xbd,
+ 0xa4, 0x60, 0x83, 0xfc, 0x30, 0xf5, 0x4e, 0xe6,
+ 0xc6, 0x6b, 0xa8, 0x3b, 0xe6, 0x4b, 0x30, 0x2d,
+ 0x7c, 0xba, 0x6c, 0xe1, 0x5b, 0xb5, 0x56, 0xf4 } },
+
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[48];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ blake2b_384_init(&md);
+ blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ blake2b_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_384", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int blake2b_256_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[32];
+ } tests[] = {
+ { "",
+ { 0x0e, 0x57, 0x51, 0xc0, 0x26, 0xe5, 0x43, 0xb2,
+ 0xe8, 0xab, 0x2e, 0xb0, 0x60, 0x99, 0xda, 0xa1,
+ 0xd1, 0xe5, 0xdf, 0x47, 0x77, 0x8f, 0x77, 0x87,
+ 0xfa, 0xab, 0x45, 0xcd, 0xf1, 0x2f, 0xe3, 0xa8 } },
+ { "abc",
+ { 0xbd, 0xdd, 0x81, 0x3c, 0x63, 0x42, 0x39, 0x72,
+ 0x31, 0x71, 0xef, 0x3f, 0xee, 0x98, 0x57, 0x9b,
+ 0x94, 0x96, 0x4e, 0x3b, 0xb1, 0xcb, 0x3e, 0x42,
+ 0x72, 0x62, 0xc8, 0xc0, 0x68, 0xd5, 0x23, 0x19 } },
+ { "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890",
+ { 0x0f, 0x6e, 0x01, 0x8d, 0x38, 0xd6, 0x3f, 0x08,
+ 0x4d, 0x58, 0xe3, 0x0c, 0x90, 0xfb, 0xa2, 0x41,
+ 0x5f, 0xca, 0x17, 0xfa, 0x66, 0x26, 0x49, 0xf3,
+ 0x8a, 0x30, 0x41, 0x7c, 0x57, 0xcd, 0xa8, 0x14 } },
+
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[32];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ blake2b_256_init(&md);
+ blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ blake2b_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_256", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int blake2b_160_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[20];
+ } tests[] = {
+ { "",
+ { 0x33, 0x45, 0x52, 0x4a, 0xbf, 0x6b, 0xbe, 0x18,
+ 0x09, 0x44, 0x92, 0x24, 0xb5, 0x97, 0x2c, 0x41,
+ 0x79, 0x0b, 0x6c, 0xf2 } },
+ { "abc",
+ { 0x38, 0x42, 0x64, 0xf6, 0x76, 0xf3, 0x95, 0x36,
+ 0x84, 0x05, 0x23, 0xf2, 0x84, 0x92, 0x1c, 0xdc,
+ 0x68, 0xb6, 0x84, 0x6b } },
+
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[20];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ blake2b_160_init(&md);
+ blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ blake2b_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_160", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/hashes/blake2s.c b/Sources/libtomcrypt/hashes/blake2s.c
new file mode 100644
index 00000000..e8cd6eb4
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/blake2s.c
@@ -0,0 +1,603 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/*
+ BLAKE2 reference source code package - reference C implementations
+
+ Copyright 2012, Samuel Neves . You may use this under the
+ terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
+ your option. The terms of these licenses can be found at:
+
+ - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ - OpenSSL license : https://www.openssl.org/source/license.html
+ - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
+
+ More information about the BLAKE2 hash function can be found at
+ https://blake2.net.
+*/
+/* see also https://www.ietf.org/rfc/rfc7693.txt */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2S
+
+enum blake2s_constant {
+ BLAKE2S_BLOCKBYTES = 64,
+ BLAKE2S_OUTBYTES = 32,
+ BLAKE2S_KEYBYTES = 32,
+ BLAKE2S_SALTBYTES = 8,
+ BLAKE2S_PERSONALBYTES = 8,
+ BLAKE2S_PARAM_SIZE = 32
+};
+
+/* param offsets */
+enum {
+ O_DIGEST_LENGTH = 0,
+ O_KEY_LENGTH = 1,
+ O_FANOUT = 2,
+ O_DEPTH = 3,
+ O_LEAF_LENGTH = 4,
+ O_NODE_OFFSET = 8,
+ O_XOF_LENGTH = 12,
+ O_NODE_DEPTH = 14,
+ O_INNER_LENGTH = 15,
+ O_SALT = 16,
+ O_PERSONAL = 24
+};
+
+/*
+struct blake2s_param {
+ unsigned char digest_length;
+ unsigned char key_length;
+ unsigned char fanout;
+ unsigned char depth;
+ ulong32 leaf_length;
+ ulong32 node_offset;
+ ushort16 xof_length;
+ unsigned char node_depth;
+ unsigned char inner_length;
+ unsigned char salt[BLAKE2S_SALTBYTES];
+ unsigned char personal[BLAKE2S_PERSONALBYTES];
+};
+*/
+
+const struct ltc_hash_descriptor blake2s_128_desc =
+{
+ "blake2s-128",
+ 21,
+ 16,
+ 64,
+ { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 4 },
+ 11,
+ &blake2s_128_init,
+ &blake2s_process,
+ &blake2s_done,
+ &blake2s_128_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor blake2s_160_desc =
+{
+ "blake2s-160",
+ 22,
+ 20,
+ 64,
+ { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 5 },
+ 11,
+ &blake2s_160_init,
+ &blake2s_process,
+ &blake2s_done,
+ &blake2s_160_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor blake2s_224_desc =
+{
+ "blake2s-224",
+ 23,
+ 28,
+ 64,
+ { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 7 },
+ 11,
+ &blake2s_224_init,
+ &blake2s_process,
+ &blake2s_done,
+ &blake2s_224_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor blake2s_256_desc =
+{
+ "blake2s-256",
+ 24,
+ 32,
+ 64,
+ { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 8 },
+ 11,
+ &blake2s_256_init,
+ &blake2s_process,
+ &blake2s_done,
+ &blake2s_256_test,
+ NULL
+};
+
+static const ulong32 blake2s_IV[8] = {
+ 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
+ 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
+};
+
+static const unsigned char blake2s_sigma[10][16] = {
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
+};
+
+static void s_blake2s_set_lastnode(hash_state *md) { md->blake2s.f[1] = 0xffffffffUL; }
+
+/* Some helper functions, not necessarily useful */
+static int s_blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; }
+
+static void s_blake2s_set_lastblock(hash_state *md)
+{
+ if (md->blake2s.last_node) {
+ s_blake2s_set_lastnode(md);
+ }
+ md->blake2s.f[0] = 0xffffffffUL;
+}
+
+static void s_blake2s_increment_counter(hash_state *md, const ulong32 inc)
+{
+ md->blake2s.t[0] += inc;
+ if (md->blake2s.t[0] < inc) md->blake2s.t[1]++;
+}
+
+static int s_blake2s_init0(hash_state *md)
+{
+ int i;
+ XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state));
+
+ for (i = 0; i < 8; ++i) {
+ md->blake2s.h[i] = blake2s_IV[i];
+ }
+
+ return CRYPT_OK;
+}
+
+/* init2 xors IV with input parameter block */
+static int s_blake2s_init_param(hash_state *md, const unsigned char *P)
+{
+ unsigned long i;
+
+ s_blake2s_init0(md);
+
+ /* IV XOR ParamBlock */
+ for (i = 0; i < 8; ++i) {
+ ulong32 tmp;
+ LOAD32L(tmp, P + i * 4);
+ md->blake2s.h[i] ^= tmp;
+ }
+
+ md->blake2s.outlen = P[O_DIGEST_LENGTH];
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the hash/MAC state
+
+ Use this function to init for arbitrary sizes.
+
+ Give a key and keylen to init for MAC mode.
+
+ @param md The hash state you wish to initialize
+ @param outlen The desired output-length
+ @param key The key of the MAC
+ @param keylen The length of the key
+ @return CRYPT_OK if successful
+*/
+int blake2s_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen)
+{
+ unsigned char P[BLAKE2S_PARAM_SIZE];
+ int err;
+
+ LTC_ARGCHK(md != NULL);
+
+ if ((!outlen) || (outlen > BLAKE2S_OUTBYTES)) {
+ return CRYPT_INVALID_ARG;
+ }
+ if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2S_KEYBYTES)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ XMEMSET(P, 0, sizeof(P));
+
+ P[O_DIGEST_LENGTH] = (unsigned char)outlen;
+ P[O_KEY_LENGTH] = (unsigned char)keylen;
+ P[O_FANOUT] = 1;
+ P[O_DEPTH] = 1;
+
+ err = s_blake2s_init_param(md, P);
+ if (err != CRYPT_OK) return err;
+
+ if (key) {
+ unsigned char block[BLAKE2S_BLOCKBYTES];
+
+ XMEMSET(block, 0, BLAKE2S_BLOCKBYTES);
+ XMEMCPY(block, key, keylen);
+ blake2s_process(md, block, BLAKE2S_BLOCKBYTES);
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(block, sizeof(block));
+#endif
+ }
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int blake2s_128_init(hash_state *md) { return blake2s_init(md, 16, NULL, 0); }
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int blake2s_160_init(hash_state *md) { return blake2s_init(md, 20, NULL, 0); }
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int blake2s_224_init(hash_state *md) { return blake2s_init(md, 28, NULL, 0); }
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int blake2s_256_init(hash_state *md) { return blake2s_init(md, 32, NULL, 0); }
+
+#define G(r, i, a, b, c, d) \
+ do { \
+ a = a + b + m[blake2s_sigma[r][2 * i + 0]]; \
+ d = ROR(d ^ a, 16); \
+ c = c + d; \
+ b = ROR(b ^ c, 12); \
+ a = a + b + m[blake2s_sigma[r][2 * i + 1]]; \
+ d = ROR(d ^ a, 8); \
+ c = c + d; \
+ b = ROR(b ^ c, 7); \
+ } while (0)
+#define ROUND(r) \
+ do { \
+ G(r, 0, v[0], v[4], v[8], v[12]); \
+ G(r, 1, v[1], v[5], v[9], v[13]); \
+ G(r, 2, v[2], v[6], v[10], v[14]); \
+ G(r, 3, v[3], v[7], v[11], v[15]); \
+ G(r, 4, v[0], v[5], v[10], v[15]); \
+ G(r, 5, v[1], v[6], v[11], v[12]); \
+ G(r, 6, v[2], v[7], v[8], v[13]); \
+ G(r, 7, v[3], v[4], v[9], v[14]); \
+ } while (0)
+
+#ifdef LTC_CLEAN_STACK
+static int ss_blake2s_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_blake2s_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ unsigned long i;
+ ulong32 m[16];
+ ulong32 v[16];
+
+ for (i = 0; i < 16; ++i) {
+ LOAD32L(m[i], buf + i * sizeof(m[i]));
+ }
+
+ for (i = 0; i < 8; ++i) {
+ v[i] = md->blake2s.h[i];
+ }
+
+ v[8] = blake2s_IV[0];
+ v[9] = blake2s_IV[1];
+ v[10] = blake2s_IV[2];
+ v[11] = blake2s_IV[3];
+ v[12] = md->blake2s.t[0] ^ blake2s_IV[4];
+ v[13] = md->blake2s.t[1] ^ blake2s_IV[5];
+ v[14] = md->blake2s.f[0] ^ blake2s_IV[6];
+ v[15] = md->blake2s.f[1] ^ blake2s_IV[7];
+
+ ROUND(0);
+ ROUND(1);
+ ROUND(2);
+ ROUND(3);
+ ROUND(4);
+ ROUND(5);
+ ROUND(6);
+ ROUND(7);
+ ROUND(8);
+ ROUND(9);
+
+ for (i = 0; i < 8; ++i) {
+ md->blake2s.h[i] = md->blake2s.h[i] ^ v[i] ^ v[i + 8];
+ }
+ return CRYPT_OK;
+}
+#undef G
+#undef ROUND
+
+#ifdef LTC_CLEAN_STACK
+static int s_blake2s_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_blake2s_compress(md, buf);
+ burn_stack(sizeof(ulong32) * (32) + sizeof(unsigned long));
+ return err;
+}
+#endif
+
+/**
+ Process a block of memory through the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+int blake2s_process(hash_state *md, const unsigned char *in, unsigned long inlen)
+{
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ if (md->blake2s.curlen > sizeof(md->blake2s.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (inlen > 0) {
+ unsigned long left = md->blake2s.curlen;
+ unsigned long fill = BLAKE2S_BLOCKBYTES - left;
+ if (inlen > fill) {
+ md->blake2s.curlen = 0;
+ XMEMCPY(md->blake2s.buf + (left % sizeof(md->blake2s.buf)), in, fill); /* Fill buffer */
+ s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
+ s_blake2s_compress(md, md->blake2s.buf); /* Compress */
+ in += fill;
+ inlen -= fill;
+ while (inlen > BLAKE2S_BLOCKBYTES) {
+ s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
+ s_blake2s_compress(md, in);
+ in += BLAKE2S_BLOCKBYTES;
+ inlen -= BLAKE2S_BLOCKBYTES;
+ }
+ }
+ XMEMCPY(md->blake2s.buf + md->blake2s.curlen, in, inlen);
+ md->blake2s.curlen += inlen;
+ }
+ return CRYPT_OK;
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (size depending on the length used on init)
+ @return CRYPT_OK if successful
+*/
+int blake2s_done(hash_state *md, unsigned char *out)
+{
+ unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 };
+ unsigned long i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */
+
+ if (s_blake2s_is_lastblock(md)) {
+ return CRYPT_ERROR;
+ }
+ s_blake2s_increment_counter(md, md->blake2s.curlen);
+ s_blake2s_set_lastblock(md);
+ XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */
+ s_blake2s_compress(md, md->blake2s.buf);
+
+ for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
+ STORE32L(md->blake2s.h[i], buffer + i * 4);
+ }
+
+ XMEMCPY(out, buffer, md->blake2s.outlen);
+ zeromem(md, sizeof(hash_state));
+#ifdef LTC_CLEAN_STACK
+ zeromem(buffer, sizeof(buffer));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int blake2s_256_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[32];
+ } tests[] = {
+ { "",
+ { 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94,
+ 0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c,
+ 0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e,
+ 0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9 } },
+ { "abc",
+ { 0x50, 0x8c, 0x5e, 0x8c, 0x32, 0x7c, 0x14, 0xe2,
+ 0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f,
+ 0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29,
+ 0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } },
+ { "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890",
+ { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41,
+ 0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41,
+ 0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70,
+ 0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } },
+
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[32];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ blake2s_256_init(&md);
+ blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ blake2s_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_256", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int blake2s_224_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[28];
+ } tests[] = {
+ { "",
+ { 0x1f, 0xa1, 0x29, 0x1e, 0x65, 0x24, 0x8b, 0x37,
+ 0xb3, 0x43, 0x34, 0x75, 0xb2, 0xa0, 0xdd, 0x63,
+ 0xd5, 0x4a, 0x11, 0xec, 0xc4, 0xe3, 0xe0, 0x34,
+ 0xe7, 0xbc, 0x1e, 0xf4 } },
+ { "abc",
+ { 0x0b, 0x03, 0x3f, 0xc2, 0x26, 0xdf, 0x7a, 0xbd,
+ 0xe2, 0x9f, 0x67, 0xa0, 0x5d, 0x3d, 0xc6, 0x2c,
+ 0xf2, 0x71, 0xef, 0x3d, 0xfe, 0xa4, 0xd3, 0x87,
+ 0x40, 0x7f, 0xbd, 0x55 } },
+
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[28];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ blake2s_224_init(&md);
+ blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ blake2s_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_224", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int blake2s_160_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[20];
+ } tests[] = {
+ { "",
+ { 0x35, 0x4c, 0x9c, 0x33, 0xf7, 0x35, 0x96, 0x24,
+ 0x18, 0xbd, 0xac, 0xb9, 0x47, 0x98, 0x73, 0x42,
+ 0x9c, 0x34, 0x91, 0x6f} },
+ { "abc",
+ { 0x5a, 0xe3, 0xb9, 0x9b, 0xe2, 0x9b, 0x01, 0x83,
+ 0x4c, 0x3b, 0x50, 0x85, 0x21, 0xed, 0xe6, 0x04,
+ 0x38, 0xf8, 0xde, 0x17 } },
+
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[20];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ blake2s_160_init(&md);
+ blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ blake2s_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_160", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ }
+ return CRYPT_OK;
+#endif
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int blake2s_128_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[16];
+ } tests[] = {
+ { "",
+ { 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01,
+ 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c } },
+ { "abc",
+ { 0xaa, 0x49, 0x38, 0x11, 0x9b, 0x1d, 0xc7, 0xb8,
+ 0x7c, 0xba, 0xd0, 0xff, 0xd2, 0x00, 0xd0, 0xae } },
+
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[16];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ blake2s_128_init(&md);
+ blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ blake2s_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_128", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/hashes/chc/chc.c b/Sources/libtomcrypt/hashes/chc/chc.c
new file mode 100644
index 00000000..e82b2b39
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/chc/chc.c
@@ -0,0 +1,302 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file chc.c
+ CHC support. (Tom St Denis)
+*/
+
+#ifdef LTC_CHC_HASH
+
+#define UNDEFED_HASH -17
+
+/* chc settings */
+static int cipher_idx=UNDEFED_HASH, /* which cipher */
+ cipher_blocksize; /* blocksize of cipher */
+
+
+const struct ltc_hash_descriptor chc_desc = {
+ "chc_hash", 12, 0, 0, { 0 }, 0,
+ &chc_init,
+ &chc_process,
+ &chc_done,
+ &chc_test,
+ NULL
+};
+
+/**
+ Initialize the CHC state with a given cipher
+ @param cipher The index of the cipher you wish to bind
+ @return CRYPT_OK if successful
+*/
+int chc_register(int cipher)
+{
+ int err, kl, idx;
+
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* will it be valid? */
+ kl = cipher_descriptor[cipher].block_length;
+
+ /* must be >64 bit block */
+ if (kl <= 8) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ /* can we use the ideal keysize? */
+ if ((err = cipher_descriptor[cipher].keysize(&kl)) != CRYPT_OK) {
+ return err;
+ }
+ /* we require that key size == block size be a valid choice */
+ if (kl != cipher_descriptor[cipher].block_length) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ /* determine if chc_hash has been register_hash'ed already */
+ if ((err = hash_is_valid(idx = find_hash("chc_hash"))) != CRYPT_OK) {
+ return err;
+ }
+
+ /* store into descriptor */
+ hash_descriptor[idx].hashsize =
+ hash_descriptor[idx].blocksize = cipher_descriptor[cipher].block_length;
+
+ /* store the idx and block size */
+ cipher_idx = cipher;
+ cipher_blocksize = cipher_descriptor[cipher].block_length;
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int chc_init(hash_state *md)
+{
+ symmetric_key *key;
+ unsigned char buf[MAXBLOCKSIZE];
+ int err;
+
+ LTC_ARGCHK(md != NULL);
+
+ /* is the cipher valid? */
+ if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ if ((key = XMALLOC(sizeof(*key))) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* zero key and what not */
+ zeromem(buf, cipher_blocksize);
+ if ((err = cipher_descriptor[cipher_idx].setup(buf, cipher_blocksize, 0, key)) != CRYPT_OK) {
+ XFREE(key);
+ return err;
+ }
+
+ /* encrypt zero block */
+ cipher_descriptor[cipher_idx].ecb_encrypt(buf, md->chc.state, key);
+
+ /* zero other members */
+ md->chc.length = 0;
+ md->chc.curlen = 0;
+ zeromem(md->chc.buf, sizeof(md->chc.buf));
+ XFREE(key);
+ return CRYPT_OK;
+}
+
+/*
+ key <= state
+ T0,T1 <= block
+ T0 <= encrypt T0
+ state <= state xor T0 xor T1
+*/
+static int s_chc_compress(hash_state *md, const unsigned char *buf)
+{
+ unsigned char T[2][MAXBLOCKSIZE];
+ symmetric_key *key;
+ int err, x;
+
+ if ((key = XMALLOC(sizeof(*key))) == NULL) {
+ return CRYPT_MEM;
+ }
+ if ((err = cipher_descriptor[cipher_idx].setup(md->chc.state, cipher_blocksize, 0, key)) != CRYPT_OK) {
+ XFREE(key);
+ return err;
+ }
+ XMEMCPY(T[1], buf, cipher_blocksize);
+ cipher_descriptor[cipher_idx].ecb_encrypt(buf, T[0], key);
+ for (x = 0; x < cipher_blocksize; x++) {
+ md->chc.state[x] ^= T[0][x] ^ T[1][x];
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(T, sizeof(T));
+ zeromem(key, sizeof(*key));
+#endif
+ XFREE(key);
+ return CRYPT_OK;
+}
+
+/**
+ Function for processing blocks
+ @param md The hash state
+ @param buf The data to hash
+ @param len The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+static int ss_chc_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+static HASH_PROCESS(ss_chc_process, s_chc_compress, chc, (unsigned long)cipher_blocksize)
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen)
+{
+ int err;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* is the cipher valid? */
+ if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
+ return err;
+ }
+ if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ return ss_chc_process(md, in, inlen);
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (length of the block size of the block cipher)
+ @return CRYPT_OK if successful
+*/
+int chc_done(hash_state *md, unsigned char *out)
+{
+ int err;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* is the cipher valid? */
+ if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
+ return err;
+ }
+ if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ if (md->chc.curlen >= sizeof(md->chc.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* increase the length of the message */
+ md->chc.length += md->chc.curlen * 8;
+
+ /* append the '1' bit */
+ md->chc.buf[md->chc.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above l-8 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->chc.curlen > (unsigned long)(cipher_blocksize - 8)) {
+ while (md->chc.curlen < (unsigned long)cipher_blocksize) {
+ md->chc.buf[md->chc.curlen++] = (unsigned char)0;
+ }
+ s_chc_compress(md, md->chc.buf);
+ md->chc.curlen = 0;
+ }
+
+ /* pad upto l-8 bytes of zeroes */
+ while (md->chc.curlen < (unsigned long)(cipher_blocksize - 8)) {
+ md->chc.buf[md->chc.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64L(md->chc.length, md->chc.buf+(cipher_blocksize-8));
+ s_chc_compress(md, md->chc.buf);
+
+ /* copy output */
+ XMEMCPY(out, md->chc.state, cipher_blocksize);
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int chc_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ unsigned char *msg,
+ hash[MAXBLOCKSIZE];
+ int len;
+ } tests[] = {
+{
+ (unsigned char *)"hello world",
+ { 0xcf, 0x57, 0x9d, 0xc3, 0x0a, 0x0e, 0xea, 0x61,
+ 0x0d, 0x54, 0x47, 0xc4, 0x3c, 0x06, 0xf5, 0x4e },
+ 16
+}
+};
+ int i, oldhashidx, idx, err;
+ unsigned char tmp[MAXBLOCKSIZE];
+ hash_state md;
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((idx = find_cipher("aes")) == -1) {
+ if ((idx = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+ oldhashidx = cipher_idx;
+ chc_register(idx);
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ if ((err = chc_init(&md)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = chc_process(&md, tests[i].msg, XSTRLEN((char *)tests[i].msg))) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = chc_done(&md, tmp)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(tmp, tests[i].len, tests[i].hash, tests[i].len, "CHC", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ if (oldhashidx != UNDEFED_HASH) {
+ chc_register(oldhashidx);
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/hashes/helper/hash_file.c b/Sources/libtomcrypt/hashes/helper/hash_file.c
new file mode 100644
index 00000000..d2711db2
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/helper/hash_file.c
@@ -0,0 +1,43 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifndef LTC_NO_FILE
+/**
+ @file hash_file.c
+ Hash a file, Tom St Denis
+*/
+
+/**
+ @param hash The index of the hash desired
+ @param fname The name of the file you wish to hash
+ @param out [out] The destination of the digest
+ @param outlen [in/out] The max size and resulting size of the message digest
+ @result CRYPT_OK if successful
+*/
+int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen)
+{
+ FILE *in;
+ int err;
+ LTC_ARGCHK(fname != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ in = fopen(fname, "rb");
+ if (in == NULL) {
+ return CRYPT_FILE_NOTFOUND;
+ }
+
+ err = hash_filehandle(hash, in, out, outlen);
+ if (fclose(in) != 0) {
+ return CRYPT_ERROR;
+ }
+
+ return err;
+}
+#endif /* #ifndef LTC_NO_FILE */
+
diff --git a/Sources/libtomcrypt/hashes/helper/hash_filehandle.c b/Sources/libtomcrypt/hashes/helper/hash_filehandle.c
new file mode 100644
index 00000000..f4eee7fb
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/helper/hash_filehandle.c
@@ -0,0 +1,64 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifndef LTC_NO_FILE
+/**
+ @file hash_filehandle.c
+ Hash open files, Tom St Denis
+*/
+
+/**
+ Hash data from an open file handle.
+ @param hash The index of the hash you want to use
+ @param in The FILE* handle of the file you want to hash
+ @param out [out] The destination of the digest
+ @param outlen [in/out] The max size and resulting size of the digest
+ @result CRYPT_OK if successful
+*/
+int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen)
+{
+ hash_state md;
+ unsigned char *buf;
+ size_t x;
+ int err;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if (*outlen < hash_descriptor[hash].hashsize) {
+ *outlen = hash_descriptor[hash].hashsize;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash].init(&md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ do {
+ x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+ if ((err = hash_descriptor[hash].process(&md, buf, (unsigned long)x)) != CRYPT_OK) {
+ goto LBL_CLEANBUF;
+ }
+ } while (x == LTC_FILE_READ_BUFSIZE);
+ if ((err = hash_descriptor[hash].done(&md, out)) == CRYPT_OK) {
+ *outlen = hash_descriptor[hash].hashsize;
+ }
+
+LBL_CLEANBUF:
+ zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+ XFREE(buf);
+ return err;
+}
+#endif /* #ifndef LTC_NO_FILE */
+
diff --git a/Sources/libtomcrypt/hashes/helper/hash_memory.c b/Sources/libtomcrypt/hashes/helper/hash_memory.c
new file mode 100644
index 00000000..f38f51ca
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/helper/hash_memory.c
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_HASH_HELPERS
+/**
+ @file hash_memory.c
+ Hash memory helper, Tom St Denis
+*/
+
+/**
+ Hash a block of memory and store the digest.
+ @param hash The index of the hash you wish to use
+ @param in The data you wish to hash
+ @param inlen The length of the data to hash (octets)
+ @param out [out] Where to store the digest
+ @param outlen [in/out] Max size and resulting size of the digest
+ @return CRYPT_OK if successful
+*/
+int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen)
+{
+ hash_state *md;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < hash_descriptor[hash].hashsize) {
+ *outlen = hash_descriptor[hash].hashsize;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ md = XMALLOC(sizeof(hash_state));
+ if (md == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ err = hash_descriptor[hash].done(md, out);
+ *outlen = hash_descriptor[hash].hashsize;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ XFREE(md);
+
+ return err;
+}
+#endif /* #ifdef LTC_HASH_HELPERS */
diff --git a/Sources/libtomcrypt/hashes/helper/hash_memory_multi.c b/Sources/libtomcrypt/hashes/helper/hash_memory_multi.c
new file mode 100644
index 00000000..88630ff3
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/helper/hash_memory_multi.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+#ifdef LTC_HASH_HELPERS
+/**
+ @file hash_memory_multi.c
+ Hash (multiple buffers) memory helper, Tom St Denis
+*/
+
+/**
+ Hash multiple (non-adjacent) blocks of memory at once.
+ @param hash The index of the hash you wish to use
+ @param out [out] Where to store the digest
+ @param outlen [in/out] Max size and resulting size of the digest
+ @param in The data you wish to hash
+ @param inlen The length of the data to hash (octets)
+ @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+{
+ hash_state *md;
+ int err;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < hash_descriptor[hash].hashsize) {
+ *outlen = hash_descriptor[hash].hashsize;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ md = XMALLOC(sizeof(hash_state));
+ if (md == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ for (;;) {
+ /* process buf */
+ if ((err = hash_descriptor[hash].process(md, curptr, curlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* step to next */
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) {
+ break;
+ }
+ curlen = va_arg(args, unsigned long);
+ }
+ err = hash_descriptor[hash].done(md, out);
+ *outlen = hash_descriptor[hash].hashsize;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ XFREE(md);
+ va_end(args);
+ return err;
+}
+#endif /* #ifdef LTC_HASH_HELPERS */
diff --git a/Sources/libtomcrypt/hashes/md2.c b/Sources/libtomcrypt/hashes/md2.c
new file mode 100644
index 00000000..6cf0a657
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/md2.c
@@ -0,0 +1,240 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @param md2.c
+ LTC_MD2 (RFC 1319) hash function implementation by Tom St Denis
+*/
+
+#ifdef LTC_MD2
+
+const struct ltc_hash_descriptor md2_desc =
+{
+ "md2",
+ 7,
+ 16,
+ 16,
+
+ /* OID */
+ { 1, 2, 840, 113549, 2, 2, },
+ 6,
+
+ &md2_init,
+ &md2_process,
+ &md2_done,
+ &md2_test,
+ NULL
+};
+
+static const unsigned char PI_SUBST[256] = {
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+};
+
+/* adds 16 bytes to the checksum */
+static void s_md2_update_chksum(hash_state *md)
+{
+ int j;
+ unsigned char L;
+ L = md->md2.chksum[15];
+ for (j = 0; j < 16; j++) {
+
+/* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say
+ otherwise.
+*/
+ L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)] & 255);
+ }
+}
+
+static void s_md2_compress(hash_state *md)
+{
+ int j, k;
+ unsigned char t;
+
+ /* copy block */
+ for (j = 0; j < 16; j++) {
+ md->md2.X[16+j] = md->md2.buf[j];
+ md->md2.X[32+j] = md->md2.X[j] ^ md->md2.X[16+j];
+ }
+
+ t = (unsigned char)0;
+
+ /* do 18 rounds */
+ for (j = 0; j < 18; j++) {
+ for (k = 0; k < 48; k++) {
+ t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]);
+ }
+ t = (t + (unsigned char)j) & 255;
+ }
+}
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int md2_init(hash_state *md)
+{
+ LTC_ARGCHK(md != NULL);
+
+ /* LTC_MD2 uses a zero'ed state... */
+ zeromem(md->md2.X, sizeof(md->md2.X));
+ zeromem(md->md2.chksum, sizeof(md->md2.chksum));
+ zeromem(md->md2.buf, sizeof(md->md2.buf));
+ md->md2.curlen = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+int md2_process(hash_state *md, const unsigned char *in, unsigned long inlen)
+{
+ unsigned long n;
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(in != NULL);
+ if (md-> md2 .curlen > sizeof(md-> md2 .buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+ while (inlen > 0) {
+ n = MIN(inlen, (16 - md->md2.curlen));
+ XMEMCPY(md->md2.buf + md->md2.curlen, in, (size_t)n);
+ md->md2.curlen += n;
+ in += n;
+ inlen -= n;
+
+ /* is 16 bytes full? */
+ if (md->md2.curlen == 16) {
+ s_md2_compress(md);
+ s_md2_update_chksum(md);
+ md->md2.curlen = 0;
+ }
+ }
+ return CRYPT_OK;
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (16 bytes)
+ @return CRYPT_OK if successful
+*/
+int md2_done(hash_state * md, unsigned char *out)
+{
+ unsigned long i, k;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->md2.curlen >= sizeof(md->md2.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* pad the message */
+ k = 16 - md->md2.curlen;
+ for (i = md->md2.curlen; i < 16; i++) {
+ md->md2.buf[i] = (unsigned char)k;
+ }
+
+ /* hash and update */
+ s_md2_compress(md);
+ s_md2_update_chksum(md);
+
+ /* hash checksum */
+ XMEMCPY(md->md2.buf, md->md2.chksum, 16);
+ s_md2_compress(md);
+
+ /* output is lower 16 bytes of X */
+ XMEMCPY(out, md->md2.X, 16);
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int md2_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[16];
+ } tests[] = {
+ { "",
+ {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d,
+ 0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73
+ }
+ },
+ { "a",
+ {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72,
+ 0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1
+ }
+ },
+ { "message digest",
+ {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b,
+ 0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0
+ }
+ },
+ { "abcdefghijklmnopqrstuvwxyz",
+ {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab,
+ 0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b
+ }
+ },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39,
+ 0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd
+ }
+ },
+ { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d,
+ 0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8
+ }
+ }
+ };
+
+ int i;
+ unsigned char tmp[16];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ md2_init(&md);
+ md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ md2_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD2", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/hashes/md4.c b/Sources/libtomcrypt/hashes/md4.c
new file mode 100644
index 00000000..aadad5f1
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/md4.c
@@ -0,0 +1,296 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @param md4.c
+ Submitted by Dobes Vandermeer (dobes@smartt.com)
+*/
+
+#ifdef LTC_MD4
+
+const struct ltc_hash_descriptor md4_desc =
+{
+ "md4",
+ 6,
+ 16,
+ 64,
+
+ /* OID */
+ { 1, 2, 840, 113549, 2, 4, },
+ 6,
+
+ &md4_init,
+ &md4_process,
+ &md4_done,
+ &md4_test,
+ NULL
+};
+
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+/* F, G and H are basic LTC_MD4 functions. */
+#define F(x, y, z) (z ^ (x & (y ^ z)))
+#define G(x, y, z) ((x & y) | (z & (x | y)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits. */
+#define ROTATE_LEFT(x, n) ROLc(x, n)
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+
+#define FF(a, b, c, d, x, s) { \
+ (a) += F ((b), (c), (d)) + (x); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define GG(a, b, c, d, x, s) { \
+ (a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define HH(a, b, c, d, x, s) { \
+ (a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+
+#ifdef LTC_CLEAN_STACK
+static int ss_md4_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_md4_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong32 x[16], a, b, c, d;
+ int i;
+
+ /* copy state */
+ a = md->md4.state[0];
+ b = md->md4.state[1];
+ c = md->md4.state[2];
+ d = md->md4.state[3];
+
+ /* copy the state into 512-bits into W[0..15] */
+ for (i = 0; i < 16; i++) {
+ LOAD32L(x[i], buf + (4*i));
+ }
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11); /* 1 */
+ FF (d, a, b, c, x[ 1], S12); /* 2 */
+ FF (c, d, a, b, x[ 2], S13); /* 3 */
+ FF (b, c, d, a, x[ 3], S14); /* 4 */
+ FF (a, b, c, d, x[ 4], S11); /* 5 */
+ FF (d, a, b, c, x[ 5], S12); /* 6 */
+ FF (c, d, a, b, x[ 6], S13); /* 7 */
+ FF (b, c, d, a, x[ 7], S14); /* 8 */
+ FF (a, b, c, d, x[ 8], S11); /* 9 */
+ FF (d, a, b, c, x[ 9], S12); /* 10 */
+ FF (c, d, a, b, x[10], S13); /* 11 */
+ FF (b, c, d, a, x[11], S14); /* 12 */
+ FF (a, b, c, d, x[12], S11); /* 13 */
+ FF (d, a, b, c, x[13], S12); /* 14 */
+ FF (c, d, a, b, x[14], S13); /* 15 */
+ FF (b, c, d, a, x[15], S14); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 0], S21); /* 17 */
+ GG (d, a, b, c, x[ 4], S22); /* 18 */
+ GG (c, d, a, b, x[ 8], S23); /* 19 */
+ GG (b, c, d, a, x[12], S24); /* 20 */
+ GG (a, b, c, d, x[ 1], S21); /* 21 */
+ GG (d, a, b, c, x[ 5], S22); /* 22 */
+ GG (c, d, a, b, x[ 9], S23); /* 23 */
+ GG (b, c, d, a, x[13], S24); /* 24 */
+ GG (a, b, c, d, x[ 2], S21); /* 25 */
+ GG (d, a, b, c, x[ 6], S22); /* 26 */
+ GG (c, d, a, b, x[10], S23); /* 27 */
+ GG (b, c, d, a, x[14], S24); /* 28 */
+ GG (a, b, c, d, x[ 3], S21); /* 29 */
+ GG (d, a, b, c, x[ 7], S22); /* 30 */
+ GG (c, d, a, b, x[11], S23); /* 31 */
+ GG (b, c, d, a, x[15], S24); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 0], S31); /* 33 */
+ HH (d, a, b, c, x[ 8], S32); /* 34 */
+ HH (c, d, a, b, x[ 4], S33); /* 35 */
+ HH (b, c, d, a, x[12], S34); /* 36 */
+ HH (a, b, c, d, x[ 2], S31); /* 37 */
+ HH (d, a, b, c, x[10], S32); /* 38 */
+ HH (c, d, a, b, x[ 6], S33); /* 39 */
+ HH (b, c, d, a, x[14], S34); /* 40 */
+ HH (a, b, c, d, x[ 1], S31); /* 41 */
+ HH (d, a, b, c, x[ 9], S32); /* 42 */
+ HH (c, d, a, b, x[ 5], S33); /* 43 */
+ HH (b, c, d, a, x[13], S34); /* 44 */
+ HH (a, b, c, d, x[ 3], S31); /* 45 */
+ HH (d, a, b, c, x[11], S32); /* 46 */
+ HH (c, d, a, b, x[ 7], S33); /* 47 */
+ HH (b, c, d, a, x[15], S34); /* 48 */
+
+
+ /* Update our state */
+ md->md4.state[0] = md->md4.state[0] + a;
+ md->md4.state[1] = md->md4.state[1] + b;
+ md->md4.state[2] = md->md4.state[2] + c;
+ md->md4.state[3] = md->md4.state[3] + d;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_md4_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_md4_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 20 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int md4_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->md4.state[0] = 0x67452301UL;
+ md->md4.state[1] = 0xefcdab89UL;
+ md->md4.state[2] = 0x98badcfeUL;
+ md->md4.state[3] = 0x10325476UL;
+ md->md4.length = 0;
+ md->md4.curlen = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(md4_process, s_md4_compress, md4, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (16 bytes)
+ @return CRYPT_OK if successful
+*/
+int md4_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->md4.curlen >= sizeof(md->md4.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* increase the length of the message */
+ md->md4.length += md->md4.curlen * 8;
+
+ /* append the '1' bit */
+ md->md4.buf[md->md4.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->md4.curlen > 56) {
+ while (md->md4.curlen < 64) {
+ md->md4.buf[md->md4.curlen++] = (unsigned char)0;
+ }
+ s_md4_compress(md, md->md4.buf);
+ md->md4.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->md4.curlen < 56) {
+ md->md4.buf[md->md4.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64L(md->md4.length, md->md4.buf+56);
+ s_md4_compress(md, md->md4.buf);
+
+ /* copy output */
+ for (i = 0; i < 4; i++) {
+ STORE32L(md->md4.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int md4_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct md4_test_case {
+ const char *input;
+ unsigned char hash[16];
+ } tests[] = {
+ { "",
+ {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
+ 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} },
+ { "a",
+ {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
+ 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} },
+ { "abc",
+ {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
+ 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} },
+ { "message digest",
+ {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
+ 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} },
+ { "abcdefghijklmnopqrstuvwxyz",
+ {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
+ 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
+ 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} },
+ { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
+ 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} },
+ };
+
+ int i;
+ unsigned char tmp[16];
+ hash_state md;
+
+ for(i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ md4_init(&md);
+ md4_process(&md, (unsigned char *)tests[i].input, (unsigned long)XSTRLEN(tests[i].input));
+ md4_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD4", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
diff --git a/Sources/libtomcrypt/hashes/md5.c b/Sources/libtomcrypt/hashes/md5.c
new file mode 100644
index 00000000..ad404e18
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/md5.c
@@ -0,0 +1,356 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+
+/**
+ @file md5.c
+ LTC_MD5 hash function by Tom St Denis
+*/
+
+#ifdef LTC_MD5
+
+const struct ltc_hash_descriptor md5_desc =
+{
+ "md5",
+ 3,
+ 16,
+ 64,
+
+ /* OID */
+ { 1, 2, 840, 113549, 2, 5, },
+ 6,
+
+ &md5_init,
+ &md5_process,
+ &md5_done,
+ &md5_test,
+ NULL
+};
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define G(x,y,z) (y ^ (z & (y ^ x)))
+#define H(x,y,z) (x^y^z)
+#define I(x,y,z) (y^(x|(~z)))
+
+#ifdef LTC_SMALL_CODE
+
+#define FF(a,b,c,d,M,s,t) \
+ a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#define GG(a,b,c,d,M,s,t) \
+ a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#define HH(a,b,c,d,M,s,t) \
+ a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#define II(a,b,c,d,M,s,t) \
+ a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;
+
+static const unsigned char Worder[64] = {
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
+ 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
+ 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
+ 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
+};
+
+static const unsigned char Rorder[64] = {
+ 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
+ 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
+ 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
+ 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
+};
+
+static const ulong32 Korder[64] = {
+0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
+0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
+0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
+0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
+0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
+0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
+0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
+0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL
+};
+
+#else
+
+#define FF(a,b,c,d,M,s,t) \
+ a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b;
+
+#define GG(a,b,c,d,M,s,t) \
+ a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b;
+
+#define HH(a,b,c,d,M,s,t) \
+ a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b;
+
+#define II(a,b,c,d,M,s,t) \
+ a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b;
+
+
+#endif
+
+#ifdef LTC_CLEAN_STACK
+static int ss_md5_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_md5_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong32 i, W[16], a, b, c, d;
+#ifdef LTC_SMALL_CODE
+ ulong32 t;
+#endif
+
+ /* copy the state into 512-bits into W[0..15] */
+ for (i = 0; i < 16; i++) {
+ LOAD32L(W[i], buf + (4*i));
+ }
+
+ /* copy state */
+ a = md->md5.state[0];
+ b = md->md5.state[1];
+ c = md->md5.state[2];
+ d = md->md5.state[3];
+
+#ifdef LTC_SMALL_CODE
+ for (i = 0; i < 16; ++i) {
+ FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+ t = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 32; ++i) {
+ GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+ t = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 48; ++i) {
+ HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+ t = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 64; ++i) {
+ II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+ t = d; d = c; c = b; b = a; a = t;
+ }
+
+#else
+ FF(a,b,c,d,W[0],7,0xd76aa478UL)
+ FF(d,a,b,c,W[1],12,0xe8c7b756UL)
+ FF(c,d,a,b,W[2],17,0x242070dbUL)
+ FF(b,c,d,a,W[3],22,0xc1bdceeeUL)
+ FF(a,b,c,d,W[4],7,0xf57c0fafUL)
+ FF(d,a,b,c,W[5],12,0x4787c62aUL)
+ FF(c,d,a,b,W[6],17,0xa8304613UL)
+ FF(b,c,d,a,W[7],22,0xfd469501UL)
+ FF(a,b,c,d,W[8],7,0x698098d8UL)
+ FF(d,a,b,c,W[9],12,0x8b44f7afUL)
+ FF(c,d,a,b,W[10],17,0xffff5bb1UL)
+ FF(b,c,d,a,W[11],22,0x895cd7beUL)
+ FF(a,b,c,d,W[12],7,0x6b901122UL)
+ FF(d,a,b,c,W[13],12,0xfd987193UL)
+ FF(c,d,a,b,W[14],17,0xa679438eUL)
+ FF(b,c,d,a,W[15],22,0x49b40821UL)
+ GG(a,b,c,d,W[1],5,0xf61e2562UL)
+ GG(d,a,b,c,W[6],9,0xc040b340UL)
+ GG(c,d,a,b,W[11],14,0x265e5a51UL)
+ GG(b,c,d,a,W[0],20,0xe9b6c7aaUL)
+ GG(a,b,c,d,W[5],5,0xd62f105dUL)
+ GG(d,a,b,c,W[10],9,0x02441453UL)
+ GG(c,d,a,b,W[15],14,0xd8a1e681UL)
+ GG(b,c,d,a,W[4],20,0xe7d3fbc8UL)
+ GG(a,b,c,d,W[9],5,0x21e1cde6UL)
+ GG(d,a,b,c,W[14],9,0xc33707d6UL)
+ GG(c,d,a,b,W[3],14,0xf4d50d87UL)
+ GG(b,c,d,a,W[8],20,0x455a14edUL)
+ GG(a,b,c,d,W[13],5,0xa9e3e905UL)
+ GG(d,a,b,c,W[2],9,0xfcefa3f8UL)
+ GG(c,d,a,b,W[7],14,0x676f02d9UL)
+ GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
+ HH(a,b,c,d,W[5],4,0xfffa3942UL)
+ HH(d,a,b,c,W[8],11,0x8771f681UL)
+ HH(c,d,a,b,W[11],16,0x6d9d6122UL)
+ HH(b,c,d,a,W[14],23,0xfde5380cUL)
+ HH(a,b,c,d,W[1],4,0xa4beea44UL)
+ HH(d,a,b,c,W[4],11,0x4bdecfa9UL)
+ HH(c,d,a,b,W[7],16,0xf6bb4b60UL)
+ HH(b,c,d,a,W[10],23,0xbebfbc70UL)
+ HH(a,b,c,d,W[13],4,0x289b7ec6UL)
+ HH(d,a,b,c,W[0],11,0xeaa127faUL)
+ HH(c,d,a,b,W[3],16,0xd4ef3085UL)
+ HH(b,c,d,a,W[6],23,0x04881d05UL)
+ HH(a,b,c,d,W[9],4,0xd9d4d039UL)
+ HH(d,a,b,c,W[12],11,0xe6db99e5UL)
+ HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
+ HH(b,c,d,a,W[2],23,0xc4ac5665UL)
+ II(a,b,c,d,W[0],6,0xf4292244UL)
+ II(d,a,b,c,W[7],10,0x432aff97UL)
+ II(c,d,a,b,W[14],15,0xab9423a7UL)
+ II(b,c,d,a,W[5],21,0xfc93a039UL)
+ II(a,b,c,d,W[12],6,0x655b59c3UL)
+ II(d,a,b,c,W[3],10,0x8f0ccc92UL)
+ II(c,d,a,b,W[10],15,0xffeff47dUL)
+ II(b,c,d,a,W[1],21,0x85845dd1UL)
+ II(a,b,c,d,W[8],6,0x6fa87e4fUL)
+ II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
+ II(c,d,a,b,W[6],15,0xa3014314UL)
+ II(b,c,d,a,W[13],21,0x4e0811a1UL)
+ II(a,b,c,d,W[4],6,0xf7537e82UL)
+ II(d,a,b,c,W[11],10,0xbd3af235UL)
+ II(c,d,a,b,W[2],15,0x2ad7d2bbUL)
+ II(b,c,d,a,W[9],21,0xeb86d391UL)
+#endif
+
+ md->md5.state[0] = md->md5.state[0] + a;
+ md->md5.state[1] = md->md5.state[1] + b;
+ md->md5.state[2] = md->md5.state[2] + c;
+ md->md5.state[3] = md->md5.state[3] + d;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_md5_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_md5_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 21);
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int md5_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->md5.state[0] = 0x67452301UL;
+ md->md5.state[1] = 0xefcdab89UL;
+ md->md5.state[2] = 0x98badcfeUL;
+ md->md5.state[3] = 0x10325476UL;
+ md->md5.curlen = 0;
+ md->md5.length = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(md5_process, s_md5_compress, md5, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (16 bytes)
+ @return CRYPT_OK if successful
+*/
+int md5_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->md5.curlen >= sizeof(md->md5.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* increase the length of the message */
+ md->md5.length += md->md5.curlen * 8;
+
+ /* append the '1' bit */
+ md->md5.buf[md->md5.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->md5.curlen > 56) {
+ while (md->md5.curlen < 64) {
+ md->md5.buf[md->md5.curlen++] = (unsigned char)0;
+ }
+ s_md5_compress(md, md->md5.buf);
+ md->md5.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->md5.curlen < 56) {
+ md->md5.buf[md->md5.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64L(md->md5.length, md->md5.buf+56);
+ s_md5_compress(md, md->md5.buf);
+
+ /* copy output */
+ for (i = 0; i < 4; i++) {
+ STORE32L(md->md5.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int md5_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[16];
+ } tests[] = {
+ { "",
+ { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+ 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
+ { "a",
+ {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
+ 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
+ { "abc",
+ { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
+ 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
+ { "message digest",
+ { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
+ 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
+ { "abcdefghijklmnopqrstuvwxyz",
+ { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
+ 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
+ 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
+ { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
+ 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } },
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[16];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ md5_init(&md);
+ md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ md5_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD5", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
diff --git a/Sources/libtomcrypt/hashes/rmd128.c b/Sources/libtomcrypt/hashes/rmd128.c
new file mode 100644
index 00000000..e8f63e1c
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/rmd128.c
@@ -0,0 +1,396 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @param rmd128.c
+ RMD128 Hash function
+*/
+
+/* Implementation of LTC_RIPEMD-128 based on the source by Antoon Bosselaers, ESAT-COSIC
+ *
+ * This source has been radically overhauled to be portable and work within
+ * the LibTomCrypt API by Tom St Denis
+ */
+
+#ifdef LTC_RIPEMD128
+
+const struct ltc_hash_descriptor rmd128_desc =
+{
+ "rmd128",
+ 8,
+ 16,
+ 64,
+
+ /* OID */
+ { 1, 0, 10118, 3, 0, 50 },
+ 6,
+
+ &rmd128_init,
+ &rmd128_process,
+ &rmd128_done,
+ &rmd128_test,
+ NULL
+};
+
+/* the four basic functions F(), G() and H() */
+#define F(x, y, z) ((x) ^ (y) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+
+/* the eight basic operations FF() through III() */
+#define FF(a, b, c, d, x, s) \
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROLc((a), (s));
+
+#define GG(a, b, c, d, x, s) \
+ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
+ (a) = ROLc((a), (s));
+
+#define HH(a, b, c, d, x, s) \
+ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
+ (a) = ROLc((a), (s));
+
+#define II(a, b, c, d, x, s) \
+ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
+ (a) = ROLc((a), (s));
+
+#define FFF(a, b, c, d, x, s) \
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROLc((a), (s));
+
+#define GGG(a, b, c, d, x, s) \
+ (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\
+ (a) = ROLc((a), (s));
+
+#define HHH(a, b, c, d, x, s) \
+ (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\
+ (a) = ROLc((a), (s));
+
+#define III(a, b, c, d, x, s) \
+ (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\
+ (a) = ROLc((a), (s));
+
+#ifdef LTC_CLEAN_STACK
+static int ss_rmd128_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_rmd128_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16];
+ int i;
+
+ /* load words X */
+ for (i = 0; i < 16; i++){
+ LOAD32L(X[i], buf + (4 * i));
+ }
+
+ /* load state */
+ aa = aaa = md->rmd128.state[0];
+ bb = bbb = md->rmd128.state[1];
+ cc = ccc = md->rmd128.state[2];
+ dd = ddd = md->rmd128.state[3];
+
+ /* round 1 */
+ FF(aa, bb, cc, dd, X[ 0], 11);
+ FF(dd, aa, bb, cc, X[ 1], 14);
+ FF(cc, dd, aa, bb, X[ 2], 15);
+ FF(bb, cc, dd, aa, X[ 3], 12);
+ FF(aa, bb, cc, dd, X[ 4], 5);
+ FF(dd, aa, bb, cc, X[ 5], 8);
+ FF(cc, dd, aa, bb, X[ 6], 7);
+ FF(bb, cc, dd, aa, X[ 7], 9);
+ FF(aa, bb, cc, dd, X[ 8], 11);
+ FF(dd, aa, bb, cc, X[ 9], 13);
+ FF(cc, dd, aa, bb, X[10], 14);
+ FF(bb, cc, dd, aa, X[11], 15);
+ FF(aa, bb, cc, dd, X[12], 6);
+ FF(dd, aa, bb, cc, X[13], 7);
+ FF(cc, dd, aa, bb, X[14], 9);
+ FF(bb, cc, dd, aa, X[15], 8);
+
+ /* round 2 */
+ GG(aa, bb, cc, dd, X[ 7], 7);
+ GG(dd, aa, bb, cc, X[ 4], 6);
+ GG(cc, dd, aa, bb, X[13], 8);
+ GG(bb, cc, dd, aa, X[ 1], 13);
+ GG(aa, bb, cc, dd, X[10], 11);
+ GG(dd, aa, bb, cc, X[ 6], 9);
+ GG(cc, dd, aa, bb, X[15], 7);
+ GG(bb, cc, dd, aa, X[ 3], 15);
+ GG(aa, bb, cc, dd, X[12], 7);
+ GG(dd, aa, bb, cc, X[ 0], 12);
+ GG(cc, dd, aa, bb, X[ 9], 15);
+ GG(bb, cc, dd, aa, X[ 5], 9);
+ GG(aa, bb, cc, dd, X[ 2], 11);
+ GG(dd, aa, bb, cc, X[14], 7);
+ GG(cc, dd, aa, bb, X[11], 13);
+ GG(bb, cc, dd, aa, X[ 8], 12);
+
+ /* round 3 */
+ HH(aa, bb, cc, dd, X[ 3], 11);
+ HH(dd, aa, bb, cc, X[10], 13);
+ HH(cc, dd, aa, bb, X[14], 6);
+ HH(bb, cc, dd, aa, X[ 4], 7);
+ HH(aa, bb, cc, dd, X[ 9], 14);
+ HH(dd, aa, bb, cc, X[15], 9);
+ HH(cc, dd, aa, bb, X[ 8], 13);
+ HH(bb, cc, dd, aa, X[ 1], 15);
+ HH(aa, bb, cc, dd, X[ 2], 14);
+ HH(dd, aa, bb, cc, X[ 7], 8);
+ HH(cc, dd, aa, bb, X[ 0], 13);
+ HH(bb, cc, dd, aa, X[ 6], 6);
+ HH(aa, bb, cc, dd, X[13], 5);
+ HH(dd, aa, bb, cc, X[11], 12);
+ HH(cc, dd, aa, bb, X[ 5], 7);
+ HH(bb, cc, dd, aa, X[12], 5);
+
+ /* round 4 */
+ II(aa, bb, cc, dd, X[ 1], 11);
+ II(dd, aa, bb, cc, X[ 9], 12);
+ II(cc, dd, aa, bb, X[11], 14);
+ II(bb, cc, dd, aa, X[10], 15);
+ II(aa, bb, cc, dd, X[ 0], 14);
+ II(dd, aa, bb, cc, X[ 8], 15);
+ II(cc, dd, aa, bb, X[12], 9);
+ II(bb, cc, dd, aa, X[ 4], 8);
+ II(aa, bb, cc, dd, X[13], 9);
+ II(dd, aa, bb, cc, X[ 3], 14);
+ II(cc, dd, aa, bb, X[ 7], 5);
+ II(bb, cc, dd, aa, X[15], 6);
+ II(aa, bb, cc, dd, X[14], 8);
+ II(dd, aa, bb, cc, X[ 5], 6);
+ II(cc, dd, aa, bb, X[ 6], 5);
+ II(bb, cc, dd, aa, X[ 2], 12);
+
+ /* parallel round 1 */
+ III(aaa, bbb, ccc, ddd, X[ 5], 8);
+ III(ddd, aaa, bbb, ccc, X[14], 9);
+ III(ccc, ddd, aaa, bbb, X[ 7], 9);
+ III(bbb, ccc, ddd, aaa, X[ 0], 11);
+ III(aaa, bbb, ccc, ddd, X[ 9], 13);
+ III(ddd, aaa, bbb, ccc, X[ 2], 15);
+ III(ccc, ddd, aaa, bbb, X[11], 15);
+ III(bbb, ccc, ddd, aaa, X[ 4], 5);
+ III(aaa, bbb, ccc, ddd, X[13], 7);
+ III(ddd, aaa, bbb, ccc, X[ 6], 7);
+ III(ccc, ddd, aaa, bbb, X[15], 8);
+ III(bbb, ccc, ddd, aaa, X[ 8], 11);
+ III(aaa, bbb, ccc, ddd, X[ 1], 14);
+ III(ddd, aaa, bbb, ccc, X[10], 14);
+ III(ccc, ddd, aaa, bbb, X[ 3], 12);
+ III(bbb, ccc, ddd, aaa, X[12], 6);
+
+ /* parallel round 2 */
+ HHH(aaa, bbb, ccc, ddd, X[ 6], 9);
+ HHH(ddd, aaa, bbb, ccc, X[11], 13);
+ HHH(ccc, ddd, aaa, bbb, X[ 3], 15);
+ HHH(bbb, ccc, ddd, aaa, X[ 7], 7);
+ HHH(aaa, bbb, ccc, ddd, X[ 0], 12);
+ HHH(ddd, aaa, bbb, ccc, X[13], 8);
+ HHH(ccc, ddd, aaa, bbb, X[ 5], 9);
+ HHH(bbb, ccc, ddd, aaa, X[10], 11);
+ HHH(aaa, bbb, ccc, ddd, X[14], 7);
+ HHH(ddd, aaa, bbb, ccc, X[15], 7);
+ HHH(ccc, ddd, aaa, bbb, X[ 8], 12);
+ HHH(bbb, ccc, ddd, aaa, X[12], 7);
+ HHH(aaa, bbb, ccc, ddd, X[ 4], 6);
+ HHH(ddd, aaa, bbb, ccc, X[ 9], 15);
+ HHH(ccc, ddd, aaa, bbb, X[ 1], 13);
+ HHH(bbb, ccc, ddd, aaa, X[ 2], 11);
+
+ /* parallel round 3 */
+ GGG(aaa, bbb, ccc, ddd, X[15], 9);
+ GGG(ddd, aaa, bbb, ccc, X[ 5], 7);
+ GGG(ccc, ddd, aaa, bbb, X[ 1], 15);
+ GGG(bbb, ccc, ddd, aaa, X[ 3], 11);
+ GGG(aaa, bbb, ccc, ddd, X[ 7], 8);
+ GGG(ddd, aaa, bbb, ccc, X[14], 6);
+ GGG(ccc, ddd, aaa, bbb, X[ 6], 6);
+ GGG(bbb, ccc, ddd, aaa, X[ 9], 14);
+ GGG(aaa, bbb, ccc, ddd, X[11], 12);
+ GGG(ddd, aaa, bbb, ccc, X[ 8], 13);
+ GGG(ccc, ddd, aaa, bbb, X[12], 5);
+ GGG(bbb, ccc, ddd, aaa, X[ 2], 14);
+ GGG(aaa, bbb, ccc, ddd, X[10], 13);
+ GGG(ddd, aaa, bbb, ccc, X[ 0], 13);
+ GGG(ccc, ddd, aaa, bbb, X[ 4], 7);
+ GGG(bbb, ccc, ddd, aaa, X[13], 5);
+
+ /* parallel round 4 */
+ FFF(aaa, bbb, ccc, ddd, X[ 8], 15);
+ FFF(ddd, aaa, bbb, ccc, X[ 6], 5);
+ FFF(ccc, ddd, aaa, bbb, X[ 4], 8);
+ FFF(bbb, ccc, ddd, aaa, X[ 1], 11);
+ FFF(aaa, bbb, ccc, ddd, X[ 3], 14);
+ FFF(ddd, aaa, bbb, ccc, X[11], 14);
+ FFF(ccc, ddd, aaa, bbb, X[15], 6);
+ FFF(bbb, ccc, ddd, aaa, X[ 0], 14);
+ FFF(aaa, bbb, ccc, ddd, X[ 5], 6);
+ FFF(ddd, aaa, bbb, ccc, X[12], 9);
+ FFF(ccc, ddd, aaa, bbb, X[ 2], 12);
+ FFF(bbb, ccc, ddd, aaa, X[13], 9);
+ FFF(aaa, bbb, ccc, ddd, X[ 9], 12);
+ FFF(ddd, aaa, bbb, ccc, X[ 7], 5);
+ FFF(ccc, ddd, aaa, bbb, X[10], 15);
+ FFF(bbb, ccc, ddd, aaa, X[14], 8);
+
+ /* combine results */
+ ddd += cc + md->rmd128.state[1]; /* final result for MDbuf[0] */
+ md->rmd128.state[1] = md->rmd128.state[2] + dd + aaa;
+ md->rmd128.state[2] = md->rmd128.state[3] + aa + bbb;
+ md->rmd128.state[3] = md->rmd128.state[0] + bb + ccc;
+ md->rmd128.state[0] = ddd;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_rmd128_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_rmd128_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 24 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int rmd128_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->rmd128.state[0] = 0x67452301UL;
+ md->rmd128.state[1] = 0xefcdab89UL;
+ md->rmd128.state[2] = 0x98badcfeUL;
+ md->rmd128.state[3] = 0x10325476UL;
+ md->rmd128.curlen = 0;
+ md->rmd128.length = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(rmd128_process, s_rmd128_compress, rmd128, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (16 bytes)
+ @return CRYPT_OK if successful
+*/
+int rmd128_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->rmd128.curlen >= sizeof(md->rmd128.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* increase the length of the message */
+ md->rmd128.length += md->rmd128.curlen * 8;
+
+ /* append the '1' bit */
+ md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->rmd128.curlen > 56) {
+ while (md->rmd128.curlen < 64) {
+ md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0;
+ }
+ s_rmd128_compress(md, md->rmd128.buf);
+ md->rmd128.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->rmd128.curlen < 56) {
+ md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64L(md->rmd128.length, md->rmd128.buf+56);
+ s_rmd128_compress(md, md->rmd128.buf);
+
+ /* copy output */
+ for (i = 0; i < 4; i++) {
+ STORE32L(md->rmd128.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int rmd128_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[16];
+ } tests[] = {
+ { "",
+ { 0xcd, 0xf2, 0x62, 0x13, 0xa1, 0x50, 0xdc, 0x3e,
+ 0xcb, 0x61, 0x0f, 0x18, 0xf6, 0xb3, 0x8b, 0x46 }
+ },
+ { "a",
+ { 0x86, 0xbe, 0x7a, 0xfa, 0x33, 0x9d, 0x0f, 0xc7,
+ 0xcf, 0xc7, 0x85, 0xe7, 0x2f, 0x57, 0x8d, 0x33 }
+ },
+ { "abc",
+ { 0xc1, 0x4a, 0x12, 0x19, 0x9c, 0x66, 0xe4, 0xba,
+ 0x84, 0x63, 0x6b, 0x0f, 0x69, 0x14, 0x4c, 0x77 }
+ },
+ { "message digest",
+ { 0x9e, 0x32, 0x7b, 0x3d, 0x6e, 0x52, 0x30, 0x62,
+ 0xaf, 0xc1, 0x13, 0x2d, 0x7d, 0xf9, 0xd1, 0xb8 }
+ },
+ { "abcdefghijklmnopqrstuvwxyz",
+ { 0xfd, 0x2a, 0xa6, 0x07, 0xf7, 0x1d, 0xc8, 0xf5,
+ 0x10, 0x71, 0x49, 0x22, 0xb3, 0x71, 0x83, 0x4e }
+ },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ { 0xd1, 0xe9, 0x59, 0xeb, 0x17, 0x9c, 0x91, 0x1f,
+ 0xae, 0xa4, 0x62, 0x4c, 0x60, 0xc5, 0xc7, 0x02 }
+ }
+ };
+
+ int i;
+ unsigned char tmp[16];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ rmd128_init(&md);
+ rmd128_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg));
+ rmd128_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD128", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/hashes/rmd160.c b/Sources/libtomcrypt/hashes/rmd160.c
new file mode 100644
index 00000000..1eba20a5
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/rmd160.c
@@ -0,0 +1,455 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rmd160.c
+ RMD160 hash function
+*/
+
+/* Implementation of LTC_RIPEMD-160 based on the source by Antoon Bosselaers, ESAT-COSIC
+ *
+ * This source has been radically overhauled to be portable and work within
+ * the LibTomCrypt API by Tom St Denis
+ */
+
+#ifdef LTC_RIPEMD160
+
+const struct ltc_hash_descriptor rmd160_desc =
+{
+ "rmd160",
+ 9,
+ 20,
+ 64,
+
+ /* OID */
+ { 1, 3, 36, 3, 2, 1, },
+ 6,
+
+ &rmd160_init,
+ &rmd160_process,
+ &rmd160_done,
+ &rmd160_test,
+ NULL
+};
+
+/* the five basic functions F(), G() and H() */
+#define F(x, y, z) ((x) ^ (y) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define J(x, y, z) ((x) ^ ((y) | ~(z)))
+
+/* the ten basic operations FF() through III() */
+#define FF(a, b, c, d, e, x, s) \
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define GG(a, b, c, d, e, x, s) \
+ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define HH(a, b, c, d, e, x, s) \
+ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define II(a, b, c, d, e, x, s) \
+ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define JJ(a, b, c, d, e, x, s) \
+ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define FFF(a, b, c, d, e, x, s) \
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define GGG(a, b, c, d, e, x, s) \
+ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define HHH(a, b, c, d, e, x, s) \
+ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define III(a, b, c, d, e, x, s) \
+ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define JJJ(a, b, c, d, e, x, s) \
+ (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+
+#ifdef LTC_CLEAN_STACK
+static int ss_rmd160_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_rmd160_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16];
+ int i;
+
+ /* load words X */
+ for (i = 0; i < 16; i++){
+ LOAD32L(X[i], buf + (4 * i));
+ }
+
+ /* load state */
+ aa = aaa = md->rmd160.state[0];
+ bb = bbb = md->rmd160.state[1];
+ cc = ccc = md->rmd160.state[2];
+ dd = ddd = md->rmd160.state[3];
+ ee = eee = md->rmd160.state[4];
+
+ /* round 1 */
+ FF(aa, bb, cc, dd, ee, X[ 0], 11);
+ FF(ee, aa, bb, cc, dd, X[ 1], 14);
+ FF(dd, ee, aa, bb, cc, X[ 2], 15);
+ FF(cc, dd, ee, aa, bb, X[ 3], 12);
+ FF(bb, cc, dd, ee, aa, X[ 4], 5);
+ FF(aa, bb, cc, dd, ee, X[ 5], 8);
+ FF(ee, aa, bb, cc, dd, X[ 6], 7);
+ FF(dd, ee, aa, bb, cc, X[ 7], 9);
+ FF(cc, dd, ee, aa, bb, X[ 8], 11);
+ FF(bb, cc, dd, ee, aa, X[ 9], 13);
+ FF(aa, bb, cc, dd, ee, X[10], 14);
+ FF(ee, aa, bb, cc, dd, X[11], 15);
+ FF(dd, ee, aa, bb, cc, X[12], 6);
+ FF(cc, dd, ee, aa, bb, X[13], 7);
+ FF(bb, cc, dd, ee, aa, X[14], 9);
+ FF(aa, bb, cc, dd, ee, X[15], 8);
+
+ /* round 2 */
+ GG(ee, aa, bb, cc, dd, X[ 7], 7);
+ GG(dd, ee, aa, bb, cc, X[ 4], 6);
+ GG(cc, dd, ee, aa, bb, X[13], 8);
+ GG(bb, cc, dd, ee, aa, X[ 1], 13);
+ GG(aa, bb, cc, dd, ee, X[10], 11);
+ GG(ee, aa, bb, cc, dd, X[ 6], 9);
+ GG(dd, ee, aa, bb, cc, X[15], 7);
+ GG(cc, dd, ee, aa, bb, X[ 3], 15);
+ GG(bb, cc, dd, ee, aa, X[12], 7);
+ GG(aa, bb, cc, dd, ee, X[ 0], 12);
+ GG(ee, aa, bb, cc, dd, X[ 9], 15);
+ GG(dd, ee, aa, bb, cc, X[ 5], 9);
+ GG(cc, dd, ee, aa, bb, X[ 2], 11);
+ GG(bb, cc, dd, ee, aa, X[14], 7);
+ GG(aa, bb, cc, dd, ee, X[11], 13);
+ GG(ee, aa, bb, cc, dd, X[ 8], 12);
+
+ /* round 3 */
+ HH(dd, ee, aa, bb, cc, X[ 3], 11);
+ HH(cc, dd, ee, aa, bb, X[10], 13);
+ HH(bb, cc, dd, ee, aa, X[14], 6);
+ HH(aa, bb, cc, dd, ee, X[ 4], 7);
+ HH(ee, aa, bb, cc, dd, X[ 9], 14);
+ HH(dd, ee, aa, bb, cc, X[15], 9);
+ HH(cc, dd, ee, aa, bb, X[ 8], 13);
+ HH(bb, cc, dd, ee, aa, X[ 1], 15);
+ HH(aa, bb, cc, dd, ee, X[ 2], 14);
+ HH(ee, aa, bb, cc, dd, X[ 7], 8);
+ HH(dd, ee, aa, bb, cc, X[ 0], 13);
+ HH(cc, dd, ee, aa, bb, X[ 6], 6);
+ HH(bb, cc, dd, ee, aa, X[13], 5);
+ HH(aa, bb, cc, dd, ee, X[11], 12);
+ HH(ee, aa, bb, cc, dd, X[ 5], 7);
+ HH(dd, ee, aa, bb, cc, X[12], 5);
+
+ /* round 4 */
+ II(cc, dd, ee, aa, bb, X[ 1], 11);
+ II(bb, cc, dd, ee, aa, X[ 9], 12);
+ II(aa, bb, cc, dd, ee, X[11], 14);
+ II(ee, aa, bb, cc, dd, X[10], 15);
+ II(dd, ee, aa, bb, cc, X[ 0], 14);
+ II(cc, dd, ee, aa, bb, X[ 8], 15);
+ II(bb, cc, dd, ee, aa, X[12], 9);
+ II(aa, bb, cc, dd, ee, X[ 4], 8);
+ II(ee, aa, bb, cc, dd, X[13], 9);
+ II(dd, ee, aa, bb, cc, X[ 3], 14);
+ II(cc, dd, ee, aa, bb, X[ 7], 5);
+ II(bb, cc, dd, ee, aa, X[15], 6);
+ II(aa, bb, cc, dd, ee, X[14], 8);
+ II(ee, aa, bb, cc, dd, X[ 5], 6);
+ II(dd, ee, aa, bb, cc, X[ 6], 5);
+ II(cc, dd, ee, aa, bb, X[ 2], 12);
+
+ /* round 5 */
+ JJ(bb, cc, dd, ee, aa, X[ 4], 9);
+ JJ(aa, bb, cc, dd, ee, X[ 0], 15);
+ JJ(ee, aa, bb, cc, dd, X[ 5], 5);
+ JJ(dd, ee, aa, bb, cc, X[ 9], 11);
+ JJ(cc, dd, ee, aa, bb, X[ 7], 6);
+ JJ(bb, cc, dd, ee, aa, X[12], 8);
+ JJ(aa, bb, cc, dd, ee, X[ 2], 13);
+ JJ(ee, aa, bb, cc, dd, X[10], 12);
+ JJ(dd, ee, aa, bb, cc, X[14], 5);
+ JJ(cc, dd, ee, aa, bb, X[ 1], 12);
+ JJ(bb, cc, dd, ee, aa, X[ 3], 13);
+ JJ(aa, bb, cc, dd, ee, X[ 8], 14);
+ JJ(ee, aa, bb, cc, dd, X[11], 11);
+ JJ(dd, ee, aa, bb, cc, X[ 6], 8);
+ JJ(cc, dd, ee, aa, bb, X[15], 5);
+ JJ(bb, cc, dd, ee, aa, X[13], 6);
+
+ /* parallel round 1 */
+ JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8);
+ JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9);
+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9);
+ JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
+ JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
+ JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5);
+ JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7);
+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7);
+ JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8);
+ JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
+ JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
+ JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6);
+
+ /* parallel round 2 */
+ III(eee, aaa, bbb, ccc, ddd, X[ 6], 9);
+ III(ddd, eee, aaa, bbb, ccc, X[11], 13);
+ III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
+ III(bbb, ccc, ddd, eee, aaa, X[ 7], 7);
+ III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
+ III(eee, aaa, bbb, ccc, ddd, X[13], 8);
+ III(ddd, eee, aaa, bbb, ccc, X[ 5], 9);
+ III(ccc, ddd, eee, aaa, bbb, X[10], 11);
+ III(bbb, ccc, ddd, eee, aaa, X[14], 7);
+ III(aaa, bbb, ccc, ddd, eee, X[15], 7);
+ III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
+ III(ddd, eee, aaa, bbb, ccc, X[12], 7);
+ III(ccc, ddd, eee, aaa, bbb, X[ 4], 6);
+ III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
+ III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
+ III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
+
+ /* parallel round 3 */
+ HHH(ddd, eee, aaa, bbb, ccc, X[15], 9);
+ HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7);
+ HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
+ HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
+ HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8);
+ HHH(ddd, eee, aaa, bbb, ccc, X[14], 6);
+ HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6);
+ HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
+ HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
+ HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
+ HHH(ddd, eee, aaa, bbb, ccc, X[12], 5);
+ HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
+ HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
+ HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
+ HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7);
+ HHH(ddd, eee, aaa, bbb, ccc, X[13], 5);
+
+ /* parallel round 4 */
+ GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
+ GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5);
+ GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8);
+ GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
+ GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
+ GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
+ GGG(bbb, ccc, ddd, eee, aaa, X[15], 6);
+ GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
+ GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6);
+ GGG(ddd, eee, aaa, bbb, ccc, X[12], 9);
+ GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
+ GGG(bbb, ccc, ddd, eee, aaa, X[13], 9);
+ GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
+ GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5);
+ GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
+ GGG(ccc, ddd, eee, aaa, bbb, X[14], 8);
+
+ /* parallel round 5 */
+ FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8);
+ FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5);
+ FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
+ FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9);
+ FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
+ FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5);
+ FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
+ FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6);
+ FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8);
+ FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
+ FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6);
+ FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5);
+ FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
+ FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
+ FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
+ FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
+
+ /* combine results */
+ ddd += cc + md->rmd160.state[1]; /* final result for md->rmd160.state[0] */
+ md->rmd160.state[1] = md->rmd160.state[2] + dd + eee;
+ md->rmd160.state[2] = md->rmd160.state[3] + ee + aaa;
+ md->rmd160.state[3] = md->rmd160.state[4] + aa + bbb;
+ md->rmd160.state[4] = md->rmd160.state[0] + bb + ccc;
+ md->rmd160.state[0] = ddd;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_rmd160_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_rmd160_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 26 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int rmd160_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->rmd160.state[0] = 0x67452301UL;
+ md->rmd160.state[1] = 0xefcdab89UL;
+ md->rmd160.state[2] = 0x98badcfeUL;
+ md->rmd160.state[3] = 0x10325476UL;
+ md->rmd160.state[4] = 0xc3d2e1f0UL;
+ md->rmd160.curlen = 0;
+ md->rmd160.length = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(rmd160_process, s_rmd160_compress, rmd160, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (20 bytes)
+ @return CRYPT_OK if successful
+*/
+int rmd160_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->rmd160.curlen >= sizeof(md->rmd160.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* increase the length of the message */
+ md->rmd160.length += md->rmd160.curlen * 8;
+
+ /* append the '1' bit */
+ md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->rmd160.curlen > 56) {
+ while (md->rmd160.curlen < 64) {
+ md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0;
+ }
+ s_rmd160_compress(md, md->rmd160.buf);
+ md->rmd160.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->rmd160.curlen < 56) {
+ md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64L(md->rmd160.length, md->rmd160.buf+56);
+ s_rmd160_compress(md, md->rmd160.buf);
+
+ /* copy output */
+ for (i = 0; i < 5; i++) {
+ STORE32L(md->rmd160.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int rmd160_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[20];
+ } tests[] = {
+ { "",
+ { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,
+ 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }
+ },
+ { "a",
+ { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,
+ 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }
+ },
+ { "abc",
+ { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,
+ 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }
+ },
+ { "message digest",
+ { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,
+ 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }
+ },
+ { "abcdefghijklmnopqrstuvwxyz",
+ { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,
+ 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }
+ },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,
+ 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }
+ }
+ };
+
+ int i;
+ unsigned char tmp[20];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ rmd160_init(&md);
+ rmd160_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg));
+ rmd160_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD160", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/hashes/rmd256.c b/Sources/libtomcrypt/hashes/rmd256.c
new file mode 100644
index 00000000..00971981
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/rmd256.c
@@ -0,0 +1,420 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @param rmd256.c
+ RLTC_MD256 Hash function
+*/
+
+#ifdef LTC_RIPEMD256
+
+const struct ltc_hash_descriptor rmd256_desc =
+{
+ "rmd256",
+ 13,
+ 32,
+ 64,
+
+ /* OID */
+ { 1, 3, 36, 3, 2, 3 },
+ 6,
+
+ &rmd256_init,
+ &rmd256_process,
+ &rmd256_done,
+ &rmd256_test,
+ NULL
+};
+
+/* the four basic functions F(), G() and H() */
+#define F(x, y, z) ((x) ^ (y) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+
+/* the eight basic operations FF() through III() */
+#define FF(a, b, c, d, x, s) \
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROLc((a), (s));
+
+#define GG(a, b, c, d, x, s) \
+ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
+ (a) = ROLc((a), (s));
+
+#define HH(a, b, c, d, x, s) \
+ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
+ (a) = ROLc((a), (s));
+
+#define II(a, b, c, d, x, s) \
+ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
+ (a) = ROLc((a), (s));
+
+#define FFF(a, b, c, d, x, s) \
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROLc((a), (s));
+
+#define GGG(a, b, c, d, x, s) \
+ (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\
+ (a) = ROLc((a), (s));
+
+#define HHH(a, b, c, d, x, s) \
+ (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\
+ (a) = ROLc((a), (s));
+
+#define III(a, b, c, d, x, s) \
+ (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\
+ (a) = ROLc((a), (s));
+
+#ifdef LTC_CLEAN_STACK
+static int ss_rmd256_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_rmd256_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,tmp,X[16];
+ int i;
+
+ /* load words X */
+ for (i = 0; i < 16; i++){
+ LOAD32L(X[i], buf + (4 * i));
+ }
+
+ /* load state */
+ aa = md->rmd256.state[0];
+ bb = md->rmd256.state[1];
+ cc = md->rmd256.state[2];
+ dd = md->rmd256.state[3];
+ aaa = md->rmd256.state[4];
+ bbb = md->rmd256.state[5];
+ ccc = md->rmd256.state[6];
+ ddd = md->rmd256.state[7];
+
+ /* round 1 */
+ FF(aa, bb, cc, dd, X[ 0], 11);
+ FF(dd, aa, bb, cc, X[ 1], 14);
+ FF(cc, dd, aa, bb, X[ 2], 15);
+ FF(bb, cc, dd, aa, X[ 3], 12);
+ FF(aa, bb, cc, dd, X[ 4], 5);
+ FF(dd, aa, bb, cc, X[ 5], 8);
+ FF(cc, dd, aa, bb, X[ 6], 7);
+ FF(bb, cc, dd, aa, X[ 7], 9);
+ FF(aa, bb, cc, dd, X[ 8], 11);
+ FF(dd, aa, bb, cc, X[ 9], 13);
+ FF(cc, dd, aa, bb, X[10], 14);
+ FF(bb, cc, dd, aa, X[11], 15);
+ FF(aa, bb, cc, dd, X[12], 6);
+ FF(dd, aa, bb, cc, X[13], 7);
+ FF(cc, dd, aa, bb, X[14], 9);
+ FF(bb, cc, dd, aa, X[15], 8);
+
+ /* parallel round 1 */
+ III(aaa, bbb, ccc, ddd, X[ 5], 8);
+ III(ddd, aaa, bbb, ccc, X[14], 9);
+ III(ccc, ddd, aaa, bbb, X[ 7], 9);
+ III(bbb, ccc, ddd, aaa, X[ 0], 11);
+ III(aaa, bbb, ccc, ddd, X[ 9], 13);
+ III(ddd, aaa, bbb, ccc, X[ 2], 15);
+ III(ccc, ddd, aaa, bbb, X[11], 15);
+ III(bbb, ccc, ddd, aaa, X[ 4], 5);
+ III(aaa, bbb, ccc, ddd, X[13], 7);
+ III(ddd, aaa, bbb, ccc, X[ 6], 7);
+ III(ccc, ddd, aaa, bbb, X[15], 8);
+ III(bbb, ccc, ddd, aaa, X[ 8], 11);
+ III(aaa, bbb, ccc, ddd, X[ 1], 14);
+ III(ddd, aaa, bbb, ccc, X[10], 14);
+ III(ccc, ddd, aaa, bbb, X[ 3], 12);
+ III(bbb, ccc, ddd, aaa, X[12], 6);
+
+ tmp = aa; aa = aaa; aaa = tmp;
+
+ /* round 2 */
+ GG(aa, bb, cc, dd, X[ 7], 7);
+ GG(dd, aa, bb, cc, X[ 4], 6);
+ GG(cc, dd, aa, bb, X[13], 8);
+ GG(bb, cc, dd, aa, X[ 1], 13);
+ GG(aa, bb, cc, dd, X[10], 11);
+ GG(dd, aa, bb, cc, X[ 6], 9);
+ GG(cc, dd, aa, bb, X[15], 7);
+ GG(bb, cc, dd, aa, X[ 3], 15);
+ GG(aa, bb, cc, dd, X[12], 7);
+ GG(dd, aa, bb, cc, X[ 0], 12);
+ GG(cc, dd, aa, bb, X[ 9], 15);
+ GG(bb, cc, dd, aa, X[ 5], 9);
+ GG(aa, bb, cc, dd, X[ 2], 11);
+ GG(dd, aa, bb, cc, X[14], 7);
+ GG(cc, dd, aa, bb, X[11], 13);
+ GG(bb, cc, dd, aa, X[ 8], 12);
+
+ /* parallel round 2 */
+ HHH(aaa, bbb, ccc, ddd, X[ 6], 9);
+ HHH(ddd, aaa, bbb, ccc, X[11], 13);
+ HHH(ccc, ddd, aaa, bbb, X[ 3], 15);
+ HHH(bbb, ccc, ddd, aaa, X[ 7], 7);
+ HHH(aaa, bbb, ccc, ddd, X[ 0], 12);
+ HHH(ddd, aaa, bbb, ccc, X[13], 8);
+ HHH(ccc, ddd, aaa, bbb, X[ 5], 9);
+ HHH(bbb, ccc, ddd, aaa, X[10], 11);
+ HHH(aaa, bbb, ccc, ddd, X[14], 7);
+ HHH(ddd, aaa, bbb, ccc, X[15], 7);
+ HHH(ccc, ddd, aaa, bbb, X[ 8], 12);
+ HHH(bbb, ccc, ddd, aaa, X[12], 7);
+ HHH(aaa, bbb, ccc, ddd, X[ 4], 6);
+ HHH(ddd, aaa, bbb, ccc, X[ 9], 15);
+ HHH(ccc, ddd, aaa, bbb, X[ 1], 13);
+ HHH(bbb, ccc, ddd, aaa, X[ 2], 11);
+
+ tmp = bb; bb = bbb; bbb = tmp;
+
+ /* round 3 */
+ HH(aa, bb, cc, dd, X[ 3], 11);
+ HH(dd, aa, bb, cc, X[10], 13);
+ HH(cc, dd, aa, bb, X[14], 6);
+ HH(bb, cc, dd, aa, X[ 4], 7);
+ HH(aa, bb, cc, dd, X[ 9], 14);
+ HH(dd, aa, bb, cc, X[15], 9);
+ HH(cc, dd, aa, bb, X[ 8], 13);
+ HH(bb, cc, dd, aa, X[ 1], 15);
+ HH(aa, bb, cc, dd, X[ 2], 14);
+ HH(dd, aa, bb, cc, X[ 7], 8);
+ HH(cc, dd, aa, bb, X[ 0], 13);
+ HH(bb, cc, dd, aa, X[ 6], 6);
+ HH(aa, bb, cc, dd, X[13], 5);
+ HH(dd, aa, bb, cc, X[11], 12);
+ HH(cc, dd, aa, bb, X[ 5], 7);
+ HH(bb, cc, dd, aa, X[12], 5);
+
+ /* parallel round 3 */
+ GGG(aaa, bbb, ccc, ddd, X[15], 9);
+ GGG(ddd, aaa, bbb, ccc, X[ 5], 7);
+ GGG(ccc, ddd, aaa, bbb, X[ 1], 15);
+ GGG(bbb, ccc, ddd, aaa, X[ 3], 11);
+ GGG(aaa, bbb, ccc, ddd, X[ 7], 8);
+ GGG(ddd, aaa, bbb, ccc, X[14], 6);
+ GGG(ccc, ddd, aaa, bbb, X[ 6], 6);
+ GGG(bbb, ccc, ddd, aaa, X[ 9], 14);
+ GGG(aaa, bbb, ccc, ddd, X[11], 12);
+ GGG(ddd, aaa, bbb, ccc, X[ 8], 13);
+ GGG(ccc, ddd, aaa, bbb, X[12], 5);
+ GGG(bbb, ccc, ddd, aaa, X[ 2], 14);
+ GGG(aaa, bbb, ccc, ddd, X[10], 13);
+ GGG(ddd, aaa, bbb, ccc, X[ 0], 13);
+ GGG(ccc, ddd, aaa, bbb, X[ 4], 7);
+ GGG(bbb, ccc, ddd, aaa, X[13], 5);
+
+ tmp = cc; cc = ccc; ccc = tmp;
+
+ /* round 4 */
+ II(aa, bb, cc, dd, X[ 1], 11);
+ II(dd, aa, bb, cc, X[ 9], 12);
+ II(cc, dd, aa, bb, X[11], 14);
+ II(bb, cc, dd, aa, X[10], 15);
+ II(aa, bb, cc, dd, X[ 0], 14);
+ II(dd, aa, bb, cc, X[ 8], 15);
+ II(cc, dd, aa, bb, X[12], 9);
+ II(bb, cc, dd, aa, X[ 4], 8);
+ II(aa, bb, cc, dd, X[13], 9);
+ II(dd, aa, bb, cc, X[ 3], 14);
+ II(cc, dd, aa, bb, X[ 7], 5);
+ II(bb, cc, dd, aa, X[15], 6);
+ II(aa, bb, cc, dd, X[14], 8);
+ II(dd, aa, bb, cc, X[ 5], 6);
+ II(cc, dd, aa, bb, X[ 6], 5);
+ II(bb, cc, dd, aa, X[ 2], 12);
+
+ /* parallel round 4 */
+ FFF(aaa, bbb, ccc, ddd, X[ 8], 15);
+ FFF(ddd, aaa, bbb, ccc, X[ 6], 5);
+ FFF(ccc, ddd, aaa, bbb, X[ 4], 8);
+ FFF(bbb, ccc, ddd, aaa, X[ 1], 11);
+ FFF(aaa, bbb, ccc, ddd, X[ 3], 14);
+ FFF(ddd, aaa, bbb, ccc, X[11], 14);
+ FFF(ccc, ddd, aaa, bbb, X[15], 6);
+ FFF(bbb, ccc, ddd, aaa, X[ 0], 14);
+ FFF(aaa, bbb, ccc, ddd, X[ 5], 6);
+ FFF(ddd, aaa, bbb, ccc, X[12], 9);
+ FFF(ccc, ddd, aaa, bbb, X[ 2], 12);
+ FFF(bbb, ccc, ddd, aaa, X[13], 9);
+ FFF(aaa, bbb, ccc, ddd, X[ 9], 12);
+ FFF(ddd, aaa, bbb, ccc, X[ 7], 5);
+ FFF(ccc, ddd, aaa, bbb, X[10], 15);
+ FFF(bbb, ccc, ddd, aaa, X[14], 8);
+
+ tmp = dd; dd = ddd; ddd = tmp;
+
+ /* combine results */
+ md->rmd256.state[0] += aa;
+ md->rmd256.state[1] += bb;
+ md->rmd256.state[2] += cc;
+ md->rmd256.state[3] += dd;
+ md->rmd256.state[4] += aaa;
+ md->rmd256.state[5] += bbb;
+ md->rmd256.state[6] += ccc;
+ md->rmd256.state[7] += ddd;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_rmd256_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_rmd256_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 25 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int rmd256_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->rmd256.state[0] = 0x67452301UL;
+ md->rmd256.state[1] = 0xefcdab89UL;
+ md->rmd256.state[2] = 0x98badcfeUL;
+ md->rmd256.state[3] = 0x10325476UL;
+ md->rmd256.state[4] = 0x76543210UL;
+ md->rmd256.state[5] = 0xfedcba98UL;
+ md->rmd256.state[6] = 0x89abcdefUL;
+ md->rmd256.state[7] = 0x01234567UL;
+ md->rmd256.curlen = 0;
+ md->rmd256.length = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(rmd256_process, s_rmd256_compress, rmd256, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (16 bytes)
+ @return CRYPT_OK if successful
+*/
+int rmd256_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->rmd256.curlen >= sizeof(md->rmd256.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* increase the length of the message */
+ md->rmd256.length += md->rmd256.curlen * 8;
+
+ /* append the '1' bit */
+ md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->rmd256.curlen > 56) {
+ while (md->rmd256.curlen < 64) {
+ md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0;
+ }
+ s_rmd256_compress(md, md->rmd256.buf);
+ md->rmd256.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->rmd256.curlen < 56) {
+ md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64L(md->rmd256.length, md->rmd256.buf+56);
+ s_rmd256_compress(md, md->rmd256.buf);
+
+ /* copy output */
+ for (i = 0; i < 8; i++) {
+ STORE32L(md->rmd256.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int rmd256_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[32];
+ } tests[] = {
+ { "",
+ { 0x02, 0xba, 0x4c, 0x4e, 0x5f, 0x8e, 0xcd, 0x18,
+ 0x77, 0xfc, 0x52, 0xd6, 0x4d, 0x30, 0xe3, 0x7a,
+ 0x2d, 0x97, 0x74, 0xfb, 0x1e, 0x5d, 0x02, 0x63,
+ 0x80, 0xae, 0x01, 0x68, 0xe3, 0xc5, 0x52, 0x2d }
+ },
+ { "a",
+ { 0xf9, 0x33, 0x3e, 0x45, 0xd8, 0x57, 0xf5, 0xd9,
+ 0x0a, 0x91, 0xba, 0xb7, 0x0a, 0x1e, 0xba, 0x0c,
+ 0xfb, 0x1b, 0xe4, 0xb0, 0x78, 0x3c, 0x9a, 0xcf,
+ 0xcd, 0x88, 0x3a, 0x91, 0x34, 0x69, 0x29, 0x25 }
+ },
+ { "abc",
+ { 0xaf, 0xbd, 0x6e, 0x22, 0x8b, 0x9d, 0x8c, 0xbb,
+ 0xce, 0xf5, 0xca, 0x2d, 0x03, 0xe6, 0xdb, 0xa1,
+ 0x0a, 0xc0, 0xbc, 0x7d, 0xcb, 0xe4, 0x68, 0x0e,
+ 0x1e, 0x42, 0xd2, 0xe9, 0x75, 0x45, 0x9b, 0x65 }
+ },
+ { "message digest",
+ { 0x87, 0xe9, 0x71, 0x75, 0x9a, 0x1c, 0xe4, 0x7a,
+ 0x51, 0x4d, 0x5c, 0x91, 0x4c, 0x39, 0x2c, 0x90,
+ 0x18, 0xc7, 0xc4, 0x6b, 0xc1, 0x44, 0x65, 0x55,
+ 0x4a, 0xfc, 0xdf, 0x54, 0xa5, 0x07, 0x0c, 0x0e }
+ },
+ { "abcdefghijklmnopqrstuvwxyz",
+ { 0x64, 0x9d, 0x30, 0x34, 0x75, 0x1e, 0xa2, 0x16,
+ 0x77, 0x6b, 0xf9, 0xa1, 0x8a, 0xcc, 0x81, 0xbc,
+ 0x78, 0x96, 0x11, 0x8a, 0x51, 0x97, 0x96, 0x87,
+ 0x82, 0xdd, 0x1f, 0xd9, 0x7d, 0x8d, 0x51, 0x33 }
+ },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ { 0x57, 0x40, 0xa4, 0x08, 0xac, 0x16, 0xb7, 0x20,
+ 0xb8, 0x44, 0x24, 0xae, 0x93, 0x1c, 0xbb, 0x1f,
+ 0xe3, 0x63, 0xd1, 0xd0, 0xbf, 0x40, 0x17, 0xf1,
+ 0xa8, 0x9f, 0x7e, 0xa6, 0xde, 0x77, 0xa0, 0xb8 }
+ }
+ };
+
+ int i;
+ unsigned char tmp[32];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ rmd256_init(&md);
+ rmd256_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg));
+ rmd256_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD256", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/hashes/rmd320.c b/Sources/libtomcrypt/hashes/rmd320.c
new file mode 100644
index 00000000..0021d673
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/rmd320.c
@@ -0,0 +1,485 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rmd320.c
+ RMD320 hash function
+*/
+
+#ifdef LTC_RIPEMD320
+
+const struct ltc_hash_descriptor rmd320_desc =
+{
+ "rmd320",
+ 14,
+ 40,
+ 64,
+
+ /* OID ... does not exist
+ * http://oid-info.com/get/1.3.36.3.2 */
+ { 0 },
+ 0,
+
+ &rmd320_init,
+ &rmd320_process,
+ &rmd320_done,
+ &rmd320_test,
+ NULL
+};
+
+/* the five basic functions F(), G() and H() */
+#define F(x, y, z) ((x) ^ (y) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define J(x, y, z) ((x) ^ ((y) | ~(z)))
+
+/* the ten basic operations FF() through III() */
+#define FF(a, b, c, d, e, x, s) \
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define GG(a, b, c, d, e, x, s) \
+ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define HH(a, b, c, d, e, x, s) \
+ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define II(a, b, c, d, e, x, s) \
+ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define JJ(a, b, c, d, e, x, s) \
+ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define FFF(a, b, c, d, e, x, s) \
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define GGG(a, b, c, d, e, x, s) \
+ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define HHH(a, b, c, d, e, x, s) \
+ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define III(a, b, c, d, e, x, s) \
+ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+#define JJJ(a, b, c, d, e, x, s) \
+ (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
+ (a) = ROLc((a), (s)) + (e);\
+ (c) = ROLc((c), 10);
+
+
+#ifdef LTC_CLEAN_STACK
+static int ss_rmd320_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_rmd320_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,tmp,X[16];
+ int i;
+
+ /* load words X */
+ for (i = 0; i < 16; i++){
+ LOAD32L(X[i], buf + (4 * i));
+ }
+
+ /* load state */
+ aa = md->rmd320.state[0];
+ bb = md->rmd320.state[1];
+ cc = md->rmd320.state[2];
+ dd = md->rmd320.state[3];
+ ee = md->rmd320.state[4];
+ aaa = md->rmd320.state[5];
+ bbb = md->rmd320.state[6];
+ ccc = md->rmd320.state[7];
+ ddd = md->rmd320.state[8];
+ eee = md->rmd320.state[9];
+
+ /* round 1 */
+ FF(aa, bb, cc, dd, ee, X[ 0], 11);
+ FF(ee, aa, bb, cc, dd, X[ 1], 14);
+ FF(dd, ee, aa, bb, cc, X[ 2], 15);
+ FF(cc, dd, ee, aa, bb, X[ 3], 12);
+ FF(bb, cc, dd, ee, aa, X[ 4], 5);
+ FF(aa, bb, cc, dd, ee, X[ 5], 8);
+ FF(ee, aa, bb, cc, dd, X[ 6], 7);
+ FF(dd, ee, aa, bb, cc, X[ 7], 9);
+ FF(cc, dd, ee, aa, bb, X[ 8], 11);
+ FF(bb, cc, dd, ee, aa, X[ 9], 13);
+ FF(aa, bb, cc, dd, ee, X[10], 14);
+ FF(ee, aa, bb, cc, dd, X[11], 15);
+ FF(dd, ee, aa, bb, cc, X[12], 6);
+ FF(cc, dd, ee, aa, bb, X[13], 7);
+ FF(bb, cc, dd, ee, aa, X[14], 9);
+ FF(aa, bb, cc, dd, ee, X[15], 8);
+
+ /* parallel round 1 */
+ JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8);
+ JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9);
+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9);
+ JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
+ JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
+ JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5);
+ JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7);
+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7);
+ JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8);
+ JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
+ JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
+ JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6);
+
+ tmp = aa; aa = aaa; aaa = tmp;
+
+ /* round 2 */
+ GG(ee, aa, bb, cc, dd, X[ 7], 7);
+ GG(dd, ee, aa, bb, cc, X[ 4], 6);
+ GG(cc, dd, ee, aa, bb, X[13], 8);
+ GG(bb, cc, dd, ee, aa, X[ 1], 13);
+ GG(aa, bb, cc, dd, ee, X[10], 11);
+ GG(ee, aa, bb, cc, dd, X[ 6], 9);
+ GG(dd, ee, aa, bb, cc, X[15], 7);
+ GG(cc, dd, ee, aa, bb, X[ 3], 15);
+ GG(bb, cc, dd, ee, aa, X[12], 7);
+ GG(aa, bb, cc, dd, ee, X[ 0], 12);
+ GG(ee, aa, bb, cc, dd, X[ 9], 15);
+ GG(dd, ee, aa, bb, cc, X[ 5], 9);
+ GG(cc, dd, ee, aa, bb, X[ 2], 11);
+ GG(bb, cc, dd, ee, aa, X[14], 7);
+ GG(aa, bb, cc, dd, ee, X[11], 13);
+ GG(ee, aa, bb, cc, dd, X[ 8], 12);
+
+ /* parallel round 2 */
+ III(eee, aaa, bbb, ccc, ddd, X[ 6], 9);
+ III(ddd, eee, aaa, bbb, ccc, X[11], 13);
+ III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
+ III(bbb, ccc, ddd, eee, aaa, X[ 7], 7);
+ III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
+ III(eee, aaa, bbb, ccc, ddd, X[13], 8);
+ III(ddd, eee, aaa, bbb, ccc, X[ 5], 9);
+ III(ccc, ddd, eee, aaa, bbb, X[10], 11);
+ III(bbb, ccc, ddd, eee, aaa, X[14], 7);
+ III(aaa, bbb, ccc, ddd, eee, X[15], 7);
+ III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
+ III(ddd, eee, aaa, bbb, ccc, X[12], 7);
+ III(ccc, ddd, eee, aaa, bbb, X[ 4], 6);
+ III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
+ III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
+ III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
+
+ tmp = bb; bb = bbb; bbb = tmp;
+
+ /* round 3 */
+ HH(dd, ee, aa, bb, cc, X[ 3], 11);
+ HH(cc, dd, ee, aa, bb, X[10], 13);
+ HH(bb, cc, dd, ee, aa, X[14], 6);
+ HH(aa, bb, cc, dd, ee, X[ 4], 7);
+ HH(ee, aa, bb, cc, dd, X[ 9], 14);
+ HH(dd, ee, aa, bb, cc, X[15], 9);
+ HH(cc, dd, ee, aa, bb, X[ 8], 13);
+ HH(bb, cc, dd, ee, aa, X[ 1], 15);
+ HH(aa, bb, cc, dd, ee, X[ 2], 14);
+ HH(ee, aa, bb, cc, dd, X[ 7], 8);
+ HH(dd, ee, aa, bb, cc, X[ 0], 13);
+ HH(cc, dd, ee, aa, bb, X[ 6], 6);
+ HH(bb, cc, dd, ee, aa, X[13], 5);
+ HH(aa, bb, cc, dd, ee, X[11], 12);
+ HH(ee, aa, bb, cc, dd, X[ 5], 7);
+ HH(dd, ee, aa, bb, cc, X[12], 5);
+
+ /* parallel round 3 */
+ HHH(ddd, eee, aaa, bbb, ccc, X[15], 9);
+ HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7);
+ HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
+ HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
+ HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8);
+ HHH(ddd, eee, aaa, bbb, ccc, X[14], 6);
+ HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6);
+ HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
+ HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
+ HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
+ HHH(ddd, eee, aaa, bbb, ccc, X[12], 5);
+ HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
+ HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
+ HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
+ HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7);
+ HHH(ddd, eee, aaa, bbb, ccc, X[13], 5);
+
+ tmp = cc; cc = ccc; ccc = tmp;
+
+ /* round 4 */
+ II(cc, dd, ee, aa, bb, X[ 1], 11);
+ II(bb, cc, dd, ee, aa, X[ 9], 12);
+ II(aa, bb, cc, dd, ee, X[11], 14);
+ II(ee, aa, bb, cc, dd, X[10], 15);
+ II(dd, ee, aa, bb, cc, X[ 0], 14);
+ II(cc, dd, ee, aa, bb, X[ 8], 15);
+ II(bb, cc, dd, ee, aa, X[12], 9);
+ II(aa, bb, cc, dd, ee, X[ 4], 8);
+ II(ee, aa, bb, cc, dd, X[13], 9);
+ II(dd, ee, aa, bb, cc, X[ 3], 14);
+ II(cc, dd, ee, aa, bb, X[ 7], 5);
+ II(bb, cc, dd, ee, aa, X[15], 6);
+ II(aa, bb, cc, dd, ee, X[14], 8);
+ II(ee, aa, bb, cc, dd, X[ 5], 6);
+ II(dd, ee, aa, bb, cc, X[ 6], 5);
+ II(cc, dd, ee, aa, bb, X[ 2], 12);
+
+ /* parallel round 4 */
+ GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
+ GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5);
+ GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8);
+ GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
+ GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
+ GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
+ GGG(bbb, ccc, ddd, eee, aaa, X[15], 6);
+ GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
+ GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6);
+ GGG(ddd, eee, aaa, bbb, ccc, X[12], 9);
+ GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
+ GGG(bbb, ccc, ddd, eee, aaa, X[13], 9);
+ GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
+ GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5);
+ GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
+ GGG(ccc, ddd, eee, aaa, bbb, X[14], 8);
+
+ tmp = dd; dd = ddd; ddd = tmp;
+
+ /* round 5 */
+ JJ(bb, cc, dd, ee, aa, X[ 4], 9);
+ JJ(aa, bb, cc, dd, ee, X[ 0], 15);
+ JJ(ee, aa, bb, cc, dd, X[ 5], 5);
+ JJ(dd, ee, aa, bb, cc, X[ 9], 11);
+ JJ(cc, dd, ee, aa, bb, X[ 7], 6);
+ JJ(bb, cc, dd, ee, aa, X[12], 8);
+ JJ(aa, bb, cc, dd, ee, X[ 2], 13);
+ JJ(ee, aa, bb, cc, dd, X[10], 12);
+ JJ(dd, ee, aa, bb, cc, X[14], 5);
+ JJ(cc, dd, ee, aa, bb, X[ 1], 12);
+ JJ(bb, cc, dd, ee, aa, X[ 3], 13);
+ JJ(aa, bb, cc, dd, ee, X[ 8], 14);
+ JJ(ee, aa, bb, cc, dd, X[11], 11);
+ JJ(dd, ee, aa, bb, cc, X[ 6], 8);
+ JJ(cc, dd, ee, aa, bb, X[15], 5);
+ JJ(bb, cc, dd, ee, aa, X[13], 6);
+
+ /* parallel round 5 */
+ FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8);
+ FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5);
+ FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
+ FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9);
+ FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
+ FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5);
+ FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
+ FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6);
+ FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8);
+ FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
+ FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6);
+ FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5);
+ FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
+ FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
+ FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
+ FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
+
+ tmp = ee; ee = eee; eee = tmp;
+
+ /* combine results */
+ md->rmd320.state[0] += aa;
+ md->rmd320.state[1] += bb;
+ md->rmd320.state[2] += cc;
+ md->rmd320.state[3] += dd;
+ md->rmd320.state[4] += ee;
+ md->rmd320.state[5] += aaa;
+ md->rmd320.state[6] += bbb;
+ md->rmd320.state[7] += ccc;
+ md->rmd320.state[8] += ddd;
+ md->rmd320.state[9] += eee;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_rmd320_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_rmd320_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 27 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int rmd320_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->rmd320.state[0] = 0x67452301UL;
+ md->rmd320.state[1] = 0xefcdab89UL;
+ md->rmd320.state[2] = 0x98badcfeUL;
+ md->rmd320.state[3] = 0x10325476UL;
+ md->rmd320.state[4] = 0xc3d2e1f0UL;
+ md->rmd320.state[5] = 0x76543210UL;
+ md->rmd320.state[6] = 0xfedcba98UL;
+ md->rmd320.state[7] = 0x89abcdefUL;
+ md->rmd320.state[8] = 0x01234567UL;
+ md->rmd320.state[9] = 0x3c2d1e0fUL;
+ md->rmd320.curlen = 0;
+ md->rmd320.length = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(rmd320_process, s_rmd320_compress, rmd320, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (20 bytes)
+ @return CRYPT_OK if successful
+*/
+int rmd320_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->rmd320.curlen >= sizeof(md->rmd320.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* increase the length of the message */
+ md->rmd320.length += md->rmd320.curlen * 8;
+
+ /* append the '1' bit */
+ md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->rmd320.curlen > 56) {
+ while (md->rmd320.curlen < 64) {
+ md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0;
+ }
+ s_rmd320_compress(md, md->rmd320.buf);
+ md->rmd320.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->rmd320.curlen < 56) {
+ md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64L(md->rmd320.length, md->rmd320.buf+56);
+ s_rmd320_compress(md, md->rmd320.buf);
+
+ /* copy output */
+ for (i = 0; i < 10; i++) {
+ STORE32L(md->rmd320.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int rmd320_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[40];
+ } tests[] = {
+ { "",
+ { 0x22, 0xd6, 0x5d, 0x56, 0x61, 0x53, 0x6c, 0xdc, 0x75, 0xc1,
+ 0xfd, 0xf5, 0xc6, 0xde, 0x7b, 0x41, 0xb9, 0xf2, 0x73, 0x25,
+ 0xeb, 0xc6, 0x1e, 0x85, 0x57, 0x17, 0x7d, 0x70, 0x5a, 0x0e,
+ 0xc8, 0x80, 0x15, 0x1c, 0x3a, 0x32, 0xa0, 0x08, 0x99, 0xb8 }
+ },
+ { "a",
+ { 0xce, 0x78, 0x85, 0x06, 0x38, 0xf9, 0x26, 0x58, 0xa5, 0xa5,
+ 0x85, 0x09, 0x75, 0x79, 0x92, 0x6d, 0xda, 0x66, 0x7a, 0x57,
+ 0x16, 0x56, 0x2c, 0xfc, 0xf6, 0xfb, 0xe7, 0x7f, 0x63, 0x54,
+ 0x2f, 0x99, 0xb0, 0x47, 0x05, 0xd6, 0x97, 0x0d, 0xff, 0x5d }
+ },
+ { "abc",
+ { 0xde, 0x4c, 0x01, 0xb3, 0x05, 0x4f, 0x89, 0x30, 0xa7, 0x9d,
+ 0x09, 0xae, 0x73, 0x8e, 0x92, 0x30, 0x1e, 0x5a, 0x17, 0x08,
+ 0x5b, 0xef, 0xfd, 0xc1, 0xb8, 0xd1, 0x16, 0x71, 0x3e, 0x74,
+ 0xf8, 0x2f, 0xa9, 0x42, 0xd6, 0x4c, 0xdb, 0xc4, 0x68, 0x2d }
+ },
+ { "message digest",
+ { 0x3a, 0x8e, 0x28, 0x50, 0x2e, 0xd4, 0x5d, 0x42, 0x2f, 0x68,
+ 0x84, 0x4f, 0x9d, 0xd3, 0x16, 0xe7, 0xb9, 0x85, 0x33, 0xfa,
+ 0x3f, 0x2a, 0x91, 0xd2, 0x9f, 0x84, 0xd4, 0x25, 0xc8, 0x8d,
+ 0x6b, 0x4e, 0xff, 0x72, 0x7d, 0xf6, 0x6a, 0x7c, 0x01, 0x97 }
+ },
+ { "abcdefghijklmnopqrstuvwxyz",
+ { 0xca, 0xbd, 0xb1, 0x81, 0x0b, 0x92, 0x47, 0x0a, 0x20, 0x93,
+ 0xaa, 0x6b, 0xce, 0x05, 0x95, 0x2c, 0x28, 0x34, 0x8c, 0xf4,
+ 0x3f, 0xf6, 0x08, 0x41, 0x97, 0x51, 0x66, 0xbb, 0x40, 0xed,
+ 0x23, 0x40, 0x04, 0xb8, 0x82, 0x44, 0x63, 0xe6, 0xb0, 0x09 }
+ },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0xd0, 0x34, 0xa7, 0x95, 0x0c, 0xf7, 0x22, 0x02, 0x1b, 0xa4,
+ 0xb8, 0x4d, 0xf7, 0x69, 0xa5, 0xde, 0x20, 0x60, 0xe2, 0x59,
+ 0xdf, 0x4c, 0x9b, 0xb4, 0xa4, 0x26, 0x8c, 0x0e, 0x93, 0x5b,
+ 0xbc, 0x74, 0x70, 0xa9, 0x69, 0xc9, 0xd0, 0x72, 0xa1, 0xac }
+ }
+ };
+
+ int i;
+ unsigned char tmp[40];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ rmd320_init(&md);
+ rmd320_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg));
+ rmd320_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD320", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/hashes/sha1.c b/Sources/libtomcrypt/hashes/sha1.c
new file mode 100644
index 00000000..40709db8
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/sha1.c
@@ -0,0 +1,276 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file sha1.c
+ LTC_SHA1 code by Tom St Denis
+*/
+
+
+#ifdef LTC_SHA1
+
+const struct ltc_hash_descriptor sha1_desc =
+{
+ "sha1",
+ 2,
+ 20,
+ 64,
+
+ /* OID */
+ { 1, 3, 14, 3, 2, 26, },
+ 6,
+
+ &sha1_init,
+ &sha1_process,
+ &sha1_done,
+ &sha1_test,
+ NULL
+};
+
+#define F0(x,y,z) (z ^ (x & (y ^ z)))
+#define F1(x,y,z) (x ^ y ^ z)
+#define F2(x,y,z) ((x & y) | (z & (x | y)))
+#define F3(x,y,z) (x ^ y ^ z)
+
+#ifdef LTC_CLEAN_STACK
+static int ss_sha1_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_sha1_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong32 a,b,c,d,e,W[80],i;
+#ifdef LTC_SMALL_CODE
+ ulong32 t;
+#endif
+
+ /* copy the state into 512-bits into W[0..15] */
+ for (i = 0; i < 16; i++) {
+ LOAD32H(W[i], buf + (4*i));
+ }
+
+ /* copy state */
+ a = md->sha1.state[0];
+ b = md->sha1.state[1];
+ c = md->sha1.state[2];
+ d = md->sha1.state[3];
+ e = md->sha1.state[4];
+
+ /* expand it */
+ for (i = 16; i < 80; i++) {
+ W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
+ }
+
+ /* compress */
+ /* round one */
+ #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);
+ #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);
+ #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);
+ #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);
+
+#ifdef LTC_SMALL_CODE
+
+ for (i = 0; i < 20; ) {
+ FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 40; ) {
+ FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 60; ) {
+ FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 80; ) {
+ FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+#else
+
+ for (i = 0; i < 20; ) {
+ FF0(a,b,c,d,e,i++);
+ FF0(e,a,b,c,d,i++);
+ FF0(d,e,a,b,c,i++);
+ FF0(c,d,e,a,b,i++);
+ FF0(b,c,d,e,a,i++);
+ }
+
+ /* round two */
+ for (; i < 40; ) {
+ FF1(a,b,c,d,e,i++);
+ FF1(e,a,b,c,d,i++);
+ FF1(d,e,a,b,c,i++);
+ FF1(c,d,e,a,b,i++);
+ FF1(b,c,d,e,a,i++);
+ }
+
+ /* round three */
+ for (; i < 60; ) {
+ FF2(a,b,c,d,e,i++);
+ FF2(e,a,b,c,d,i++);
+ FF2(d,e,a,b,c,i++);
+ FF2(c,d,e,a,b,i++);
+ FF2(b,c,d,e,a,i++);
+ }
+
+ /* round four */
+ for (; i < 80; ) {
+ FF3(a,b,c,d,e,i++);
+ FF3(e,a,b,c,d,i++);
+ FF3(d,e,a,b,c,i++);
+ FF3(c,d,e,a,b,i++);
+ FF3(b,c,d,e,a,i++);
+ }
+#endif
+
+ #undef FF0
+ #undef FF1
+ #undef FF2
+ #undef FF3
+
+ /* store */
+ md->sha1.state[0] = md->sha1.state[0] + a;
+ md->sha1.state[1] = md->sha1.state[1] + b;
+ md->sha1.state[2] = md->sha1.state[2] + c;
+ md->sha1.state[3] = md->sha1.state[3] + d;
+ md->sha1.state[4] = md->sha1.state[4] + e;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_sha1_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_sha1_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 87);
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha1_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->sha1.state[0] = 0x67452301UL;
+ md->sha1.state[1] = 0xefcdab89UL;
+ md->sha1.state[2] = 0x98badcfeUL;
+ md->sha1.state[3] = 0x10325476UL;
+ md->sha1.state[4] = 0xc3d2e1f0UL;
+ md->sha1.curlen = 0;
+ md->sha1.length = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(sha1_process, s_sha1_compress, sha1, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (20 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha1_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha1.curlen >= sizeof(md->sha1.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* increase the length of the message */
+ md->sha1.length += md->sha1.curlen * 8;
+
+ /* append the '1' bit */
+ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->sha1.curlen > 56) {
+ while (md->sha1.curlen < 64) {
+ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
+ }
+ s_sha1_compress(md, md->sha1.buf);
+ md->sha1.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->sha1.curlen < 56) {
+ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64H(md->sha1.length, md->sha1.buf+56);
+ s_sha1_compress(md, md->sha1.buf);
+
+ /* copy output */
+ for (i = 0; i < 5; i++) {
+ STORE32H(md->sha1.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha1_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[20];
+ } tests[] = {
+ { "abc",
+ { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
+ 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
+ 0x9c, 0xd0, 0xd8, 0x9d }
+ },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
+ 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
+ 0xE5, 0x46, 0x70, 0xF1 }
+ }
+ };
+
+ int i;
+ unsigned char tmp[20];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ sha1_init(&md);
+ sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ sha1_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA1", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
diff --git a/Sources/libtomcrypt/hashes/sha2/sha224.c b/Sources/libtomcrypt/hashes/sha2/sha224.c
new file mode 100644
index 00000000..1e2f2955
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/sha2/sha224.c
@@ -0,0 +1,119 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**
+ @param sha224.c
+ LTC_SHA-224 new NIST standard based off of LTC_SHA-256 truncated to 224 bits (Tom St Denis)
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_SHA224) && defined(LTC_SHA256)
+
+const struct ltc_hash_descriptor sha224_desc =
+{
+ "sha224",
+ 10,
+ 28,
+ 64,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 4, },
+ 9,
+
+ &sha224_init,
+ &sha256_process,
+ &sha224_done,
+ &sha224_test,
+ NULL
+};
+
+/* init the sha256 er... sha224 state ;-) */
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha224_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+
+ md->sha256.curlen = 0;
+ md->sha256.length = 0;
+ md->sha256.state[0] = 0xc1059ed8UL;
+ md->sha256.state[1] = 0x367cd507UL;
+ md->sha256.state[2] = 0x3070dd17UL;
+ md->sha256.state[3] = 0xf70e5939UL;
+ md->sha256.state[4] = 0xffc00b31UL;
+ md->sha256.state[5] = 0x68581511UL;
+ md->sha256.state[6] = 0x64f98fa7UL;
+ md->sha256.state[7] = 0xbefa4fa4UL;
+ return CRYPT_OK;
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (28 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha224_done(hash_state * md, unsigned char *out)
+{
+ unsigned char buf[32];
+ int err;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ err = sha256_done(md, buf);
+ XMEMCPY(out, buf, 28);
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, sizeof(buf));
+#endif
+ return err;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha224_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[28];
+ } tests[] = {
+ { "abc",
+ { 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8,
+ 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2,
+ 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd,
+ 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 }
+ },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76,
+ 0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89,
+ 0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4,
+ 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 }
+ },
+ };
+
+ int i;
+ unsigned char tmp[28];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ sha224_init(&md);
+ sha224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ sha224_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA224", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif /* defined(LTC_SHA224) && defined(LTC_SHA256) */
+
diff --git a/Sources/libtomcrypt/hashes/sha2/sha256.c b/Sources/libtomcrypt/hashes/sha2/sha256.c
new file mode 100644
index 00000000..ff200680
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/sha2/sha256.c
@@ -0,0 +1,322 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file sha256.c
+ LTC_SHA256 by Tom St Denis
+*/
+
+#ifdef LTC_SHA256
+
+const struct ltc_hash_descriptor sha256_desc =
+{
+ "sha256",
+ 0,
+ 32,
+ 64,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 1, },
+ 9,
+
+ &sha256_init,
+ &sha256_process,
+ &sha256_done,
+ &sha256_test,
+ NULL
+};
+
+#ifdef LTC_SMALL_CODE
+/* the K array */
+static const ulong32 K[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+ 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+ 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+ 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+ 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+ 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+ 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+ 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+ 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+ 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+#endif
+
+/* Various logical functions */
+#define Ch(x,y,z) (z ^ (x & (y ^ z)))
+#define Maj(x,y,z) (((x | y) & z) | (x & y))
+#define S(x, n) RORc((x),(n))
+#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+
+/* compress 512-bits */
+#ifdef LTC_CLEAN_STACK
+static int ss_sha256_compress(hash_state * md, const unsigned char *buf)
+#else
+static int s_sha256_compress(hash_state * md, const unsigned char *buf)
+#endif
+{
+ ulong32 S[8], W[64], t0, t1;
+#ifdef LTC_SMALL_CODE
+ ulong32 t;
+#endif
+ int i;
+
+ /* copy state into S */
+ for (i = 0; i < 8; i++) {
+ S[i] = md->sha256.state[i];
+ }
+
+ /* copy the state into 512-bits into W[0..15] */
+ for (i = 0; i < 16; i++) {
+ LOAD32H(W[i], buf + (4*i));
+ }
+
+ /* fill W[16..63] */
+ for (i = 16; i < 64; i++) {
+ W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
+ }
+
+ /* Compress */
+#ifdef LTC_SMALL_CODE
+#define RND(a,b,c,d,e,f,g,h,i) \
+ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+ t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+ for (i = 0; i < 64; ++i) {
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);
+ t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
+ S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
+ }
+#else
+#define RND(a,b,c,d,e,f,g,h,i,ki) \
+ t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
+ t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
+#endif
+#undef RND
+
+ /* feedback */
+ for (i = 0; i < 8; i++) {
+ md->sha256.state[i] = md->sha256.state[i] + S[i];
+ }
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_sha256_compress(hash_state * md, const unsigned char *buf)
+{
+ int err;
+ err = ss_sha256_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 74);
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha256_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+
+ md->sha256.curlen = 0;
+ md->sha256.length = 0;
+ md->sha256.state[0] = 0x6A09E667UL;
+ md->sha256.state[1] = 0xBB67AE85UL;
+ md->sha256.state[2] = 0x3C6EF372UL;
+ md->sha256.state[3] = 0xA54FF53AUL;
+ md->sha256.state[4] = 0x510E527FUL;
+ md->sha256.state[5] = 0x9B05688CUL;
+ md->sha256.state[6] = 0x1F83D9ABUL;
+ md->sha256.state[7] = 0x5BE0CD19UL;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(sha256_process,s_sha256_compress, sha256, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (32 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha256_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* increase the length of the message */
+ md->sha256.length += md->sha256.curlen * 8;
+
+ /* append the '1' bit */
+ md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->sha256.curlen > 56) {
+ while (md->sha256.curlen < 64) {
+ md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
+ }
+ s_sha256_compress(md, md->sha256.buf);
+ md->sha256.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->sha256.curlen < 56) {
+ md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64H(md->sha256.length, md->sha256.buf+56);
+ s_sha256_compress(md, md->sha256.buf);
+
+ /* copy output */
+ for (i = 0; i < 8; i++) {
+ STORE32H(md->sha256.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha256_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[32];
+ } tests[] = {
+ { "abc",
+ { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
+ 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+ 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+ 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
+ },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
+ 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+ 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
+ 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
+ },
+ };
+
+ int i;
+ unsigned char tmp[32];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ sha256_init(&md);
+ sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ sha256_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA256", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
diff --git a/Sources/libtomcrypt/hashes/sha2/sha384.c b/Sources/libtomcrypt/hashes/sha2/sha384.c
new file mode 100644
index 00000000..cb3391aa
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/sha2/sha384.c
@@ -0,0 +1,124 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**
+ @param sha384.c
+ LTC_SHA384 hash included in sha512.c, Tom St Denis
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_SHA384) && defined(LTC_SHA512)
+
+const struct ltc_hash_descriptor sha384_desc =
+{
+ "sha384",
+ 4,
+ 48,
+ 128,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 2, },
+ 9,
+
+ &sha384_init,
+ &sha512_process,
+ &sha384_done,
+ &sha384_test,
+ NULL
+};
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha384_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+
+ md->sha512.curlen = 0;
+ md->sha512.length = 0;
+ md->sha512.state[0] = CONST64(0xcbbb9d5dc1059ed8);
+ md->sha512.state[1] = CONST64(0x629a292a367cd507);
+ md->sha512.state[2] = CONST64(0x9159015a3070dd17);
+ md->sha512.state[3] = CONST64(0x152fecd8f70e5939);
+ md->sha512.state[4] = CONST64(0x67332667ffc00b31);
+ md->sha512.state[5] = CONST64(0x8eb44a8768581511);
+ md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7);
+ md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4);
+ return CRYPT_OK;
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (48 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha384_done(hash_state * md, unsigned char *out)
+{
+ unsigned char buf[64];
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ sha512_done(md, buf);
+ XMEMCPY(out, buf, 48);
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, sizeof(buf));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha384_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[48];
+ } tests[] = {
+ { "abc",
+ { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
+ 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
+ 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
+ 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
+ 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
+ 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 }
+ },
+ { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
+ 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
+ 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
+ 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
+ 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
+ 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 }
+ },
+ };
+
+ int i;
+ unsigned char tmp[48];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ sha384_init(&md);
+ sha384_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ sha384_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA384", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */
diff --git a/Sources/libtomcrypt/hashes/sha2/sha512.c b/Sources/libtomcrypt/hashes/sha2/sha512.c
new file mode 100644
index 00000000..ef3a8c81
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/sha2/sha512.c
@@ -0,0 +1,303 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @param sha512.c
+ LTC_SHA512 by Tom St Denis
+*/
+
+#ifdef LTC_SHA512
+
+const struct ltc_hash_descriptor sha512_desc =
+{
+ "sha512",
+ 5,
+ 64,
+ 128,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 3, },
+ 9,
+
+ &sha512_init,
+ &sha512_process,
+ &sha512_done,
+ &sha512_test,
+ NULL
+};
+
+/* the K array */
+static const ulong64 K[80] = {
+CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
+CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
+CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
+CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
+CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
+CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
+CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
+CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
+CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
+CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
+CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
+CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
+CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
+CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
+CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
+CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
+CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
+CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
+CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
+CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
+CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
+CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
+CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
+CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
+CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
+CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
+CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
+CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
+CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
+CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
+CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
+CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
+CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
+CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
+CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
+CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
+CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
+CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
+CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
+CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
+};
+
+/* Various logical functions */
+#define Ch(x,y,z) (z ^ (x & (y ^ z)))
+#define Maj(x,y,z) (((x | y) & z) | (x & y))
+#define S(x, n) ROR64c(x, n)
+#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n))
+#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
+#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
+#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
+#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
+
+/* compress 1024-bits */
+#ifdef LTC_CLEAN_STACK
+static int ss_sha512_compress(hash_state * md, const unsigned char *buf)
+#else
+static int s_sha512_compress(hash_state * md, const unsigned char *buf)
+#endif
+{
+ ulong64 S[8], W[80], t0, t1;
+ int i;
+
+ /* copy state into S */
+ for (i = 0; i < 8; i++) {
+ S[i] = md->sha512.state[i];
+ }
+
+ /* copy the state into 1024-bits into W[0..15] */
+ for (i = 0; i < 16; i++) {
+ LOAD64H(W[i], buf + (8*i));
+ }
+
+ /* fill W[16..79] */
+ for (i = 16; i < 80; i++) {
+ W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
+ }
+
+ /* Compress */
+#ifdef LTC_SMALL_CODE
+ for (i = 0; i < 80; i++) {
+ t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
+ t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
+ S[7] = S[6];
+ S[6] = S[5];
+ S[5] = S[4];
+ S[4] = S[3] + t0;
+ S[3] = S[2];
+ S[2] = S[1];
+ S[1] = S[0];
+ S[0] = t0 + t1;
+ }
+#else
+#define RND(a,b,c,d,e,f,g,h,i) \
+ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+ t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+ for (i = 0; i < 80; i += 8) {
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
+ }
+#endif
+
+
+ /* feedback */
+ for (i = 0; i < 8; i++) {
+ md->sha512.state[i] = md->sha512.state[i] + S[i];
+ }
+
+ return CRYPT_OK;
+}
+
+/* compress 1024-bits */
+#ifdef LTC_CLEAN_STACK
+static int s_sha512_compress(hash_state * md, const unsigned char *buf)
+{
+ int err;
+ err = ss_sha512_compress(md, buf);
+ burn_stack(sizeof(ulong64) * 90 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha512_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->sha512.curlen = 0;
+ md->sha512.length = 0;
+ md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
+ md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
+ md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
+ md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
+ md->sha512.state[4] = CONST64(0x510e527fade682d1);
+ md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
+ md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
+ md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(sha512_process, s_sha512_compress, sha512, 128)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (64 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha512_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* increase the length of the message */
+ md->sha512.length += md->sha512.curlen * CONST64(8);
+
+ /* append the '1' bit */
+ md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 112 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->sha512.curlen > 112) {
+ while (md->sha512.curlen < 128) {
+ md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
+ }
+ s_sha512_compress(md, md->sha512.buf);
+ md->sha512.curlen = 0;
+ }
+
+ /* pad upto 120 bytes of zeroes
+ * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash
+ * > 2^64 bits of data... :-)
+ */
+ while (md->sha512.curlen < 120) {
+ md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64H(md->sha512.length, md->sha512.buf+120);
+ s_sha512_compress(md, md->sha512.buf);
+
+ /* copy output */
+ for (i = 0; i < 8; i++) {
+ STORE64H(md->sha512.state[i], out+(8*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha512_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[64];
+ } tests[] = {
+ { "abc",
+ { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
+ 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+ 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
+ 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+ 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
+ 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+ 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
+ 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
+ },
+ { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
+ 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
+ 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
+ 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
+ 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
+ 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
+ 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
+ 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
+ },
+ };
+
+ int i;
+ unsigned char tmp[64];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ sha512_init(&md);
+ sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ sha512_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
+
diff --git a/Sources/libtomcrypt/hashes/sha2/sha512_224.c b/Sources/libtomcrypt/hashes/sha2/sha512_224.c
new file mode 100644
index 00000000..861852e5
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/sha2/sha512_224.c
@@ -0,0 +1,120 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**
+ @param sha512_224.c
+ SHA512/224 hash included in sha512.c
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_SHA512_224) && defined(LTC_SHA512)
+
+const struct ltc_hash_descriptor sha512_224_desc =
+{
+ "sha512-224",
+ 15,
+ 28,
+ 128,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 5, },
+ 9,
+
+ &sha512_224_init,
+ &sha512_process,
+ &sha512_224_done,
+ &sha512_224_test,
+ NULL
+};
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha512_224_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+
+ md->sha512.curlen = 0;
+ md->sha512.length = 0;
+ md->sha512.state[0] = CONST64(0x8C3D37C819544DA2);
+ md->sha512.state[1] = CONST64(0x73E1996689DCD4D6);
+ md->sha512.state[2] = CONST64(0x1DFAB7AE32FF9C82);
+ md->sha512.state[3] = CONST64(0x679DD514582F9FCF);
+ md->sha512.state[4] = CONST64(0x0F6D2B697BD44DA8);
+ md->sha512.state[5] = CONST64(0x77E36F7304C48942);
+ md->sha512.state[6] = CONST64(0x3F9D85A86A1D36C8);
+ md->sha512.state[7] = CONST64(0x1112E6AD91D692A1);
+ return CRYPT_OK;
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (48 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha512_224_done(hash_state * md, unsigned char *out)
+{
+ unsigned char buf[64];
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ sha512_done(md, buf);
+ XMEMCPY(out, buf, 28);
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, sizeof(buf));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha512_224_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[28];
+ } tests[] = {
+ { "abc",
+ { 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54,
+ 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2,
+ 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4,
+ 0x3E, 0x89, 0x24, 0xAA }
+ },
+ { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ { 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23,
+ 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33,
+ 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72,
+ 0x68, 0x67, 0x4A, 0xF9 }
+ },
+ };
+
+ int i;
+ unsigned char tmp[28];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ sha512_224_init(&md);
+ sha512_224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ sha512_224_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-224", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */
diff --git a/Sources/libtomcrypt/hashes/sha2/sha512_256.c b/Sources/libtomcrypt/hashes/sha2/sha512_256.c
new file mode 100644
index 00000000..1f041541
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/sha2/sha512_256.c
@@ -0,0 +1,120 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**
+ @param sha512_256.c
+ SHA512/256 hash included in sha512.c
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_SHA512_256) && defined(LTC_SHA512)
+
+const struct ltc_hash_descriptor sha512_256_desc =
+{
+ "sha512-256",
+ 16,
+ 32,
+ 128,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 6, },
+ 9,
+
+ &sha512_256_init,
+ &sha512_process,
+ &sha512_256_done,
+ &sha512_256_test,
+ NULL
+};
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha512_256_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+
+ md->sha512.curlen = 0;
+ md->sha512.length = 0;
+ md->sha512.state[0] = CONST64(0x22312194FC2BF72C);
+ md->sha512.state[1] = CONST64(0x9F555FA3C84C64C2);
+ md->sha512.state[2] = CONST64(0x2393B86B6F53B151);
+ md->sha512.state[3] = CONST64(0x963877195940EABD);
+ md->sha512.state[4] = CONST64(0x96283EE2A88EFFE3);
+ md->sha512.state[5] = CONST64(0xBE5E1E2553863992);
+ md->sha512.state[6] = CONST64(0x2B0199FC2C85B8AA);
+ md->sha512.state[7] = CONST64(0x0EB72DDC81C52CA2);
+ return CRYPT_OK;
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (48 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha512_256_done(hash_state * md, unsigned char *out)
+{
+ unsigned char buf[64];
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ sha512_done(md, buf);
+ XMEMCPY(out, buf, 32);
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, sizeof(buf));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha512_256_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[32];
+ } tests[] = {
+ { "abc",
+ { 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9,
+ 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB,
+ 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46,
+ 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23 }
+ },
+ { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ { 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8,
+ 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE,
+ 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14,
+ 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A }
+ },
+ };
+
+ int i;
+ unsigned char tmp[32];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ sha512_256_init(&md);
+ sha512_256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ sha512_256_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-265", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */
diff --git a/Sources/libtomcrypt/hashes/sha3.c b/Sources/libtomcrypt/hashes/sha3.c
new file mode 100644
index 00000000..4758e342
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/sha3.c
@@ -0,0 +1,378 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* based on https://github.com/brainhub/SHA3IUF (public domain) */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SHA3
+
+const struct ltc_hash_descriptor sha3_224_desc =
+{
+ "sha3-224", /* name of hash */
+ 17, /* internal ID */
+ 28, /* Size of digest in octets */
+ 144, /* Input block size in octets */
+ { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */
+ 9, /* Length OID */
+ &sha3_224_init,
+ &sha3_process,
+ &sha3_done,
+ &sha3_224_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor sha3_256_desc =
+{
+ "sha3-256", /* name of hash */
+ 18, /* internal ID */
+ 32, /* Size of digest in octets */
+ 136, /* Input block size in octets */
+ { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */
+ 9, /* Length OID */
+ &sha3_256_init,
+ &sha3_process,
+ &sha3_done,
+ &sha3_256_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor sha3_384_desc =
+{
+ "sha3-384", /* name of hash */
+ 19, /* internal ID */
+ 48, /* Size of digest in octets */
+ 104, /* Input block size in octets */
+ { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */
+ 9, /* Length OID */
+ &sha3_384_init,
+ &sha3_process,
+ &sha3_done,
+ &sha3_384_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor sha3_512_desc =
+{
+ "sha3-512", /* name of hash */
+ 20, /* internal ID */
+ 64, /* Size of digest in octets */
+ 72, /* Input block size in octets */
+ { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */
+ 9, /* Length OID */
+ &sha3_512_init,
+ &sha3_process,
+ &sha3_done,
+ &sha3_512_test,
+ NULL
+};
+#endif
+
+#ifdef LTC_KECCAK
+const struct ltc_hash_descriptor keccak_224_desc =
+{
+ "keccak224", /* name of hash */
+ 29, /* internal ID */
+ 28, /* Size of digest in octets */
+ 144, /* Input block size in octets */
+ { 0 }, 0, /* no ASN.1 OID */
+ &sha3_224_init,
+ &sha3_process,
+ &keccak_done,
+ &keccak_224_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor keccak_256_desc =
+{
+ "keccak256", /* name of hash */
+ 30, /* internal ID */
+ 32, /* Size of digest in octets */
+ 136, /* Input block size in octets */
+ { 0 }, 0, /* no ASN.1 OID */
+ &sha3_256_init,
+ &sha3_process,
+ &keccak_done,
+ &keccak_256_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor keccak_384_desc =
+{
+ "keccak384", /* name of hash */
+ 31, /* internal ID */
+ 48, /* Size of digest in octets */
+ 104, /* Input block size in octets */
+ { 0 }, 0, /* no ASN.1 OID */
+ &sha3_384_init,
+ &sha3_process,
+ &keccak_done,
+ &keccak_384_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor keccak_512_desc =
+{
+ "keccak512", /* name of hash */
+ 32, /* internal ID */
+ 64, /* Size of digest in octets */
+ 72, /* Input block size in octets */
+ { 0 }, 0, /* no ASN.1 OID */
+ &sha3_512_init,
+ &sha3_process,
+ &keccak_done,
+ &keccak_512_test,
+ NULL
+};
+#endif
+
+#if defined(LTC_SHA3) || defined(LTC_KECCAK)
+
+#define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */
+#define SHA3_KECCAK_ROUNDS 24
+
+static const ulong64 s_keccakf_rndc[24] = {
+ CONST64(0x0000000000000001), CONST64(0x0000000000008082),
+ CONST64(0x800000000000808a), CONST64(0x8000000080008000),
+ CONST64(0x000000000000808b), CONST64(0x0000000080000001),
+ CONST64(0x8000000080008081), CONST64(0x8000000000008009),
+ CONST64(0x000000000000008a), CONST64(0x0000000000000088),
+ CONST64(0x0000000080008009), CONST64(0x000000008000000a),
+ CONST64(0x000000008000808b), CONST64(0x800000000000008b),
+ CONST64(0x8000000000008089), CONST64(0x8000000000008003),
+ CONST64(0x8000000000008002), CONST64(0x8000000000000080),
+ CONST64(0x000000000000800a), CONST64(0x800000008000000a),
+ CONST64(0x8000000080008081), CONST64(0x8000000000008080),
+ CONST64(0x0000000080000001), CONST64(0x8000000080008008)
+};
+
+static const unsigned s_keccakf_rotc[24] = {
+ 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
+};
+
+static const unsigned s_keccakf_piln[24] = {
+ 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
+};
+
+static void s_keccakf(ulong64 s[25])
+{
+ int i, j, round;
+ ulong64 t, bc[5];
+
+ for(round = 0; round < SHA3_KECCAK_ROUNDS; round++) {
+ /* Theta */
+ for(i = 0; i < 5; i++) {
+ bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
+ }
+ for(i = 0; i < 5; i++) {
+ t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1);
+ for(j = 0; j < 25; j += 5) {
+ s[j + i] ^= t;
+ }
+ }
+ /* Rho Pi */
+ t = s[1];
+ for(i = 0; i < 24; i++) {
+ j = s_keccakf_piln[i];
+ bc[0] = s[j];
+ s[j] = ROL64(t, s_keccakf_rotc[i]);
+ t = bc[0];
+ }
+ /* Chi */
+ for(j = 0; j < 25; j += 5) {
+ for(i = 0; i < 5; i++) {
+ bc[i] = s[j + i];
+ }
+ for(i = 0; i < 5; i++) {
+ s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
+ }
+ }
+ /* Iota */
+ s[0] ^= s_keccakf_rndc[round];
+ }
+}
+
+static LTC_INLINE int ss_done(hash_state *md, unsigned char *hash, ulong64 pad)
+{
+ unsigned i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(hash != NULL);
+
+ md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (pad << (md->sha3.byte_index * 8)));
+ md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
+ s_keccakf(md->sha3.s);
+
+ /* store sha3.s[] as little-endian bytes into sha3.sb */
+ for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
+ STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
+ }
+
+ XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4);
+ return CRYPT_OK;
+}
+
+/* Public Inteface */
+
+int sha3_224_init(hash_state *md)
+{
+ LTC_ARGCHK(md != NULL);
+ XMEMSET(&md->sha3, 0, sizeof(md->sha3));
+ md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64));
+ return CRYPT_OK;
+}
+
+int sha3_256_init(hash_state *md)
+{
+ LTC_ARGCHK(md != NULL);
+ XMEMSET(&md->sha3, 0, sizeof(md->sha3));
+ md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64));
+ return CRYPT_OK;
+}
+
+int sha3_384_init(hash_state *md)
+{
+ LTC_ARGCHK(md != NULL);
+ XMEMSET(&md->sha3, 0, sizeof(md->sha3));
+ md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64));
+ return CRYPT_OK;
+}
+
+int sha3_512_init(hash_state *md)
+{
+ LTC_ARGCHK(md != NULL);
+ XMEMSET(&md->sha3, 0, sizeof(md->sha3));
+ md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64));
+ return CRYPT_OK;
+}
+
+#ifdef LTC_SHA3
+int sha3_shake_init(hash_state *md, int num)
+{
+ LTC_ARGCHK(md != NULL);
+ if (num != 128 && num != 256) return CRYPT_INVALID_ARG;
+ XMEMSET(&md->sha3, 0, sizeof(md->sha3));
+ md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64)));
+ return CRYPT_OK;
+}
+#endif
+
+int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen)
+{
+ /* 0...7 -- how much is needed to have a word */
+ unsigned old_tail = (8 - md->sha3.byte_index) & 7;
+
+ unsigned long words;
+ unsigned tail;
+ unsigned long i;
+
+ if (inlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ if(inlen < old_tail) { /* have no complete word or haven't started the word yet */
+ while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
+ return CRYPT_OK;
+ }
+
+ if(old_tail) { /* will have one word to process */
+ inlen -= old_tail;
+ while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
+ /* now ready to add saved to the sponge */
+ md->sha3.s[md->sha3.word_index] ^= md->sha3.saved;
+ md->sha3.byte_index = 0;
+ md->sha3.saved = 0;
+ if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
+ s_keccakf(md->sha3.s);
+ md->sha3.word_index = 0;
+ }
+ }
+
+ /* now work in full words directly from input */
+ words = inlen / sizeof(ulong64);
+ tail = inlen - words * sizeof(ulong64);
+
+ for(i = 0; i < words; i++, in += sizeof(ulong64)) {
+ ulong64 t;
+ LOAD64L(t, in);
+ md->sha3.s[md->sha3.word_index] ^= t;
+ if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
+ s_keccakf(md->sha3.s);
+ md->sha3.word_index = 0;
+ }
+ }
+
+ /* finally, save the partial word */
+ while (tail--) {
+ md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
+ }
+ return CRYPT_OK;
+}
+
+#ifdef LTC_SHA3
+int sha3_done(hash_state *md, unsigned char *out)
+{
+ return ss_done(md, out, CONST64(0x06));
+}
+#endif
+
+#ifdef LTC_KECCAK
+int keccak_done(hash_state *md, unsigned char *out)
+{
+ return ss_done(md, out, CONST64(0x01));
+}
+#endif
+
+#ifdef LTC_SHA3
+int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen)
+{
+ /* IMPORTANT NOTE: sha3_shake_done can be called many times */
+ unsigned long idx;
+ unsigned i;
+
+ if (outlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (!md->sha3.xof_flag) {
+ /* shake_xof operation must be done only once */
+ md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8)));
+ md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
+ s_keccakf(md->sha3.s);
+ /* store sha3.s[] as little-endian bytes into sha3.sb */
+ for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
+ STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
+ }
+ md->sha3.byte_index = 0;
+ md->sha3.xof_flag = 1;
+ }
+
+ for (idx = 0; idx < outlen; idx++) {
+ if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) {
+ s_keccakf(md->sha3.s);
+ /* store sha3.s[] as little-endian bytes into sha3.sb */
+ for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
+ STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
+ }
+ md->sha3.byte_index = 0;
+ }
+ out[idx] = md->sha3.sb[md->sha3.byte_index++];
+ }
+ return CRYPT_OK;
+}
+
+int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen)
+{
+ hash_state md;
+ int err;
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ if ((err = sha3_shake_init(&md, num)) != CRYPT_OK) return err;
+ if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err;
+ if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err;
+ return CRYPT_OK;
+}
+#endif
+
+#endif
diff --git a/Sources/libtomcrypt/hashes/sha3_test.c b/Sources/libtomcrypt/hashes/sha3_test.c
new file mode 100644
index 00000000..95fcfcbb
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/sha3_test.c
@@ -0,0 +1,719 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* based on https://github.com/brainhub/SHA3IUF (public domain) */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SHA3
+
+int sha3_224_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ unsigned char buf[200], hash[224 / 8];
+ int i;
+ hash_state c;
+ const unsigned char c1 = 0xa3;
+
+ const unsigned char sha3_224_empty[224 / 8] = {
+ 0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7,
+ 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab,
+ 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f,
+ 0x5b, 0x5a, 0x6b, 0xc7
+ };
+
+ const unsigned char sha3_224_0xa3_200_times[224 / 8] = {
+ 0x93, 0x76, 0x81, 0x6a, 0xba, 0x50, 0x3f, 0x72,
+ 0xf9, 0x6c, 0xe7, 0xeb, 0x65, 0xac, 0x09, 0x5d,
+ 0xee, 0xe3, 0xbe, 0x4b, 0xf9, 0xbb, 0xc2, 0xa1,
+ 0xcb, 0x7e, 0x11, 0xe0
+ };
+
+ XMEMSET(buf, c1, sizeof(buf));
+
+ /* SHA3-224 on an empty buffer */
+ sha3_224_init(&c);
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_224_empty, sizeof(sha3_224_empty), "SHA3-224", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-224 in two steps. [FIPS 202] */
+ sha3_224_init(&c);
+ sha3_process(&c, buf, sizeof(buf) / 2);
+ sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2);
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 1)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-224 byte-by-byte: 200 steps. [FIPS 202] */
+ i = 200;
+ sha3_224_init(&c);
+ while (i--) {
+ sha3_process(&c, &c1, 1);
+ }
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 2)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int sha3_256_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ unsigned char buf[200], hash[256 / 8];
+ int i;
+ hash_state c;
+ const unsigned char c1 = 0xa3;
+
+ const unsigned char sha3_256_empty[256 / 8] = {
+ 0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66,
+ 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62,
+ 0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa,
+ 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a
+ };
+ const unsigned char sha3_256_0xa3_200_times[256 / 8] = {
+ 0x79, 0xf3, 0x8a, 0xde, 0xc5, 0xc2, 0x03, 0x07,
+ 0xa9, 0x8e, 0xf7, 0x6e, 0x83, 0x24, 0xaf, 0xbf,
+ 0xd4, 0x6c, 0xfd, 0x81, 0xb2, 0x2e, 0x39, 0x73,
+ 0xc6, 0x5f, 0xa1, 0xbd, 0x9d, 0xe3, 0x17, 0x87
+ };
+
+ XMEMSET(buf, c1, sizeof(buf));
+
+ /* SHA3-256 on an empty buffer */
+ sha3_256_init(&c);
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_256_empty, sizeof(sha3_256_empty), "SHA3-256", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-256 as a single buffer. [FIPS 202] */
+ sha3_256_init(&c);
+ sha3_process(&c, buf, sizeof(buf));
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 1)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-256 in two steps. [FIPS 202] */
+ sha3_256_init(&c);
+ sha3_process(&c, buf, sizeof(buf) / 2);
+ sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2);
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 2)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-256 byte-by-byte: 200 steps. [FIPS 202] */
+ i = 200;
+ sha3_256_init(&c);
+ while (i--) {
+ sha3_process(&c, &c1, 1);
+ }
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 3)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-256 byte-by-byte: 135 bytes. Input from [Keccak]. Output
+ * matched with sha3sum. */
+ sha3_256_init(&c);
+ sha3_process(&c, (unsigned char*)
+ "\xb7\x71\xd5\xce\xf5\xd1\xa4\x1a"
+ "\x93\xd1\x56\x43\xd7\x18\x1d\x2a"
+ "\x2e\xf0\xa8\xe8\x4d\x91\x81\x2f"
+ "\x20\xed\x21\xf1\x47\xbe\xf7\x32"
+ "\xbf\x3a\x60\xef\x40\x67\xc3\x73"
+ "\x4b\x85\xbc\x8c\xd4\x71\x78\x0f"
+ "\x10\xdc\x9e\x82\x91\xb5\x83\x39"
+ "\xa6\x77\xb9\x60\x21\x8f\x71\xe7"
+ "\x93\xf2\x79\x7a\xea\x34\x94\x06"
+ "\x51\x28\x29\x06\x5d\x37\xbb\x55"
+ "\xea\x79\x6f\xa4\xf5\x6f\xd8\x89"
+ "\x6b\x49\xb2\xcd\x19\xb4\x32\x15"
+ "\xad\x96\x7c\x71\x2b\x24\xe5\x03"
+ "\x2d\x06\x52\x32\xe0\x2c\x12\x74"
+ "\x09\xd2\xed\x41\x46\xb9\xd7\x5d"
+ "\x76\x3d\x52\xdb\x98\xd9\x49\xd3"
+ "\xb0\xfe\xd6\xa8\x05\x2f\xbb", 1080 / 8);
+ sha3_done(&c, hash);
+ if(compare_testvector(hash, sizeof(hash),
+ "\xa1\x9e\xee\x92\xbb\x20\x97\xb6"
+ "\x4e\x82\x3d\x59\x77\x98\xaa\x18"
+ "\xbe\x9b\x7c\x73\x6b\x80\x59\xab"
+ "\xfd\x67\x79\xac\x35\xac\x81\xb5", 256 / 8, "SHA3-256", 4)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int sha3_384_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ unsigned char buf[200], hash[384 / 8];
+ int i;
+ hash_state c;
+ const unsigned char c1 = 0xa3;
+
+ const unsigned char sha3_384_0xa3_200_times[384 / 8] = {
+ 0x18, 0x81, 0xde, 0x2c, 0xa7, 0xe4, 0x1e, 0xf9,
+ 0x5d, 0xc4, 0x73, 0x2b, 0x8f, 0x5f, 0x00, 0x2b,
+ 0x18, 0x9c, 0xc1, 0xe4, 0x2b, 0x74, 0x16, 0x8e,
+ 0xd1, 0x73, 0x26, 0x49, 0xce, 0x1d, 0xbc, 0xdd,
+ 0x76, 0x19, 0x7a, 0x31, 0xfd, 0x55, 0xee, 0x98,
+ 0x9f, 0x2d, 0x70, 0x50, 0xdd, 0x47, 0x3e, 0x8f
+ };
+
+ XMEMSET(buf, c1, sizeof(buf));
+
+ /* SHA3-384 as a single buffer. [FIPS 202] */
+ sha3_384_init(&c);
+ sha3_process(&c, buf, sizeof(buf));
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-384 in two steps. [FIPS 202] */
+ sha3_384_init(&c);
+ sha3_process(&c, buf, sizeof(buf) / 2);
+ sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2);
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 1)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-384 byte-by-byte: 200 steps. [FIPS 202] */
+ i = 200;
+ sha3_384_init(&c);
+ while (i--) {
+ sha3_process(&c, &c1, 1);
+ }
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 2)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int sha3_512_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ unsigned char buf[200], hash[512 / 8];
+ int i;
+ hash_state c;
+ const unsigned char c1 = 0xa3;
+
+ const unsigned char sha3_512_0xa3_200_times[512 / 8] = {
+ 0xe7, 0x6d, 0xfa, 0xd2, 0x20, 0x84, 0xa8, 0xb1,
+ 0x46, 0x7f, 0xcf, 0x2f, 0xfa, 0x58, 0x36, 0x1b,
+ 0xec, 0x76, 0x28, 0xed, 0xf5, 0xf3, 0xfd, 0xc0,
+ 0xe4, 0x80, 0x5d, 0xc4, 0x8c, 0xae, 0xec, 0xa8,
+ 0x1b, 0x7c, 0x13, 0xc3, 0x0a, 0xdf, 0x52, 0xa3,
+ 0x65, 0x95, 0x84, 0x73, 0x9a, 0x2d, 0xf4, 0x6b,
+ 0xe5, 0x89, 0xc5, 0x1c, 0xa1, 0xa4, 0xa8, 0x41,
+ 0x6d, 0xf6, 0x54, 0x5a, 0x1c, 0xe8, 0xba, 0x00
+ };
+
+ XMEMSET(buf, c1, sizeof(buf));
+
+ /* SHA3-512 as a single buffer. [FIPS 202] */
+ sha3_512_init(&c);
+ sha3_process(&c, buf, sizeof(buf));
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-512 in two steps. [FIPS 202] */
+ sha3_512_init(&c);
+ sha3_process(&c, buf, sizeof(buf) / 2);
+ sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2);
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 1)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHA3-512 byte-by-byte: 200 steps. [FIPS 202] */
+ i = 200;
+ sha3_512_init(&c);
+ while (i--) {
+ sha3_process(&c, &c1, 1);
+ }
+ sha3_done(&c, hash);
+ if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 2)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int sha3_shake_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ unsigned char buf[200], hash[512];
+ int i;
+ hash_state c;
+ const unsigned char c1 = 0xa3;
+ unsigned long len;
+
+ const unsigned char shake256_empty[32] = {
+ 0xab, 0x0b, 0xae, 0x31, 0x63, 0x39, 0x89, 0x43,
+ 0x04, 0xe3, 0x58, 0x77, 0xb0, 0xc2, 0x8a, 0x9b,
+ 0x1f, 0xd1, 0x66, 0xc7, 0x96, 0xb9, 0xcc, 0x25,
+ 0x8a, 0x06, 0x4a, 0x8f, 0x57, 0xe2, 0x7f, 0x2a
+ };
+ const unsigned char shake256_0xa3_200_times[32] = {
+ 0x6a, 0x1a, 0x9d, 0x78, 0x46, 0x43, 0x6e, 0x4d,
+ 0xca, 0x57, 0x28, 0xb6, 0xf7, 0x60, 0xee, 0xf0,
+ 0xca, 0x92, 0xbf, 0x0b, 0xe5, 0x61, 0x5e, 0x96,
+ 0x95, 0x9d, 0x76, 0x71, 0x97, 0xa0, 0xbe, 0xeb
+ };
+ const unsigned char shake128_empty[32] = {
+ 0x43, 0xe4, 0x1b, 0x45, 0xa6, 0x53, 0xf2, 0xa5,
+ 0xc4, 0x49, 0x2c, 0x1a, 0xdd, 0x54, 0x45, 0x12,
+ 0xdd, 0xa2, 0x52, 0x98, 0x33, 0x46, 0x2b, 0x71,
+ 0xa4, 0x1a, 0x45, 0xbe, 0x97, 0x29, 0x0b, 0x6f
+ };
+ const unsigned char shake128_0xa3_200_times[32] = {
+ 0x44, 0xc9, 0xfb, 0x35, 0x9f, 0xd5, 0x6a, 0xc0,
+ 0xa9, 0xa7, 0x5a, 0x74, 0x3c, 0xff, 0x68, 0x62,
+ 0xf1, 0x7d, 0x72, 0x59, 0xab, 0x07, 0x52, 0x16,
+ 0xc0, 0x69, 0x95, 0x11, 0x64, 0x3b, 0x64, 0x39
+ };
+
+ XMEMSET(buf, c1, sizeof(buf));
+
+ /* SHAKE256 on an empty buffer */
+ sha3_shake_init(&c, 256);
+ for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */
+ if (compare_testvector(hash, sizeof(shake256_empty), shake256_empty, sizeof(shake256_empty), "SHAKE256", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHAKE256 via sha3_shake_memory [FIPS 202] */
+ len = 512;
+ sha3_shake_memory(256, buf, sizeof(buf), hash, &len);
+ if (compare_testvector(hash + 480, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 1)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHAKE256 as a single buffer. [FIPS 202] */
+ sha3_shake_init(&c, 256);
+ sha3_shake_process(&c, buf, sizeof(buf));
+ for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */
+ if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 2)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHAKE256 in two steps. [FIPS 202] */
+ sha3_shake_init(&c, 256);
+ sha3_shake_process(&c, buf, sizeof(buf) / 2);
+ sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2);
+ for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */
+ if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 3)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHAKE256 byte-by-byte: 200 steps. [FIPS 202] */
+ i = 200;
+ sha3_shake_init(&c, 256);
+ while (i--) sha3_shake_process(&c, &c1, 1);
+ for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */
+ if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 4)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHAKE128 on an empty buffer */
+ sha3_shake_init(&c, 128);
+ for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */
+ if (compare_testvector(hash, sizeof(shake128_empty), shake128_empty, sizeof(shake128_empty), "SHAKE128", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHAKE128 via sha3_shake_memory [FIPS 202] */
+ len = 512;
+ sha3_shake_memory(128, buf, sizeof(buf), hash, &len);
+ if (compare_testvector(hash + 480, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 1)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHAKE128 as a single buffer. [FIPS 202] */
+ sha3_shake_init(&c, 128);
+ sha3_shake_process(&c, buf, sizeof(buf));
+ for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */
+ if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 2)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHAKE128 in two steps. [FIPS 202] */
+ sha3_shake_init(&c, 128);
+ sha3_shake_process(&c, buf, sizeof(buf) / 2);
+ sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2);
+ for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */
+ if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 3)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* SHAKE128 byte-by-byte: 200 steps. [FIPS 202] */
+ i = 200;
+ sha3_shake_init(&c, 128);
+ while (i--) sha3_shake_process(&c, &c1, 1);
+ for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */
+ if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 4)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
+#ifdef LTC_KECCAK
+
+int keccak_224_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ hash_state c;
+ unsigned char hash[MAXBLOCKSIZE];
+
+ keccak_224_init(&c);
+ keccak_process(&c, (unsigned char*) "\xcc", 1);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 28,
+ "\xa9\xca\xb5\x9e\xb4\x0a\x10\xb2"
+ "\x46\x29\x0f\x2d\x60\x86\xe3\x2e"
+ "\x36\x89\xfa\xf1\xd2\x6b\x47\x0c"
+ "\x89\x9f\x28\x02", 28,
+ "KECCAK-224", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_224_init(&c);
+ keccak_process(&c, (unsigned char*)"\x41\xfb", 2);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 28,
+ "\x61\x5b\xa3\x67\xaf\xdc\x35\xaa"
+ "\xc3\x97\xbc\x7e\xb5\xd5\x8d\x10"
+ "\x6a\x73\x4b\x24\x98\x6d\x5d\x97"
+ "\x8f\xef\xd6\x2c", 28,
+ "KECCAK-224", 1) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_224_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x52\xa6\x08\xab\x21\xcc\xdd\x8a"
+ "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 28,
+ "\x56\x79\xcd\x50\x9c\x51\x20\xaf"
+ "\x54\x79\x5c\xf4\x77\x14\x96\x41"
+ "\xcf\x27\xb2\xeb\xb6\xa5\xf9\x03"
+ "\x40\x70\x4e\x57", 28,
+ "KECCAK-224", 2) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_224_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x43\x3c\x53\x03\x13\x16\x24\xc0"
+ "\x02\x1d\x86\x8a\x30\x82\x54\x75"
+ "\xe8\xd0\xbd\x30\x52\xa0\x22\x18"
+ "\x03\x98\xf4\xca\x44\x23\xb9\x82"
+ "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07"
+ "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0"
+ "\x92\xcc\x1b\x06\xce\xdf\x32\x24"
+ "\xd5\xed\x1e\xc2\x97\x84\x44\x4f"
+ "\x22\xe0\x8a\x55\xaa\x58\x54\x2b"
+ "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69"
+ "\x07\xaf\xe7\x1c\x5d\x74\x62\x22"
+ "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84"
+ "\x6d\xcb\xb4\xce", 100);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 28,
+ "\x62\xb1\x0f\x1b\x62\x36\xeb\xc2"
+ "\xda\x72\x95\x77\x42\xa8\xd4\xe4"
+ "\x8e\x21\x3b\x5f\x89\x34\x60\x4b"
+ "\xfd\x4d\x2c\x3a", 28,
+ "KECCAK-224", 3) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int keccak_256_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ hash_state c;
+ unsigned char hash[MAXBLOCKSIZE];
+
+ keccak_256_init(&c);
+ keccak_process(&c, (unsigned char*) "\xcc", 1);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 32,
+ "\xee\xad\x6d\xbf\xc7\x34\x0a\x56"
+ "\xca\xed\xc0\x44\x69\x6a\x16\x88"
+ "\x70\x54\x9a\x6a\x7f\x6f\x56\x96"
+ "\x1e\x84\xa5\x4b\xd9\x97\x0b\x8a", 32,
+ "KECCAK-256", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_256_init(&c);
+ keccak_process(&c, (unsigned char*)"\x41\xfb", 2);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 32,
+ "\xa8\xea\xce\xda\x4d\x47\xb3\x28"
+ "\x1a\x79\x5a\xd9\xe1\xea\x21\x22"
+ "\xb4\x07\xba\xf9\xaa\xbc\xb9\xe1"
+ "\x8b\x57\x17\xb7\x87\x35\x37\xd2", 32,
+ "KECCAK-256", 1) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_256_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x52\xa6\x08\xab\x21\xcc\xdd\x8a"
+ "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 32,
+ "\x0e\x32\xde\xfa\x20\x71\xf0\xb5"
+ "\xac\x0e\x6a\x10\x8b\x84\x2e\xd0"
+ "\xf1\xd3\x24\x97\x12\xf5\x8e\xe0"
+ "\xdd\xf9\x56\xfe\x33\x2a\x5f\x95", 32,
+ "KECCAK-256", 2) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_256_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x43\x3c\x53\x03\x13\x16\x24\xc0"
+ "\x02\x1d\x86\x8a\x30\x82\x54\x75"
+ "\xe8\xd0\xbd\x30\x52\xa0\x22\x18"
+ "\x03\x98\xf4\xca\x44\x23\xb9\x82"
+ "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07"
+ "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0"
+ "\x92\xcc\x1b\x06\xce\xdf\x32\x24"
+ "\xd5\xed\x1e\xc2\x97\x84\x44\x4f"
+ "\x22\xe0\x8a\x55\xaa\x58\x54\x2b"
+ "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69"
+ "\x07\xaf\xe7\x1c\x5d\x74\x62\x22"
+ "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84"
+ "\x6d\xcb\xb4\xce", 100);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 32,
+ "\xce\x87\xa5\x17\x3b\xff\xd9\x23"
+ "\x99\x22\x16\x58\xf8\x01\xd4\x5c"
+ "\x29\x4d\x90\x06\xee\x9f\x3f\x9d"
+ "\x41\x9c\x8d\x42\x77\x48\xdc\x41", 32,
+ "KECCAK-256", 3) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int keccak_384_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ hash_state c;
+ unsigned char hash[MAXBLOCKSIZE];
+
+ keccak_384_init(&c);
+ keccak_process(&c, (unsigned char*) "\xcc", 1);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 48,
+ "\x1b\x84\xe6\x2a\x46\xe5\xa2\x01"
+ "\x86\x17\x54\xaf\x5d\xc9\x5c\x4a"
+ "\x1a\x69\xca\xf4\xa7\x96\xae\x40"
+ "\x56\x80\x16\x1e\x29\x57\x26\x41"
+ "\xf5\xfa\x1e\x86\x41\xd7\x95\x83"
+ "\x36\xee\x7b\x11\xc5\x8f\x73\xe9", 48,
+ "KECCAK-384", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_384_init(&c);
+ keccak_process(&c, (unsigned char*)"\x41\xfb", 2);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 48,
+ "\x49\x5c\xce\x27\x14\xcd\x72\xc8"
+ "\xc5\x3c\x33\x63\xd2\x2c\x58\xb5"
+ "\x59\x60\xfe\x26\xbe\x0b\xf3\xbb"
+ "\xc7\xa3\x31\x6d\xd5\x63\xad\x1d"
+ "\xb8\x41\x0e\x75\xee\xfe\xa6\x55"
+ "\xe3\x9d\x46\x70\xec\x0b\x17\x92", 48,
+ "KECCAK-384", 1) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_384_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x52\xa6\x08\xab\x21\xcc\xdd\x8a"
+ "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 48,
+ "\x18\x42\x2a\xc1\xd3\xa1\xe5\x4b"
+ "\xad\x87\x68\x83\xd2\xd6\xdd\x65"
+ "\xf6\x5c\x1d\x5f\x33\xa7\x12\x5c"
+ "\xc4\xc1\x86\x40\x5a\x12\xed\x64"
+ "\xba\x96\x67\x2e\xed\xda\x8c\x5a"
+ "\x63\x31\xd2\x86\x83\xf4\x88\xeb", 48,
+ "KECCAK-384", 2) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_384_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x43\x3c\x53\x03\x13\x16\x24\xc0"
+ "\x02\x1d\x86\x8a\x30\x82\x54\x75"
+ "\xe8\xd0\xbd\x30\x52\xa0\x22\x18"
+ "\x03\x98\xf4\xca\x44\x23\xb9\x82"
+ "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07"
+ "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0"
+ "\x92\xcc\x1b\x06\xce\xdf\x32\x24"
+ "\xd5\xed\x1e\xc2\x97\x84\x44\x4f"
+ "\x22\xe0\x8a\x55\xaa\x58\x54\x2b"
+ "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69"
+ "\x07\xaf\xe7\x1c\x5d\x74\x62\x22"
+ "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84"
+ "\x6d\xcb\xb4\xce", 100);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 48,
+ "\x13\x51\x14\x50\x8d\xd6\x3e\x27"
+ "\x9e\x70\x9c\x26\xf7\x81\x7c\x04"
+ "\x82\x76\x6c\xde\x49\x13\x2e\x3e"
+ "\xdf\x2e\xed\xd8\x99\x6f\x4e\x35"
+ "\x96\xd1\x84\x10\x0b\x38\x48\x68"
+ "\x24\x9f\x1d\x8b\x8f\xda\xa2\xc9", 48,
+ "KECCAK-384", 3) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int keccak_512_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ hash_state c;
+ unsigned char hash[MAXBLOCKSIZE];
+
+ keccak_512_init(&c);
+ keccak_process(&c, (unsigned char*) "\xcc", 1);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 64,
+ "\x86\x30\xc1\x3c\xbd\x06\x6e\xa7"
+ "\x4b\xbe\x7f\xe4\x68\xfe\xc1\xde"
+ "\xe1\x0e\xdc\x12\x54\xfb\x4c\x1b"
+ "\x7c\x5f\xd6\x9b\x64\x6e\x44\x16"
+ "\x0b\x8c\xe0\x1d\x05\xa0\x90\x8c"
+ "\xa7\x90\xdf\xb0\x80\xf4\xb5\x13"
+ "\xbc\x3b\x62\x25\xec\xe7\xa8\x10"
+ "\x37\x14\x41\xa5\xac\x66\x6e\xb9", 64,
+ "KECCAK-512", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_512_init(&c);
+ keccak_process(&c, (unsigned char*)"\x41\xfb", 2);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 64,
+ "\x55\x1d\xa6\x23\x6f\x8b\x96\xfc"
+ "\xe9\xf9\x7f\x11\x90\xe9\x01\x32"
+ "\x4f\x0b\x45\xe0\x6d\xbb\xb5\xcd"
+ "\xb8\x35\x5d\x6e\xd1\xdc\x34\xb3"
+ "\xf0\xea\xe7\xdc\xb6\x86\x22\xff"
+ "\x23\x2f\xa3\xce\xce\x0d\x46\x16"
+ "\xcd\xeb\x39\x31\xf9\x38\x03\x66"
+ "\x2a\x28\xdf\x1c\xd5\x35\xb7\x31", 64,
+ "KECCAK-512", 1) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_512_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x52\xa6\x08\xab\x21\xcc\xdd\x8a"
+ "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 64,
+ "\x4b\x39\xd3\xda\x5b\xcd\xf4\xd9"
+ "\xb7\x69\x01\x59\x95\x64\x43\x11"
+ "\xc1\x4c\x43\x5b\xf7\x2b\x10\x09"
+ "\xd6\xdd\x71\xb0\x1a\x63\xb9\x7c"
+ "\xfb\x59\x64\x18\xe8\xe4\x23\x42"
+ "\xd1\x17\xe0\x74\x71\xa8\x91\x43"
+ "\x14\xba\x7b\x0e\x26\x4d\xad\xf0"
+ "\xce\xa3\x81\x86\x8c\xbd\x43\xd1", 64,
+ "KECCAK-512", 2) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_512_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x43\x3c\x53\x03\x13\x16\x24\xc0"
+ "\x02\x1d\x86\x8a\x30\x82\x54\x75"
+ "\xe8\xd0\xbd\x30\x52\xa0\x22\x18"
+ "\x03\x98\xf4\xca\x44\x23\xb9\x82"
+ "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07"
+ "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0"
+ "\x92\xcc\x1b\x06\xce\xdf\x32\x24"
+ "\xd5\xed\x1e\xc2\x97\x84\x44\x4f"
+ "\x22\xe0\x8a\x55\xaa\x58\x54\x2b"
+ "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69"
+ "\x07\xaf\xe7\x1c\x5d\x74\x62\x22"
+ "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84"
+ "\x6d\xcb\xb4\xce", 100);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 64,
+ "\x52\x7d\x28\xe3\x41\xe6\xb1\x4f"
+ "\x46\x84\xad\xb4\xb8\x24\xc4\x96"
+ "\xc6\x48\x2e\x51\x14\x95\x65\xd3"
+ "\xd1\x72\x26\x82\x88\x84\x30\x6b"
+ "\x51\xd6\x14\x8a\x72\x62\x2c\x2b"
+ "\x75\xf5\xd3\x51\x0b\x79\x9d\x8b"
+ "\xdc\x03\xea\xed\xe4\x53\x67\x6a"
+ "\x6e\xc8\xfe\x03\xa1\xad\x0e\xab", 64,
+ "KECCAK-512", 3) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/hashes/tiger.c b/Sources/libtomcrypt/hashes/tiger.c
new file mode 100644
index 00000000..8d48ded3
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/tiger.c
@@ -0,0 +1,915 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file tiger.c
+ Tiger hash function, Tom St Denis
+*/
+
+#ifdef LTC_TIGER
+
+const struct ltc_hash_descriptor tiger_desc =
+{
+ "tiger",
+ 1,
+ 24,
+ 64,
+
+ /* OID */
+ { 1, 3, 6, 1, 4, 1, 11591, 12, 2, },
+ 9,
+
+ &tiger_init,
+ &tiger_process,
+ &tiger_done,
+ &tiger_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor tiger2_desc =
+{
+ "tiger2",
+ 33,
+ 24,
+ 64,
+
+ /* OID ... does not exist */
+ { 0 },
+ 0,
+
+ &tiger2_init,
+ &tiger_process,
+ &tiger_done,
+ &tiger2_test,
+ NULL
+};
+
+#define t1 (table)
+#define t2 (table+256)
+#define t3 (table+256*2)
+#define t4 (table+256*3)
+
+static const ulong64 table[4*256] = {
+ CONST64(0x02AAB17CF7E90C5E) /* 0 */, CONST64(0xAC424B03E243A8EC) /* 1 */,
+ CONST64(0x72CD5BE30DD5FCD3) /* 2 */, CONST64(0x6D019B93F6F97F3A) /* 3 */,
+ CONST64(0xCD9978FFD21F9193) /* 4 */, CONST64(0x7573A1C9708029E2) /* 5 */,
+ CONST64(0xB164326B922A83C3) /* 6 */, CONST64(0x46883EEE04915870) /* 7 */,
+ CONST64(0xEAACE3057103ECE6) /* 8 */, CONST64(0xC54169B808A3535C) /* 9 */,
+ CONST64(0x4CE754918DDEC47C) /* 10 */, CONST64(0x0AA2F4DFDC0DF40C) /* 11 */,
+ CONST64(0x10B76F18A74DBEFA) /* 12 */, CONST64(0xC6CCB6235AD1AB6A) /* 13 */,
+ CONST64(0x13726121572FE2FF) /* 14 */, CONST64(0x1A488C6F199D921E) /* 15 */,
+ CONST64(0x4BC9F9F4DA0007CA) /* 16 */, CONST64(0x26F5E6F6E85241C7) /* 17 */,
+ CONST64(0x859079DBEA5947B6) /* 18 */, CONST64(0x4F1885C5C99E8C92) /* 19 */,
+ CONST64(0xD78E761EA96F864B) /* 20 */, CONST64(0x8E36428C52B5C17D) /* 21 */,
+ CONST64(0x69CF6827373063C1) /* 22 */, CONST64(0xB607C93D9BB4C56E) /* 23 */,
+ CONST64(0x7D820E760E76B5EA) /* 24 */, CONST64(0x645C9CC6F07FDC42) /* 25 */,
+ CONST64(0xBF38A078243342E0) /* 26 */, CONST64(0x5F6B343C9D2E7D04) /* 27 */,
+ CONST64(0xF2C28AEB600B0EC6) /* 28 */, CONST64(0x6C0ED85F7254BCAC) /* 29 */,
+ CONST64(0x71592281A4DB4FE5) /* 30 */, CONST64(0x1967FA69CE0FED9F) /* 31 */,
+ CONST64(0xFD5293F8B96545DB) /* 32 */, CONST64(0xC879E9D7F2A7600B) /* 33 */,
+ CONST64(0x860248920193194E) /* 34 */, CONST64(0xA4F9533B2D9CC0B3) /* 35 */,
+ CONST64(0x9053836C15957613) /* 36 */, CONST64(0xDB6DCF8AFC357BF1) /* 37 */,
+ CONST64(0x18BEEA7A7A370F57) /* 38 */, CONST64(0x037117CA50B99066) /* 39 */,
+ CONST64(0x6AB30A9774424A35) /* 40 */, CONST64(0xF4E92F02E325249B) /* 41 */,
+ CONST64(0x7739DB07061CCAE1) /* 42 */, CONST64(0xD8F3B49CECA42A05) /* 43 */,
+ CONST64(0xBD56BE3F51382F73) /* 44 */, CONST64(0x45FAED5843B0BB28) /* 45 */,
+ CONST64(0x1C813D5C11BF1F83) /* 46 */, CONST64(0x8AF0E4B6D75FA169) /* 47 */,
+ CONST64(0x33EE18A487AD9999) /* 48 */, CONST64(0x3C26E8EAB1C94410) /* 49 */,
+ CONST64(0xB510102BC0A822F9) /* 50 */, CONST64(0x141EEF310CE6123B) /* 51 */,
+ CONST64(0xFC65B90059DDB154) /* 52 */, CONST64(0xE0158640C5E0E607) /* 53 */,
+ CONST64(0x884E079826C3A3CF) /* 54 */, CONST64(0x930D0D9523C535FD) /* 55 */,
+ CONST64(0x35638D754E9A2B00) /* 56 */, CONST64(0x4085FCCF40469DD5) /* 57 */,
+ CONST64(0xC4B17AD28BE23A4C) /* 58 */, CONST64(0xCAB2F0FC6A3E6A2E) /* 59 */,
+ CONST64(0x2860971A6B943FCD) /* 60 */, CONST64(0x3DDE6EE212E30446) /* 61 */,
+ CONST64(0x6222F32AE01765AE) /* 62 */, CONST64(0x5D550BB5478308FE) /* 63 */,
+ CONST64(0xA9EFA98DA0EDA22A) /* 64 */, CONST64(0xC351A71686C40DA7) /* 65 */,
+ CONST64(0x1105586D9C867C84) /* 66 */, CONST64(0xDCFFEE85FDA22853) /* 67 */,
+ CONST64(0xCCFBD0262C5EEF76) /* 68 */, CONST64(0xBAF294CB8990D201) /* 69 */,
+ CONST64(0xE69464F52AFAD975) /* 70 */, CONST64(0x94B013AFDF133E14) /* 71 */,
+ CONST64(0x06A7D1A32823C958) /* 72 */, CONST64(0x6F95FE5130F61119) /* 73 */,
+ CONST64(0xD92AB34E462C06C0) /* 74 */, CONST64(0xED7BDE33887C71D2) /* 75 */,
+ CONST64(0x79746D6E6518393E) /* 76 */, CONST64(0x5BA419385D713329) /* 77 */,
+ CONST64(0x7C1BA6B948A97564) /* 78 */, CONST64(0x31987C197BFDAC67) /* 79 */,
+ CONST64(0xDE6C23C44B053D02) /* 80 */, CONST64(0x581C49FED002D64D) /* 81 */,
+ CONST64(0xDD474D6338261571) /* 82 */, CONST64(0xAA4546C3E473D062) /* 83 */,
+ CONST64(0x928FCE349455F860) /* 84 */, CONST64(0x48161BBACAAB94D9) /* 85 */,
+ CONST64(0x63912430770E6F68) /* 86 */, CONST64(0x6EC8A5E602C6641C) /* 87 */,
+ CONST64(0x87282515337DDD2B) /* 88 */, CONST64(0x2CDA6B42034B701B) /* 89 */,
+ CONST64(0xB03D37C181CB096D) /* 90 */, CONST64(0xE108438266C71C6F) /* 91 */,
+ CONST64(0x2B3180C7EB51B255) /* 92 */, CONST64(0xDF92B82F96C08BBC) /* 93 */,
+ CONST64(0x5C68C8C0A632F3BA) /* 94 */, CONST64(0x5504CC861C3D0556) /* 95 */,
+ CONST64(0xABBFA4E55FB26B8F) /* 96 */, CONST64(0x41848B0AB3BACEB4) /* 97 */,
+ CONST64(0xB334A273AA445D32) /* 98 */, CONST64(0xBCA696F0A85AD881) /* 99 */,
+ CONST64(0x24F6EC65B528D56C) /* 100 */, CONST64(0x0CE1512E90F4524A) /* 101 */,
+ CONST64(0x4E9DD79D5506D35A) /* 102 */, CONST64(0x258905FAC6CE9779) /* 103 */,
+ CONST64(0x2019295B3E109B33) /* 104 */, CONST64(0xF8A9478B73A054CC) /* 105 */,
+ CONST64(0x2924F2F934417EB0) /* 106 */, CONST64(0x3993357D536D1BC4) /* 107 */,
+ CONST64(0x38A81AC21DB6FF8B) /* 108 */, CONST64(0x47C4FBF17D6016BF) /* 109 */,
+ CONST64(0x1E0FAADD7667E3F5) /* 110 */, CONST64(0x7ABCFF62938BEB96) /* 111 */,
+ CONST64(0xA78DAD948FC179C9) /* 112 */, CONST64(0x8F1F98B72911E50D) /* 113 */,
+ CONST64(0x61E48EAE27121A91) /* 114 */, CONST64(0x4D62F7AD31859808) /* 115 */,
+ CONST64(0xECEBA345EF5CEAEB) /* 116 */, CONST64(0xF5CEB25EBC9684CE) /* 117 */,
+ CONST64(0xF633E20CB7F76221) /* 118 */, CONST64(0xA32CDF06AB8293E4) /* 119 */,
+ CONST64(0x985A202CA5EE2CA4) /* 120 */, CONST64(0xCF0B8447CC8A8FB1) /* 121 */,
+ CONST64(0x9F765244979859A3) /* 122 */, CONST64(0xA8D516B1A1240017) /* 123 */,
+ CONST64(0x0BD7BA3EBB5DC726) /* 124 */, CONST64(0xE54BCA55B86ADB39) /* 125 */,
+ CONST64(0x1D7A3AFD6C478063) /* 126 */, CONST64(0x519EC608E7669EDD) /* 127 */,
+ CONST64(0x0E5715A2D149AA23) /* 128 */, CONST64(0x177D4571848FF194) /* 129 */,
+ CONST64(0xEEB55F3241014C22) /* 130 */, CONST64(0x0F5E5CA13A6E2EC2) /* 131 */,
+ CONST64(0x8029927B75F5C361) /* 132 */, CONST64(0xAD139FABC3D6E436) /* 133 */,
+ CONST64(0x0D5DF1A94CCF402F) /* 134 */, CONST64(0x3E8BD948BEA5DFC8) /* 135 */,
+ CONST64(0xA5A0D357BD3FF77E) /* 136 */, CONST64(0xA2D12E251F74F645) /* 137 */,
+ CONST64(0x66FD9E525E81A082) /* 138 */, CONST64(0x2E0C90CE7F687A49) /* 139 */,
+ CONST64(0xC2E8BCBEBA973BC5) /* 140 */, CONST64(0x000001BCE509745F) /* 141 */,
+ CONST64(0x423777BBE6DAB3D6) /* 142 */, CONST64(0xD1661C7EAEF06EB5) /* 143 */,
+ CONST64(0xA1781F354DAACFD8) /* 144 */, CONST64(0x2D11284A2B16AFFC) /* 145 */,
+ CONST64(0xF1FC4F67FA891D1F) /* 146 */, CONST64(0x73ECC25DCB920ADA) /* 147 */,
+ CONST64(0xAE610C22C2A12651) /* 148 */, CONST64(0x96E0A810D356B78A) /* 149 */,
+ CONST64(0x5A9A381F2FE7870F) /* 150 */, CONST64(0xD5AD62EDE94E5530) /* 151 */,
+ CONST64(0xD225E5E8368D1427) /* 152 */, CONST64(0x65977B70C7AF4631) /* 153 */,
+ CONST64(0x99F889B2DE39D74F) /* 154 */, CONST64(0x233F30BF54E1D143) /* 155 */,
+ CONST64(0x9A9675D3D9A63C97) /* 156 */, CONST64(0x5470554FF334F9A8) /* 157 */,
+ CONST64(0x166ACB744A4F5688) /* 158 */, CONST64(0x70C74CAAB2E4AEAD) /* 159 */,
+ CONST64(0xF0D091646F294D12) /* 160 */, CONST64(0x57B82A89684031D1) /* 161 */,
+ CONST64(0xEFD95A5A61BE0B6B) /* 162 */, CONST64(0x2FBD12E969F2F29A) /* 163 */,
+ CONST64(0x9BD37013FEFF9FE8) /* 164 */, CONST64(0x3F9B0404D6085A06) /* 165 */,
+ CONST64(0x4940C1F3166CFE15) /* 166 */, CONST64(0x09542C4DCDF3DEFB) /* 167 */,
+ CONST64(0xB4C5218385CD5CE3) /* 168 */, CONST64(0xC935B7DC4462A641) /* 169 */,
+ CONST64(0x3417F8A68ED3B63F) /* 170 */, CONST64(0xB80959295B215B40) /* 171 */,
+ CONST64(0xF99CDAEF3B8C8572) /* 172 */, CONST64(0x018C0614F8FCB95D) /* 173 */,
+ CONST64(0x1B14ACCD1A3ACDF3) /* 174 */, CONST64(0x84D471F200BB732D) /* 175 */,
+ CONST64(0xC1A3110E95E8DA16) /* 176 */, CONST64(0x430A7220BF1A82B8) /* 177 */,
+ CONST64(0xB77E090D39DF210E) /* 178 */, CONST64(0x5EF4BD9F3CD05E9D) /* 179 */,
+ CONST64(0x9D4FF6DA7E57A444) /* 180 */, CONST64(0xDA1D60E183D4A5F8) /* 181 */,
+ CONST64(0xB287C38417998E47) /* 182 */, CONST64(0xFE3EDC121BB31886) /* 183 */,
+ CONST64(0xC7FE3CCC980CCBEF) /* 184 */, CONST64(0xE46FB590189BFD03) /* 185 */,
+ CONST64(0x3732FD469A4C57DC) /* 186 */, CONST64(0x7EF700A07CF1AD65) /* 187 */,
+ CONST64(0x59C64468A31D8859) /* 188 */, CONST64(0x762FB0B4D45B61F6) /* 189 */,
+ CONST64(0x155BAED099047718) /* 190 */, CONST64(0x68755E4C3D50BAA6) /* 191 */,
+ CONST64(0xE9214E7F22D8B4DF) /* 192 */, CONST64(0x2ADDBF532EAC95F4) /* 193 */,
+ CONST64(0x32AE3909B4BD0109) /* 194 */, CONST64(0x834DF537B08E3450) /* 195 */,
+ CONST64(0xFA209DA84220728D) /* 196 */, CONST64(0x9E691D9B9EFE23F7) /* 197 */,
+ CONST64(0x0446D288C4AE8D7F) /* 198 */, CONST64(0x7B4CC524E169785B) /* 199 */,
+ CONST64(0x21D87F0135CA1385) /* 200 */, CONST64(0xCEBB400F137B8AA5) /* 201 */,
+ CONST64(0x272E2B66580796BE) /* 202 */, CONST64(0x3612264125C2B0DE) /* 203 */,
+ CONST64(0x057702BDAD1EFBB2) /* 204 */, CONST64(0xD4BABB8EACF84BE9) /* 205 */,
+ CONST64(0x91583139641BC67B) /* 206 */, CONST64(0x8BDC2DE08036E024) /* 207 */,
+ CONST64(0x603C8156F49F68ED) /* 208 */, CONST64(0xF7D236F7DBEF5111) /* 209 */,
+ CONST64(0x9727C4598AD21E80) /* 210 */, CONST64(0xA08A0896670A5FD7) /* 211 */,
+ CONST64(0xCB4A8F4309EBA9CB) /* 212 */, CONST64(0x81AF564B0F7036A1) /* 213 */,
+ CONST64(0xC0B99AA778199ABD) /* 214 */, CONST64(0x959F1EC83FC8E952) /* 215 */,
+ CONST64(0x8C505077794A81B9) /* 216 */, CONST64(0x3ACAAF8F056338F0) /* 217 */,
+ CONST64(0x07B43F50627A6778) /* 218 */, CONST64(0x4A44AB49F5ECCC77) /* 219 */,
+ CONST64(0x3BC3D6E4B679EE98) /* 220 */, CONST64(0x9CC0D4D1CF14108C) /* 221 */,
+ CONST64(0x4406C00B206BC8A0) /* 222 */, CONST64(0x82A18854C8D72D89) /* 223 */,
+ CONST64(0x67E366B35C3C432C) /* 224 */, CONST64(0xB923DD61102B37F2) /* 225 */,
+ CONST64(0x56AB2779D884271D) /* 226 */, CONST64(0xBE83E1B0FF1525AF) /* 227 */,
+ CONST64(0xFB7C65D4217E49A9) /* 228 */, CONST64(0x6BDBE0E76D48E7D4) /* 229 */,
+ CONST64(0x08DF828745D9179E) /* 230 */, CONST64(0x22EA6A9ADD53BD34) /* 231 */,
+ CONST64(0xE36E141C5622200A) /* 232 */, CONST64(0x7F805D1B8CB750EE) /* 233 */,
+ CONST64(0xAFE5C7A59F58E837) /* 234 */, CONST64(0xE27F996A4FB1C23C) /* 235 */,
+ CONST64(0xD3867DFB0775F0D0) /* 236 */, CONST64(0xD0E673DE6E88891A) /* 237 */,
+ CONST64(0x123AEB9EAFB86C25) /* 238 */, CONST64(0x30F1D5D5C145B895) /* 239 */,
+ CONST64(0xBB434A2DEE7269E7) /* 240 */, CONST64(0x78CB67ECF931FA38) /* 241 */,
+ CONST64(0xF33B0372323BBF9C) /* 242 */, CONST64(0x52D66336FB279C74) /* 243 */,
+ CONST64(0x505F33AC0AFB4EAA) /* 244 */, CONST64(0xE8A5CD99A2CCE187) /* 245 */,
+ CONST64(0x534974801E2D30BB) /* 246 */, CONST64(0x8D2D5711D5876D90) /* 247 */,
+ CONST64(0x1F1A412891BC038E) /* 248 */, CONST64(0xD6E2E71D82E56648) /* 249 */,
+ CONST64(0x74036C3A497732B7) /* 250 */, CONST64(0x89B67ED96361F5AB) /* 251 */,
+ CONST64(0xFFED95D8F1EA02A2) /* 252 */, CONST64(0xE72B3BD61464D43D) /* 253 */,
+ CONST64(0xA6300F170BDC4820) /* 254 */, CONST64(0xEBC18760ED78A77A) /* 255 */,
+ CONST64(0xE6A6BE5A05A12138) /* 256 */, CONST64(0xB5A122A5B4F87C98) /* 257 */,
+ CONST64(0x563C6089140B6990) /* 258 */, CONST64(0x4C46CB2E391F5DD5) /* 259 */,
+ CONST64(0xD932ADDBC9B79434) /* 260 */, CONST64(0x08EA70E42015AFF5) /* 261 */,
+ CONST64(0xD765A6673E478CF1) /* 262 */, CONST64(0xC4FB757EAB278D99) /* 263 */,
+ CONST64(0xDF11C6862D6E0692) /* 264 */, CONST64(0xDDEB84F10D7F3B16) /* 265 */,
+ CONST64(0x6F2EF604A665EA04) /* 266 */, CONST64(0x4A8E0F0FF0E0DFB3) /* 267 */,
+ CONST64(0xA5EDEEF83DBCBA51) /* 268 */, CONST64(0xFC4F0A2A0EA4371E) /* 269 */,
+ CONST64(0xE83E1DA85CB38429) /* 270 */, CONST64(0xDC8FF882BA1B1CE2) /* 271 */,
+ CONST64(0xCD45505E8353E80D) /* 272 */, CONST64(0x18D19A00D4DB0717) /* 273 */,
+ CONST64(0x34A0CFEDA5F38101) /* 274 */, CONST64(0x0BE77E518887CAF2) /* 275 */,
+ CONST64(0x1E341438B3C45136) /* 276 */, CONST64(0xE05797F49089CCF9) /* 277 */,
+ CONST64(0xFFD23F9DF2591D14) /* 278 */, CONST64(0x543DDA228595C5CD) /* 279 */,
+ CONST64(0x661F81FD99052A33) /* 280 */, CONST64(0x8736E641DB0F7B76) /* 281 */,
+ CONST64(0x15227725418E5307) /* 282 */, CONST64(0xE25F7F46162EB2FA) /* 283 */,
+ CONST64(0x48A8B2126C13D9FE) /* 284 */, CONST64(0xAFDC541792E76EEA) /* 285 */,
+ CONST64(0x03D912BFC6D1898F) /* 286 */, CONST64(0x31B1AAFA1B83F51B) /* 287 */,
+ CONST64(0xF1AC2796E42AB7D9) /* 288 */, CONST64(0x40A3A7D7FCD2EBAC) /* 289 */,
+ CONST64(0x1056136D0AFBBCC5) /* 290 */, CONST64(0x7889E1DD9A6D0C85) /* 291 */,
+ CONST64(0xD33525782A7974AA) /* 292 */, CONST64(0xA7E25D09078AC09B) /* 293 */,
+ CONST64(0xBD4138B3EAC6EDD0) /* 294 */, CONST64(0x920ABFBE71EB9E70) /* 295 */,
+ CONST64(0xA2A5D0F54FC2625C) /* 296 */, CONST64(0xC054E36B0B1290A3) /* 297 */,
+ CONST64(0xF6DD59FF62FE932B) /* 298 */, CONST64(0x3537354511A8AC7D) /* 299 */,
+ CONST64(0xCA845E9172FADCD4) /* 300 */, CONST64(0x84F82B60329D20DC) /* 301 */,
+ CONST64(0x79C62CE1CD672F18) /* 302 */, CONST64(0x8B09A2ADD124642C) /* 303 */,
+ CONST64(0xD0C1E96A19D9E726) /* 304 */, CONST64(0x5A786A9B4BA9500C) /* 305 */,
+ CONST64(0x0E020336634C43F3) /* 306 */, CONST64(0xC17B474AEB66D822) /* 307 */,
+ CONST64(0x6A731AE3EC9BAAC2) /* 308 */, CONST64(0x8226667AE0840258) /* 309 */,
+ CONST64(0x67D4567691CAECA5) /* 310 */, CONST64(0x1D94155C4875ADB5) /* 311 */,
+ CONST64(0x6D00FD985B813FDF) /* 312 */, CONST64(0x51286EFCB774CD06) /* 313 */,
+ CONST64(0x5E8834471FA744AF) /* 314 */, CONST64(0xF72CA0AEE761AE2E) /* 315 */,
+ CONST64(0xBE40E4CDAEE8E09A) /* 316 */, CONST64(0xE9970BBB5118F665) /* 317 */,
+ CONST64(0x726E4BEB33DF1964) /* 318 */, CONST64(0x703B000729199762) /* 319 */,
+ CONST64(0x4631D816F5EF30A7) /* 320 */, CONST64(0xB880B5B51504A6BE) /* 321 */,
+ CONST64(0x641793C37ED84B6C) /* 322 */, CONST64(0x7B21ED77F6E97D96) /* 323 */,
+ CONST64(0x776306312EF96B73) /* 324 */, CONST64(0xAE528948E86FF3F4) /* 325 */,
+ CONST64(0x53DBD7F286A3F8F8) /* 326 */, CONST64(0x16CADCE74CFC1063) /* 327 */,
+ CONST64(0x005C19BDFA52C6DD) /* 328 */, CONST64(0x68868F5D64D46AD3) /* 329 */,
+ CONST64(0x3A9D512CCF1E186A) /* 330 */, CONST64(0x367E62C2385660AE) /* 331 */,
+ CONST64(0xE359E7EA77DCB1D7) /* 332 */, CONST64(0x526C0773749ABE6E) /* 333 */,
+ CONST64(0x735AE5F9D09F734B) /* 334 */, CONST64(0x493FC7CC8A558BA8) /* 335 */,
+ CONST64(0xB0B9C1533041AB45) /* 336 */, CONST64(0x321958BA470A59BD) /* 337 */,
+ CONST64(0x852DB00B5F46C393) /* 338 */, CONST64(0x91209B2BD336B0E5) /* 339 */,
+ CONST64(0x6E604F7D659EF19F) /* 340 */, CONST64(0xB99A8AE2782CCB24) /* 341 */,
+ CONST64(0xCCF52AB6C814C4C7) /* 342 */, CONST64(0x4727D9AFBE11727B) /* 343 */,
+ CONST64(0x7E950D0C0121B34D) /* 344 */, CONST64(0x756F435670AD471F) /* 345 */,
+ CONST64(0xF5ADD442615A6849) /* 346 */, CONST64(0x4E87E09980B9957A) /* 347 */,
+ CONST64(0x2ACFA1DF50AEE355) /* 348 */, CONST64(0xD898263AFD2FD556) /* 349 */,
+ CONST64(0xC8F4924DD80C8FD6) /* 350 */, CONST64(0xCF99CA3D754A173A) /* 351 */,
+ CONST64(0xFE477BACAF91BF3C) /* 352 */, CONST64(0xED5371F6D690C12D) /* 353 */,
+ CONST64(0x831A5C285E687094) /* 354 */, CONST64(0xC5D3C90A3708A0A4) /* 355 */,
+ CONST64(0x0F7F903717D06580) /* 356 */, CONST64(0x19F9BB13B8FDF27F) /* 357 */,
+ CONST64(0xB1BD6F1B4D502843) /* 358 */, CONST64(0x1C761BA38FFF4012) /* 359 */,
+ CONST64(0x0D1530C4E2E21F3B) /* 360 */, CONST64(0x8943CE69A7372C8A) /* 361 */,
+ CONST64(0xE5184E11FEB5CE66) /* 362 */, CONST64(0x618BDB80BD736621) /* 363 */,
+ CONST64(0x7D29BAD68B574D0B) /* 364 */, CONST64(0x81BB613E25E6FE5B) /* 365 */,
+ CONST64(0x071C9C10BC07913F) /* 366 */, CONST64(0xC7BEEB7909AC2D97) /* 367 */,
+ CONST64(0xC3E58D353BC5D757) /* 368 */, CONST64(0xEB017892F38F61E8) /* 369 */,
+ CONST64(0xD4EFFB9C9B1CC21A) /* 370 */, CONST64(0x99727D26F494F7AB) /* 371 */,
+ CONST64(0xA3E063A2956B3E03) /* 372 */, CONST64(0x9D4A8B9A4AA09C30) /* 373 */,
+ CONST64(0x3F6AB7D500090FB4) /* 374 */, CONST64(0x9CC0F2A057268AC0) /* 375 */,
+ CONST64(0x3DEE9D2DEDBF42D1) /* 376 */, CONST64(0x330F49C87960A972) /* 377 */,
+ CONST64(0xC6B2720287421B41) /* 378 */, CONST64(0x0AC59EC07C00369C) /* 379 */,
+ CONST64(0xEF4EAC49CB353425) /* 380 */, CONST64(0xF450244EEF0129D8) /* 381 */,
+ CONST64(0x8ACC46E5CAF4DEB6) /* 382 */, CONST64(0x2FFEAB63989263F7) /* 383 */,
+ CONST64(0x8F7CB9FE5D7A4578) /* 384 */, CONST64(0x5BD8F7644E634635) /* 385 */,
+ CONST64(0x427A7315BF2DC900) /* 386 */, CONST64(0x17D0C4AA2125261C) /* 387 */,
+ CONST64(0x3992486C93518E50) /* 388 */, CONST64(0xB4CBFEE0A2D7D4C3) /* 389 */,
+ CONST64(0x7C75D6202C5DDD8D) /* 390 */, CONST64(0xDBC295D8E35B6C61) /* 391 */,
+ CONST64(0x60B369D302032B19) /* 392 */, CONST64(0xCE42685FDCE44132) /* 393 */,
+ CONST64(0x06F3DDB9DDF65610) /* 394 */, CONST64(0x8EA4D21DB5E148F0) /* 395 */,
+ CONST64(0x20B0FCE62FCD496F) /* 396 */, CONST64(0x2C1B912358B0EE31) /* 397 */,
+ CONST64(0xB28317B818F5A308) /* 398 */, CONST64(0xA89C1E189CA6D2CF) /* 399 */,
+ CONST64(0x0C6B18576AAADBC8) /* 400 */, CONST64(0xB65DEAA91299FAE3) /* 401 */,
+ CONST64(0xFB2B794B7F1027E7) /* 402 */, CONST64(0x04E4317F443B5BEB) /* 403 */,
+ CONST64(0x4B852D325939D0A6) /* 404 */, CONST64(0xD5AE6BEEFB207FFC) /* 405 */,
+ CONST64(0x309682B281C7D374) /* 406 */, CONST64(0xBAE309A194C3B475) /* 407 */,
+ CONST64(0x8CC3F97B13B49F05) /* 408 */, CONST64(0x98A9422FF8293967) /* 409 */,
+ CONST64(0x244B16B01076FF7C) /* 410 */, CONST64(0xF8BF571C663D67EE) /* 411 */,
+ CONST64(0x1F0D6758EEE30DA1) /* 412 */, CONST64(0xC9B611D97ADEB9B7) /* 413 */,
+ CONST64(0xB7AFD5887B6C57A2) /* 414 */, CONST64(0x6290AE846B984FE1) /* 415 */,
+ CONST64(0x94DF4CDEACC1A5FD) /* 416 */, CONST64(0x058A5BD1C5483AFF) /* 417 */,
+ CONST64(0x63166CC142BA3C37) /* 418 */, CONST64(0x8DB8526EB2F76F40) /* 419 */,
+ CONST64(0xE10880036F0D6D4E) /* 420 */, CONST64(0x9E0523C9971D311D) /* 421 */,
+ CONST64(0x45EC2824CC7CD691) /* 422 */, CONST64(0x575B8359E62382C9) /* 423 */,
+ CONST64(0xFA9E400DC4889995) /* 424 */, CONST64(0xD1823ECB45721568) /* 425 */,
+ CONST64(0xDAFD983B8206082F) /* 426 */, CONST64(0xAA7D29082386A8CB) /* 427 */,
+ CONST64(0x269FCD4403B87588) /* 428 */, CONST64(0x1B91F5F728BDD1E0) /* 429 */,
+ CONST64(0xE4669F39040201F6) /* 430 */, CONST64(0x7A1D7C218CF04ADE) /* 431 */,
+ CONST64(0x65623C29D79CE5CE) /* 432 */, CONST64(0x2368449096C00BB1) /* 433 */,
+ CONST64(0xAB9BF1879DA503BA) /* 434 */, CONST64(0xBC23ECB1A458058E) /* 435 */,
+ CONST64(0x9A58DF01BB401ECC) /* 436 */, CONST64(0xA070E868A85F143D) /* 437 */,
+ CONST64(0x4FF188307DF2239E) /* 438 */, CONST64(0x14D565B41A641183) /* 439 */,
+ CONST64(0xEE13337452701602) /* 440 */, CONST64(0x950E3DCF3F285E09) /* 441 */,
+ CONST64(0x59930254B9C80953) /* 442 */, CONST64(0x3BF299408930DA6D) /* 443 */,
+ CONST64(0xA955943F53691387) /* 444 */, CONST64(0xA15EDECAA9CB8784) /* 445 */,
+ CONST64(0x29142127352BE9A0) /* 446 */, CONST64(0x76F0371FFF4E7AFB) /* 447 */,
+ CONST64(0x0239F450274F2228) /* 448 */, CONST64(0xBB073AF01D5E868B) /* 449 */,
+ CONST64(0xBFC80571C10E96C1) /* 450 */, CONST64(0xD267088568222E23) /* 451 */,
+ CONST64(0x9671A3D48E80B5B0) /* 452 */, CONST64(0x55B5D38AE193BB81) /* 453 */,
+ CONST64(0x693AE2D0A18B04B8) /* 454 */, CONST64(0x5C48B4ECADD5335F) /* 455 */,
+ CONST64(0xFD743B194916A1CA) /* 456 */, CONST64(0x2577018134BE98C4) /* 457 */,
+ CONST64(0xE77987E83C54A4AD) /* 458 */, CONST64(0x28E11014DA33E1B9) /* 459 */,
+ CONST64(0x270CC59E226AA213) /* 460 */, CONST64(0x71495F756D1A5F60) /* 461 */,
+ CONST64(0x9BE853FB60AFEF77) /* 462 */, CONST64(0xADC786A7F7443DBF) /* 463 */,
+ CONST64(0x0904456173B29A82) /* 464 */, CONST64(0x58BC7A66C232BD5E) /* 465 */,
+ CONST64(0xF306558C673AC8B2) /* 466 */, CONST64(0x41F639C6B6C9772A) /* 467 */,
+ CONST64(0x216DEFE99FDA35DA) /* 468 */, CONST64(0x11640CC71C7BE615) /* 469 */,
+ CONST64(0x93C43694565C5527) /* 470 */, CONST64(0xEA038E6246777839) /* 471 */,
+ CONST64(0xF9ABF3CE5A3E2469) /* 472 */, CONST64(0x741E768D0FD312D2) /* 473 */,
+ CONST64(0x0144B883CED652C6) /* 474 */, CONST64(0xC20B5A5BA33F8552) /* 475 */,
+ CONST64(0x1AE69633C3435A9D) /* 476 */, CONST64(0x97A28CA4088CFDEC) /* 477 */,
+ CONST64(0x8824A43C1E96F420) /* 478 */, CONST64(0x37612FA66EEEA746) /* 479 */,
+ CONST64(0x6B4CB165F9CF0E5A) /* 480 */, CONST64(0x43AA1C06A0ABFB4A) /* 481 */,
+ CONST64(0x7F4DC26FF162796B) /* 482 */, CONST64(0x6CBACC8E54ED9B0F) /* 483 */,
+ CONST64(0xA6B7FFEFD2BB253E) /* 484 */, CONST64(0x2E25BC95B0A29D4F) /* 485 */,
+ CONST64(0x86D6A58BDEF1388C) /* 486 */, CONST64(0xDED74AC576B6F054) /* 487 */,
+ CONST64(0x8030BDBC2B45805D) /* 488 */, CONST64(0x3C81AF70E94D9289) /* 489 */,
+ CONST64(0x3EFF6DDA9E3100DB) /* 490 */, CONST64(0xB38DC39FDFCC8847) /* 491 */,
+ CONST64(0x123885528D17B87E) /* 492 */, CONST64(0xF2DA0ED240B1B642) /* 493 */,
+ CONST64(0x44CEFADCD54BF9A9) /* 494 */, CONST64(0x1312200E433C7EE6) /* 495 */,
+ CONST64(0x9FFCC84F3A78C748) /* 496 */, CONST64(0xF0CD1F72248576BB) /* 497 */,
+ CONST64(0xEC6974053638CFE4) /* 498 */, CONST64(0x2BA7B67C0CEC4E4C) /* 499 */,
+ CONST64(0xAC2F4DF3E5CE32ED) /* 500 */, CONST64(0xCB33D14326EA4C11) /* 501 */,
+ CONST64(0xA4E9044CC77E58BC) /* 502 */, CONST64(0x5F513293D934FCEF) /* 503 */,
+ CONST64(0x5DC9645506E55444) /* 504 */, CONST64(0x50DE418F317DE40A) /* 505 */,
+ CONST64(0x388CB31A69DDE259) /* 506 */, CONST64(0x2DB4A83455820A86) /* 507 */,
+ CONST64(0x9010A91E84711AE9) /* 508 */, CONST64(0x4DF7F0B7B1498371) /* 509 */,
+ CONST64(0xD62A2EABC0977179) /* 510 */, CONST64(0x22FAC097AA8D5C0E) /* 511 */,
+ CONST64(0xF49FCC2FF1DAF39B) /* 512 */, CONST64(0x487FD5C66FF29281) /* 513 */,
+ CONST64(0xE8A30667FCDCA83F) /* 514 */, CONST64(0x2C9B4BE3D2FCCE63) /* 515 */,
+ CONST64(0xDA3FF74B93FBBBC2) /* 516 */, CONST64(0x2FA165D2FE70BA66) /* 517 */,
+ CONST64(0xA103E279970E93D4) /* 518 */, CONST64(0xBECDEC77B0E45E71) /* 519 */,
+ CONST64(0xCFB41E723985E497) /* 520 */, CONST64(0xB70AAA025EF75017) /* 521 */,
+ CONST64(0xD42309F03840B8E0) /* 522 */, CONST64(0x8EFC1AD035898579) /* 523 */,
+ CONST64(0x96C6920BE2B2ABC5) /* 524 */, CONST64(0x66AF4163375A9172) /* 525 */,
+ CONST64(0x2174ABDCCA7127FB) /* 526 */, CONST64(0xB33CCEA64A72FF41) /* 527 */,
+ CONST64(0xF04A4933083066A5) /* 528 */, CONST64(0x8D970ACDD7289AF5) /* 529 */,
+ CONST64(0x8F96E8E031C8C25E) /* 530 */, CONST64(0xF3FEC02276875D47) /* 531 */,
+ CONST64(0xEC7BF310056190DD) /* 532 */, CONST64(0xF5ADB0AEBB0F1491) /* 533 */,
+ CONST64(0x9B50F8850FD58892) /* 534 */, CONST64(0x4975488358B74DE8) /* 535 */,
+ CONST64(0xA3354FF691531C61) /* 536 */, CONST64(0x0702BBE481D2C6EE) /* 537 */,
+ CONST64(0x89FB24057DEDED98) /* 538 */, CONST64(0xAC3075138596E902) /* 539 */,
+ CONST64(0x1D2D3580172772ED) /* 540 */, CONST64(0xEB738FC28E6BC30D) /* 541 */,
+ CONST64(0x5854EF8F63044326) /* 542 */, CONST64(0x9E5C52325ADD3BBE) /* 543 */,
+ CONST64(0x90AA53CF325C4623) /* 544 */, CONST64(0xC1D24D51349DD067) /* 545 */,
+ CONST64(0x2051CFEEA69EA624) /* 546 */, CONST64(0x13220F0A862E7E4F) /* 547 */,
+ CONST64(0xCE39399404E04864) /* 548 */, CONST64(0xD9C42CA47086FCB7) /* 549 */,
+ CONST64(0x685AD2238A03E7CC) /* 550 */, CONST64(0x066484B2AB2FF1DB) /* 551 */,
+ CONST64(0xFE9D5D70EFBF79EC) /* 552 */, CONST64(0x5B13B9DD9C481854) /* 553 */,
+ CONST64(0x15F0D475ED1509AD) /* 554 */, CONST64(0x0BEBCD060EC79851) /* 555 */,
+ CONST64(0xD58C6791183AB7F8) /* 556 */, CONST64(0xD1187C5052F3EEE4) /* 557 */,
+ CONST64(0xC95D1192E54E82FF) /* 558 */, CONST64(0x86EEA14CB9AC6CA2) /* 559 */,
+ CONST64(0x3485BEB153677D5D) /* 560 */, CONST64(0xDD191D781F8C492A) /* 561 */,
+ CONST64(0xF60866BAA784EBF9) /* 562 */, CONST64(0x518F643BA2D08C74) /* 563 */,
+ CONST64(0x8852E956E1087C22) /* 564 */, CONST64(0xA768CB8DC410AE8D) /* 565 */,
+ CONST64(0x38047726BFEC8E1A) /* 566 */, CONST64(0xA67738B4CD3B45AA) /* 567 */,
+ CONST64(0xAD16691CEC0DDE19) /* 568 */, CONST64(0xC6D4319380462E07) /* 569 */,
+ CONST64(0xC5A5876D0BA61938) /* 570 */, CONST64(0x16B9FA1FA58FD840) /* 571 */,
+ CONST64(0x188AB1173CA74F18) /* 572 */, CONST64(0xABDA2F98C99C021F) /* 573 */,
+ CONST64(0x3E0580AB134AE816) /* 574 */, CONST64(0x5F3B05B773645ABB) /* 575 */,
+ CONST64(0x2501A2BE5575F2F6) /* 576 */, CONST64(0x1B2F74004E7E8BA9) /* 577 */,
+ CONST64(0x1CD7580371E8D953) /* 578 */, CONST64(0x7F6ED89562764E30) /* 579 */,
+ CONST64(0xB15926FF596F003D) /* 580 */, CONST64(0x9F65293DA8C5D6B9) /* 581 */,
+ CONST64(0x6ECEF04DD690F84C) /* 582 */, CONST64(0x4782275FFF33AF88) /* 583 */,
+ CONST64(0xE41433083F820801) /* 584 */, CONST64(0xFD0DFE409A1AF9B5) /* 585 */,
+ CONST64(0x4325A3342CDB396B) /* 586 */, CONST64(0x8AE77E62B301B252) /* 587 */,
+ CONST64(0xC36F9E9F6655615A) /* 588 */, CONST64(0x85455A2D92D32C09) /* 589 */,
+ CONST64(0xF2C7DEA949477485) /* 590 */, CONST64(0x63CFB4C133A39EBA) /* 591 */,
+ CONST64(0x83B040CC6EBC5462) /* 592 */, CONST64(0x3B9454C8FDB326B0) /* 593 */,
+ CONST64(0x56F56A9E87FFD78C) /* 594 */, CONST64(0x2DC2940D99F42BC6) /* 595 */,
+ CONST64(0x98F7DF096B096E2D) /* 596 */, CONST64(0x19A6E01E3AD852BF) /* 597 */,
+ CONST64(0x42A99CCBDBD4B40B) /* 598 */, CONST64(0xA59998AF45E9C559) /* 599 */,
+ CONST64(0x366295E807D93186) /* 600 */, CONST64(0x6B48181BFAA1F773) /* 601 */,
+ CONST64(0x1FEC57E2157A0A1D) /* 602 */, CONST64(0x4667446AF6201AD5) /* 603 */,
+ CONST64(0xE615EBCACFB0F075) /* 604 */, CONST64(0xB8F31F4F68290778) /* 605 */,
+ CONST64(0x22713ED6CE22D11E) /* 606 */, CONST64(0x3057C1A72EC3C93B) /* 607 */,
+ CONST64(0xCB46ACC37C3F1F2F) /* 608 */, CONST64(0xDBB893FD02AAF50E) /* 609 */,
+ CONST64(0x331FD92E600B9FCF) /* 610 */, CONST64(0xA498F96148EA3AD6) /* 611 */,
+ CONST64(0xA8D8426E8B6A83EA) /* 612 */, CONST64(0xA089B274B7735CDC) /* 613 */,
+ CONST64(0x87F6B3731E524A11) /* 614 */, CONST64(0x118808E5CBC96749) /* 615 */,
+ CONST64(0x9906E4C7B19BD394) /* 616 */, CONST64(0xAFED7F7E9B24A20C) /* 617 */,
+ CONST64(0x6509EADEEB3644A7) /* 618 */, CONST64(0x6C1EF1D3E8EF0EDE) /* 619 */,
+ CONST64(0xB9C97D43E9798FB4) /* 620 */, CONST64(0xA2F2D784740C28A3) /* 621 */,
+ CONST64(0x7B8496476197566F) /* 622 */, CONST64(0x7A5BE3E6B65F069D) /* 623 */,
+ CONST64(0xF96330ED78BE6F10) /* 624 */, CONST64(0xEEE60DE77A076A15) /* 625 */,
+ CONST64(0x2B4BEE4AA08B9BD0) /* 626 */, CONST64(0x6A56A63EC7B8894E) /* 627 */,
+ CONST64(0x02121359BA34FEF4) /* 628 */, CONST64(0x4CBF99F8283703FC) /* 629 */,
+ CONST64(0x398071350CAF30C8) /* 630 */, CONST64(0xD0A77A89F017687A) /* 631 */,
+ CONST64(0xF1C1A9EB9E423569) /* 632 */, CONST64(0x8C7976282DEE8199) /* 633 */,
+ CONST64(0x5D1737A5DD1F7ABD) /* 634 */, CONST64(0x4F53433C09A9FA80) /* 635 */,
+ CONST64(0xFA8B0C53DF7CA1D9) /* 636 */, CONST64(0x3FD9DCBC886CCB77) /* 637 */,
+ CONST64(0xC040917CA91B4720) /* 638 */, CONST64(0x7DD00142F9D1DCDF) /* 639 */,
+ CONST64(0x8476FC1D4F387B58) /* 640 */, CONST64(0x23F8E7C5F3316503) /* 641 */,
+ CONST64(0x032A2244E7E37339) /* 642 */, CONST64(0x5C87A5D750F5A74B) /* 643 */,
+ CONST64(0x082B4CC43698992E) /* 644 */, CONST64(0xDF917BECB858F63C) /* 645 */,
+ CONST64(0x3270B8FC5BF86DDA) /* 646 */, CONST64(0x10AE72BB29B5DD76) /* 647 */,
+ CONST64(0x576AC94E7700362B) /* 648 */, CONST64(0x1AD112DAC61EFB8F) /* 649 */,
+ CONST64(0x691BC30EC5FAA427) /* 650 */, CONST64(0xFF246311CC327143) /* 651 */,
+ CONST64(0x3142368E30E53206) /* 652 */, CONST64(0x71380E31E02CA396) /* 653 */,
+ CONST64(0x958D5C960AAD76F1) /* 654 */, CONST64(0xF8D6F430C16DA536) /* 655 */,
+ CONST64(0xC8FFD13F1BE7E1D2) /* 656 */, CONST64(0x7578AE66004DDBE1) /* 657 */,
+ CONST64(0x05833F01067BE646) /* 658 */, CONST64(0xBB34B5AD3BFE586D) /* 659 */,
+ CONST64(0x095F34C9A12B97F0) /* 660 */, CONST64(0x247AB64525D60CA8) /* 661 */,
+ CONST64(0xDCDBC6F3017477D1) /* 662 */, CONST64(0x4A2E14D4DECAD24D) /* 663 */,
+ CONST64(0xBDB5E6D9BE0A1EEB) /* 664 */, CONST64(0x2A7E70F7794301AB) /* 665 */,
+ CONST64(0xDEF42D8A270540FD) /* 666 */, CONST64(0x01078EC0A34C22C1) /* 667 */,
+ CONST64(0xE5DE511AF4C16387) /* 668 */, CONST64(0x7EBB3A52BD9A330A) /* 669 */,
+ CONST64(0x77697857AA7D6435) /* 670 */, CONST64(0x004E831603AE4C32) /* 671 */,
+ CONST64(0xE7A21020AD78E312) /* 672 */, CONST64(0x9D41A70C6AB420F2) /* 673 */,
+ CONST64(0x28E06C18EA1141E6) /* 674 */, CONST64(0xD2B28CBD984F6B28) /* 675 */,
+ CONST64(0x26B75F6C446E9D83) /* 676 */, CONST64(0xBA47568C4D418D7F) /* 677 */,
+ CONST64(0xD80BADBFE6183D8E) /* 678 */, CONST64(0x0E206D7F5F166044) /* 679 */,
+ CONST64(0xE258A43911CBCA3E) /* 680 */, CONST64(0x723A1746B21DC0BC) /* 681 */,
+ CONST64(0xC7CAA854F5D7CDD3) /* 682 */, CONST64(0x7CAC32883D261D9C) /* 683 */,
+ CONST64(0x7690C26423BA942C) /* 684 */, CONST64(0x17E55524478042B8) /* 685 */,
+ CONST64(0xE0BE477656A2389F) /* 686 */, CONST64(0x4D289B5E67AB2DA0) /* 687 */,
+ CONST64(0x44862B9C8FBBFD31) /* 688 */, CONST64(0xB47CC8049D141365) /* 689 */,
+ CONST64(0x822C1B362B91C793) /* 690 */, CONST64(0x4EB14655FB13DFD8) /* 691 */,
+ CONST64(0x1ECBBA0714E2A97B) /* 692 */, CONST64(0x6143459D5CDE5F14) /* 693 */,
+ CONST64(0x53A8FBF1D5F0AC89) /* 694 */, CONST64(0x97EA04D81C5E5B00) /* 695 */,
+ CONST64(0x622181A8D4FDB3F3) /* 696 */, CONST64(0xE9BCD341572A1208) /* 697 */,
+ CONST64(0x1411258643CCE58A) /* 698 */, CONST64(0x9144C5FEA4C6E0A4) /* 699 */,
+ CONST64(0x0D33D06565CF620F) /* 700 */, CONST64(0x54A48D489F219CA1) /* 701 */,
+ CONST64(0xC43E5EAC6D63C821) /* 702 */, CONST64(0xA9728B3A72770DAF) /* 703 */,
+ CONST64(0xD7934E7B20DF87EF) /* 704 */, CONST64(0xE35503B61A3E86E5) /* 705 */,
+ CONST64(0xCAE321FBC819D504) /* 706 */, CONST64(0x129A50B3AC60BFA6) /* 707 */,
+ CONST64(0xCD5E68EA7E9FB6C3) /* 708 */, CONST64(0xB01C90199483B1C7) /* 709 */,
+ CONST64(0x3DE93CD5C295376C) /* 710 */, CONST64(0xAED52EDF2AB9AD13) /* 711 */,
+ CONST64(0x2E60F512C0A07884) /* 712 */, CONST64(0xBC3D86A3E36210C9) /* 713 */,
+ CONST64(0x35269D9B163951CE) /* 714 */, CONST64(0x0C7D6E2AD0CDB5FA) /* 715 */,
+ CONST64(0x59E86297D87F5733) /* 716 */, CONST64(0x298EF221898DB0E7) /* 717 */,
+ CONST64(0x55000029D1A5AA7E) /* 718 */, CONST64(0x8BC08AE1B5061B45) /* 719 */,
+ CONST64(0xC2C31C2B6C92703A) /* 720 */, CONST64(0x94CC596BAF25EF42) /* 721 */,
+ CONST64(0x0A1D73DB22540456) /* 722 */, CONST64(0x04B6A0F9D9C4179A) /* 723 */,
+ CONST64(0xEFFDAFA2AE3D3C60) /* 724 */, CONST64(0xF7C8075BB49496C4) /* 725 */,
+ CONST64(0x9CC5C7141D1CD4E3) /* 726 */, CONST64(0x78BD1638218E5534) /* 727 */,
+ CONST64(0xB2F11568F850246A) /* 728 */, CONST64(0xEDFABCFA9502BC29) /* 729 */,
+ CONST64(0x796CE5F2DA23051B) /* 730 */, CONST64(0xAAE128B0DC93537C) /* 731 */,
+ CONST64(0x3A493DA0EE4B29AE) /* 732 */, CONST64(0xB5DF6B2C416895D7) /* 733 */,
+ CONST64(0xFCABBD25122D7F37) /* 734 */, CONST64(0x70810B58105DC4B1) /* 735 */,
+ CONST64(0xE10FDD37F7882A90) /* 736 */, CONST64(0x524DCAB5518A3F5C) /* 737 */,
+ CONST64(0x3C9E85878451255B) /* 738 */, CONST64(0x4029828119BD34E2) /* 739 */,
+ CONST64(0x74A05B6F5D3CECCB) /* 740 */, CONST64(0xB610021542E13ECA) /* 741 */,
+ CONST64(0x0FF979D12F59E2AC) /* 742 */, CONST64(0x6037DA27E4F9CC50) /* 743 */,
+ CONST64(0x5E92975A0DF1847D) /* 744 */, CONST64(0xD66DE190D3E623FE) /* 745 */,
+ CONST64(0x5032D6B87B568048) /* 746 */, CONST64(0x9A36B7CE8235216E) /* 747 */,
+ CONST64(0x80272A7A24F64B4A) /* 748 */, CONST64(0x93EFED8B8C6916F7) /* 749 */,
+ CONST64(0x37DDBFF44CCE1555) /* 750 */, CONST64(0x4B95DB5D4B99BD25) /* 751 */,
+ CONST64(0x92D3FDA169812FC0) /* 752 */, CONST64(0xFB1A4A9A90660BB6) /* 753 */,
+ CONST64(0x730C196946A4B9B2) /* 754 */, CONST64(0x81E289AA7F49DA68) /* 755 */,
+ CONST64(0x64669A0F83B1A05F) /* 756 */, CONST64(0x27B3FF7D9644F48B) /* 757 */,
+ CONST64(0xCC6B615C8DB675B3) /* 758 */, CONST64(0x674F20B9BCEBBE95) /* 759 */,
+ CONST64(0x6F31238275655982) /* 760 */, CONST64(0x5AE488713E45CF05) /* 761 */,
+ CONST64(0xBF619F9954C21157) /* 762 */, CONST64(0xEABAC46040A8EAE9) /* 763 */,
+ CONST64(0x454C6FE9F2C0C1CD) /* 764 */, CONST64(0x419CF6496412691C) /* 765 */,
+ CONST64(0xD3DC3BEF265B0F70) /* 766 */, CONST64(0x6D0E60F5C3578A9E) /* 767 */,
+ CONST64(0x5B0E608526323C55) /* 768 */, CONST64(0x1A46C1A9FA1B59F5) /* 769 */,
+ CONST64(0xA9E245A17C4C8FFA) /* 770 */, CONST64(0x65CA5159DB2955D7) /* 771 */,
+ CONST64(0x05DB0A76CE35AFC2) /* 772 */, CONST64(0x81EAC77EA9113D45) /* 773 */,
+ CONST64(0x528EF88AB6AC0A0D) /* 774 */, CONST64(0xA09EA253597BE3FF) /* 775 */,
+ CONST64(0x430DDFB3AC48CD56) /* 776 */, CONST64(0xC4B3A67AF45CE46F) /* 777 */,
+ CONST64(0x4ECECFD8FBE2D05E) /* 778 */, CONST64(0x3EF56F10B39935F0) /* 779 */,
+ CONST64(0x0B22D6829CD619C6) /* 780 */, CONST64(0x17FD460A74DF2069) /* 781 */,
+ CONST64(0x6CF8CC8E8510ED40) /* 782 */, CONST64(0xD6C824BF3A6ECAA7) /* 783 */,
+ CONST64(0x61243D581A817049) /* 784 */, CONST64(0x048BACB6BBC163A2) /* 785 */,
+ CONST64(0xD9A38AC27D44CC32) /* 786 */, CONST64(0x7FDDFF5BAAF410AB) /* 787 */,
+ CONST64(0xAD6D495AA804824B) /* 788 */, CONST64(0xE1A6A74F2D8C9F94) /* 789 */,
+ CONST64(0xD4F7851235DEE8E3) /* 790 */, CONST64(0xFD4B7F886540D893) /* 791 */,
+ CONST64(0x247C20042AA4BFDA) /* 792 */, CONST64(0x096EA1C517D1327C) /* 793 */,
+ CONST64(0xD56966B4361A6685) /* 794 */, CONST64(0x277DA5C31221057D) /* 795 */,
+ CONST64(0x94D59893A43ACFF7) /* 796 */, CONST64(0x64F0C51CCDC02281) /* 797 */,
+ CONST64(0x3D33BCC4FF6189DB) /* 798 */, CONST64(0xE005CB184CE66AF1) /* 799 */,
+ CONST64(0xFF5CCD1D1DB99BEA) /* 800 */, CONST64(0xB0B854A7FE42980F) /* 801 */,
+ CONST64(0x7BD46A6A718D4B9F) /* 802 */, CONST64(0xD10FA8CC22A5FD8C) /* 803 */,
+ CONST64(0xD31484952BE4BD31) /* 804 */, CONST64(0xC7FA975FCB243847) /* 805 */,
+ CONST64(0x4886ED1E5846C407) /* 806 */, CONST64(0x28CDDB791EB70B04) /* 807 */,
+ CONST64(0xC2B00BE2F573417F) /* 808 */, CONST64(0x5C9590452180F877) /* 809 */,
+ CONST64(0x7A6BDDFFF370EB00) /* 810 */, CONST64(0xCE509E38D6D9D6A4) /* 811 */,
+ CONST64(0xEBEB0F00647FA702) /* 812 */, CONST64(0x1DCC06CF76606F06) /* 813 */,
+ CONST64(0xE4D9F28BA286FF0A) /* 814 */, CONST64(0xD85A305DC918C262) /* 815 */,
+ CONST64(0x475B1D8732225F54) /* 816 */, CONST64(0x2D4FB51668CCB5FE) /* 817 */,
+ CONST64(0xA679B9D9D72BBA20) /* 818 */, CONST64(0x53841C0D912D43A5) /* 819 */,
+ CONST64(0x3B7EAA48BF12A4E8) /* 820 */, CONST64(0x781E0E47F22F1DDF) /* 821 */,
+ CONST64(0xEFF20CE60AB50973) /* 822 */, CONST64(0x20D261D19DFFB742) /* 823 */,
+ CONST64(0x16A12B03062A2E39) /* 824 */, CONST64(0x1960EB2239650495) /* 825 */,
+ CONST64(0x251C16FED50EB8B8) /* 826 */, CONST64(0x9AC0C330F826016E) /* 827 */,
+ CONST64(0xED152665953E7671) /* 828 */, CONST64(0x02D63194A6369570) /* 829 */,
+ CONST64(0x5074F08394B1C987) /* 830 */, CONST64(0x70BA598C90B25CE1) /* 831 */,
+ CONST64(0x794A15810B9742F6) /* 832 */, CONST64(0x0D5925E9FCAF8C6C) /* 833 */,
+ CONST64(0x3067716CD868744E) /* 834 */, CONST64(0x910AB077E8D7731B) /* 835 */,
+ CONST64(0x6A61BBDB5AC42F61) /* 836 */, CONST64(0x93513EFBF0851567) /* 837 */,
+ CONST64(0xF494724B9E83E9D5) /* 838 */, CONST64(0xE887E1985C09648D) /* 839 */,
+ CONST64(0x34B1D3C675370CFD) /* 840 */, CONST64(0xDC35E433BC0D255D) /* 841 */,
+ CONST64(0xD0AAB84234131BE0) /* 842 */, CONST64(0x08042A50B48B7EAF) /* 843 */,
+ CONST64(0x9997C4EE44A3AB35) /* 844 */, CONST64(0x829A7B49201799D0) /* 845 */,
+ CONST64(0x263B8307B7C54441) /* 846 */, CONST64(0x752F95F4FD6A6CA6) /* 847 */,
+ CONST64(0x927217402C08C6E5) /* 848 */, CONST64(0x2A8AB754A795D9EE) /* 849 */,
+ CONST64(0xA442F7552F72943D) /* 850 */, CONST64(0x2C31334E19781208) /* 851 */,
+ CONST64(0x4FA98D7CEAEE6291) /* 852 */, CONST64(0x55C3862F665DB309) /* 853 */,
+ CONST64(0xBD0610175D53B1F3) /* 854 */, CONST64(0x46FE6CB840413F27) /* 855 */,
+ CONST64(0x3FE03792DF0CFA59) /* 856 */, CONST64(0xCFE700372EB85E8F) /* 857 */,
+ CONST64(0xA7BE29E7ADBCE118) /* 858 */, CONST64(0xE544EE5CDE8431DD) /* 859 */,
+ CONST64(0x8A781B1B41F1873E) /* 860 */, CONST64(0xA5C94C78A0D2F0E7) /* 861 */,
+ CONST64(0x39412E2877B60728) /* 862 */, CONST64(0xA1265EF3AFC9A62C) /* 863 */,
+ CONST64(0xBCC2770C6A2506C5) /* 864 */, CONST64(0x3AB66DD5DCE1CE12) /* 865 */,
+ CONST64(0xE65499D04A675B37) /* 866 */, CONST64(0x7D8F523481BFD216) /* 867 */,
+ CONST64(0x0F6F64FCEC15F389) /* 868 */, CONST64(0x74EFBE618B5B13C8) /* 869 */,
+ CONST64(0xACDC82B714273E1D) /* 870 */, CONST64(0xDD40BFE003199D17) /* 871 */,
+ CONST64(0x37E99257E7E061F8) /* 872 */, CONST64(0xFA52626904775AAA) /* 873 */,
+ CONST64(0x8BBBF63A463D56F9) /* 874 */, CONST64(0xF0013F1543A26E64) /* 875 */,
+ CONST64(0xA8307E9F879EC898) /* 876 */, CONST64(0xCC4C27A4150177CC) /* 877 */,
+ CONST64(0x1B432F2CCA1D3348) /* 878 */, CONST64(0xDE1D1F8F9F6FA013) /* 879 */,
+ CONST64(0x606602A047A7DDD6) /* 880 */, CONST64(0xD237AB64CC1CB2C7) /* 881 */,
+ CONST64(0x9B938E7225FCD1D3) /* 882 */, CONST64(0xEC4E03708E0FF476) /* 883 */,
+ CONST64(0xFEB2FBDA3D03C12D) /* 884 */, CONST64(0xAE0BCED2EE43889A) /* 885 */,
+ CONST64(0x22CB8923EBFB4F43) /* 886 */, CONST64(0x69360D013CF7396D) /* 887 */,
+ CONST64(0x855E3602D2D4E022) /* 888 */, CONST64(0x073805BAD01F784C) /* 889 */,
+ CONST64(0x33E17A133852F546) /* 890 */, CONST64(0xDF4874058AC7B638) /* 891 */,
+ CONST64(0xBA92B29C678AA14A) /* 892 */, CONST64(0x0CE89FC76CFAADCD) /* 893 */,
+ CONST64(0x5F9D4E0908339E34) /* 894 */, CONST64(0xF1AFE9291F5923B9) /* 895 */,
+ CONST64(0x6E3480F60F4A265F) /* 896 */, CONST64(0xEEBF3A2AB29B841C) /* 897 */,
+ CONST64(0xE21938A88F91B4AD) /* 898 */, CONST64(0x57DFEFF845C6D3C3) /* 899 */,
+ CONST64(0x2F006B0BF62CAAF2) /* 900 */, CONST64(0x62F479EF6F75EE78) /* 901 */,
+ CONST64(0x11A55AD41C8916A9) /* 902 */, CONST64(0xF229D29084FED453) /* 903 */,
+ CONST64(0x42F1C27B16B000E6) /* 904 */, CONST64(0x2B1F76749823C074) /* 905 */,
+ CONST64(0x4B76ECA3C2745360) /* 906 */, CONST64(0x8C98F463B91691BD) /* 907 */,
+ CONST64(0x14BCC93CF1ADE66A) /* 908 */, CONST64(0x8885213E6D458397) /* 909 */,
+ CONST64(0x8E177DF0274D4711) /* 910 */, CONST64(0xB49B73B5503F2951) /* 911 */,
+ CONST64(0x10168168C3F96B6B) /* 912 */, CONST64(0x0E3D963B63CAB0AE) /* 913 */,
+ CONST64(0x8DFC4B5655A1DB14) /* 914 */, CONST64(0xF789F1356E14DE5C) /* 915 */,
+ CONST64(0x683E68AF4E51DAC1) /* 916 */, CONST64(0xC9A84F9D8D4B0FD9) /* 917 */,
+ CONST64(0x3691E03F52A0F9D1) /* 918 */, CONST64(0x5ED86E46E1878E80) /* 919 */,
+ CONST64(0x3C711A0E99D07150) /* 920 */, CONST64(0x5A0865B20C4E9310) /* 921 */,
+ CONST64(0x56FBFC1FE4F0682E) /* 922 */, CONST64(0xEA8D5DE3105EDF9B) /* 923 */,
+ CONST64(0x71ABFDB12379187A) /* 924 */, CONST64(0x2EB99DE1BEE77B9C) /* 925 */,
+ CONST64(0x21ECC0EA33CF4523) /* 926 */, CONST64(0x59A4D7521805C7A1) /* 927 */,
+ CONST64(0x3896F5EB56AE7C72) /* 928 */, CONST64(0xAA638F3DB18F75DC) /* 929 */,
+ CONST64(0x9F39358DABE9808E) /* 930 */, CONST64(0xB7DEFA91C00B72AC) /* 931 */,
+ CONST64(0x6B5541FD62492D92) /* 932 */, CONST64(0x6DC6DEE8F92E4D5B) /* 933 */,
+ CONST64(0x353F57ABC4BEEA7E) /* 934 */, CONST64(0x735769D6DA5690CE) /* 935 */,
+ CONST64(0x0A234AA642391484) /* 936 */, CONST64(0xF6F9508028F80D9D) /* 937 */,
+ CONST64(0xB8E319A27AB3F215) /* 938 */, CONST64(0x31AD9C1151341A4D) /* 939 */,
+ CONST64(0x773C22A57BEF5805) /* 940 */, CONST64(0x45C7561A07968633) /* 941 */,
+ CONST64(0xF913DA9E249DBE36) /* 942 */, CONST64(0xDA652D9B78A64C68) /* 943 */,
+ CONST64(0x4C27A97F3BC334EF) /* 944 */, CONST64(0x76621220E66B17F4) /* 945 */,
+ CONST64(0x967743899ACD7D0B) /* 946 */, CONST64(0xF3EE5BCAE0ED6782) /* 947 */,
+ CONST64(0x409F753600C879FC) /* 948 */, CONST64(0x06D09A39B5926DB6) /* 949 */,
+ CONST64(0x6F83AEB0317AC588) /* 950 */, CONST64(0x01E6CA4A86381F21) /* 951 */,
+ CONST64(0x66FF3462D19F3025) /* 952 */, CONST64(0x72207C24DDFD3BFB) /* 953 */,
+ CONST64(0x4AF6B6D3E2ECE2EB) /* 954 */, CONST64(0x9C994DBEC7EA08DE) /* 955 */,
+ CONST64(0x49ACE597B09A8BC4) /* 956 */, CONST64(0xB38C4766CF0797BA) /* 957 */,
+ CONST64(0x131B9373C57C2A75) /* 958 */, CONST64(0xB1822CCE61931E58) /* 959 */,
+ CONST64(0x9D7555B909BA1C0C) /* 960 */, CONST64(0x127FAFDD937D11D2) /* 961 */,
+ CONST64(0x29DA3BADC66D92E4) /* 962 */, CONST64(0xA2C1D57154C2ECBC) /* 963 */,
+ CONST64(0x58C5134D82F6FE24) /* 964 */, CONST64(0x1C3AE3515B62274F) /* 965 */,
+ CONST64(0xE907C82E01CB8126) /* 966 */, CONST64(0xF8ED091913E37FCB) /* 967 */,
+ CONST64(0x3249D8F9C80046C9) /* 968 */, CONST64(0x80CF9BEDE388FB63) /* 969 */,
+ CONST64(0x1881539A116CF19E) /* 970 */, CONST64(0x5103F3F76BD52457) /* 971 */,
+ CONST64(0x15B7E6F5AE47F7A8) /* 972 */, CONST64(0xDBD7C6DED47E9CCF) /* 973 */,
+ CONST64(0x44E55C410228BB1A) /* 974 */, CONST64(0xB647D4255EDB4E99) /* 975 */,
+ CONST64(0x5D11882BB8AAFC30) /* 976 */, CONST64(0xF5098BBB29D3212A) /* 977 */,
+ CONST64(0x8FB5EA14E90296B3) /* 978 */, CONST64(0x677B942157DD025A) /* 979 */,
+ CONST64(0xFB58E7C0A390ACB5) /* 980 */, CONST64(0x89D3674C83BD4A01) /* 981 */,
+ CONST64(0x9E2DA4DF4BF3B93B) /* 982 */, CONST64(0xFCC41E328CAB4829) /* 983 */,
+ CONST64(0x03F38C96BA582C52) /* 984 */, CONST64(0xCAD1BDBD7FD85DB2) /* 985 */,
+ CONST64(0xBBB442C16082AE83) /* 986 */, CONST64(0xB95FE86BA5DA9AB0) /* 987 */,
+ CONST64(0xB22E04673771A93F) /* 988 */, CONST64(0x845358C9493152D8) /* 989 */,
+ CONST64(0xBE2A488697B4541E) /* 990 */, CONST64(0x95A2DC2DD38E6966) /* 991 */,
+ CONST64(0xC02C11AC923C852B) /* 992 */, CONST64(0x2388B1990DF2A87B) /* 993 */,
+ CONST64(0x7C8008FA1B4F37BE) /* 994 */, CONST64(0x1F70D0C84D54E503) /* 995 */,
+ CONST64(0x5490ADEC7ECE57D4) /* 996 */, CONST64(0x002B3C27D9063A3A) /* 997 */,
+ CONST64(0x7EAEA3848030A2BF) /* 998 */, CONST64(0xC602326DED2003C0) /* 999 */,
+ CONST64(0x83A7287D69A94086) /* 1000 */, CONST64(0xC57A5FCB30F57A8A) /* 1001 */,
+ CONST64(0xB56844E479EBE779) /* 1002 */, CONST64(0xA373B40F05DCBCE9) /* 1003 */,
+ CONST64(0xD71A786E88570EE2) /* 1004 */, CONST64(0x879CBACDBDE8F6A0) /* 1005 */,
+ CONST64(0x976AD1BCC164A32F) /* 1006 */, CONST64(0xAB21E25E9666D78B) /* 1007 */,
+ CONST64(0x901063AAE5E5C33C) /* 1008 */, CONST64(0x9818B34448698D90) /* 1009 */,
+ CONST64(0xE36487AE3E1E8ABB) /* 1010 */, CONST64(0xAFBDF931893BDCB4) /* 1011 */,
+ CONST64(0x6345A0DC5FBBD519) /* 1012 */, CONST64(0x8628FE269B9465CA) /* 1013 */,
+ CONST64(0x1E5D01603F9C51EC) /* 1014 */, CONST64(0x4DE44006A15049B7) /* 1015 */,
+ CONST64(0xBF6C70E5F776CBB1) /* 1016 */, CONST64(0x411218F2EF552BED) /* 1017 */,
+ CONST64(0xCB0C0708705A36A3) /* 1018 */, CONST64(0xE74D14754F986044) /* 1019 */,
+ CONST64(0xCD56D9430EA8280E) /* 1020 */, CONST64(0xC12591D7535F5065) /* 1021 */,
+ CONST64(0xC83223F1720AEF96) /* 1022 */, CONST64(0xC3A0396F7363A51F) /* 1023 */};
+
+/* one round of the hash function */
+LTC_INLINE static void tiger_round(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 x, int mul)
+{
+ ulong64 tmp;
+ tmp = (*c ^= x);
+ *a -= t1[LTC_BYTE(tmp, 0)] ^ t2[LTC_BYTE(tmp, 2)] ^ t3[LTC_BYTE(tmp, 4)] ^ t4[LTC_BYTE(tmp, 6)];
+ tmp = (*b += t4[LTC_BYTE(tmp, 1)] ^ t3[LTC_BYTE(tmp, 3)] ^ t2[LTC_BYTE(tmp,5)] ^ t1[LTC_BYTE(tmp,7)]);
+ switch (mul) {
+ case 5: *b = (tmp << 2) + tmp; break;
+ case 7: *b = (tmp << 3) - tmp; break;
+ case 9: *b = (tmp << 3) + tmp; break;
+ }
+}
+
+/* one complete pass */
+static void s_pass(ulong64 *a, ulong64 *b, ulong64 *c, const ulong64 *x, int mul)
+{
+ tiger_round(a,b,c,x[0],mul);
+ tiger_round(b,c,a,x[1],mul);
+ tiger_round(c,a,b,x[2],mul);
+ tiger_round(a,b,c,x[3],mul);
+ tiger_round(b,c,a,x[4],mul);
+ tiger_round(c,a,b,x[5],mul);
+ tiger_round(a,b,c,x[6],mul);
+ tiger_round(b,c,a,x[7],mul);
+}
+
+/* The key mixing schedule */
+static void s_key_schedule(ulong64 *x)
+{
+ x[0] -= x[7] ^ CONST64(0xA5A5A5A5A5A5A5A5);
+ x[1] ^= x[0];
+ x[2] += x[1];
+ x[3] -= x[2] ^ ((~x[1])<<19);
+ x[4] ^= x[3];
+ x[5] += x[4];
+ x[6] -= x[5] ^ ((~x[4])>>23);
+ x[7] ^= x[6];
+ x[0] += x[7];
+ x[1] -= x[0] ^ ((~x[7])<<19);
+ x[2] ^= x[1];
+ x[3] += x[2];
+ x[4] -= x[3] ^ ((~x[2])>>23);
+ x[5] ^= x[4];
+ x[6] += x[5];
+ x[7] -= x[6] ^ CONST64(0x0123456789ABCDEF);
+}
+
+#ifdef LTC_CLEAN_STACK
+static int ss_tiger_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_tiger_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong64 a, b, c, x[8], t;
+ unsigned long i;
+
+ /* load words */
+ for (i = 0; i < 8; i++) {
+ LOAD64L(x[i],&buf[8*i]);
+ }
+ a = md->tiger.state[0];
+ b = md->tiger.state[1];
+ c = md->tiger.state[2];
+
+ s_pass(&a,&b,&c,x,5);
+ s_key_schedule(x);
+ s_pass(&c,&a,&b,x,7);
+ s_key_schedule(x);
+ s_pass(&b,&c,&a,x,9);
+ for (i = 3; i < md->tiger.passes; ++i) {
+ s_key_schedule(x);
+ s_pass(&a,&b,&c,x,9);
+ t = a; a = c; c = b; b = t;
+ }
+
+ /* store state */
+ md->tiger.state[0] = a ^ md->tiger.state[0];
+ md->tiger.state[1] = b - md->tiger.state[1];
+ md->tiger.state[2] = c + md->tiger.state[2];
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_tiger_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_tiger_compress(md, buf);
+ burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long));
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int tiger_init(hash_state *md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->tiger.state[0] = CONST64(0x0123456789ABCDEF);
+ md->tiger.state[1] = CONST64(0xFEDCBA9876543210);
+ md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187);
+ md->tiger.curlen = 0;
+ md->tiger.length = 0;
+ md->tiger.passes = 3;
+ md->tiger.pad = 0x01u;
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the hash state (extended version)
+ @param md The hash state you wish to initialize
+ @param passes The number of passes that should be executed
+ when the compress function is called.
+ @return CRYPT_OK if successful
+*/
+int tiger_init_ex(hash_state *md, unsigned long passes)
+{
+ int err;
+ if ((err = tiger_init(md) != CRYPT_OK)) {
+ return err;
+ }
+ md->tiger.passes = passes;
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the hash state (extended version)
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int tiger2_init(hash_state *md)
+{
+ int err;
+ if ((err = tiger_init(md) != CRYPT_OK)) {
+ return err;
+ }
+ md->tiger.pad = 0x80u;
+ return CRYPT_OK;
+}
+
+/**
+ Initialize the hash state (extended version)
+ @param md The hash state you wish to initialize
+ @param passes The number of passes that should be executed
+ when the compress function is called.
+ @return CRYPT_OK if successful
+*/
+int tiger2_init_ex(hash_state *md, unsigned long passes)
+{
+ int err;
+ if ((err = tiger2_init(md) != CRYPT_OK)) {
+ return err;
+ }
+ md->tiger.passes = passes;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(tiger_process, s_tiger_compress, tiger, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (24 bytes)
+ @return CRYPT_OK if successful
+*/
+int tiger_done(hash_state * md, unsigned char *out)
+{
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->tiger.curlen >= sizeof(md->tiger.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* increase the length of the message */
+ md->tiger.length += md->tiger.curlen * 8;
+
+ /* append the padding bit */
+ md->tiger.buf[md->tiger.curlen++] = md->tiger.pad;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal. */
+ if (md->tiger.curlen > 56) {
+ while (md->tiger.curlen < 64) {
+ md->tiger.buf[md->tiger.curlen++] = (unsigned char)0;
+ }
+ s_tiger_compress(md, md->tiger.buf);
+ md->tiger.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->tiger.curlen < 56) {
+ md->tiger.buf[md->tiger.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64L(md->tiger.length, md->tiger.buf+56);
+ s_tiger_compress(md, md->tiger.buf);
+
+ /* copy output */
+ STORE64L(md->tiger.state[0], &out[0]);
+ STORE64L(md->tiger.state[1], &out[8]);
+ STORE64L(md->tiger.state[2], &out[16]);
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+static int s_tiger_test(unsigned int idx)
+{
+ #ifndef LTC_TEST
+ LTC_UNUSED_PARAM(idx);
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[2][24];
+ } tests[] = {
+ { "",
+ {
+ { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24,
+ 0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16,
+ 0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 },
+ { 0x44, 0x41, 0xbe, 0x75, 0xf6, 0x01, 0x87, 0x73,
+ 0xc2, 0x06, 0xc2, 0x27, 0x45, 0x37, 0x4b, 0x92,
+ 0x4a, 0xa8, 0x31, 0x3f, 0xef, 0x91, 0x9f, 0x41 },
+ },
+ },
+ { "abc",
+ {
+ { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2,
+ 0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52,
+ 0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 },
+ { 0xf6, 0x8d, 0x7b, 0xc5, 0xaf, 0x4b, 0x43, 0xa0,
+ 0x6e, 0x04, 0x8d, 0x78, 0x29, 0x56, 0x0d, 0x4a,
+ 0x94, 0x15, 0x65, 0x8b, 0xb0, 0xb1, 0xf3, 0xbf },
+ },
+ },
+ { "Tiger",
+ {
+ { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f,
+ 0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27,
+ 0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 },
+ { 0xfe, 0x40, 0x79, 0x8b, 0x8e, 0xb9, 0x37, 0xfd,
+ 0x97, 0x76, 0x08, 0x93, 0x05, 0x48, 0xd6, 0xa8,
+ 0x94, 0xc2, 0x0b, 0x04, 0xcb, 0xef, 0x7a, 0x42 },
+ },
+ },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ {
+ { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87,
+ 0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47,
+ 0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 },
+ { 0x15, 0x9b, 0x38, 0x0a, 0xb7, 0x92, 0x94, 0xe0,
+ 0xda, 0x19, 0xf1, 0x62, 0x82, 0xce, 0x6d, 0xce,
+ 0x0f, 0x84, 0xd3, 0x4f, 0x72, 0x9d, 0xbe, 0xa3 },
+ },
+ },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ {
+ { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00,
+ 0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76,
+ 0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 },
+ { 0x01, 0xef, 0x91, 0x0b, 0x9b, 0xb2, 0xcb, 0x4c,
+ 0x6c, 0x47, 0x49, 0x5c, 0x86, 0xb3, 0x64, 0x1a,
+ 0xff, 0x14, 0xfb, 0xf7, 0x79, 0x40, 0x9c, 0x0e },
+ },
+ },
+ };
+ int (*init[2])(hash_state *hash) = { tiger_init, tiger2_init };
+
+ int i;
+ unsigned char tmp[24];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ init[idx](&md);
+ tiger_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ tiger_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash[idx], sizeof(tests[i].hash[idx]), !idx ? "TIGER": "TIGER2", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int tiger_test(void)
+{
+ return s_tiger_test(0);
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int tiger2_test(void)
+{
+ return s_tiger_test(1);
+}
+
+#endif
+
+/*
+Hash of "":
+ 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A
+Hash of "abc":
+ F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951
+Hash of "Tiger":
+ 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF
+Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-":
+ 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386
+Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789":
+ 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197
+Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham":
+ 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303
+Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.":
+ EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193
+Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.":
+ 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC
+Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-":
+ 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4
+*/
+
+
+
diff --git a/Sources/libtomcrypt/hashes/whirl/whirl.c b/Sources/libtomcrypt/hashes/whirl/whirl.c
new file mode 100644
index 00000000..da7db9cf
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/whirl/whirl.c
@@ -0,0 +1,296 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file whirl.c
+ LTC_WHIRLPOOL (using their new sbox) hash function by Tom St Denis
+*/
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_WHIRLPOOL
+
+const struct ltc_hash_descriptor whirlpool_desc =
+{
+ "whirlpool",
+ 11,
+ 64,
+ 64,
+
+ /* OID */
+ { 1, 0, 10118, 3, 0, 55 },
+ 6,
+
+ &whirlpool_init,
+ &whirlpool_process,
+ &whirlpool_done,
+ &whirlpool_test,
+ NULL
+};
+
+/* the sboxes */
+#define LTC_WHIRLTAB_C
+#include "whirltab.c"
+
+/* get a_{i,j} */
+#define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255)
+
+/* shortcut macro to perform three functions at once */
+#define theta_pi_gamma(a, i) \
+ (SB0(GB(a, i-0, 7)) ^ \
+ SB1(GB(a, i-1, 6)) ^ \
+ SB2(GB(a, i-2, 5)) ^ \
+ SB3(GB(a, i-3, 4)) ^ \
+ SB4(GB(a, i-4, 3)) ^ \
+ SB5(GB(a, i-5, 2)) ^ \
+ SB6(GB(a, i-6, 1)) ^ \
+ SB7(GB(a, i-7, 0)))
+
+#ifdef LTC_CLEAN_STACK
+static int ss_whirlpool_compress(hash_state *md, const unsigned char *buf)
+#else
+static int s_whirlpool_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+ ulong64 K[2][8], T[3][8];
+ int x, y;
+
+ /* load the block/state */
+ for (x = 0; x < 8; x++) {
+ K[0][x] = md->whirlpool.state[x];
+
+ LOAD64H(T[0][x], buf + (8 * x));
+ T[2][x] = T[0][x];
+ T[0][x] ^= K[0][x];
+ }
+
+ /* do rounds 1..10 */
+ for (x = 0; x < 10; x += 2) {
+ /* odd round */
+ /* apply main transform to K[0] into K[1] */
+ for (y = 0; y < 8; y++) {
+ K[1][y] = theta_pi_gamma(K[0], y);
+ }
+ /* xor the constant */
+ K[1][0] ^= cont[x];
+
+ /* apply main transform to T[0] into T[1] */
+ for (y = 0; y < 8; y++) {
+ T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y];
+ }
+
+ /* even round */
+ /* apply main transform to K[1] into K[0] */
+ for (y = 0; y < 8; y++) {
+ K[0][y] = theta_pi_gamma(K[1], y);
+ }
+ /* xor the constant */
+ K[0][0] ^= cont[x+1];
+
+ /* apply main transform to T[1] into T[0] */
+ for (y = 0; y < 8; y++) {
+ T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y];
+ }
+ }
+
+ /* store state */
+ for (x = 0; x < 8; x++) {
+ md->whirlpool.state[x] ^= T[0][x] ^ T[2][x];
+ }
+
+ return CRYPT_OK;
+}
+
+
+#ifdef LTC_CLEAN_STACK
+static int s_whirlpool_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_whirlpool_compress(md, buf);
+ burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int)));
+ return err;
+}
+#endif
+
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int whirlpool_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ zeromem(&md->whirlpool, sizeof(md->whirlpool));
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(whirlpool_process, s_whirlpool_compress, whirlpool, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (64 bytes)
+ @return CRYPT_OK if successful
+*/
+int whirlpool_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* increase the length of the message */
+ md->whirlpool.length += md->whirlpool.curlen * 8;
+
+ /* append the '1' bit */
+ md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 32 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->whirlpool.curlen > 32) {
+ while (md->whirlpool.curlen < 64) {
+ md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0;
+ }
+ s_whirlpool_compress(md, md->whirlpool.buf);
+ md->whirlpool.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths) */
+ while (md->whirlpool.curlen < 56) {
+ md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64H(md->whirlpool.length, md->whirlpool.buf+56);
+ s_whirlpool_compress(md, md->whirlpool.buf);
+
+ /* copy output */
+ for (i = 0; i < 8; i++) {
+ STORE64H(md->whirlpool.state[i], out+(8*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(*md));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int whirlpool_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ int len;
+ unsigned char msg[128], hash[64];
+ } tests[] = {
+
+ /* NULL Message */
+{
+ 0,
+ { 0x00 },
+ { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+ 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+ 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57,
+ 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 }
+},
+
+
+ /* 448-bits of 0 bits */
+{
+
+ 56,
+ { 0x00 },
+ { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03,
+ 0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70,
+ 0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61,
+ 0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 }
+},
+
+ /* 520-bits of 0 bits */
+{
+ 65,
+ { 0x00 },
+ { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D,
+ 0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4,
+ 0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF,
+ 0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 }
+},
+
+ /* 512-bits, leading set */
+{
+ 64,
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A,
+ 0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94,
+ 0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6,
+ 0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB }
+},
+
+ /* 512-bits, leading set of second byte */
+{
+ 64,
+ { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E,
+ 0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F,
+ 0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35,
+ 0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 }
+},
+
+ /* 512-bits, leading set of last byte */
+{
+ 64,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },
+ { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6,
+ 0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F,
+ 0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B,
+ 0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 }
+},
+
+};
+
+ int i;
+ unsigned char tmp[64];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+ whirlpool_init(&md);
+ whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len);
+ whirlpool_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "WHIRLPOOL", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+
+#endif
+
diff --git a/Sources/libtomcrypt/hashes/whirl/whirltab.c b/Sources/libtomcrypt/hashes/whirl/whirltab.c
new file mode 100644
index 00000000..42ecae4e
--- /dev/null
+++ b/Sources/libtomcrypt/hashes/whirl/whirltab.c
@@ -0,0 +1,586 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file whirltab.c
+ LTC_WHIRLPOOL tables, Tom St Denis
+*/
+
+#ifdef LTC_WHIRLTAB_C
+
+static const ulong64 sbox0[] = {
+CONST64(0x18186018c07830d8), CONST64(0x23238c2305af4626), CONST64(0xc6c63fc67ef991b8), CONST64(0xe8e887e8136fcdfb),
+CONST64(0x878726874ca113cb), CONST64(0xb8b8dab8a9626d11), CONST64(0x0101040108050209), CONST64(0x4f4f214f426e9e0d),
+CONST64(0x3636d836adee6c9b), CONST64(0xa6a6a2a6590451ff), CONST64(0xd2d26fd2debdb90c), CONST64(0xf5f5f3f5fb06f70e),
+CONST64(0x7979f979ef80f296), CONST64(0x6f6fa16f5fcede30), CONST64(0x91917e91fcef3f6d), CONST64(0x52525552aa07a4f8),
+CONST64(0x60609d6027fdc047), CONST64(0xbcbccabc89766535), CONST64(0x9b9b569baccd2b37), CONST64(0x8e8e028e048c018a),
+CONST64(0xa3a3b6a371155bd2), CONST64(0x0c0c300c603c186c), CONST64(0x7b7bf17bff8af684), CONST64(0x3535d435b5e16a80),
+CONST64(0x1d1d741de8693af5), CONST64(0xe0e0a7e05347ddb3), CONST64(0xd7d77bd7f6acb321), CONST64(0xc2c22fc25eed999c),
+CONST64(0x2e2eb82e6d965c43), CONST64(0x4b4b314b627a9629), CONST64(0xfefedffea321e15d), CONST64(0x575741578216aed5),
+CONST64(0x15155415a8412abd), CONST64(0x7777c1779fb6eee8), CONST64(0x3737dc37a5eb6e92), CONST64(0xe5e5b3e57b56d79e),
+CONST64(0x9f9f469f8cd92313), CONST64(0xf0f0e7f0d317fd23), CONST64(0x4a4a354a6a7f9420), CONST64(0xdada4fda9e95a944),
+CONST64(0x58587d58fa25b0a2), CONST64(0xc9c903c906ca8fcf), CONST64(0x2929a429558d527c), CONST64(0x0a0a280a5022145a),
+CONST64(0xb1b1feb1e14f7f50), CONST64(0xa0a0baa0691a5dc9), CONST64(0x6b6bb16b7fdad614), CONST64(0x85852e855cab17d9),
+CONST64(0xbdbdcebd8173673c), CONST64(0x5d5d695dd234ba8f), CONST64(0x1010401080502090), CONST64(0xf4f4f7f4f303f507),
+CONST64(0xcbcb0bcb16c08bdd), CONST64(0x3e3ef83eedc67cd3), CONST64(0x0505140528110a2d), CONST64(0x676781671fe6ce78),
+CONST64(0xe4e4b7e47353d597), CONST64(0x27279c2725bb4e02), CONST64(0x4141194132588273), CONST64(0x8b8b168b2c9d0ba7),
+CONST64(0xa7a7a6a7510153f6), CONST64(0x7d7de97dcf94fab2), CONST64(0x95956e95dcfb3749), CONST64(0xd8d847d88e9fad56),
+CONST64(0xfbfbcbfb8b30eb70), CONST64(0xeeee9fee2371c1cd), CONST64(0x7c7ced7cc791f8bb), CONST64(0x6666856617e3cc71),
+CONST64(0xdddd53dda68ea77b), CONST64(0x17175c17b84b2eaf), CONST64(0x4747014702468e45), CONST64(0x9e9e429e84dc211a),
+CONST64(0xcaca0fca1ec589d4), CONST64(0x2d2db42d75995a58), CONST64(0xbfbfc6bf9179632e), CONST64(0x07071c07381b0e3f),
+CONST64(0xadad8ead012347ac), CONST64(0x5a5a755aea2fb4b0), CONST64(0x838336836cb51bef), CONST64(0x3333cc3385ff66b6),
+CONST64(0x636391633ff2c65c), CONST64(0x02020802100a0412), CONST64(0xaaaa92aa39384993), CONST64(0x7171d971afa8e2de),
+CONST64(0xc8c807c80ecf8dc6), CONST64(0x19196419c87d32d1), CONST64(0x494939497270923b), CONST64(0xd9d943d9869aaf5f),
+CONST64(0xf2f2eff2c31df931), CONST64(0xe3e3abe34b48dba8), CONST64(0x5b5b715be22ab6b9), CONST64(0x88881a8834920dbc),
+CONST64(0x9a9a529aa4c8293e), CONST64(0x262698262dbe4c0b), CONST64(0x3232c8328dfa64bf), CONST64(0xb0b0fab0e94a7d59),
+CONST64(0xe9e983e91b6acff2), CONST64(0x0f0f3c0f78331e77), CONST64(0xd5d573d5e6a6b733), CONST64(0x80803a8074ba1df4),
+CONST64(0xbebec2be997c6127), CONST64(0xcdcd13cd26de87eb), CONST64(0x3434d034bde46889), CONST64(0x48483d487a759032),
+CONST64(0xffffdbffab24e354), CONST64(0x7a7af57af78ff48d), CONST64(0x90907a90f4ea3d64), CONST64(0x5f5f615fc23ebe9d),
+CONST64(0x202080201da0403d), CONST64(0x6868bd6867d5d00f), CONST64(0x1a1a681ad07234ca), CONST64(0xaeae82ae192c41b7),
+CONST64(0xb4b4eab4c95e757d), CONST64(0x54544d549a19a8ce), CONST64(0x93937693ece53b7f), CONST64(0x222288220daa442f),
+CONST64(0x64648d6407e9c863), CONST64(0xf1f1e3f1db12ff2a), CONST64(0x7373d173bfa2e6cc), CONST64(0x12124812905a2482),
+CONST64(0x40401d403a5d807a), CONST64(0x0808200840281048), CONST64(0xc3c32bc356e89b95), CONST64(0xecec97ec337bc5df),
+CONST64(0xdbdb4bdb9690ab4d), CONST64(0xa1a1bea1611f5fc0), CONST64(0x8d8d0e8d1c830791), CONST64(0x3d3df43df5c97ac8),
+CONST64(0x97976697ccf1335b), CONST64(0x0000000000000000), CONST64(0xcfcf1bcf36d483f9), CONST64(0x2b2bac2b4587566e),
+CONST64(0x7676c57697b3ece1), CONST64(0x8282328264b019e6), CONST64(0xd6d67fd6fea9b128), CONST64(0x1b1b6c1bd87736c3),
+CONST64(0xb5b5eeb5c15b7774), CONST64(0xafaf86af112943be), CONST64(0x6a6ab56a77dfd41d), CONST64(0x50505d50ba0da0ea),
+CONST64(0x45450945124c8a57), CONST64(0xf3f3ebf3cb18fb38), CONST64(0x3030c0309df060ad), CONST64(0xefef9bef2b74c3c4),
+CONST64(0x3f3ffc3fe5c37eda), CONST64(0x55554955921caac7), CONST64(0xa2a2b2a2791059db), CONST64(0xeaea8fea0365c9e9),
+CONST64(0x656589650fecca6a), CONST64(0xbabad2bab9686903), CONST64(0x2f2fbc2f65935e4a), CONST64(0xc0c027c04ee79d8e),
+CONST64(0xdede5fdebe81a160), CONST64(0x1c1c701ce06c38fc), CONST64(0xfdfdd3fdbb2ee746), CONST64(0x4d4d294d52649a1f),
+CONST64(0x92927292e4e03976), CONST64(0x7575c9758fbceafa), CONST64(0x06061806301e0c36), CONST64(0x8a8a128a249809ae),
+CONST64(0xb2b2f2b2f940794b), CONST64(0xe6e6bfe66359d185), CONST64(0x0e0e380e70361c7e), CONST64(0x1f1f7c1ff8633ee7),
+CONST64(0x6262956237f7c455), CONST64(0xd4d477d4eea3b53a), CONST64(0xa8a89aa829324d81), CONST64(0x96966296c4f43152),
+CONST64(0xf9f9c3f99b3aef62), CONST64(0xc5c533c566f697a3), CONST64(0x2525942535b14a10), CONST64(0x59597959f220b2ab),
+CONST64(0x84842a8454ae15d0), CONST64(0x7272d572b7a7e4c5), CONST64(0x3939e439d5dd72ec), CONST64(0x4c4c2d4c5a619816),
+CONST64(0x5e5e655eca3bbc94), CONST64(0x7878fd78e785f09f), CONST64(0x3838e038ddd870e5), CONST64(0x8c8c0a8c14860598),
+CONST64(0xd1d163d1c6b2bf17), CONST64(0xa5a5aea5410b57e4), CONST64(0xe2e2afe2434dd9a1), CONST64(0x616199612ff8c24e),
+CONST64(0xb3b3f6b3f1457b42), CONST64(0x2121842115a54234), CONST64(0x9c9c4a9c94d62508), CONST64(0x1e1e781ef0663cee),
+CONST64(0x4343114322528661), CONST64(0xc7c73bc776fc93b1), CONST64(0xfcfcd7fcb32be54f), CONST64(0x0404100420140824),
+CONST64(0x51515951b208a2e3), CONST64(0x99995e99bcc72f25), CONST64(0x6d6da96d4fc4da22), CONST64(0x0d0d340d68391a65),
+CONST64(0xfafacffa8335e979), CONST64(0xdfdf5bdfb684a369), CONST64(0x7e7ee57ed79bfca9), CONST64(0x242490243db44819),
+CONST64(0x3b3bec3bc5d776fe), CONST64(0xabab96ab313d4b9a), CONST64(0xcece1fce3ed181f0), CONST64(0x1111441188552299),
+CONST64(0x8f8f068f0c890383), CONST64(0x4e4e254e4a6b9c04), CONST64(0xb7b7e6b7d1517366), CONST64(0xebeb8beb0b60cbe0),
+CONST64(0x3c3cf03cfdcc78c1), CONST64(0x81813e817cbf1ffd), CONST64(0x94946a94d4fe3540), CONST64(0xf7f7fbf7eb0cf31c),
+CONST64(0xb9b9deb9a1676f18), CONST64(0x13134c13985f268b), CONST64(0x2c2cb02c7d9c5851), CONST64(0xd3d36bd3d6b8bb05),
+CONST64(0xe7e7bbe76b5cd38c), CONST64(0x6e6ea56e57cbdc39), CONST64(0xc4c437c46ef395aa), CONST64(0x03030c03180f061b),
+CONST64(0x565645568a13acdc), CONST64(0x44440d441a49885e), CONST64(0x7f7fe17fdf9efea0), CONST64(0xa9a99ea921374f88),
+CONST64(0x2a2aa82a4d825467), CONST64(0xbbbbd6bbb16d6b0a), CONST64(0xc1c123c146e29f87), CONST64(0x53535153a202a6f1),
+CONST64(0xdcdc57dcae8ba572), CONST64(0x0b0b2c0b58271653), CONST64(0x9d9d4e9d9cd32701), CONST64(0x6c6cad6c47c1d82b),
+CONST64(0x3131c43195f562a4), CONST64(0x7474cd7487b9e8f3), CONST64(0xf6f6fff6e309f115), CONST64(0x464605460a438c4c),
+CONST64(0xacac8aac092645a5), CONST64(0x89891e893c970fb5), CONST64(0x14145014a04428b4), CONST64(0xe1e1a3e15b42dfba),
+CONST64(0x16165816b04e2ca6), CONST64(0x3a3ae83acdd274f7), CONST64(0x6969b9696fd0d206), CONST64(0x09092409482d1241),
+CONST64(0x7070dd70a7ade0d7), CONST64(0xb6b6e2b6d954716f), CONST64(0xd0d067d0ceb7bd1e), CONST64(0xeded93ed3b7ec7d6),
+CONST64(0xcccc17cc2edb85e2), CONST64(0x424215422a578468), CONST64(0x98985a98b4c22d2c), CONST64(0xa4a4aaa4490e55ed),
+CONST64(0x2828a0285d885075), CONST64(0x5c5c6d5cda31b886), CONST64(0xf8f8c7f8933fed6b), CONST64(0x8686228644a411c2)
+};
+
+#ifdef LTC_SMALL_CODE
+
+#define SB0(x) sbox0[x]
+#define SB1(x) ROR64c(sbox0[x], 8)
+#define SB2(x) ROR64c(sbox0[x], 16)
+#define SB3(x) ROR64c(sbox0[x], 24)
+#define SB4(x) ROR64c(sbox0[x], 32)
+#define SB5(x) ROR64c(sbox0[x], 40)
+#define SB6(x) ROR64c(sbox0[x], 48)
+#define SB7(x) ROR64c(sbox0[x], 56)
+
+#else
+
+#define SB0(x) sbox0[x]
+#define SB1(x) sbox1[x]
+#define SB2(x) sbox2[x]
+#define SB3(x) sbox3[x]
+#define SB4(x) sbox4[x]
+#define SB5(x) sbox5[x]
+#define SB6(x) sbox6[x]
+#define SB7(x) sbox7[x]
+
+
+static const ulong64 sbox1[] = {
+CONST64(0xd818186018c07830), CONST64(0x2623238c2305af46), CONST64(0xb8c6c63fc67ef991), CONST64(0xfbe8e887e8136fcd),
+CONST64(0xcb878726874ca113), CONST64(0x11b8b8dab8a9626d), CONST64(0x0901010401080502), CONST64(0x0d4f4f214f426e9e),
+CONST64(0x9b3636d836adee6c), CONST64(0xffa6a6a2a6590451), CONST64(0x0cd2d26fd2debdb9), CONST64(0x0ef5f5f3f5fb06f7),
+CONST64(0x967979f979ef80f2), CONST64(0x306f6fa16f5fcede), CONST64(0x6d91917e91fcef3f), CONST64(0xf852525552aa07a4),
+CONST64(0x4760609d6027fdc0), CONST64(0x35bcbccabc897665), CONST64(0x379b9b569baccd2b), CONST64(0x8a8e8e028e048c01),
+CONST64(0xd2a3a3b6a371155b), CONST64(0x6c0c0c300c603c18), CONST64(0x847b7bf17bff8af6), CONST64(0x803535d435b5e16a),
+CONST64(0xf51d1d741de8693a), CONST64(0xb3e0e0a7e05347dd), CONST64(0x21d7d77bd7f6acb3), CONST64(0x9cc2c22fc25eed99),
+CONST64(0x432e2eb82e6d965c), CONST64(0x294b4b314b627a96), CONST64(0x5dfefedffea321e1), CONST64(0xd5575741578216ae),
+CONST64(0xbd15155415a8412a), CONST64(0xe87777c1779fb6ee), CONST64(0x923737dc37a5eb6e), CONST64(0x9ee5e5b3e57b56d7),
+CONST64(0x139f9f469f8cd923), CONST64(0x23f0f0e7f0d317fd), CONST64(0x204a4a354a6a7f94), CONST64(0x44dada4fda9e95a9),
+CONST64(0xa258587d58fa25b0), CONST64(0xcfc9c903c906ca8f), CONST64(0x7c2929a429558d52), CONST64(0x5a0a0a280a502214),
+CONST64(0x50b1b1feb1e14f7f), CONST64(0xc9a0a0baa0691a5d), CONST64(0x146b6bb16b7fdad6), CONST64(0xd985852e855cab17),
+CONST64(0x3cbdbdcebd817367), CONST64(0x8f5d5d695dd234ba), CONST64(0x9010104010805020), CONST64(0x07f4f4f7f4f303f5),
+CONST64(0xddcbcb0bcb16c08b), CONST64(0xd33e3ef83eedc67c), CONST64(0x2d0505140528110a), CONST64(0x78676781671fe6ce),
+CONST64(0x97e4e4b7e47353d5), CONST64(0x0227279c2725bb4e), CONST64(0x7341411941325882), CONST64(0xa78b8b168b2c9d0b),
+CONST64(0xf6a7a7a6a7510153), CONST64(0xb27d7de97dcf94fa), CONST64(0x4995956e95dcfb37), CONST64(0x56d8d847d88e9fad),
+CONST64(0x70fbfbcbfb8b30eb), CONST64(0xcdeeee9fee2371c1), CONST64(0xbb7c7ced7cc791f8), CONST64(0x716666856617e3cc),
+CONST64(0x7bdddd53dda68ea7), CONST64(0xaf17175c17b84b2e), CONST64(0x454747014702468e), CONST64(0x1a9e9e429e84dc21),
+CONST64(0xd4caca0fca1ec589), CONST64(0x582d2db42d75995a), CONST64(0x2ebfbfc6bf917963), CONST64(0x3f07071c07381b0e),
+CONST64(0xacadad8ead012347), CONST64(0xb05a5a755aea2fb4), CONST64(0xef838336836cb51b), CONST64(0xb63333cc3385ff66),
+CONST64(0x5c636391633ff2c6), CONST64(0x1202020802100a04), CONST64(0x93aaaa92aa393849), CONST64(0xde7171d971afa8e2),
+CONST64(0xc6c8c807c80ecf8d), CONST64(0xd119196419c87d32), CONST64(0x3b49493949727092), CONST64(0x5fd9d943d9869aaf),
+CONST64(0x31f2f2eff2c31df9), CONST64(0xa8e3e3abe34b48db), CONST64(0xb95b5b715be22ab6), CONST64(0xbc88881a8834920d),
+CONST64(0x3e9a9a529aa4c829), CONST64(0x0b262698262dbe4c), CONST64(0xbf3232c8328dfa64), CONST64(0x59b0b0fab0e94a7d),
+CONST64(0xf2e9e983e91b6acf), CONST64(0x770f0f3c0f78331e), CONST64(0x33d5d573d5e6a6b7), CONST64(0xf480803a8074ba1d),
+CONST64(0x27bebec2be997c61), CONST64(0xebcdcd13cd26de87), CONST64(0x893434d034bde468), CONST64(0x3248483d487a7590),
+CONST64(0x54ffffdbffab24e3), CONST64(0x8d7a7af57af78ff4), CONST64(0x6490907a90f4ea3d), CONST64(0x9d5f5f615fc23ebe),
+CONST64(0x3d202080201da040), CONST64(0x0f6868bd6867d5d0), CONST64(0xca1a1a681ad07234), CONST64(0xb7aeae82ae192c41),
+CONST64(0x7db4b4eab4c95e75), CONST64(0xce54544d549a19a8), CONST64(0x7f93937693ece53b), CONST64(0x2f222288220daa44),
+CONST64(0x6364648d6407e9c8), CONST64(0x2af1f1e3f1db12ff), CONST64(0xcc7373d173bfa2e6), CONST64(0x8212124812905a24),
+CONST64(0x7a40401d403a5d80), CONST64(0x4808082008402810), CONST64(0x95c3c32bc356e89b), CONST64(0xdfecec97ec337bc5),
+CONST64(0x4ddbdb4bdb9690ab), CONST64(0xc0a1a1bea1611f5f), CONST64(0x918d8d0e8d1c8307), CONST64(0xc83d3df43df5c97a),
+CONST64(0x5b97976697ccf133), CONST64(0x0000000000000000), CONST64(0xf9cfcf1bcf36d483), CONST64(0x6e2b2bac2b458756),
+CONST64(0xe17676c57697b3ec), CONST64(0xe68282328264b019), CONST64(0x28d6d67fd6fea9b1), CONST64(0xc31b1b6c1bd87736),
+CONST64(0x74b5b5eeb5c15b77), CONST64(0xbeafaf86af112943), CONST64(0x1d6a6ab56a77dfd4), CONST64(0xea50505d50ba0da0),
+CONST64(0x5745450945124c8a), CONST64(0x38f3f3ebf3cb18fb), CONST64(0xad3030c0309df060), CONST64(0xc4efef9bef2b74c3),
+CONST64(0xda3f3ffc3fe5c37e), CONST64(0xc755554955921caa), CONST64(0xdba2a2b2a2791059), CONST64(0xe9eaea8fea0365c9),
+CONST64(0x6a656589650fecca), CONST64(0x03babad2bab96869), CONST64(0x4a2f2fbc2f65935e), CONST64(0x8ec0c027c04ee79d),
+CONST64(0x60dede5fdebe81a1), CONST64(0xfc1c1c701ce06c38), CONST64(0x46fdfdd3fdbb2ee7), CONST64(0x1f4d4d294d52649a),
+CONST64(0x7692927292e4e039), CONST64(0xfa7575c9758fbcea), CONST64(0x3606061806301e0c), CONST64(0xae8a8a128a249809),
+CONST64(0x4bb2b2f2b2f94079), CONST64(0x85e6e6bfe66359d1), CONST64(0x7e0e0e380e70361c), CONST64(0xe71f1f7c1ff8633e),
+CONST64(0x556262956237f7c4), CONST64(0x3ad4d477d4eea3b5), CONST64(0x81a8a89aa829324d), CONST64(0x5296966296c4f431),
+CONST64(0x62f9f9c3f99b3aef), CONST64(0xa3c5c533c566f697), CONST64(0x102525942535b14a), CONST64(0xab59597959f220b2),
+CONST64(0xd084842a8454ae15), CONST64(0xc57272d572b7a7e4), CONST64(0xec3939e439d5dd72), CONST64(0x164c4c2d4c5a6198),
+CONST64(0x945e5e655eca3bbc), CONST64(0x9f7878fd78e785f0), CONST64(0xe53838e038ddd870), CONST64(0x988c8c0a8c148605),
+CONST64(0x17d1d163d1c6b2bf), CONST64(0xe4a5a5aea5410b57), CONST64(0xa1e2e2afe2434dd9), CONST64(0x4e616199612ff8c2),
+CONST64(0x42b3b3f6b3f1457b), CONST64(0x342121842115a542), CONST64(0x089c9c4a9c94d625), CONST64(0xee1e1e781ef0663c),
+CONST64(0x6143431143225286), CONST64(0xb1c7c73bc776fc93), CONST64(0x4ffcfcd7fcb32be5), CONST64(0x2404041004201408),
+CONST64(0xe351515951b208a2), CONST64(0x2599995e99bcc72f), CONST64(0x226d6da96d4fc4da), CONST64(0x650d0d340d68391a),
+CONST64(0x79fafacffa8335e9), CONST64(0x69dfdf5bdfb684a3), CONST64(0xa97e7ee57ed79bfc), CONST64(0x19242490243db448),
+CONST64(0xfe3b3bec3bc5d776), CONST64(0x9aabab96ab313d4b), CONST64(0xf0cece1fce3ed181), CONST64(0x9911114411885522),
+CONST64(0x838f8f068f0c8903), CONST64(0x044e4e254e4a6b9c), CONST64(0x66b7b7e6b7d15173), CONST64(0xe0ebeb8beb0b60cb),
+CONST64(0xc13c3cf03cfdcc78), CONST64(0xfd81813e817cbf1f), CONST64(0x4094946a94d4fe35), CONST64(0x1cf7f7fbf7eb0cf3),
+CONST64(0x18b9b9deb9a1676f), CONST64(0x8b13134c13985f26), CONST64(0x512c2cb02c7d9c58), CONST64(0x05d3d36bd3d6b8bb),
+CONST64(0x8ce7e7bbe76b5cd3), CONST64(0x396e6ea56e57cbdc), CONST64(0xaac4c437c46ef395), CONST64(0x1b03030c03180f06),
+CONST64(0xdc565645568a13ac), CONST64(0x5e44440d441a4988), CONST64(0xa07f7fe17fdf9efe), CONST64(0x88a9a99ea921374f),
+CONST64(0x672a2aa82a4d8254), CONST64(0x0abbbbd6bbb16d6b), CONST64(0x87c1c123c146e29f), CONST64(0xf153535153a202a6),
+CONST64(0x72dcdc57dcae8ba5), CONST64(0x530b0b2c0b582716), CONST64(0x019d9d4e9d9cd327), CONST64(0x2b6c6cad6c47c1d8),
+CONST64(0xa43131c43195f562), CONST64(0xf37474cd7487b9e8), CONST64(0x15f6f6fff6e309f1), CONST64(0x4c464605460a438c),
+CONST64(0xa5acac8aac092645), CONST64(0xb589891e893c970f), CONST64(0xb414145014a04428), CONST64(0xbae1e1a3e15b42df),
+CONST64(0xa616165816b04e2c), CONST64(0xf73a3ae83acdd274), CONST64(0x066969b9696fd0d2), CONST64(0x4109092409482d12),
+CONST64(0xd77070dd70a7ade0), CONST64(0x6fb6b6e2b6d95471), CONST64(0x1ed0d067d0ceb7bd), CONST64(0xd6eded93ed3b7ec7),
+CONST64(0xe2cccc17cc2edb85), CONST64(0x68424215422a5784), CONST64(0x2c98985a98b4c22d), CONST64(0xeda4a4aaa4490e55),
+CONST64(0x752828a0285d8850), CONST64(0x865c5c6d5cda31b8), CONST64(0x6bf8f8c7f8933fed), CONST64(0xc28686228644a411)
+};
+
+static const ulong64 sbox2[] = {
+CONST64(0x30d818186018c078), CONST64(0x462623238c2305af), CONST64(0x91b8c6c63fc67ef9), CONST64(0xcdfbe8e887e8136f),
+CONST64(0x13cb878726874ca1), CONST64(0x6d11b8b8dab8a962), CONST64(0x0209010104010805), CONST64(0x9e0d4f4f214f426e),
+CONST64(0x6c9b3636d836adee), CONST64(0x51ffa6a6a2a65904), CONST64(0xb90cd2d26fd2debd), CONST64(0xf70ef5f5f3f5fb06),
+CONST64(0xf2967979f979ef80), CONST64(0xde306f6fa16f5fce), CONST64(0x3f6d91917e91fcef), CONST64(0xa4f852525552aa07),
+CONST64(0xc04760609d6027fd), CONST64(0x6535bcbccabc8976), CONST64(0x2b379b9b569baccd), CONST64(0x018a8e8e028e048c),
+CONST64(0x5bd2a3a3b6a37115), CONST64(0x186c0c0c300c603c), CONST64(0xf6847b7bf17bff8a), CONST64(0x6a803535d435b5e1),
+CONST64(0x3af51d1d741de869), CONST64(0xddb3e0e0a7e05347), CONST64(0xb321d7d77bd7f6ac), CONST64(0x999cc2c22fc25eed),
+CONST64(0x5c432e2eb82e6d96), CONST64(0x96294b4b314b627a), CONST64(0xe15dfefedffea321), CONST64(0xaed5575741578216),
+CONST64(0x2abd15155415a841), CONST64(0xeee87777c1779fb6), CONST64(0x6e923737dc37a5eb), CONST64(0xd79ee5e5b3e57b56),
+CONST64(0x23139f9f469f8cd9), CONST64(0xfd23f0f0e7f0d317), CONST64(0x94204a4a354a6a7f), CONST64(0xa944dada4fda9e95),
+CONST64(0xb0a258587d58fa25), CONST64(0x8fcfc9c903c906ca), CONST64(0x527c2929a429558d), CONST64(0x145a0a0a280a5022),
+CONST64(0x7f50b1b1feb1e14f), CONST64(0x5dc9a0a0baa0691a), CONST64(0xd6146b6bb16b7fda), CONST64(0x17d985852e855cab),
+CONST64(0x673cbdbdcebd8173), CONST64(0xba8f5d5d695dd234), CONST64(0x2090101040108050), CONST64(0xf507f4f4f7f4f303),
+CONST64(0x8bddcbcb0bcb16c0), CONST64(0x7cd33e3ef83eedc6), CONST64(0x0a2d050514052811), CONST64(0xce78676781671fe6),
+CONST64(0xd597e4e4b7e47353), CONST64(0x4e0227279c2725bb), CONST64(0x8273414119413258), CONST64(0x0ba78b8b168b2c9d),
+CONST64(0x53f6a7a7a6a75101), CONST64(0xfab27d7de97dcf94), CONST64(0x374995956e95dcfb), CONST64(0xad56d8d847d88e9f),
+CONST64(0xeb70fbfbcbfb8b30), CONST64(0xc1cdeeee9fee2371), CONST64(0xf8bb7c7ced7cc791), CONST64(0xcc716666856617e3),
+CONST64(0xa77bdddd53dda68e), CONST64(0x2eaf17175c17b84b), CONST64(0x8e45474701470246), CONST64(0x211a9e9e429e84dc),
+CONST64(0x89d4caca0fca1ec5), CONST64(0x5a582d2db42d7599), CONST64(0x632ebfbfc6bf9179), CONST64(0x0e3f07071c07381b),
+CONST64(0x47acadad8ead0123), CONST64(0xb4b05a5a755aea2f), CONST64(0x1bef838336836cb5), CONST64(0x66b63333cc3385ff),
+CONST64(0xc65c636391633ff2), CONST64(0x041202020802100a), CONST64(0x4993aaaa92aa3938), CONST64(0xe2de7171d971afa8),
+CONST64(0x8dc6c8c807c80ecf), CONST64(0x32d119196419c87d), CONST64(0x923b494939497270), CONST64(0xaf5fd9d943d9869a),
+CONST64(0xf931f2f2eff2c31d), CONST64(0xdba8e3e3abe34b48), CONST64(0xb6b95b5b715be22a), CONST64(0x0dbc88881a883492),
+CONST64(0x293e9a9a529aa4c8), CONST64(0x4c0b262698262dbe), CONST64(0x64bf3232c8328dfa), CONST64(0x7d59b0b0fab0e94a),
+CONST64(0xcff2e9e983e91b6a), CONST64(0x1e770f0f3c0f7833), CONST64(0xb733d5d573d5e6a6), CONST64(0x1df480803a8074ba),
+CONST64(0x6127bebec2be997c), CONST64(0x87ebcdcd13cd26de), CONST64(0x68893434d034bde4), CONST64(0x903248483d487a75),
+CONST64(0xe354ffffdbffab24), CONST64(0xf48d7a7af57af78f), CONST64(0x3d6490907a90f4ea), CONST64(0xbe9d5f5f615fc23e),
+CONST64(0x403d202080201da0), CONST64(0xd00f6868bd6867d5), CONST64(0x34ca1a1a681ad072), CONST64(0x41b7aeae82ae192c),
+CONST64(0x757db4b4eab4c95e), CONST64(0xa8ce54544d549a19), CONST64(0x3b7f93937693ece5), CONST64(0x442f222288220daa),
+CONST64(0xc86364648d6407e9), CONST64(0xff2af1f1e3f1db12), CONST64(0xe6cc7373d173bfa2), CONST64(0x248212124812905a),
+CONST64(0x807a40401d403a5d), CONST64(0x1048080820084028), CONST64(0x9b95c3c32bc356e8), CONST64(0xc5dfecec97ec337b),
+CONST64(0xab4ddbdb4bdb9690), CONST64(0x5fc0a1a1bea1611f), CONST64(0x07918d8d0e8d1c83), CONST64(0x7ac83d3df43df5c9),
+CONST64(0x335b97976697ccf1), CONST64(0x0000000000000000), CONST64(0x83f9cfcf1bcf36d4), CONST64(0x566e2b2bac2b4587),
+CONST64(0xece17676c57697b3), CONST64(0x19e68282328264b0), CONST64(0xb128d6d67fd6fea9), CONST64(0x36c31b1b6c1bd877),
+CONST64(0x7774b5b5eeb5c15b), CONST64(0x43beafaf86af1129), CONST64(0xd41d6a6ab56a77df), CONST64(0xa0ea50505d50ba0d),
+CONST64(0x8a5745450945124c), CONST64(0xfb38f3f3ebf3cb18), CONST64(0x60ad3030c0309df0), CONST64(0xc3c4efef9bef2b74),
+CONST64(0x7eda3f3ffc3fe5c3), CONST64(0xaac755554955921c), CONST64(0x59dba2a2b2a27910), CONST64(0xc9e9eaea8fea0365),
+CONST64(0xca6a656589650fec), CONST64(0x6903babad2bab968), CONST64(0x5e4a2f2fbc2f6593), CONST64(0x9d8ec0c027c04ee7),
+CONST64(0xa160dede5fdebe81), CONST64(0x38fc1c1c701ce06c), CONST64(0xe746fdfdd3fdbb2e), CONST64(0x9a1f4d4d294d5264),
+CONST64(0x397692927292e4e0), CONST64(0xeafa7575c9758fbc), CONST64(0x0c3606061806301e), CONST64(0x09ae8a8a128a2498),
+CONST64(0x794bb2b2f2b2f940), CONST64(0xd185e6e6bfe66359), CONST64(0x1c7e0e0e380e7036), CONST64(0x3ee71f1f7c1ff863),
+CONST64(0xc4556262956237f7), CONST64(0xb53ad4d477d4eea3), CONST64(0x4d81a8a89aa82932), CONST64(0x315296966296c4f4),
+CONST64(0xef62f9f9c3f99b3a), CONST64(0x97a3c5c533c566f6), CONST64(0x4a102525942535b1), CONST64(0xb2ab59597959f220),
+CONST64(0x15d084842a8454ae), CONST64(0xe4c57272d572b7a7), CONST64(0x72ec3939e439d5dd), CONST64(0x98164c4c2d4c5a61),
+CONST64(0xbc945e5e655eca3b), CONST64(0xf09f7878fd78e785), CONST64(0x70e53838e038ddd8), CONST64(0x05988c8c0a8c1486),
+CONST64(0xbf17d1d163d1c6b2), CONST64(0x57e4a5a5aea5410b), CONST64(0xd9a1e2e2afe2434d), CONST64(0xc24e616199612ff8),
+CONST64(0x7b42b3b3f6b3f145), CONST64(0x42342121842115a5), CONST64(0x25089c9c4a9c94d6), CONST64(0x3cee1e1e781ef066),
+CONST64(0x8661434311432252), CONST64(0x93b1c7c73bc776fc), CONST64(0xe54ffcfcd7fcb32b), CONST64(0x0824040410042014),
+CONST64(0xa2e351515951b208), CONST64(0x2f2599995e99bcc7), CONST64(0xda226d6da96d4fc4), CONST64(0x1a650d0d340d6839),
+CONST64(0xe979fafacffa8335), CONST64(0xa369dfdf5bdfb684), CONST64(0xfca97e7ee57ed79b), CONST64(0x4819242490243db4),
+CONST64(0x76fe3b3bec3bc5d7), CONST64(0x4b9aabab96ab313d), CONST64(0x81f0cece1fce3ed1), CONST64(0x2299111144118855),
+CONST64(0x03838f8f068f0c89), CONST64(0x9c044e4e254e4a6b), CONST64(0x7366b7b7e6b7d151), CONST64(0xcbe0ebeb8beb0b60),
+CONST64(0x78c13c3cf03cfdcc), CONST64(0x1ffd81813e817cbf), CONST64(0x354094946a94d4fe), CONST64(0xf31cf7f7fbf7eb0c),
+CONST64(0x6f18b9b9deb9a167), CONST64(0x268b13134c13985f), CONST64(0x58512c2cb02c7d9c), CONST64(0xbb05d3d36bd3d6b8),
+CONST64(0xd38ce7e7bbe76b5c), CONST64(0xdc396e6ea56e57cb), CONST64(0x95aac4c437c46ef3), CONST64(0x061b03030c03180f),
+CONST64(0xacdc565645568a13), CONST64(0x885e44440d441a49), CONST64(0xfea07f7fe17fdf9e), CONST64(0x4f88a9a99ea92137),
+CONST64(0x54672a2aa82a4d82), CONST64(0x6b0abbbbd6bbb16d), CONST64(0x9f87c1c123c146e2), CONST64(0xa6f153535153a202),
+CONST64(0xa572dcdc57dcae8b), CONST64(0x16530b0b2c0b5827), CONST64(0x27019d9d4e9d9cd3), CONST64(0xd82b6c6cad6c47c1),
+CONST64(0x62a43131c43195f5), CONST64(0xe8f37474cd7487b9), CONST64(0xf115f6f6fff6e309), CONST64(0x8c4c464605460a43),
+CONST64(0x45a5acac8aac0926), CONST64(0x0fb589891e893c97), CONST64(0x28b414145014a044), CONST64(0xdfbae1e1a3e15b42),
+CONST64(0x2ca616165816b04e), CONST64(0x74f73a3ae83acdd2), CONST64(0xd2066969b9696fd0), CONST64(0x124109092409482d),
+CONST64(0xe0d77070dd70a7ad), CONST64(0x716fb6b6e2b6d954), CONST64(0xbd1ed0d067d0ceb7), CONST64(0xc7d6eded93ed3b7e),
+CONST64(0x85e2cccc17cc2edb), CONST64(0x8468424215422a57), CONST64(0x2d2c98985a98b4c2), CONST64(0x55eda4a4aaa4490e),
+CONST64(0x50752828a0285d88), CONST64(0xb8865c5c6d5cda31), CONST64(0xed6bf8f8c7f8933f), CONST64(0x11c28686228644a4)
+};
+
+static const ulong64 sbox3[] = {
+CONST64(0x7830d818186018c0), CONST64(0xaf462623238c2305), CONST64(0xf991b8c6c63fc67e), CONST64(0x6fcdfbe8e887e813),
+CONST64(0xa113cb878726874c), CONST64(0x626d11b8b8dab8a9), CONST64(0x0502090101040108), CONST64(0x6e9e0d4f4f214f42),
+CONST64(0xee6c9b3636d836ad), CONST64(0x0451ffa6a6a2a659), CONST64(0xbdb90cd2d26fd2de), CONST64(0x06f70ef5f5f3f5fb),
+CONST64(0x80f2967979f979ef), CONST64(0xcede306f6fa16f5f), CONST64(0xef3f6d91917e91fc), CONST64(0x07a4f852525552aa),
+CONST64(0xfdc04760609d6027), CONST64(0x766535bcbccabc89), CONST64(0xcd2b379b9b569bac), CONST64(0x8c018a8e8e028e04),
+CONST64(0x155bd2a3a3b6a371), CONST64(0x3c186c0c0c300c60), CONST64(0x8af6847b7bf17bff), CONST64(0xe16a803535d435b5),
+CONST64(0x693af51d1d741de8), CONST64(0x47ddb3e0e0a7e053), CONST64(0xacb321d7d77bd7f6), CONST64(0xed999cc2c22fc25e),
+CONST64(0x965c432e2eb82e6d), CONST64(0x7a96294b4b314b62), CONST64(0x21e15dfefedffea3), CONST64(0x16aed55757415782),
+CONST64(0x412abd15155415a8), CONST64(0xb6eee87777c1779f), CONST64(0xeb6e923737dc37a5), CONST64(0x56d79ee5e5b3e57b),
+CONST64(0xd923139f9f469f8c), CONST64(0x17fd23f0f0e7f0d3), CONST64(0x7f94204a4a354a6a), CONST64(0x95a944dada4fda9e),
+CONST64(0x25b0a258587d58fa), CONST64(0xca8fcfc9c903c906), CONST64(0x8d527c2929a42955), CONST64(0x22145a0a0a280a50),
+CONST64(0x4f7f50b1b1feb1e1), CONST64(0x1a5dc9a0a0baa069), CONST64(0xdad6146b6bb16b7f), CONST64(0xab17d985852e855c),
+CONST64(0x73673cbdbdcebd81), CONST64(0x34ba8f5d5d695dd2), CONST64(0x5020901010401080), CONST64(0x03f507f4f4f7f4f3),
+CONST64(0xc08bddcbcb0bcb16), CONST64(0xc67cd33e3ef83eed), CONST64(0x110a2d0505140528), CONST64(0xe6ce78676781671f),
+CONST64(0x53d597e4e4b7e473), CONST64(0xbb4e0227279c2725), CONST64(0x5882734141194132), CONST64(0x9d0ba78b8b168b2c),
+CONST64(0x0153f6a7a7a6a751), CONST64(0x94fab27d7de97dcf), CONST64(0xfb374995956e95dc), CONST64(0x9fad56d8d847d88e),
+CONST64(0x30eb70fbfbcbfb8b), CONST64(0x71c1cdeeee9fee23), CONST64(0x91f8bb7c7ced7cc7), CONST64(0xe3cc716666856617),
+CONST64(0x8ea77bdddd53dda6), CONST64(0x4b2eaf17175c17b8), CONST64(0x468e454747014702), CONST64(0xdc211a9e9e429e84),
+CONST64(0xc589d4caca0fca1e), CONST64(0x995a582d2db42d75), CONST64(0x79632ebfbfc6bf91), CONST64(0x1b0e3f07071c0738),
+CONST64(0x2347acadad8ead01), CONST64(0x2fb4b05a5a755aea), CONST64(0xb51bef838336836c), CONST64(0xff66b63333cc3385),
+CONST64(0xf2c65c636391633f), CONST64(0x0a04120202080210), CONST64(0x384993aaaa92aa39), CONST64(0xa8e2de7171d971af),
+CONST64(0xcf8dc6c8c807c80e), CONST64(0x7d32d119196419c8), CONST64(0x70923b4949394972), CONST64(0x9aaf5fd9d943d986),
+CONST64(0x1df931f2f2eff2c3), CONST64(0x48dba8e3e3abe34b), CONST64(0x2ab6b95b5b715be2), CONST64(0x920dbc88881a8834),
+CONST64(0xc8293e9a9a529aa4), CONST64(0xbe4c0b262698262d), CONST64(0xfa64bf3232c8328d), CONST64(0x4a7d59b0b0fab0e9),
+CONST64(0x6acff2e9e983e91b), CONST64(0x331e770f0f3c0f78), CONST64(0xa6b733d5d573d5e6), CONST64(0xba1df480803a8074),
+CONST64(0x7c6127bebec2be99), CONST64(0xde87ebcdcd13cd26), CONST64(0xe468893434d034bd), CONST64(0x75903248483d487a),
+CONST64(0x24e354ffffdbffab), CONST64(0x8ff48d7a7af57af7), CONST64(0xea3d6490907a90f4), CONST64(0x3ebe9d5f5f615fc2),
+CONST64(0xa0403d202080201d), CONST64(0xd5d00f6868bd6867), CONST64(0x7234ca1a1a681ad0), CONST64(0x2c41b7aeae82ae19),
+CONST64(0x5e757db4b4eab4c9), CONST64(0x19a8ce54544d549a), CONST64(0xe53b7f93937693ec), CONST64(0xaa442f222288220d),
+CONST64(0xe9c86364648d6407), CONST64(0x12ff2af1f1e3f1db), CONST64(0xa2e6cc7373d173bf), CONST64(0x5a24821212481290),
+CONST64(0x5d807a40401d403a), CONST64(0x2810480808200840), CONST64(0xe89b95c3c32bc356), CONST64(0x7bc5dfecec97ec33),
+CONST64(0x90ab4ddbdb4bdb96), CONST64(0x1f5fc0a1a1bea161), CONST64(0x8307918d8d0e8d1c), CONST64(0xc97ac83d3df43df5),
+CONST64(0xf1335b97976697cc), CONST64(0x0000000000000000), CONST64(0xd483f9cfcf1bcf36), CONST64(0x87566e2b2bac2b45),
+CONST64(0xb3ece17676c57697), CONST64(0xb019e68282328264), CONST64(0xa9b128d6d67fd6fe), CONST64(0x7736c31b1b6c1bd8),
+CONST64(0x5b7774b5b5eeb5c1), CONST64(0x2943beafaf86af11), CONST64(0xdfd41d6a6ab56a77), CONST64(0x0da0ea50505d50ba),
+CONST64(0x4c8a574545094512), CONST64(0x18fb38f3f3ebf3cb), CONST64(0xf060ad3030c0309d), CONST64(0x74c3c4efef9bef2b),
+CONST64(0xc37eda3f3ffc3fe5), CONST64(0x1caac75555495592), CONST64(0x1059dba2a2b2a279), CONST64(0x65c9e9eaea8fea03),
+CONST64(0xecca6a656589650f), CONST64(0x686903babad2bab9), CONST64(0x935e4a2f2fbc2f65), CONST64(0xe79d8ec0c027c04e),
+CONST64(0x81a160dede5fdebe), CONST64(0x6c38fc1c1c701ce0), CONST64(0x2ee746fdfdd3fdbb), CONST64(0x649a1f4d4d294d52),
+CONST64(0xe0397692927292e4), CONST64(0xbceafa7575c9758f), CONST64(0x1e0c360606180630), CONST64(0x9809ae8a8a128a24),
+CONST64(0x40794bb2b2f2b2f9), CONST64(0x59d185e6e6bfe663), CONST64(0x361c7e0e0e380e70), CONST64(0x633ee71f1f7c1ff8),
+CONST64(0xf7c4556262956237), CONST64(0xa3b53ad4d477d4ee), CONST64(0x324d81a8a89aa829), CONST64(0xf4315296966296c4),
+CONST64(0x3aef62f9f9c3f99b), CONST64(0xf697a3c5c533c566), CONST64(0xb14a102525942535), CONST64(0x20b2ab59597959f2),
+CONST64(0xae15d084842a8454), CONST64(0xa7e4c57272d572b7), CONST64(0xdd72ec3939e439d5), CONST64(0x6198164c4c2d4c5a),
+CONST64(0x3bbc945e5e655eca), CONST64(0x85f09f7878fd78e7), CONST64(0xd870e53838e038dd), CONST64(0x8605988c8c0a8c14),
+CONST64(0xb2bf17d1d163d1c6), CONST64(0x0b57e4a5a5aea541), CONST64(0x4dd9a1e2e2afe243), CONST64(0xf8c24e616199612f),
+CONST64(0x457b42b3b3f6b3f1), CONST64(0xa542342121842115), CONST64(0xd625089c9c4a9c94), CONST64(0x663cee1e1e781ef0),
+CONST64(0x5286614343114322), CONST64(0xfc93b1c7c73bc776), CONST64(0x2be54ffcfcd7fcb3), CONST64(0x1408240404100420),
+CONST64(0x08a2e351515951b2), CONST64(0xc72f2599995e99bc), CONST64(0xc4da226d6da96d4f), CONST64(0x391a650d0d340d68),
+CONST64(0x35e979fafacffa83), CONST64(0x84a369dfdf5bdfb6), CONST64(0x9bfca97e7ee57ed7), CONST64(0xb44819242490243d),
+CONST64(0xd776fe3b3bec3bc5), CONST64(0x3d4b9aabab96ab31), CONST64(0xd181f0cece1fce3e), CONST64(0x5522991111441188),
+CONST64(0x8903838f8f068f0c), CONST64(0x6b9c044e4e254e4a), CONST64(0x517366b7b7e6b7d1), CONST64(0x60cbe0ebeb8beb0b),
+CONST64(0xcc78c13c3cf03cfd), CONST64(0xbf1ffd81813e817c), CONST64(0xfe354094946a94d4), CONST64(0x0cf31cf7f7fbf7eb),
+CONST64(0x676f18b9b9deb9a1), CONST64(0x5f268b13134c1398), CONST64(0x9c58512c2cb02c7d), CONST64(0xb8bb05d3d36bd3d6),
+CONST64(0x5cd38ce7e7bbe76b), CONST64(0xcbdc396e6ea56e57), CONST64(0xf395aac4c437c46e), CONST64(0x0f061b03030c0318),
+CONST64(0x13acdc565645568a), CONST64(0x49885e44440d441a), CONST64(0x9efea07f7fe17fdf), CONST64(0x374f88a9a99ea921),
+CONST64(0x8254672a2aa82a4d), CONST64(0x6d6b0abbbbd6bbb1), CONST64(0xe29f87c1c123c146), CONST64(0x02a6f153535153a2),
+CONST64(0x8ba572dcdc57dcae), CONST64(0x2716530b0b2c0b58), CONST64(0xd327019d9d4e9d9c), CONST64(0xc1d82b6c6cad6c47),
+CONST64(0xf562a43131c43195), CONST64(0xb9e8f37474cd7487), CONST64(0x09f115f6f6fff6e3), CONST64(0x438c4c464605460a),
+CONST64(0x2645a5acac8aac09), CONST64(0x970fb589891e893c), CONST64(0x4428b414145014a0), CONST64(0x42dfbae1e1a3e15b),
+CONST64(0x4e2ca616165816b0), CONST64(0xd274f73a3ae83acd), CONST64(0xd0d2066969b9696f), CONST64(0x2d12410909240948),
+CONST64(0xade0d77070dd70a7), CONST64(0x54716fb6b6e2b6d9), CONST64(0xb7bd1ed0d067d0ce), CONST64(0x7ec7d6eded93ed3b),
+CONST64(0xdb85e2cccc17cc2e), CONST64(0x578468424215422a), CONST64(0xc22d2c98985a98b4), CONST64(0x0e55eda4a4aaa449),
+CONST64(0x8850752828a0285d), CONST64(0x31b8865c5c6d5cda), CONST64(0x3fed6bf8f8c7f893), CONST64(0xa411c28686228644)
+};
+
+static const ulong64 sbox4[] = {
+CONST64(0xc07830d818186018), CONST64(0x05af462623238c23), CONST64(0x7ef991b8c6c63fc6), CONST64(0x136fcdfbe8e887e8),
+CONST64(0x4ca113cb87872687), CONST64(0xa9626d11b8b8dab8), CONST64(0x0805020901010401), CONST64(0x426e9e0d4f4f214f),
+CONST64(0xadee6c9b3636d836), CONST64(0x590451ffa6a6a2a6), CONST64(0xdebdb90cd2d26fd2), CONST64(0xfb06f70ef5f5f3f5),
+CONST64(0xef80f2967979f979), CONST64(0x5fcede306f6fa16f), CONST64(0xfcef3f6d91917e91), CONST64(0xaa07a4f852525552),
+CONST64(0x27fdc04760609d60), CONST64(0x89766535bcbccabc), CONST64(0xaccd2b379b9b569b), CONST64(0x048c018a8e8e028e),
+CONST64(0x71155bd2a3a3b6a3), CONST64(0x603c186c0c0c300c), CONST64(0xff8af6847b7bf17b), CONST64(0xb5e16a803535d435),
+CONST64(0xe8693af51d1d741d), CONST64(0x5347ddb3e0e0a7e0), CONST64(0xf6acb321d7d77bd7), CONST64(0x5eed999cc2c22fc2),
+CONST64(0x6d965c432e2eb82e), CONST64(0x627a96294b4b314b), CONST64(0xa321e15dfefedffe), CONST64(0x8216aed557574157),
+CONST64(0xa8412abd15155415), CONST64(0x9fb6eee87777c177), CONST64(0xa5eb6e923737dc37), CONST64(0x7b56d79ee5e5b3e5),
+CONST64(0x8cd923139f9f469f), CONST64(0xd317fd23f0f0e7f0), CONST64(0x6a7f94204a4a354a), CONST64(0x9e95a944dada4fda),
+CONST64(0xfa25b0a258587d58), CONST64(0x06ca8fcfc9c903c9), CONST64(0x558d527c2929a429), CONST64(0x5022145a0a0a280a),
+CONST64(0xe14f7f50b1b1feb1), CONST64(0x691a5dc9a0a0baa0), CONST64(0x7fdad6146b6bb16b), CONST64(0x5cab17d985852e85),
+CONST64(0x8173673cbdbdcebd), CONST64(0xd234ba8f5d5d695d), CONST64(0x8050209010104010), CONST64(0xf303f507f4f4f7f4),
+CONST64(0x16c08bddcbcb0bcb), CONST64(0xedc67cd33e3ef83e), CONST64(0x28110a2d05051405), CONST64(0x1fe6ce7867678167),
+CONST64(0x7353d597e4e4b7e4), CONST64(0x25bb4e0227279c27), CONST64(0x3258827341411941), CONST64(0x2c9d0ba78b8b168b),
+CONST64(0x510153f6a7a7a6a7), CONST64(0xcf94fab27d7de97d), CONST64(0xdcfb374995956e95), CONST64(0x8e9fad56d8d847d8),
+CONST64(0x8b30eb70fbfbcbfb), CONST64(0x2371c1cdeeee9fee), CONST64(0xc791f8bb7c7ced7c), CONST64(0x17e3cc7166668566),
+CONST64(0xa68ea77bdddd53dd), CONST64(0xb84b2eaf17175c17), CONST64(0x02468e4547470147), CONST64(0x84dc211a9e9e429e),
+CONST64(0x1ec589d4caca0fca), CONST64(0x75995a582d2db42d), CONST64(0x9179632ebfbfc6bf), CONST64(0x381b0e3f07071c07),
+CONST64(0x012347acadad8ead), CONST64(0xea2fb4b05a5a755a), CONST64(0x6cb51bef83833683), CONST64(0x85ff66b63333cc33),
+CONST64(0x3ff2c65c63639163), CONST64(0x100a041202020802), CONST64(0x39384993aaaa92aa), CONST64(0xafa8e2de7171d971),
+CONST64(0x0ecf8dc6c8c807c8), CONST64(0xc87d32d119196419), CONST64(0x7270923b49493949), CONST64(0x869aaf5fd9d943d9),
+CONST64(0xc31df931f2f2eff2), CONST64(0x4b48dba8e3e3abe3), CONST64(0xe22ab6b95b5b715b), CONST64(0x34920dbc88881a88),
+CONST64(0xa4c8293e9a9a529a), CONST64(0x2dbe4c0b26269826), CONST64(0x8dfa64bf3232c832), CONST64(0xe94a7d59b0b0fab0),
+CONST64(0x1b6acff2e9e983e9), CONST64(0x78331e770f0f3c0f), CONST64(0xe6a6b733d5d573d5), CONST64(0x74ba1df480803a80),
+CONST64(0x997c6127bebec2be), CONST64(0x26de87ebcdcd13cd), CONST64(0xbde468893434d034), CONST64(0x7a75903248483d48),
+CONST64(0xab24e354ffffdbff), CONST64(0xf78ff48d7a7af57a), CONST64(0xf4ea3d6490907a90), CONST64(0xc23ebe9d5f5f615f),
+CONST64(0x1da0403d20208020), CONST64(0x67d5d00f6868bd68), CONST64(0xd07234ca1a1a681a), CONST64(0x192c41b7aeae82ae),
+CONST64(0xc95e757db4b4eab4), CONST64(0x9a19a8ce54544d54), CONST64(0xece53b7f93937693), CONST64(0x0daa442f22228822),
+CONST64(0x07e9c86364648d64), CONST64(0xdb12ff2af1f1e3f1), CONST64(0xbfa2e6cc7373d173), CONST64(0x905a248212124812),
+CONST64(0x3a5d807a40401d40), CONST64(0x4028104808082008), CONST64(0x56e89b95c3c32bc3), CONST64(0x337bc5dfecec97ec),
+CONST64(0x9690ab4ddbdb4bdb), CONST64(0x611f5fc0a1a1bea1), CONST64(0x1c8307918d8d0e8d), CONST64(0xf5c97ac83d3df43d),
+CONST64(0xccf1335b97976697), CONST64(0x0000000000000000), CONST64(0x36d483f9cfcf1bcf), CONST64(0x4587566e2b2bac2b),
+CONST64(0x97b3ece17676c576), CONST64(0x64b019e682823282), CONST64(0xfea9b128d6d67fd6), CONST64(0xd87736c31b1b6c1b),
+CONST64(0xc15b7774b5b5eeb5), CONST64(0x112943beafaf86af), CONST64(0x77dfd41d6a6ab56a), CONST64(0xba0da0ea50505d50),
+CONST64(0x124c8a5745450945), CONST64(0xcb18fb38f3f3ebf3), CONST64(0x9df060ad3030c030), CONST64(0x2b74c3c4efef9bef),
+CONST64(0xe5c37eda3f3ffc3f), CONST64(0x921caac755554955), CONST64(0x791059dba2a2b2a2), CONST64(0x0365c9e9eaea8fea),
+CONST64(0x0fecca6a65658965), CONST64(0xb9686903babad2ba), CONST64(0x65935e4a2f2fbc2f), CONST64(0x4ee79d8ec0c027c0),
+CONST64(0xbe81a160dede5fde), CONST64(0xe06c38fc1c1c701c), CONST64(0xbb2ee746fdfdd3fd), CONST64(0x52649a1f4d4d294d),
+CONST64(0xe4e0397692927292), CONST64(0x8fbceafa7575c975), CONST64(0x301e0c3606061806), CONST64(0x249809ae8a8a128a),
+CONST64(0xf940794bb2b2f2b2), CONST64(0x6359d185e6e6bfe6), CONST64(0x70361c7e0e0e380e), CONST64(0xf8633ee71f1f7c1f),
+CONST64(0x37f7c45562629562), CONST64(0xeea3b53ad4d477d4), CONST64(0x29324d81a8a89aa8), CONST64(0xc4f4315296966296),
+CONST64(0x9b3aef62f9f9c3f9), CONST64(0x66f697a3c5c533c5), CONST64(0x35b14a1025259425), CONST64(0xf220b2ab59597959),
+CONST64(0x54ae15d084842a84), CONST64(0xb7a7e4c57272d572), CONST64(0xd5dd72ec3939e439), CONST64(0x5a6198164c4c2d4c),
+CONST64(0xca3bbc945e5e655e), CONST64(0xe785f09f7878fd78), CONST64(0xddd870e53838e038), CONST64(0x148605988c8c0a8c),
+CONST64(0xc6b2bf17d1d163d1), CONST64(0x410b57e4a5a5aea5), CONST64(0x434dd9a1e2e2afe2), CONST64(0x2ff8c24e61619961),
+CONST64(0xf1457b42b3b3f6b3), CONST64(0x15a5423421218421), CONST64(0x94d625089c9c4a9c), CONST64(0xf0663cee1e1e781e),
+CONST64(0x2252866143431143), CONST64(0x76fc93b1c7c73bc7), CONST64(0xb32be54ffcfcd7fc), CONST64(0x2014082404041004),
+CONST64(0xb208a2e351515951), CONST64(0xbcc72f2599995e99), CONST64(0x4fc4da226d6da96d), CONST64(0x68391a650d0d340d),
+CONST64(0x8335e979fafacffa), CONST64(0xb684a369dfdf5bdf), CONST64(0xd79bfca97e7ee57e), CONST64(0x3db4481924249024),
+CONST64(0xc5d776fe3b3bec3b), CONST64(0x313d4b9aabab96ab), CONST64(0x3ed181f0cece1fce), CONST64(0x8855229911114411),
+CONST64(0x0c8903838f8f068f), CONST64(0x4a6b9c044e4e254e), CONST64(0xd1517366b7b7e6b7), CONST64(0x0b60cbe0ebeb8beb),
+CONST64(0xfdcc78c13c3cf03c), CONST64(0x7cbf1ffd81813e81), CONST64(0xd4fe354094946a94), CONST64(0xeb0cf31cf7f7fbf7),
+CONST64(0xa1676f18b9b9deb9), CONST64(0x985f268b13134c13), CONST64(0x7d9c58512c2cb02c), CONST64(0xd6b8bb05d3d36bd3),
+CONST64(0x6b5cd38ce7e7bbe7), CONST64(0x57cbdc396e6ea56e), CONST64(0x6ef395aac4c437c4), CONST64(0x180f061b03030c03),
+CONST64(0x8a13acdc56564556), CONST64(0x1a49885e44440d44), CONST64(0xdf9efea07f7fe17f), CONST64(0x21374f88a9a99ea9),
+CONST64(0x4d8254672a2aa82a), CONST64(0xb16d6b0abbbbd6bb), CONST64(0x46e29f87c1c123c1), CONST64(0xa202a6f153535153),
+CONST64(0xae8ba572dcdc57dc), CONST64(0x582716530b0b2c0b), CONST64(0x9cd327019d9d4e9d), CONST64(0x47c1d82b6c6cad6c),
+CONST64(0x95f562a43131c431), CONST64(0x87b9e8f37474cd74), CONST64(0xe309f115f6f6fff6), CONST64(0x0a438c4c46460546),
+CONST64(0x092645a5acac8aac), CONST64(0x3c970fb589891e89), CONST64(0xa04428b414145014), CONST64(0x5b42dfbae1e1a3e1),
+CONST64(0xb04e2ca616165816), CONST64(0xcdd274f73a3ae83a), CONST64(0x6fd0d2066969b969), CONST64(0x482d124109092409),
+CONST64(0xa7ade0d77070dd70), CONST64(0xd954716fb6b6e2b6), CONST64(0xceb7bd1ed0d067d0), CONST64(0x3b7ec7d6eded93ed),
+CONST64(0x2edb85e2cccc17cc), CONST64(0x2a57846842421542), CONST64(0xb4c22d2c98985a98), CONST64(0x490e55eda4a4aaa4),
+CONST64(0x5d8850752828a028), CONST64(0xda31b8865c5c6d5c), CONST64(0x933fed6bf8f8c7f8), CONST64(0x44a411c286862286)
+};
+
+static const ulong64 sbox5[] = {
+CONST64(0x18c07830d8181860), CONST64(0x2305af462623238c), CONST64(0xc67ef991b8c6c63f), CONST64(0xe8136fcdfbe8e887),
+CONST64(0x874ca113cb878726), CONST64(0xb8a9626d11b8b8da), CONST64(0x0108050209010104), CONST64(0x4f426e9e0d4f4f21),
+CONST64(0x36adee6c9b3636d8), CONST64(0xa6590451ffa6a6a2), CONST64(0xd2debdb90cd2d26f), CONST64(0xf5fb06f70ef5f5f3),
+CONST64(0x79ef80f2967979f9), CONST64(0x6f5fcede306f6fa1), CONST64(0x91fcef3f6d91917e), CONST64(0x52aa07a4f8525255),
+CONST64(0x6027fdc04760609d), CONST64(0xbc89766535bcbcca), CONST64(0x9baccd2b379b9b56), CONST64(0x8e048c018a8e8e02),
+CONST64(0xa371155bd2a3a3b6), CONST64(0x0c603c186c0c0c30), CONST64(0x7bff8af6847b7bf1), CONST64(0x35b5e16a803535d4),
+CONST64(0x1de8693af51d1d74), CONST64(0xe05347ddb3e0e0a7), CONST64(0xd7f6acb321d7d77b), CONST64(0xc25eed999cc2c22f),
+CONST64(0x2e6d965c432e2eb8), CONST64(0x4b627a96294b4b31), CONST64(0xfea321e15dfefedf), CONST64(0x578216aed5575741),
+CONST64(0x15a8412abd151554), CONST64(0x779fb6eee87777c1), CONST64(0x37a5eb6e923737dc), CONST64(0xe57b56d79ee5e5b3),
+CONST64(0x9f8cd923139f9f46), CONST64(0xf0d317fd23f0f0e7), CONST64(0x4a6a7f94204a4a35), CONST64(0xda9e95a944dada4f),
+CONST64(0x58fa25b0a258587d), CONST64(0xc906ca8fcfc9c903), CONST64(0x29558d527c2929a4), CONST64(0x0a5022145a0a0a28),
+CONST64(0xb1e14f7f50b1b1fe), CONST64(0xa0691a5dc9a0a0ba), CONST64(0x6b7fdad6146b6bb1), CONST64(0x855cab17d985852e),
+CONST64(0xbd8173673cbdbdce), CONST64(0x5dd234ba8f5d5d69), CONST64(0x1080502090101040), CONST64(0xf4f303f507f4f4f7),
+CONST64(0xcb16c08bddcbcb0b), CONST64(0x3eedc67cd33e3ef8), CONST64(0x0528110a2d050514), CONST64(0x671fe6ce78676781),
+CONST64(0xe47353d597e4e4b7), CONST64(0x2725bb4e0227279c), CONST64(0x4132588273414119), CONST64(0x8b2c9d0ba78b8b16),
+CONST64(0xa7510153f6a7a7a6), CONST64(0x7dcf94fab27d7de9), CONST64(0x95dcfb374995956e), CONST64(0xd88e9fad56d8d847),
+CONST64(0xfb8b30eb70fbfbcb), CONST64(0xee2371c1cdeeee9f), CONST64(0x7cc791f8bb7c7ced), CONST64(0x6617e3cc71666685),
+CONST64(0xdda68ea77bdddd53), CONST64(0x17b84b2eaf17175c), CONST64(0x4702468e45474701), CONST64(0x9e84dc211a9e9e42),
+CONST64(0xca1ec589d4caca0f), CONST64(0x2d75995a582d2db4), CONST64(0xbf9179632ebfbfc6), CONST64(0x07381b0e3f07071c),
+CONST64(0xad012347acadad8e), CONST64(0x5aea2fb4b05a5a75), CONST64(0x836cb51bef838336), CONST64(0x3385ff66b63333cc),
+CONST64(0x633ff2c65c636391), CONST64(0x02100a0412020208), CONST64(0xaa39384993aaaa92), CONST64(0x71afa8e2de7171d9),
+CONST64(0xc80ecf8dc6c8c807), CONST64(0x19c87d32d1191964), CONST64(0x497270923b494939), CONST64(0xd9869aaf5fd9d943),
+CONST64(0xf2c31df931f2f2ef), CONST64(0xe34b48dba8e3e3ab), CONST64(0x5be22ab6b95b5b71), CONST64(0x8834920dbc88881a),
+CONST64(0x9aa4c8293e9a9a52), CONST64(0x262dbe4c0b262698), CONST64(0x328dfa64bf3232c8), CONST64(0xb0e94a7d59b0b0fa),
+CONST64(0xe91b6acff2e9e983), CONST64(0x0f78331e770f0f3c), CONST64(0xd5e6a6b733d5d573), CONST64(0x8074ba1df480803a),
+CONST64(0xbe997c6127bebec2), CONST64(0xcd26de87ebcdcd13), CONST64(0x34bde468893434d0), CONST64(0x487a75903248483d),
+CONST64(0xffab24e354ffffdb), CONST64(0x7af78ff48d7a7af5), CONST64(0x90f4ea3d6490907a), CONST64(0x5fc23ebe9d5f5f61),
+CONST64(0x201da0403d202080), CONST64(0x6867d5d00f6868bd), CONST64(0x1ad07234ca1a1a68), CONST64(0xae192c41b7aeae82),
+CONST64(0xb4c95e757db4b4ea), CONST64(0x549a19a8ce54544d), CONST64(0x93ece53b7f939376), CONST64(0x220daa442f222288),
+CONST64(0x6407e9c86364648d), CONST64(0xf1db12ff2af1f1e3), CONST64(0x73bfa2e6cc7373d1), CONST64(0x12905a2482121248),
+CONST64(0x403a5d807a40401d), CONST64(0x0840281048080820), CONST64(0xc356e89b95c3c32b), CONST64(0xec337bc5dfecec97),
+CONST64(0xdb9690ab4ddbdb4b), CONST64(0xa1611f5fc0a1a1be), CONST64(0x8d1c8307918d8d0e), CONST64(0x3df5c97ac83d3df4),
+CONST64(0x97ccf1335b979766), CONST64(0x0000000000000000), CONST64(0xcf36d483f9cfcf1b), CONST64(0x2b4587566e2b2bac),
+CONST64(0x7697b3ece17676c5), CONST64(0x8264b019e6828232), CONST64(0xd6fea9b128d6d67f), CONST64(0x1bd87736c31b1b6c),
+CONST64(0xb5c15b7774b5b5ee), CONST64(0xaf112943beafaf86), CONST64(0x6a77dfd41d6a6ab5), CONST64(0x50ba0da0ea50505d),
+CONST64(0x45124c8a57454509), CONST64(0xf3cb18fb38f3f3eb), CONST64(0x309df060ad3030c0), CONST64(0xef2b74c3c4efef9b),
+CONST64(0x3fe5c37eda3f3ffc), CONST64(0x55921caac7555549), CONST64(0xa2791059dba2a2b2), CONST64(0xea0365c9e9eaea8f),
+CONST64(0x650fecca6a656589), CONST64(0xbab9686903babad2), CONST64(0x2f65935e4a2f2fbc), CONST64(0xc04ee79d8ec0c027),
+CONST64(0xdebe81a160dede5f), CONST64(0x1ce06c38fc1c1c70), CONST64(0xfdbb2ee746fdfdd3), CONST64(0x4d52649a1f4d4d29),
+CONST64(0x92e4e03976929272), CONST64(0x758fbceafa7575c9), CONST64(0x06301e0c36060618), CONST64(0x8a249809ae8a8a12),
+CONST64(0xb2f940794bb2b2f2), CONST64(0xe66359d185e6e6bf), CONST64(0x0e70361c7e0e0e38), CONST64(0x1ff8633ee71f1f7c),
+CONST64(0x6237f7c455626295), CONST64(0xd4eea3b53ad4d477), CONST64(0xa829324d81a8a89a), CONST64(0x96c4f43152969662),
+CONST64(0xf99b3aef62f9f9c3), CONST64(0xc566f697a3c5c533), CONST64(0x2535b14a10252594), CONST64(0x59f220b2ab595979),
+CONST64(0x8454ae15d084842a), CONST64(0x72b7a7e4c57272d5), CONST64(0x39d5dd72ec3939e4), CONST64(0x4c5a6198164c4c2d),
+CONST64(0x5eca3bbc945e5e65), CONST64(0x78e785f09f7878fd), CONST64(0x38ddd870e53838e0), CONST64(0x8c148605988c8c0a),
+CONST64(0xd1c6b2bf17d1d163), CONST64(0xa5410b57e4a5a5ae), CONST64(0xe2434dd9a1e2e2af), CONST64(0x612ff8c24e616199),
+CONST64(0xb3f1457b42b3b3f6), CONST64(0x2115a54234212184), CONST64(0x9c94d625089c9c4a), CONST64(0x1ef0663cee1e1e78),
+CONST64(0x4322528661434311), CONST64(0xc776fc93b1c7c73b), CONST64(0xfcb32be54ffcfcd7), CONST64(0x0420140824040410),
+CONST64(0x51b208a2e3515159), CONST64(0x99bcc72f2599995e), CONST64(0x6d4fc4da226d6da9), CONST64(0x0d68391a650d0d34),
+CONST64(0xfa8335e979fafacf), CONST64(0xdfb684a369dfdf5b), CONST64(0x7ed79bfca97e7ee5), CONST64(0x243db44819242490),
+CONST64(0x3bc5d776fe3b3bec), CONST64(0xab313d4b9aabab96), CONST64(0xce3ed181f0cece1f), CONST64(0x1188552299111144),
+CONST64(0x8f0c8903838f8f06), CONST64(0x4e4a6b9c044e4e25), CONST64(0xb7d1517366b7b7e6), CONST64(0xeb0b60cbe0ebeb8b),
+CONST64(0x3cfdcc78c13c3cf0), CONST64(0x817cbf1ffd81813e), CONST64(0x94d4fe354094946a), CONST64(0xf7eb0cf31cf7f7fb),
+CONST64(0xb9a1676f18b9b9de), CONST64(0x13985f268b13134c), CONST64(0x2c7d9c58512c2cb0), CONST64(0xd3d6b8bb05d3d36b),
+CONST64(0xe76b5cd38ce7e7bb), CONST64(0x6e57cbdc396e6ea5), CONST64(0xc46ef395aac4c437), CONST64(0x03180f061b03030c),
+CONST64(0x568a13acdc565645), CONST64(0x441a49885e44440d), CONST64(0x7fdf9efea07f7fe1), CONST64(0xa921374f88a9a99e),
+CONST64(0x2a4d8254672a2aa8), CONST64(0xbbb16d6b0abbbbd6), CONST64(0xc146e29f87c1c123), CONST64(0x53a202a6f1535351),
+CONST64(0xdcae8ba572dcdc57), CONST64(0x0b582716530b0b2c), CONST64(0x9d9cd327019d9d4e), CONST64(0x6c47c1d82b6c6cad),
+CONST64(0x3195f562a43131c4), CONST64(0x7487b9e8f37474cd), CONST64(0xf6e309f115f6f6ff), CONST64(0x460a438c4c464605),
+CONST64(0xac092645a5acac8a), CONST64(0x893c970fb589891e), CONST64(0x14a04428b4141450), CONST64(0xe15b42dfbae1e1a3),
+CONST64(0x16b04e2ca6161658), CONST64(0x3acdd274f73a3ae8), CONST64(0x696fd0d2066969b9), CONST64(0x09482d1241090924),
+CONST64(0x70a7ade0d77070dd), CONST64(0xb6d954716fb6b6e2), CONST64(0xd0ceb7bd1ed0d067), CONST64(0xed3b7ec7d6eded93),
+CONST64(0xcc2edb85e2cccc17), CONST64(0x422a578468424215), CONST64(0x98b4c22d2c98985a), CONST64(0xa4490e55eda4a4aa),
+CONST64(0x285d8850752828a0), CONST64(0x5cda31b8865c5c6d), CONST64(0xf8933fed6bf8f8c7), CONST64(0x8644a411c2868622)
+};
+
+static const ulong64 sbox6[] = {
+CONST64(0x6018c07830d81818), CONST64(0x8c2305af46262323), CONST64(0x3fc67ef991b8c6c6), CONST64(0x87e8136fcdfbe8e8),
+CONST64(0x26874ca113cb8787), CONST64(0xdab8a9626d11b8b8), CONST64(0x0401080502090101), CONST64(0x214f426e9e0d4f4f),
+CONST64(0xd836adee6c9b3636), CONST64(0xa2a6590451ffa6a6), CONST64(0x6fd2debdb90cd2d2), CONST64(0xf3f5fb06f70ef5f5),
+CONST64(0xf979ef80f2967979), CONST64(0xa16f5fcede306f6f), CONST64(0x7e91fcef3f6d9191), CONST64(0x5552aa07a4f85252),
+CONST64(0x9d6027fdc0476060), CONST64(0xcabc89766535bcbc), CONST64(0x569baccd2b379b9b), CONST64(0x028e048c018a8e8e),
+CONST64(0xb6a371155bd2a3a3), CONST64(0x300c603c186c0c0c), CONST64(0xf17bff8af6847b7b), CONST64(0xd435b5e16a803535),
+CONST64(0x741de8693af51d1d), CONST64(0xa7e05347ddb3e0e0), CONST64(0x7bd7f6acb321d7d7), CONST64(0x2fc25eed999cc2c2),
+CONST64(0xb82e6d965c432e2e), CONST64(0x314b627a96294b4b), CONST64(0xdffea321e15dfefe), CONST64(0x41578216aed55757),
+CONST64(0x5415a8412abd1515), CONST64(0xc1779fb6eee87777), CONST64(0xdc37a5eb6e923737), CONST64(0xb3e57b56d79ee5e5),
+CONST64(0x469f8cd923139f9f), CONST64(0xe7f0d317fd23f0f0), CONST64(0x354a6a7f94204a4a), CONST64(0x4fda9e95a944dada),
+CONST64(0x7d58fa25b0a25858), CONST64(0x03c906ca8fcfc9c9), CONST64(0xa429558d527c2929), CONST64(0x280a5022145a0a0a),
+CONST64(0xfeb1e14f7f50b1b1), CONST64(0xbaa0691a5dc9a0a0), CONST64(0xb16b7fdad6146b6b), CONST64(0x2e855cab17d98585),
+CONST64(0xcebd8173673cbdbd), CONST64(0x695dd234ba8f5d5d), CONST64(0x4010805020901010), CONST64(0xf7f4f303f507f4f4),
+CONST64(0x0bcb16c08bddcbcb), CONST64(0xf83eedc67cd33e3e), CONST64(0x140528110a2d0505), CONST64(0x81671fe6ce786767),
+CONST64(0xb7e47353d597e4e4), CONST64(0x9c2725bb4e022727), CONST64(0x1941325882734141), CONST64(0x168b2c9d0ba78b8b),
+CONST64(0xa6a7510153f6a7a7), CONST64(0xe97dcf94fab27d7d), CONST64(0x6e95dcfb37499595), CONST64(0x47d88e9fad56d8d8),
+CONST64(0xcbfb8b30eb70fbfb), CONST64(0x9fee2371c1cdeeee), CONST64(0xed7cc791f8bb7c7c), CONST64(0x856617e3cc716666),
+CONST64(0x53dda68ea77bdddd), CONST64(0x5c17b84b2eaf1717), CONST64(0x014702468e454747), CONST64(0x429e84dc211a9e9e),
+CONST64(0x0fca1ec589d4caca), CONST64(0xb42d75995a582d2d), CONST64(0xc6bf9179632ebfbf), CONST64(0x1c07381b0e3f0707),
+CONST64(0x8ead012347acadad), CONST64(0x755aea2fb4b05a5a), CONST64(0x36836cb51bef8383), CONST64(0xcc3385ff66b63333),
+CONST64(0x91633ff2c65c6363), CONST64(0x0802100a04120202), CONST64(0x92aa39384993aaaa), CONST64(0xd971afa8e2de7171),
+CONST64(0x07c80ecf8dc6c8c8), CONST64(0x6419c87d32d11919), CONST64(0x39497270923b4949), CONST64(0x43d9869aaf5fd9d9),
+CONST64(0xeff2c31df931f2f2), CONST64(0xabe34b48dba8e3e3), CONST64(0x715be22ab6b95b5b), CONST64(0x1a8834920dbc8888),
+CONST64(0x529aa4c8293e9a9a), CONST64(0x98262dbe4c0b2626), CONST64(0xc8328dfa64bf3232), CONST64(0xfab0e94a7d59b0b0),
+CONST64(0x83e91b6acff2e9e9), CONST64(0x3c0f78331e770f0f), CONST64(0x73d5e6a6b733d5d5), CONST64(0x3a8074ba1df48080),
+CONST64(0xc2be997c6127bebe), CONST64(0x13cd26de87ebcdcd), CONST64(0xd034bde468893434), CONST64(0x3d487a7590324848),
+CONST64(0xdbffab24e354ffff), CONST64(0xf57af78ff48d7a7a), CONST64(0x7a90f4ea3d649090), CONST64(0x615fc23ebe9d5f5f),
+CONST64(0x80201da0403d2020), CONST64(0xbd6867d5d00f6868), CONST64(0x681ad07234ca1a1a), CONST64(0x82ae192c41b7aeae),
+CONST64(0xeab4c95e757db4b4), CONST64(0x4d549a19a8ce5454), CONST64(0x7693ece53b7f9393), CONST64(0x88220daa442f2222),
+CONST64(0x8d6407e9c8636464), CONST64(0xe3f1db12ff2af1f1), CONST64(0xd173bfa2e6cc7373), CONST64(0x4812905a24821212),
+CONST64(0x1d403a5d807a4040), CONST64(0x2008402810480808), CONST64(0x2bc356e89b95c3c3), CONST64(0x97ec337bc5dfecec),
+CONST64(0x4bdb9690ab4ddbdb), CONST64(0xbea1611f5fc0a1a1), CONST64(0x0e8d1c8307918d8d), CONST64(0xf43df5c97ac83d3d),
+CONST64(0x6697ccf1335b9797), CONST64(0x0000000000000000), CONST64(0x1bcf36d483f9cfcf), CONST64(0xac2b4587566e2b2b),
+CONST64(0xc57697b3ece17676), CONST64(0x328264b019e68282), CONST64(0x7fd6fea9b128d6d6), CONST64(0x6c1bd87736c31b1b),
+CONST64(0xeeb5c15b7774b5b5), CONST64(0x86af112943beafaf), CONST64(0xb56a77dfd41d6a6a), CONST64(0x5d50ba0da0ea5050),
+CONST64(0x0945124c8a574545), CONST64(0xebf3cb18fb38f3f3), CONST64(0xc0309df060ad3030), CONST64(0x9bef2b74c3c4efef),
+CONST64(0xfc3fe5c37eda3f3f), CONST64(0x4955921caac75555), CONST64(0xb2a2791059dba2a2), CONST64(0x8fea0365c9e9eaea),
+CONST64(0x89650fecca6a6565), CONST64(0xd2bab9686903baba), CONST64(0xbc2f65935e4a2f2f), CONST64(0x27c04ee79d8ec0c0),
+CONST64(0x5fdebe81a160dede), CONST64(0x701ce06c38fc1c1c), CONST64(0xd3fdbb2ee746fdfd), CONST64(0x294d52649a1f4d4d),
+CONST64(0x7292e4e039769292), CONST64(0xc9758fbceafa7575), CONST64(0x1806301e0c360606), CONST64(0x128a249809ae8a8a),
+CONST64(0xf2b2f940794bb2b2), CONST64(0xbfe66359d185e6e6), CONST64(0x380e70361c7e0e0e), CONST64(0x7c1ff8633ee71f1f),
+CONST64(0x956237f7c4556262), CONST64(0x77d4eea3b53ad4d4), CONST64(0x9aa829324d81a8a8), CONST64(0x6296c4f431529696),
+CONST64(0xc3f99b3aef62f9f9), CONST64(0x33c566f697a3c5c5), CONST64(0x942535b14a102525), CONST64(0x7959f220b2ab5959),
+CONST64(0x2a8454ae15d08484), CONST64(0xd572b7a7e4c57272), CONST64(0xe439d5dd72ec3939), CONST64(0x2d4c5a6198164c4c),
+CONST64(0x655eca3bbc945e5e), CONST64(0xfd78e785f09f7878), CONST64(0xe038ddd870e53838), CONST64(0x0a8c148605988c8c),
+CONST64(0x63d1c6b2bf17d1d1), CONST64(0xaea5410b57e4a5a5), CONST64(0xafe2434dd9a1e2e2), CONST64(0x99612ff8c24e6161),
+CONST64(0xf6b3f1457b42b3b3), CONST64(0x842115a542342121), CONST64(0x4a9c94d625089c9c), CONST64(0x781ef0663cee1e1e),
+CONST64(0x1143225286614343), CONST64(0x3bc776fc93b1c7c7), CONST64(0xd7fcb32be54ffcfc), CONST64(0x1004201408240404),
+CONST64(0x5951b208a2e35151), CONST64(0x5e99bcc72f259999), CONST64(0xa96d4fc4da226d6d), CONST64(0x340d68391a650d0d),
+CONST64(0xcffa8335e979fafa), CONST64(0x5bdfb684a369dfdf), CONST64(0xe57ed79bfca97e7e), CONST64(0x90243db448192424),
+CONST64(0xec3bc5d776fe3b3b), CONST64(0x96ab313d4b9aabab), CONST64(0x1fce3ed181f0cece), CONST64(0x4411885522991111),
+CONST64(0x068f0c8903838f8f), CONST64(0x254e4a6b9c044e4e), CONST64(0xe6b7d1517366b7b7), CONST64(0x8beb0b60cbe0ebeb),
+CONST64(0xf03cfdcc78c13c3c), CONST64(0x3e817cbf1ffd8181), CONST64(0x6a94d4fe35409494), CONST64(0xfbf7eb0cf31cf7f7),
+CONST64(0xdeb9a1676f18b9b9), CONST64(0x4c13985f268b1313), CONST64(0xb02c7d9c58512c2c), CONST64(0x6bd3d6b8bb05d3d3),
+CONST64(0xbbe76b5cd38ce7e7), CONST64(0xa56e57cbdc396e6e), CONST64(0x37c46ef395aac4c4), CONST64(0x0c03180f061b0303),
+CONST64(0x45568a13acdc5656), CONST64(0x0d441a49885e4444), CONST64(0xe17fdf9efea07f7f), CONST64(0x9ea921374f88a9a9),
+CONST64(0xa82a4d8254672a2a), CONST64(0xd6bbb16d6b0abbbb), CONST64(0x23c146e29f87c1c1), CONST64(0x5153a202a6f15353),
+CONST64(0x57dcae8ba572dcdc), CONST64(0x2c0b582716530b0b), CONST64(0x4e9d9cd327019d9d), CONST64(0xad6c47c1d82b6c6c),
+CONST64(0xc43195f562a43131), CONST64(0xcd7487b9e8f37474), CONST64(0xfff6e309f115f6f6), CONST64(0x05460a438c4c4646),
+CONST64(0x8aac092645a5acac), CONST64(0x1e893c970fb58989), CONST64(0x5014a04428b41414), CONST64(0xa3e15b42dfbae1e1),
+CONST64(0x5816b04e2ca61616), CONST64(0xe83acdd274f73a3a), CONST64(0xb9696fd0d2066969), CONST64(0x2409482d12410909),
+CONST64(0xdd70a7ade0d77070), CONST64(0xe2b6d954716fb6b6), CONST64(0x67d0ceb7bd1ed0d0), CONST64(0x93ed3b7ec7d6eded),
+CONST64(0x17cc2edb85e2cccc), CONST64(0x15422a5784684242), CONST64(0x5a98b4c22d2c9898), CONST64(0xaaa4490e55eda4a4),
+CONST64(0xa0285d8850752828), CONST64(0x6d5cda31b8865c5c), CONST64(0xc7f8933fed6bf8f8), CONST64(0x228644a411c28686)
+};
+
+static const ulong64 sbox7[] = {
+CONST64(0x186018c07830d818), CONST64(0x238c2305af462623), CONST64(0xc63fc67ef991b8c6), CONST64(0xe887e8136fcdfbe8),
+CONST64(0x8726874ca113cb87), CONST64(0xb8dab8a9626d11b8), CONST64(0x0104010805020901), CONST64(0x4f214f426e9e0d4f),
+CONST64(0x36d836adee6c9b36), CONST64(0xa6a2a6590451ffa6), CONST64(0xd26fd2debdb90cd2), CONST64(0xf5f3f5fb06f70ef5),
+CONST64(0x79f979ef80f29679), CONST64(0x6fa16f5fcede306f), CONST64(0x917e91fcef3f6d91), CONST64(0x525552aa07a4f852),
+CONST64(0x609d6027fdc04760), CONST64(0xbccabc89766535bc), CONST64(0x9b569baccd2b379b), CONST64(0x8e028e048c018a8e),
+CONST64(0xa3b6a371155bd2a3), CONST64(0x0c300c603c186c0c), CONST64(0x7bf17bff8af6847b), CONST64(0x35d435b5e16a8035),
+CONST64(0x1d741de8693af51d), CONST64(0xe0a7e05347ddb3e0), CONST64(0xd77bd7f6acb321d7), CONST64(0xc22fc25eed999cc2),
+CONST64(0x2eb82e6d965c432e), CONST64(0x4b314b627a96294b), CONST64(0xfedffea321e15dfe), CONST64(0x5741578216aed557),
+CONST64(0x155415a8412abd15), CONST64(0x77c1779fb6eee877), CONST64(0x37dc37a5eb6e9237), CONST64(0xe5b3e57b56d79ee5),
+CONST64(0x9f469f8cd923139f), CONST64(0xf0e7f0d317fd23f0), CONST64(0x4a354a6a7f94204a), CONST64(0xda4fda9e95a944da),
+CONST64(0x587d58fa25b0a258), CONST64(0xc903c906ca8fcfc9), CONST64(0x29a429558d527c29), CONST64(0x0a280a5022145a0a),
+CONST64(0xb1feb1e14f7f50b1), CONST64(0xa0baa0691a5dc9a0), CONST64(0x6bb16b7fdad6146b), CONST64(0x852e855cab17d985),
+CONST64(0xbdcebd8173673cbd), CONST64(0x5d695dd234ba8f5d), CONST64(0x1040108050209010), CONST64(0xf4f7f4f303f507f4),
+CONST64(0xcb0bcb16c08bddcb), CONST64(0x3ef83eedc67cd33e), CONST64(0x05140528110a2d05), CONST64(0x6781671fe6ce7867),
+CONST64(0xe4b7e47353d597e4), CONST64(0x279c2725bb4e0227), CONST64(0x4119413258827341), CONST64(0x8b168b2c9d0ba78b),
+CONST64(0xa7a6a7510153f6a7), CONST64(0x7de97dcf94fab27d), CONST64(0x956e95dcfb374995), CONST64(0xd847d88e9fad56d8),
+CONST64(0xfbcbfb8b30eb70fb), CONST64(0xee9fee2371c1cdee), CONST64(0x7ced7cc791f8bb7c), CONST64(0x66856617e3cc7166),
+CONST64(0xdd53dda68ea77bdd), CONST64(0x175c17b84b2eaf17), CONST64(0x47014702468e4547), CONST64(0x9e429e84dc211a9e),
+CONST64(0xca0fca1ec589d4ca), CONST64(0x2db42d75995a582d), CONST64(0xbfc6bf9179632ebf), CONST64(0x071c07381b0e3f07),
+CONST64(0xad8ead012347acad), CONST64(0x5a755aea2fb4b05a), CONST64(0x8336836cb51bef83), CONST64(0x33cc3385ff66b633),
+CONST64(0x6391633ff2c65c63), CONST64(0x020802100a041202), CONST64(0xaa92aa39384993aa), CONST64(0x71d971afa8e2de71),
+CONST64(0xc807c80ecf8dc6c8), CONST64(0x196419c87d32d119), CONST64(0x4939497270923b49), CONST64(0xd943d9869aaf5fd9),
+CONST64(0xf2eff2c31df931f2), CONST64(0xe3abe34b48dba8e3), CONST64(0x5b715be22ab6b95b), CONST64(0x881a8834920dbc88),
+CONST64(0x9a529aa4c8293e9a), CONST64(0x2698262dbe4c0b26), CONST64(0x32c8328dfa64bf32), CONST64(0xb0fab0e94a7d59b0),
+CONST64(0xe983e91b6acff2e9), CONST64(0x0f3c0f78331e770f), CONST64(0xd573d5e6a6b733d5), CONST64(0x803a8074ba1df480),
+CONST64(0xbec2be997c6127be), CONST64(0xcd13cd26de87ebcd), CONST64(0x34d034bde4688934), CONST64(0x483d487a75903248),
+CONST64(0xffdbffab24e354ff), CONST64(0x7af57af78ff48d7a), CONST64(0x907a90f4ea3d6490), CONST64(0x5f615fc23ebe9d5f),
+CONST64(0x2080201da0403d20), CONST64(0x68bd6867d5d00f68), CONST64(0x1a681ad07234ca1a), CONST64(0xae82ae192c41b7ae),
+CONST64(0xb4eab4c95e757db4), CONST64(0x544d549a19a8ce54), CONST64(0x937693ece53b7f93), CONST64(0x2288220daa442f22),
+CONST64(0x648d6407e9c86364), CONST64(0xf1e3f1db12ff2af1), CONST64(0x73d173bfa2e6cc73), CONST64(0x124812905a248212),
+CONST64(0x401d403a5d807a40), CONST64(0x0820084028104808), CONST64(0xc32bc356e89b95c3), CONST64(0xec97ec337bc5dfec),
+CONST64(0xdb4bdb9690ab4ddb), CONST64(0xa1bea1611f5fc0a1), CONST64(0x8d0e8d1c8307918d), CONST64(0x3df43df5c97ac83d),
+CONST64(0x976697ccf1335b97), CONST64(0x0000000000000000), CONST64(0xcf1bcf36d483f9cf), CONST64(0x2bac2b4587566e2b),
+CONST64(0x76c57697b3ece176), CONST64(0x82328264b019e682), CONST64(0xd67fd6fea9b128d6), CONST64(0x1b6c1bd87736c31b),
+CONST64(0xb5eeb5c15b7774b5), CONST64(0xaf86af112943beaf), CONST64(0x6ab56a77dfd41d6a), CONST64(0x505d50ba0da0ea50),
+CONST64(0x450945124c8a5745), CONST64(0xf3ebf3cb18fb38f3), CONST64(0x30c0309df060ad30), CONST64(0xef9bef2b74c3c4ef),
+CONST64(0x3ffc3fe5c37eda3f), CONST64(0x554955921caac755), CONST64(0xa2b2a2791059dba2), CONST64(0xea8fea0365c9e9ea),
+CONST64(0x6589650fecca6a65), CONST64(0xbad2bab9686903ba), CONST64(0x2fbc2f65935e4a2f), CONST64(0xc027c04ee79d8ec0),
+CONST64(0xde5fdebe81a160de), CONST64(0x1c701ce06c38fc1c), CONST64(0xfdd3fdbb2ee746fd), CONST64(0x4d294d52649a1f4d),
+CONST64(0x927292e4e0397692), CONST64(0x75c9758fbceafa75), CONST64(0x061806301e0c3606), CONST64(0x8a128a249809ae8a),
+CONST64(0xb2f2b2f940794bb2), CONST64(0xe6bfe66359d185e6), CONST64(0x0e380e70361c7e0e), CONST64(0x1f7c1ff8633ee71f),
+CONST64(0x62956237f7c45562), CONST64(0xd477d4eea3b53ad4), CONST64(0xa89aa829324d81a8), CONST64(0x966296c4f4315296),
+CONST64(0xf9c3f99b3aef62f9), CONST64(0xc533c566f697a3c5), CONST64(0x25942535b14a1025), CONST64(0x597959f220b2ab59),
+CONST64(0x842a8454ae15d084), CONST64(0x72d572b7a7e4c572), CONST64(0x39e439d5dd72ec39), CONST64(0x4c2d4c5a6198164c),
+CONST64(0x5e655eca3bbc945e), CONST64(0x78fd78e785f09f78), CONST64(0x38e038ddd870e538), CONST64(0x8c0a8c148605988c),
+CONST64(0xd163d1c6b2bf17d1), CONST64(0xa5aea5410b57e4a5), CONST64(0xe2afe2434dd9a1e2), CONST64(0x6199612ff8c24e61),
+CONST64(0xb3f6b3f1457b42b3), CONST64(0x21842115a5423421), CONST64(0x9c4a9c94d625089c), CONST64(0x1e781ef0663cee1e),
+CONST64(0x4311432252866143), CONST64(0xc73bc776fc93b1c7), CONST64(0xfcd7fcb32be54ffc), CONST64(0x0410042014082404),
+CONST64(0x515951b208a2e351), CONST64(0x995e99bcc72f2599), CONST64(0x6da96d4fc4da226d), CONST64(0x0d340d68391a650d),
+CONST64(0xfacffa8335e979fa), CONST64(0xdf5bdfb684a369df), CONST64(0x7ee57ed79bfca97e), CONST64(0x2490243db4481924),
+CONST64(0x3bec3bc5d776fe3b), CONST64(0xab96ab313d4b9aab), CONST64(0xce1fce3ed181f0ce), CONST64(0x1144118855229911),
+CONST64(0x8f068f0c8903838f), CONST64(0x4e254e4a6b9c044e), CONST64(0xb7e6b7d1517366b7), CONST64(0xeb8beb0b60cbe0eb),
+CONST64(0x3cf03cfdcc78c13c), CONST64(0x813e817cbf1ffd81), CONST64(0x946a94d4fe354094), CONST64(0xf7fbf7eb0cf31cf7),
+CONST64(0xb9deb9a1676f18b9), CONST64(0x134c13985f268b13), CONST64(0x2cb02c7d9c58512c), CONST64(0xd36bd3d6b8bb05d3),
+CONST64(0xe7bbe76b5cd38ce7), CONST64(0x6ea56e57cbdc396e), CONST64(0xc437c46ef395aac4), CONST64(0x030c03180f061b03),
+CONST64(0x5645568a13acdc56), CONST64(0x440d441a49885e44), CONST64(0x7fe17fdf9efea07f), CONST64(0xa99ea921374f88a9),
+CONST64(0x2aa82a4d8254672a), CONST64(0xbbd6bbb16d6b0abb), CONST64(0xc123c146e29f87c1), CONST64(0x535153a202a6f153),
+CONST64(0xdc57dcae8ba572dc), CONST64(0x0b2c0b582716530b), CONST64(0x9d4e9d9cd327019d), CONST64(0x6cad6c47c1d82b6c),
+CONST64(0x31c43195f562a431), CONST64(0x74cd7487b9e8f374), CONST64(0xf6fff6e309f115f6), CONST64(0x4605460a438c4c46),
+CONST64(0xac8aac092645a5ac), CONST64(0x891e893c970fb589), CONST64(0x145014a04428b414), CONST64(0xe1a3e15b42dfbae1),
+CONST64(0x165816b04e2ca616), CONST64(0x3ae83acdd274f73a), CONST64(0x69b9696fd0d20669), CONST64(0x092409482d124109),
+CONST64(0x70dd70a7ade0d770), CONST64(0xb6e2b6d954716fb6), CONST64(0xd067d0ceb7bd1ed0), CONST64(0xed93ed3b7ec7d6ed),
+CONST64(0xcc17cc2edb85e2cc), CONST64(0x4215422a57846842), CONST64(0x985a98b4c22d2c98), CONST64(0xa4aaa4490e55eda4),
+CONST64(0x28a0285d88507528), CONST64(0x5c6d5cda31b8865c), CONST64(0xf8c7f8933fed6bf8), CONST64(0x86228644a411c286)
+};
+
+#endif
+
+static const ulong64 cont[] = {
+CONST64(0x1823c6e887b8014f),
+CONST64(0x36a6d2f5796f9152),
+CONST64(0x60bc9b8ea30c7b35),
+CONST64(0x1de0d7c22e4bfe57),
+CONST64(0x157737e59ff04ada),
+CONST64(0x58c9290ab1a06b85),
+CONST64(0xbd5d10f4cb3e0567),
+CONST64(0xe427418ba77d95d8),
+CONST64(0xfbee7c66dd17479e),
+CONST64(0xca2dbf07ad5a8333),
+CONST64(0x6302aa71c81949d9),
+};
+
+#endif /* LTC_WHIRLTAB_C */
diff --git a/Sources/libtomcrypt/include/tomcrypt.h b/Sources/libtomcrypt/include/tomcrypt.h
new file mode 100644
index 00000000..5d44c961
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt.h
@@ -0,0 +1,97 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_H_
+#define TOMCRYPT_H_
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* use configuration data */
+#include "tomcrypt_custom.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* version */
+#define CRYPT 0x0118
+#define SCRYPT "1.18.2-develop"
+
+/* max size of either a cipher/hash block or symmetric key [largest of the two] */
+#define MAXBLOCKSIZE 144
+
+#ifndef TAB_SIZE
+/* descriptor table size */
+#define TAB_SIZE 48
+#endif
+
+/* error codes [will be expanded in future releases] */
+enum {
+ CRYPT_OK=0, /* Result OK */
+ CRYPT_ERROR, /* Generic Error */
+ CRYPT_NOP, /* Not a failure but no operation was performed */
+
+ CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
+ CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
+ CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
+
+ CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
+ CRYPT_INVALID_PACKET, /* Invalid input packet given */
+
+ CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
+ CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
+
+ CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
+ CRYPT_INVALID_HASH, /* Invalid hash specified */
+ CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
+
+ CRYPT_MEM, /* Out of memory */
+
+ CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
+ CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
+
+ CRYPT_INVALID_ARG, /* Generic invalid argument */
+ CRYPT_FILE_NOTFOUND, /* File Not Found */
+
+ CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
+
+ CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */
+
+ CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */
+
+ CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */
+
+ CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
+
+ CRYPT_INVALID_PRIME_SIZE, /* Invalid size of prime requested */
+ CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */
+
+ CRYPT_HASH_OVERFLOW, /* Hash applied to too many bits */
+ CRYPT_PW_CTX_MISSING, /* Password context to decrypt key file is missing */
+ CRYPT_UNKNOWN_PEM, /* The PEM header was not recognized */
+};
+
+#include "tomcrypt_cfg.h"
+#include "tomcrypt_macros.h"
+#include "tomcrypt_cipher.h"
+#include "tomcrypt_hash.h"
+#include "tomcrypt_mac.h"
+#include "tomcrypt_prng.h"
+#include "tomcrypt_pk.h"
+#include "tomcrypt_math.h"
+#include "tomcrypt_misc.h"
+#include "tomcrypt_argchk.h"
+#include "tomcrypt_pkcs.h"
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* TOMCRYPT_H_ */
+
diff --git a/Sources/libtomcrypt/include/tomcrypt_argchk.h b/Sources/libtomcrypt/include/tomcrypt_argchk.h
new file mode 100644
index 00000000..1d514e46
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_argchk.h
@@ -0,0 +1,42 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_ARGCHK_H_
+#define TOMCRYPT_ARGCHK_H_
+
+/* Defines the LTC_ARGCHK macro used within the library */
+/* ARGTYPE is defined in tomcrypt_cfg.h */
+
+/* ARGTYPE is per default defined to 0 */
+#if ARGTYPE == 0
+
+#include
+
+LTC_NORETURN void crypt_argchk(const char *v, const char *s, int d);
+#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
+#define LTC_ARGCHKVD(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
+
+#elif ARGTYPE == 1
+
+/* fatal type of error */
+#define LTC_ARGCHK(x) assert((x))
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 2
+
+#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); }
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 3
+
+#define LTC_ARGCHK(x) LTC_UNUSED_PARAM(x)
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 4
+
+#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG;
+#define LTC_ARGCHKVD(x) if (!(x)) return;
+
+#endif
+
+#endif /* TOMCRYPT_ARGCHK_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_cfg.h b/Sources/libtomcrypt/include/tomcrypt_cfg.h
new file mode 100644
index 00000000..294b6bd4
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_cfg.h
@@ -0,0 +1,341 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* This is the build config file.
+ *
+ * With this you can setup what to include/exclude automatically during any build. Just comment
+ * out the line that #define's the word for the thing you want to remove. phew!
+ */
+
+#ifndef TOMCRYPT_CFG_H
+#define TOMCRYPT_CFG_H
+
+#if defined(_WIN32) || defined(_MSC_VER)
+ #define LTC_CALL __cdecl
+#elif !defined(LTC_CALL)
+ #define LTC_CALL
+#endif
+
+#ifndef LTC_EXPORT
+ #define LTC_EXPORT
+#endif
+
+/* certain platforms use macros for these, making the prototypes broken */
+#ifndef LTC_NO_PROTOTYPES
+
+/* you can change how memory allocation works ... */
+LTC_EXPORT void * LTC_CALL XMALLOC(size_t n);
+LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n);
+LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s);
+LTC_EXPORT void LTC_CALL XFREE(void *p);
+
+LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
+
+
+/* change the clock function too */
+LTC_EXPORT clock_t LTC_CALL XCLOCK(void);
+
+/* various other functions */
+LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n);
+LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n);
+LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n);
+
+LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2);
+
+#endif
+
+/* some compilers do not like "inline" (or maybe "static inline"), namely: HP cc, IBM xlc */
+#if defined(__GNUC__) || defined(__xlc__)
+ #define LTC_INLINE __inline__
+#elif defined(_MSC_VER) || defined(__HP_cc)
+ #define LTC_INLINE __inline
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ #define LTC_INLINE inline
+#else
+ #define LTC_INLINE
+#endif
+
+#if defined(__clang__) || defined(__GNUC_MINOR__)
+#define LTC_NORETURN __attribute__ ((noreturn))
+#elif defined(_MSC_VER)
+#define LTC_NORETURN __declspec(noreturn)
+#else
+#define LTC_NORETURN
+#endif
+
+/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */
+#ifndef ARGTYPE
+ #define ARGTYPE 0
+#endif
+
+#undef LTC_ENCRYPT
+#define LTC_ENCRYPT 0
+#undef LTC_DECRYPT
+#define LTC_DECRYPT 1
+
+/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code
+ *
+ * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.
+ * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST**
+ * use the portable [slower] macros.
+ */
+/* detect x86/i386/ARM 32bit */
+#if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_ARM)
+ #define ENDIAN_LITTLE
+ #define ENDIAN_32BITWORD
+ #define LTC_FAST
+#endif
+
+/* detect amd64/x64/arm64 */
+#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(_M_ARM64)
+ #define ENDIAN_LITTLE
+ #define ENDIAN_64BITWORD
+ #define LTC_FAST
+#endif
+
+/* detect PPC32 */
+#if defined(LTC_PPC32)
+ #define ENDIAN_BIG
+ #define ENDIAN_32BITWORD
+ #define LTC_FAST
+#endif
+
+/* detects MIPS R5900 processors (PS2) */
+#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))
+ #define ENDIAN_64BITWORD
+ #if defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
+ #define ENDIAN_BIG
+ #else
+ #define ENDIAN_LITTLE
+ #endif
+#endif
+
+/* detect AIX */
+#if defined(_AIX) && defined(_BIG_ENDIAN)
+ #define ENDIAN_BIG
+ #if defined(__LP64__) || defined(_ARCH_PPC64)
+ #define ENDIAN_64BITWORD
+ #else
+ #define ENDIAN_32BITWORD
+ #endif
+#endif
+
+/* detect HP-UX */
+#if defined(__hpux) || defined(__hpux__)
+ #define ENDIAN_BIG
+ #if defined(__ia64) || defined(__ia64__) || defined(__LP64__)
+ #define ENDIAN_64BITWORD
+ #else
+ #define ENDIAN_32BITWORD
+ #endif
+#endif
+
+/* detect Apple OS X */
+#if defined(__APPLE__) && defined(__MACH__)
+ #if defined(__LITTLE_ENDIAN__) || defined(__x86_64__)
+ #define ENDIAN_LITTLE
+ #else
+ #define ENDIAN_BIG
+ #endif
+ #if defined(__LP64__) || defined(__x86_64__)
+ #define ENDIAN_64BITWORD
+ #else
+ #define ENDIAN_32BITWORD
+ #endif
+#endif
+
+/* detect SPARC and SPARC64 */
+#if defined(__sparc__) || defined(__sparc)
+ #define ENDIAN_BIG
+ #if defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__)
+ #define ENDIAN_64BITWORD
+ #else
+ #define ENDIAN_32BITWORD
+ #endif
+#endif
+
+/* detect IBM S390(x) */
+#if defined(__s390x__) || defined(__s390__)
+ #define ENDIAN_BIG
+ #if defined(__s390x__)
+ #define ENDIAN_64BITWORD
+ #else
+ #define ENDIAN_32BITWORD
+ #endif
+#endif
+
+/* detect PPC64 */
+#if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
+ #define ENDIAN_64BITWORD
+ #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ #define ENDIAN_BIG
+ #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ #define ENDIAN_LITTLE
+ #endif
+ #define LTC_FAST
+#endif
+
+/* endianness fallback */
+#if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE)
+ #if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN || \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
+ defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \
+ defined(__BIG_ENDIAN__) || \
+ defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
+ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \
+ defined(__m68k__)
+ #define ENDIAN_BIG
+ #elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN || \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
+ defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \
+ defined(__LITTLE_ENDIAN__) || \
+ defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
+ defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \
+ defined(_M_ARM) || defined(_M_ARM64)
+ #define ENDIAN_LITTLE
+ #else
+ #error Cannot detect endianness
+ #endif
+#endif
+
+/* ulong64: 64-bit data type */
+#ifdef _MSC_VER
+ #define CONST64(n) n ## ui64
+ typedef unsigned __int64 ulong64;
+ typedef __int64 long64;
+#else
+ #define CONST64(n) n ## uLL
+ typedef unsigned long long ulong64;
+ typedef long long long64;
+#endif
+
+/* ulong32: "32-bit at least" data type */
+#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \
+ defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \
+ defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \
+ defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \
+ defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \
+ defined(__LP64__) || defined(_LP64) || defined(__64BIT__) || defined(_M_ARM64)
+ typedef unsigned ulong32;
+ #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD)
+ #define ENDIAN_64BITWORD
+ #endif
+#else
+ typedef unsigned long ulong32;
+ #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD)
+ #define ENDIAN_32BITWORD
+ #endif
+#endif
+
+#if defined(ENDIAN_64BITWORD) && !defined(_MSC_VER)
+typedef unsigned long long ltc_mp_digit;
+#else
+typedef unsigned long ltc_mp_digit;
+#endif
+
+/* No asm is a quick way to disable anything "not portable" */
+#ifdef LTC_NO_ASM
+ #define ENDIAN_NEUTRAL
+ #undef ENDIAN_32BITWORD
+ #undef ENDIAN_64BITWORD
+ #undef LTC_FAST
+ #define LTC_NO_BSWAP
+ #define LTC_NO_ROLC
+ #define LTC_NO_ROTATE
+#endif
+
+/* No LTC_FAST if: explicitly disabled OR non-gcc/non-clang compiler OR old gcc OR using -ansi -std=c99 */
+#if defined(LTC_NO_FAST) || (__GNUC__ < 4) || defined(__STRICT_ANSI__)
+ #undef LTC_FAST
+#endif
+
+#ifdef LTC_FAST
+ #define LTC_FAST_TYPE_PTR_CAST(x) ((LTC_FAST_TYPE*)(void*)(x))
+ #ifdef ENDIAN_64BITWORD
+ typedef ulong64 __attribute__((__may_alias__)) LTC_FAST_TYPE;
+ #else
+ typedef ulong32 __attribute__((__may_alias__)) LTC_FAST_TYPE;
+ #endif
+#endif
+
+#if !defined(ENDIAN_NEUTRAL) && (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
+ #error You must specify a word size as well as endianess in tomcrypt_cfg.h
+#endif
+
+#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
+ #define ENDIAN_NEUTRAL
+#endif
+
+#if (defined(ENDIAN_32BITWORD) && defined(ENDIAN_64BITWORD))
+ #error Cannot be 32 and 64 bit words...
+#endif
+
+/* gcc 4.3 and up has a bswap builtin; detect it by gcc version.
+ * clang also supports the bswap builtin, and although clang pretends
+ * to be gcc (macro-wise, anyway), clang pretends to be a version
+ * prior to gcc 4.3, so we can't detect bswap that way. Instead,
+ * clang has a __has_builtin mechanism that can be used to check
+ * for builtins:
+ * http://clang.llvm.org/docs/LanguageExtensions.html#feature_check */
+#ifndef __has_builtin
+ #define __has_builtin(x) 0
+#endif
+#if !defined(LTC_NO_BSWAP) && defined(__GNUC__) && \
+ ((__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || \
+ (__has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)))
+ #define LTC_HAVE_BSWAP_BUILTIN
+#endif
+
+#if !defined(LTC_NO_ROTATE) && (__has_builtin(__builtin_rotateleft32) && __has_builtin(__builtin_rotateright32))
+ #define LTC_HAVE_ROTATE_BUILTIN
+#endif
+
+#if defined(__GNUC__)
+ #define LTC_ALIGN(n) __attribute__((aligned(n)))
+#else
+ #define LTC_ALIGN(n)
+#endif
+
+/* Choose Windows Vista as minimum Version if we're compiling with at least VS2019
+ * This is done in order to test the bcrypt RNG and can still be overridden by the user. */
+#if defined(_MSC_VER) && _MSC_VER >= 1920
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0600
+# endif
+# ifndef WINVER
+# define WINVER 0x0600
+# endif
+#endif
+
+/* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code
+ * before including `tomcrypt.h` to disable this functionality.
+ */
+#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(LTC_NO_NULL_TERMINATION_CHECK)
+# define LTC_NULL_TERMINATED __attribute__((sentinel))
+#else
+# define LTC_NULL_TERMINATED
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
+# define LTC_DEPRECATED(s) __attribute__((deprecated("replaced by " #s)))
+# define PRIVATE_LTC_DEPRECATED_PRAGMA(s) _Pragma(#s)
+# define LTC_DEPRECATED_PRAGMA(s) PRIVATE_LTC_DEPRECATED_PRAGMA(GCC warning s)
+#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301)
+# define LTC_DEPRECATED(s) __attribute__((deprecated))
+# define LTC_DEPRECATED_PRAGMA(s)
+#elif defined(_MSC_VER) && _MSC_VER >= 1500
+ /* supported since Visual Studio 2008 */
+# define LTC_DEPRECATED(s) __declspec(deprecated("replaced by " #s))
+# define LTC_DEPRECATED_PRAGMA(s) __pragma(message(s))
+#else
+# define LTC_DEPRECATED(s)
+# define LTC_DEPRECATED_PRAGMA(s)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+# define LTC_ATTRIBUTE(x) __attribute__(x)
+#else
+# define LTC_ATTRIBUTE(x)
+#endif
+
+#endif /* TOMCRYPT_CFG_H */
diff --git a/Sources/libtomcrypt/include/tomcrypt_cipher.h b/Sources/libtomcrypt/include/tomcrypt_cipher.h
new file mode 100644
index 00000000..680e436c
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_cipher.h
@@ -0,0 +1,1215 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_CIPHER_H_
+#define TOMCRYPT_CIPHER_H_
+
+/* ---- SYMMETRIC KEY STUFF -----
+ *
+ * We put each of the ciphers scheduled keys in their own structs then we put all of
+ * the key formats in one union. This makes the function prototypes easier to use.
+ */
+#ifdef LTC_BLOWFISH
+struct blowfish_key {
+ ulong32 S[4][256];
+ ulong32 K[18];
+};
+#endif
+
+#ifdef LTC_RC5
+struct rc5_key {
+ int rounds;
+ ulong32 K[50];
+};
+#endif
+
+#ifdef LTC_RC6
+struct rc6_key {
+ ulong32 K[44];
+};
+#endif
+
+#ifdef LTC_SAFERP
+struct saferp_key {
+ unsigned char K[33][16];
+ long rounds;
+};
+#endif
+
+#ifdef LTC_RIJNDAEL
+struct rijndael_key {
+ unsigned char K[(60 + 60 + 4) * sizeof(ulong32)];
+ ulong32 *eK;
+ ulong32 *dK;
+ int Nr;
+};
+#endif
+
+#ifdef LTC_KSEED
+struct kseed_key {
+ ulong32 K[32], dK[32];
+};
+#endif
+
+#ifdef LTC_KASUMI
+struct kasumi_key {
+ ulong32 KLi1[8], KLi2[8],
+ KOi1[8], KOi2[8], KOi3[8],
+ KIi1[8], KIi2[8], KIi3[8];
+};
+#endif
+
+#ifdef LTC_XTEA
+struct xtea_key {
+ unsigned long A[32], B[32];
+};
+#endif
+
+#ifdef LTC_TWOFISH
+#ifndef LTC_TWOFISH_SMALL
+ struct twofish_key {
+ ulong32 S[4][256], K[40];
+ };
+#else
+ struct twofish_key {
+ ulong32 K[40];
+ unsigned char S[32], start;
+ };
+#endif
+#endif
+
+#ifdef LTC_SAFER
+#define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6
+#define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10
+#define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8
+#define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10
+#define LTC_SAFER_MAX_NOF_ROUNDS 13
+#define LTC_SAFER_BLOCK_LEN 8
+#define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS))
+typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN];
+typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN];
+struct safer_key { safer_key_t key; };
+#endif
+
+#ifdef LTC_RC2
+struct rc2_key { unsigned xkey[64]; };
+#endif
+
+#ifdef LTC_DES
+struct des_key {
+ ulong32 ek[32], dk[32];
+};
+
+struct desx_key {
+ ulong32 ek[32], dk[32];
+ ulong32 k[2][2];
+};
+
+struct des3_key {
+ ulong32 ek[3][32], dk[3][32];
+};
+#endif
+
+#ifdef LTC_SM4
+struct sm4_key {
+ ulong32 ek[32], dk[32];
+};
+#endif
+
+#ifdef LTC_CAST5
+struct cast5_key {
+ ulong32 K[32], keylen;
+};
+#endif
+
+#ifdef LTC_NOEKEON
+struct noekeon_key {
+ ulong32 K[4], dK[4];
+};
+#endif
+
+#ifdef LTC_SKIPJACK
+struct skipjack_key {
+ unsigned char key[10];
+};
+#endif
+
+#ifdef LTC_KHAZAD
+struct khazad_key {
+ ulong64 roundKeyEnc[8 + 1];
+ ulong64 roundKeyDec[8 + 1];
+};
+#endif
+
+#ifdef LTC_ANUBIS
+struct anubis_key {
+ ulong32 roundKeyEnc[18 + 1][4];
+ ulong32 roundKeyDec[18 + 1][4];
+ int keyBits;
+ int R;
+};
+#endif
+
+#ifdef LTC_MULTI2
+struct multi2_key {
+ ulong32 uk[8];
+ int N;
+};
+#endif
+
+#ifdef LTC_CAMELLIA
+struct camellia_key {
+ ulong64 kw[4], k[24], kl[6];
+ int R;
+};
+#endif
+
+#ifdef LTC_IDEA
+/* rounds */
+#define LTC_IDEA_ROUNDS 8
+/* key schedule length in # of unsigned shorts */
+#define LTC_IDEA_KEYLEN 6*LTC_IDEA_ROUNDS+4
+struct idea_key {
+ unsigned short int ek[LTC_IDEA_KEYLEN]; /* enc key */
+ unsigned short int dk[LTC_IDEA_KEYLEN]; /* dec key */
+};
+#endif
+
+#ifdef LTC_SERPENT
+struct serpent_key {
+ ulong32 k[33*4];
+};
+#endif
+
+#ifdef LTC_TEA
+struct tea_key {
+ ulong32 k[4];
+};
+#endif
+
+typedef union Symmetric_key {
+#ifdef LTC_DES
+ struct des_key des;
+ struct desx_key desx;
+ struct des3_key des3;
+#endif
+#ifdef LTC_SM4
+ struct sm4_key sm4;
+#endif
+#ifdef LTC_RC2
+ struct rc2_key rc2;
+#endif
+#ifdef LTC_SAFER
+ struct safer_key safer;
+#endif
+#ifdef LTC_TWOFISH
+ struct twofish_key twofish;
+#endif
+#ifdef LTC_BLOWFISH
+ struct blowfish_key blowfish;
+#endif
+#ifdef LTC_RC5
+ struct rc5_key rc5;
+#endif
+#ifdef LTC_RC6
+ struct rc6_key rc6;
+#endif
+#ifdef LTC_SAFERP
+ struct saferp_key saferp;
+#endif
+#ifdef LTC_RIJNDAEL
+ struct rijndael_key rijndael;
+#endif
+#ifdef LTC_XTEA
+ struct xtea_key xtea;
+#endif
+#ifdef LTC_CAST5
+ struct cast5_key cast5;
+#endif
+#ifdef LTC_NOEKEON
+ struct noekeon_key noekeon;
+#endif
+#ifdef LTC_SKIPJACK
+ struct skipjack_key skipjack;
+#endif
+#ifdef LTC_KHAZAD
+ struct khazad_key khazad;
+#endif
+#ifdef LTC_ANUBIS
+ struct anubis_key anubis;
+#endif
+#ifdef LTC_KSEED
+ struct kseed_key kseed;
+#endif
+#ifdef LTC_KASUMI
+ struct kasumi_key kasumi;
+#endif
+#ifdef LTC_MULTI2
+ struct multi2_key multi2;
+#endif
+#ifdef LTC_CAMELLIA
+ struct camellia_key camellia;
+#endif
+#ifdef LTC_IDEA
+ struct idea_key idea;
+#endif
+#ifdef LTC_SERPENT
+ struct serpent_key serpent;
+#endif
+#ifdef LTC_TEA
+ struct tea_key tea;
+#endif
+ void *data;
+} symmetric_key;
+
+#ifdef LTC_ECB_MODE
+/** A block cipher ECB structure */
+typedef struct {
+ /** The scheduled key */
+ symmetric_key key;
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen;
+} symmetric_ECB;
+#endif
+
+#ifdef LTC_CFB_MODE
+/** A block cipher CFB structure */
+typedef struct {
+ /** The current IV */
+ unsigned char IV[MAXBLOCKSIZE],
+ /** The pad used to encrypt/decrypt */
+ pad[MAXBLOCKSIZE];
+ /** The scheduled key */
+ symmetric_key key;
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen,
+ /** The width of the mode: 1, 8, 64, or 128 */
+ width,
+ /** The padding offset */
+ padlen;
+} symmetric_CFB;
+#endif
+
+#ifdef LTC_OFB_MODE
+/** A block cipher OFB structure */
+typedef struct {
+ /** The current IV */
+ unsigned char IV[MAXBLOCKSIZE];
+ /** The scheduled key */
+ symmetric_key key;
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen,
+ /** The padding offset */
+ padlen;
+} symmetric_OFB;
+#endif
+
+#ifdef LTC_CBC_MODE
+/** A block cipher CBC structure */
+typedef struct {
+ /** The current IV */
+ unsigned char IV[MAXBLOCKSIZE];
+ /** The scheduled key */
+ symmetric_key key;
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen;
+} symmetric_CBC;
+#endif
+
+
+#ifdef LTC_CTR_MODE
+/** A block cipher CTR structure */
+typedef struct {
+ /** The counter */
+ unsigned char ctr[MAXBLOCKSIZE];
+ /** The pad used to encrypt/decrypt */
+ unsigned char pad[MAXBLOCKSIZE];
+ /** The scheduled key */
+ symmetric_key key;
+
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen,
+ /** The padding offset */
+ padlen,
+ /** The mode (endianess) of the CTR, 0==little, 1==big */
+ mode,
+ /** counter width */
+ ctrlen;
+} symmetric_CTR;
+#endif
+
+
+#ifdef LTC_LRW_MODE
+/** A LRW structure */
+typedef struct {
+ /** The current IV */
+ unsigned char IV[16],
+
+ /** the tweak key */
+ tweak[16],
+
+ /** The current pad, it's the product of the first 15 bytes against the tweak key */
+ pad[16];
+
+ /** The scheduled symmetric key */
+ symmetric_key key;
+
+#ifdef LTC_LRW_TABLES
+ /** The pre-computed multiplication table */
+ unsigned char PC[16][256][16];
+#endif
+
+ /** The index of the cipher chosen (must be a 128-bit block cipher) */
+ int cipher;
+} symmetric_LRW;
+#endif
+
+#ifdef LTC_F8_MODE
+/** A block cipher F8 structure */
+typedef struct {
+ /** The current IV */
+ unsigned char IV[MAXBLOCKSIZE],
+ MIV[MAXBLOCKSIZE];
+ /** The scheduled key */
+ symmetric_key key;
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen,
+ /** The padding offset */
+ padlen;
+ /** Current block count */
+ ulong32 blockcnt;
+} symmetric_F8;
+#endif
+
+
+/** cipher descriptor table, last entry has "name == NULL" to mark the end of table */
+extern struct ltc_cipher_descriptor {
+ /** name of cipher */
+ const char *name;
+ /** internal ID */
+ unsigned char ID;
+ /** min keysize (octets) */
+ int min_key_length,
+ /** max keysize (octets) */
+ max_key_length,
+ /** block size (octets) */
+ block_length,
+ /** default number of rounds */
+ default_rounds;
+ /** Setup the cipher
+ @param key The input symmetric key
+ @param keylen The length of the input key (octets)
+ @param num_rounds The requested number of rounds (0==default)
+ @param skey [out] The destination of the scheduled key
+ @return CRYPT_OK if successful
+ */
+ int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ /** Encrypt a block
+ @param pt The plaintext
+ @param ct [out] The ciphertext
+ @param skey The scheduled key
+ @return CRYPT_OK if successful
+ */
+ int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+ /** Decrypt a block
+ @param ct The ciphertext
+ @param pt [out] The plaintext
+ @param skey The scheduled key
+ @return CRYPT_OK if successful
+ */
+ int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+ /** Test the block cipher
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+ */
+ int (*test)(void);
+
+ /** Terminate the context
+ @param skey The scheduled key
+ */
+ void (*done)(symmetric_key *skey);
+
+ /** Determine a key size
+ @param keysize [in/out] The size of the key desired and the suggested size
+ @return CRYPT_OK if successful
+ */
+ int (*keysize)(int *keysize);
+
+/** Accelerators **/
+ /** Accelerated ECB encryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey);
+
+ /** Accelerated ECB decryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey);
+
+ /** Accelerated CBC encryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
+
+ /** Accelerated CBC decryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
+
+ /** Accelerated CTR encryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param mode little or big endian counter (mode=0 or mode=1)
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey);
+
+ /** Accelerated LRW
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param tweak The LRW tweak
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
+
+ /** Accelerated LRW
+ @param ct Ciphertext
+ @param pt Plaintext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param tweak The LRW tweak
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
+
+ /** Accelerated CCM packet (one-shot)
+ @param key The secret key to use
+ @param keylen The length of the secret key (octets)
+ @param uskey A previously scheduled key [optional can be NULL]
+ @param nonce The session nonce [use once]
+ @param noncelen The length of the nonce
+ @param header The header for the session
+ @param headerlen The length of the header (octets)
+ @param pt [out] The plaintext
+ @param ptlen The length of the plaintext (octets)
+ @param ct [out] The ciphertext
+ @param tag [out] The destination tag
+ @param taglen [in/out] The max size and resulting size of the authentication tag
+ @param direction Encrypt or Decrypt direction (0 or 1)
+ @return CRYPT_OK if successful
+ */
+ int (*accel_ccm_memory)(
+ const unsigned char *key, unsigned long keylen,
+ symmetric_key *uskey,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction);
+
+ /** Accelerated GCM packet (one shot)
+ @param key The secret key
+ @param keylen The length of the secret key
+ @param IV The initialization vector
+ @param IVlen The length of the initialization vector
+ @param adata The additional authentication data (header)
+ @param adatalen The length of the adata
+ @param pt The plaintext
+ @param ptlen The length of the plaintext (ciphertext length is the same)
+ @param ct The ciphertext
+ @param tag [out] The MAC tag
+ @param taglen [in/out] The MAC tag length
+ @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
+ @return CRYPT_OK on success
+ */
+ int (*accel_gcm_memory)(
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *IV, unsigned long IVlen,
+ const unsigned char *adata, unsigned long adatalen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction);
+
+ /** Accelerated one shot LTC_OMAC
+ @param key The secret key
+ @param keylen The key length (octets)
+ @param in The message
+ @param inlen Length of message (octets)
+ @param out [out] Destination for tag
+ @param outlen [in/out] Initial and final size of out
+ @return CRYPT_OK on success
+ */
+ int (*omac_memory)(
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+ /** Accelerated one shot XCBC
+ @param key The secret key
+ @param keylen The key length (octets)
+ @param in The message
+ @param inlen Length of message (octets)
+ @param out [out] Destination for tag
+ @param outlen [in/out] Initial and final size of out
+ @return CRYPT_OK on success
+ */
+ int (*xcbc_memory)(
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+ /** Accelerated one shot F9
+ @param key The secret key
+ @param keylen The key length (octets)
+ @param in The message
+ @param inlen Length of message (octets)
+ @param out [out] Destination for tag
+ @param outlen [in/out] Initial and final size of out
+ @return CRYPT_OK on success
+ @remark Requires manual padding
+ */
+ int (*f9_memory)(
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+ /** Accelerated XTS encryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param tweak The 128-bit encryption tweak (input/output).
+ The tweak should not be encrypted on input, but
+ next tweak will be copied encrypted on output.
+ @param skey1 The first scheduled key context
+ @param skey2 The second scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_xts_encrypt)(const unsigned char *pt, unsigned char *ct,
+ unsigned long blocks, unsigned char *tweak,
+ const symmetric_key *skey1, const symmetric_key *skey2);
+
+ /** Accelerated XTS decryption
+ @param ct Ciphertext
+ @param pt Plaintext
+ @param blocks The number of complete blocks to process
+ @param tweak The 128-bit encryption tweak (input/output).
+ The tweak should not be encrypted on input, but
+ next tweak will be copied encrypted on output.
+ @param skey1 The first scheduled key context
+ @param skey2 The second scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_xts_decrypt)(const unsigned char *ct, unsigned char *pt,
+ unsigned long blocks, unsigned char *tweak,
+ const symmetric_key *skey1, const symmetric_key *skey2);
+} cipher_descriptor[];
+
+#ifdef LTC_BLOWFISH
+int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int blowfish_test(void);
+void blowfish_done(symmetric_key *skey);
+int blowfish_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor blowfish_desc;
+#endif
+
+#ifdef LTC_RC5
+int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int rc5_test(void);
+void rc5_done(symmetric_key *skey);
+int rc5_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor rc5_desc;
+#endif
+
+#ifdef LTC_RC6
+int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int rc6_test(void);
+void rc6_done(symmetric_key *skey);
+int rc6_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor rc6_desc;
+#endif
+
+#ifdef LTC_RC2
+int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey);
+int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int rc2_test(void);
+void rc2_done(symmetric_key *skey);
+int rc2_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor rc2_desc;
+#endif
+
+#ifdef LTC_SAFERP
+int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int saferp_test(void);
+void saferp_done(symmetric_key *skey);
+int saferp_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor saferp_desc;
+#endif
+
+#ifdef LTC_SAFER
+int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int safer_k64_test(void);
+int safer_sk64_test(void);
+int safer_sk128_test(void);
+void safer_done(symmetric_key *skey);
+int safer_64_keysize(int *keysize);
+int safer_128_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;
+#endif
+
+#ifdef LTC_RIJNDAEL
+/* declare aes properly now */
+int aes_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int aes_test(void);
+void aes_done(symmetric_key *skey);
+int aes_keysize(int *keysize);
+int aes_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int aes_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int aes_enc_test(void);
+void aes_enc_done(symmetric_key *skey);
+int aes_enc_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor aes_desc;
+extern const struct ltc_cipher_descriptor aes_enc_desc;
+
+int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int rijndael_test(void);
+void rijndael_done(symmetric_key *skey);
+int rijndael_keysize(int *keysize);
+int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+void rijndael_enc_done(symmetric_key *skey);
+int rijndael_enc_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor rijndael_desc;
+extern const struct ltc_cipher_descriptor rijndael_enc_desc;
+#endif
+
+#if defined(LTC_AES_NI)
+int aesni_is_supported(void);
+int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int aesni_test(void);
+void aesni_done(symmetric_key *skey);
+int aesni_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor aesni_desc;
+#endif
+
+#ifdef LTC_XTEA
+int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int xtea_test(void);
+void xtea_done(symmetric_key *skey);
+int xtea_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor xtea_desc;
+#endif
+
+#ifdef LTC_TWOFISH
+int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int twofish_test(void);
+void twofish_done(symmetric_key *skey);
+int twofish_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor twofish_desc;
+#endif
+
+#ifdef LTC_DES
+int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int des_test(void);
+void des_done(symmetric_key *skey);
+int des_keysize(int *keysize);
+int desx_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int desx_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int desx_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int desx_test(void);
+void desx_done(symmetric_key *skey);
+int desx_keysize(int *keysize);
+int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int des3_test(void);
+void des3_done(symmetric_key *skey);
+int des3_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor des_desc, desx_desc, des3_desc;
+#endif
+
+#ifdef LTC_SM4
+int sm4_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int sm4_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int sm4_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int sm4_test(void);
+void sm4_done(symmetric_key *skey);
+int sm4_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor sm4_desc;
+#endif
+
+#ifdef LTC_CAST5
+int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int cast5_test(void);
+void cast5_done(symmetric_key *skey);
+int cast5_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor cast5_desc;
+#endif
+
+#ifdef LTC_NOEKEON
+int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int noekeon_test(void);
+void noekeon_done(symmetric_key *skey);
+int noekeon_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor noekeon_desc;
+#endif
+
+#ifdef LTC_SKIPJACK
+int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int skipjack_test(void);
+void skipjack_done(symmetric_key *skey);
+int skipjack_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor skipjack_desc;
+#endif
+
+#ifdef LTC_KHAZAD
+int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int khazad_test(void);
+void khazad_done(symmetric_key *skey);
+int khazad_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor khazad_desc;
+#endif
+
+#ifdef LTC_ANUBIS
+int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int anubis_test(void);
+void anubis_done(symmetric_key *skey);
+int anubis_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor anubis_desc;
+#endif
+
+#ifdef LTC_KSEED
+int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int kseed_test(void);
+void kseed_done(symmetric_key *skey);
+int kseed_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor kseed_desc;
+#endif
+
+#ifdef LTC_KASUMI
+int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int kasumi_test(void);
+void kasumi_done(symmetric_key *skey);
+int kasumi_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor kasumi_desc;
+#endif
+
+
+#ifdef LTC_MULTI2
+int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int multi2_test(void);
+void multi2_done(symmetric_key *skey);
+int multi2_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor multi2_desc;
+#endif
+
+#ifdef LTC_CAMELLIA
+int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int camellia_test(void);
+void camellia_done(symmetric_key *skey);
+int camellia_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor camellia_desc;
+#endif
+
+#ifdef LTC_IDEA
+int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int idea_test(void);
+void idea_done(symmetric_key *skey);
+int idea_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor idea_desc;
+#endif
+
+#ifdef LTC_SERPENT
+int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int serpent_test(void);
+void serpent_done(symmetric_key *skey);
+int serpent_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor serpent_desc;
+#endif
+
+#ifdef LTC_TEA
+int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int tea_test(void);
+void tea_done(symmetric_key *skey);
+int tea_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor tea_desc;
+#endif
+
+#ifdef LTC_ECB_MODE
+int ecb_start(int cipher, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_ECB *ecb);
+int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb);
+int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb);
+int ecb_done(symmetric_ECB *ecb);
+#endif
+
+#ifdef LTC_CFB_MODE
+int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_CFB *cfb);
+int cfb_start_ex(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, int width, symmetric_CFB *cfb);
+int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);
+int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);
+int cfb_getiv(unsigned char *IV, unsigned long *len, const symmetric_CFB *cfb);
+int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb);
+int cfb_done(symmetric_CFB *cfb);
+#endif
+
+#ifdef LTC_OFB_MODE
+int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_OFB *ofb);
+int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);
+int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);
+int ofb_getiv(unsigned char *IV, unsigned long *len, const symmetric_OFB *ofb);
+int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb);
+int ofb_done(symmetric_OFB *ofb);
+#endif
+
+#ifdef LTC_CBC_MODE
+int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_CBC *cbc);
+int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc);
+int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc);
+int cbc_getiv(unsigned char *IV, unsigned long *len, const symmetric_CBC *cbc);
+int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);
+int cbc_done(symmetric_CBC *cbc);
+#endif
+
+#ifdef LTC_CTR_MODE
+
+#define CTR_COUNTER_LITTLE_ENDIAN 0x0000
+#define CTR_COUNTER_BIG_ENDIAN 0x1000
+#define LTC_CTR_RFC3686 0x2000
+
+int ctr_start( int cipher,
+ const unsigned char *IV,
+ const unsigned char *key, int keylen,
+ int num_rounds, int ctr_mode,
+ symmetric_CTR *ctr);
+int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);
+int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);
+int ctr_getiv(unsigned char *IV, unsigned long *len, const symmetric_CTR *ctr);
+int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr);
+int ctr_done(symmetric_CTR *ctr);
+int ctr_test(void);
+#endif
+
+#ifdef LTC_LRW_MODE
+
+#define LRW_ENCRYPT LTC_ENCRYPT
+#define LRW_DECRYPT LTC_DECRYPT
+
+int lrw_start( int cipher,
+ const unsigned char *IV,
+ const unsigned char *key, int keylen,
+ const unsigned char *tweak,
+ int num_rounds,
+ symmetric_LRW *lrw);
+int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw);
+int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw);
+int lrw_getiv(unsigned char *IV, unsigned long *len, const symmetric_LRW *lrw);
+int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw);
+int lrw_done(symmetric_LRW *lrw);
+int lrw_test(void);
+
+/* don't call */
+int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw);
+#endif
+
+#ifdef LTC_F8_MODE
+int f8_start( int cipher, const unsigned char *IV,
+ const unsigned char *key, int keylen,
+ const unsigned char *salt_key, int skeylen,
+ int num_rounds, symmetric_F8 *f8);
+int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8);
+int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8);
+int f8_getiv(unsigned char *IV, unsigned long *len, const symmetric_F8 *f8);
+int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8);
+int f8_done(symmetric_F8 *f8);
+int f8_test_mode(void);
+#endif
+
+#ifdef LTC_XTS_MODE
+typedef struct {
+ symmetric_key key1, key2;
+ int cipher;
+} symmetric_xts;
+
+int xts_start( int cipher,
+ const unsigned char *key1,
+ const unsigned char *key2,
+ unsigned long keylen,
+ int num_rounds,
+ symmetric_xts *xts);
+
+int xts_encrypt(
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tweak,
+ const symmetric_xts *xts);
+int xts_decrypt(
+ const unsigned char *ct, unsigned long ptlen,
+ unsigned char *pt,
+ unsigned char *tweak,
+ const symmetric_xts *xts);
+
+void xts_done(symmetric_xts *xts);
+int xts_test(void);
+void xts_mult_x(unsigned char *I);
+#endif
+
+int find_cipher(const char *name);
+int find_cipher_any(const char *name, int blocklen, int keylen);
+int find_cipher_id(unsigned char ID);
+int register_cipher(const struct ltc_cipher_descriptor *cipher);
+int unregister_cipher(const struct ltc_cipher_descriptor *cipher);
+int register_all_ciphers(void);
+int cipher_is_valid(int idx);
+
+LTC_MUTEX_PROTO(ltc_cipher_mutex)
+
+/* ---- stream ciphers ---- */
+
+#ifdef LTC_CHACHA
+
+typedef struct {
+ ulong32 input[16];
+ unsigned char kstream[64];
+ unsigned long ksleft;
+ unsigned long ivlen;
+ int rounds;
+} chacha_state;
+
+int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds);
+int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter);
+int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter);
+int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
+int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen);
+int chacha_done(chacha_state *st);
+int chacha_test(void);
+int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds,
+ const unsigned char *iv, unsigned long ivlen, ulong64 counter,
+ const unsigned char *datain, unsigned long datalen, unsigned char *dataout);
+
+#endif /* LTC_CHACHA */
+
+#ifdef LTC_SALSA20
+
+typedef struct {
+ ulong32 input[16];
+ unsigned char kstream[64];
+ unsigned long ksleft;
+ unsigned long ivlen;
+ int rounds;
+} salsa20_state;
+
+int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds);
+int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter);
+int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
+int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen);
+int salsa20_done(salsa20_state *st);
+int salsa20_test(void);
+int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds,
+ const unsigned char *iv, unsigned long ivlen, ulong64 counter,
+ const unsigned char *datain, unsigned long datalen, unsigned char *dataout);
+
+#endif /* LTC_SALSA20 */
+
+#ifdef LTC_XSALSA20
+
+int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ int rounds);
+int xsalsa20_test(void);
+int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *datain, unsigned long datalen, unsigned char *dataout);
+
+#endif /* LTC_XSALSA20 */
+
+#ifdef LTC_SOSEMANUK
+
+typedef struct {
+ ulong32 kc[100]; /* key_context */
+ ulong32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09;
+ ulong32 r1, r2;
+ /*
+ * Buffering: the stream cipher produces output data by
+ * blocks of 640 bits. buf[] contains such a block, and
+ * "ptr" is the index of the next output byte.
+ */
+ unsigned char buf[80];
+ unsigned ptr;
+} sosemanuk_state;
+
+int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen);
+int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen);
+int sosemanuk_crypt(sosemanuk_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
+int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen);
+int sosemanuk_done(sosemanuk_state *st);
+int sosemanuk_test(void);
+int sosemanuk_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout);
+
+#endif /* LTC_SOSEMANUK */
+
+#ifdef LTC_RABBIT
+
+typedef struct {
+ ulong32 x[8];
+ ulong32 c[8];
+ ulong32 carry;
+} rabbit_ctx;
+
+typedef struct {
+ rabbit_ctx master_ctx;
+ rabbit_ctx work_ctx;
+ unsigned char block[16]; /* last keystream block containing unused bytes */
+ ulong32 unused; /* count fm right */
+} rabbit_state;
+
+int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen);
+int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen);
+int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out);
+int rabbit_keystream(rabbit_state* st, unsigned char *out, unsigned long outlen);
+int rabbit_done(rabbit_state *st);
+int rabbit_test(void);
+int rabbit_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout);
+
+#endif /* LTC_RABBIT */
+
+#ifdef LTC_RC4_STREAM
+
+typedef struct {
+ unsigned int x, y;
+ unsigned char buf[256];
+} rc4_state;
+
+int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen);
+int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
+int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen);
+int rc4_stream_done(rc4_state *st);
+int rc4_stream_test(void);
+int rc4_stream_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout);
+
+#endif /* LTC_RC4_STREAM */
+
+#ifdef LTC_SOBER128_STREAM
+
+typedef struct {
+ ulong32 R[17], /* Working storage for the shift register */
+ initR[17], /* saved register contents */
+ konst, /* key dependent constant */
+ sbuf; /* partial word encryption buffer */
+ int nbuf; /* number of part-word stream bits buffered */
+} sober128_state;
+
+int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen);
+int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen);
+int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
+int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen);
+int sober128_stream_done(sober128_state *st);
+int sober128_stream_test(void);
+int sober128_stream_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout);
+
+#endif /* LTC_SOBER128_STREAM */
+
+#endif /* TOMCRYPT_CIPHER_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_custom.h b/Sources/libtomcrypt/include/tomcrypt_custom.h
new file mode 100644
index 00000000..7ce348e2
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_custom.h
@@ -0,0 +1,775 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_CUSTOM_H_
+#define TOMCRYPT_CUSTOM_H_
+
+/* macros for various libc functions you can change for embedded targets */
+#ifndef XMALLOC
+#define XMALLOC malloc
+#endif
+#ifndef XREALLOC
+#define XREALLOC realloc
+#endif
+#ifndef XCALLOC
+#define XCALLOC calloc
+#endif
+#ifndef XFREE
+#define XFREE free
+#endif
+
+#ifndef XMEMSET
+#define XMEMSET memset
+#endif
+#ifndef XMEMCPY
+#define XMEMCPY memcpy
+#endif
+#ifndef XMEMMOVE
+#define XMEMMOVE memmove
+#endif
+#ifndef XMEMCMP
+#define XMEMCMP memcmp
+#endif
+/* A memory compare function that has to run in constant time,
+ * c.f. mem_neq() API summary.
+ */
+#ifndef XMEM_NEQ
+#define XMEM_NEQ mem_neq
+#endif
+#ifndef XSTRCMP
+#define XSTRCMP strcmp
+#endif
+#ifndef XSTRLEN
+#define XSTRLEN strlen
+#endif
+#ifndef XSTRNCPY
+#define XSTRNCPY strncpy
+#endif
+
+#ifndef XCLOCK
+#define XCLOCK clock
+#endif
+
+#ifndef XQSORT
+#define XQSORT qsort
+#endif
+
+#if ( defined(malloc) || defined(realloc) || defined(calloc) || defined(free) || \
+ defined(memset) || defined(memcpy) || defined(memcmp) || defined(strcmp) || \
+ defined(strlen) || defined(strncpy) || defined(clock) || defined(qsort) ) \
+ && !defined(LTC_NO_PROTOTYPES)
+#define LTC_NO_PROTOTYPES
+#endif
+
+/* shortcut to disable automatic inclusion */
+#if defined LTC_NOTHING && !defined LTC_EASY
+ #define LTC_NO_CIPHERS
+ #define LTC_NO_MODES
+ #define LTC_NO_HASHES
+ #define LTC_NO_MACS
+ #define LTC_NO_PRNGS
+ #define LTC_NO_PK
+ #define LTC_NO_PKCS
+ #define LTC_NO_MISC
+#endif /* LTC_NOTHING */
+
+/* Easy button? */
+#ifdef LTC_EASY
+ #define LTC_NO_CIPHERS
+ #define LTC_RIJNDAEL
+ #define LTC_BLOWFISH
+ #define LTC_DES
+ #define LTC_SM4
+ #define LTC_CAST5
+
+ #define LTC_NO_MODES
+ #define LTC_ECB_MODE
+ #define LTC_CBC_MODE
+ #define LTC_CTR_MODE
+
+ #define LTC_NO_HASHES
+ #define LTC_SHA1
+ #define LTC_SHA3
+ #define LTC_SHA512
+ #define LTC_SHA384
+ #define LTC_SHA256
+ #define LTC_SHA224
+ #define LTC_HASH_HELPERS
+
+ #define LTC_NO_MACS
+ #define LTC_HMAC
+ #define LTC_OMAC
+ #define LTC_CCM_MODE
+
+ #define LTC_NO_PRNGS
+ #define LTC_SPRNG
+ #define LTC_YARROW
+ #define LTC_DEVRANDOM
+ #define LTC_TRY_URANDOM_FIRST
+ #define LTC_RNG_GET_BYTES
+ #define LTC_RNG_MAKE_PRNG
+
+ #define LTC_NO_PK
+ #define LTC_MRSA
+ #define LTC_MECC
+
+ #define LTC_NO_MISC
+ #define LTC_BASE64
+ #define LTC_BASE16
+ #define LTC_PEM
+#endif /* LTC_EASY */
+
+/* The minimal set of functionality to run the tests */
+#ifdef LTC_MINIMAL
+ #define LTC_RIJNDAEL
+ #define LTC_SHA256
+ #define LTC_YARROW
+ #define LTC_CTR_MODE
+
+ #define LTC_RNG_MAKE_PRNG
+ #define LTC_RNG_GET_BYTES
+ #define LTC_DEVRANDOM
+ #define LTC_TRY_URANDOM_FIRST
+
+ #undef LTC_NO_FILE
+#endif /* LTC_MINIMAL */
+
+/* Enable self-test test vector checking */
+#ifndef LTC_NO_TEST
+ #define LTC_TEST
+#endif
+/* Enable extended self-tests */
+/* #define LTC_TEST_EXT */
+
+/* Use small code where possible */
+/* #define LTC_SMALL_CODE */
+
+/* clean the stack of functions which put private information on stack */
+/* #define LTC_CLEAN_STACK */
+
+/* disable all file related functions */
+/* #define LTC_NO_FILE */
+
+/* disable all forms of ASM */
+/* #define LTC_NO_ASM */
+
+/* disable FAST mode */
+/* #define LTC_NO_FAST */
+
+/* disable BSWAP on x86 */
+/* #define LTC_NO_BSWAP */
+
+/* ---> math provider? <--- */
+#ifndef LTC_NO_MATH
+
+/* LibTomMath */
+/* #define LTM_DESC */
+
+/* TomsFastMath */
+/* #define TFM_DESC */
+
+/* GNU Multiple Precision Arithmetic Library */
+/* #define GMP_DESC */
+
+#endif /* LTC_NO_MATH */
+
+/* ---> Symmetric Block Ciphers <--- */
+#ifndef LTC_NO_CIPHERS
+
+#define LTC_BLOWFISH
+#define LTC_RC2
+#define LTC_RC5
+#define LTC_RC6
+#define LTC_SAFERP
+#define LTC_RIJNDAEL
+#define LTC_XTEA
+/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
+ * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
+#define LTC_TWOFISH
+#ifndef LTC_NO_TABLES
+ #define LTC_TWOFISH_TABLES
+ /* #define LTC_TWOFISH_ALL_TABLES */
+#else
+ #define LTC_TWOFISH_SMALL
+#endif
+/* #define LTC_TWOFISH_SMALL */
+/* LTC_DES includes EDE triple-DES */
+#define LTC_DES
+#define LTC_SM4
+#define LTC_CAST5
+#define LTC_NOEKEON
+#define LTC_SKIPJACK
+#define LTC_SAFER
+#define LTC_KHAZAD
+#define LTC_ANUBIS
+#define LTC_ANUBIS_TWEAK
+#define LTC_KSEED
+#define LTC_KASUMI
+#define LTC_MULTI2
+#define LTC_CAMELLIA
+#define LTC_IDEA
+#define LTC_SERPENT
+#define LTC_TEA
+
+/* stream ciphers */
+#define LTC_CHACHA
+#define LTC_SALSA20
+#define LTC_XSALSA20
+#define LTC_SOSEMANUK
+#define LTC_RABBIT
+#define LTC_RC4_STREAM
+#define LTC_SOBER128_STREAM
+
+#endif /* LTC_NO_CIPHERS */
+
+
+/* ---> Block Cipher Modes of Operation <--- */
+#ifndef LTC_NO_MODES
+
+#define LTC_CFB_MODE
+#define LTC_OFB_MODE
+#define LTC_ECB_MODE
+#define LTC_CBC_MODE
+#define LTC_CTR_MODE
+
+/* F8 chaining mode */
+#define LTC_F8_MODE
+
+/* LRW mode */
+#define LTC_LRW_MODE
+#ifndef LTC_NO_TABLES
+ /* like GCM mode this will enable 16 8x128 tables [64KB] that make
+ * seeking very fast.
+ */
+ #define LTC_LRW_TABLES
+#endif
+
+/* XTS mode */
+#define LTC_XTS_MODE
+
+#endif /* LTC_NO_MODES */
+
+/* ---> One-Way Hash Functions <--- */
+#ifndef LTC_NO_HASHES
+
+#define LTC_CHC_HASH
+#define LTC_WHIRLPOOL
+#define LTC_SHA3
+#define LTC_KECCAK
+#define LTC_SHA512
+#define LTC_SHA512_256
+#define LTC_SHA512_224
+#define LTC_SHA384
+#define LTC_SHA256
+#define LTC_SHA224
+#define LTC_TIGER
+#define LTC_SHA1
+#define LTC_MD5
+#define LTC_MD4
+#define LTC_MD2
+#define LTC_RIPEMD128
+#define LTC_RIPEMD160
+#define LTC_RIPEMD256
+#define LTC_RIPEMD320
+#define LTC_BLAKE2S
+#define LTC_BLAKE2B
+
+#define LTC_HASH_HELPERS
+
+#endif /* LTC_NO_HASHES */
+
+
+/* ---> MAC functions <--- */
+#ifndef LTC_NO_MACS
+
+#define LTC_HMAC
+#define LTC_OMAC
+#define LTC_PMAC
+#define LTC_XCBC
+#define LTC_F9_MODE
+#define LTC_PELICAN
+#define LTC_POLY1305
+#define LTC_BLAKE2SMAC
+#define LTC_BLAKE2BMAC
+
+/* ---> Encrypt + Authenticate Modes <--- */
+
+#define LTC_EAX_MODE
+
+#define LTC_OCB_MODE
+#define LTC_OCB3_MODE
+#define LTC_CCM_MODE
+#define LTC_GCM_MODE
+#define LTC_CHACHA20POLY1305_MODE
+
+/* Use 64KiB tables */
+#ifndef LTC_NO_TABLES
+ #define LTC_GCM_TABLES
+#endif
+
+/* USE SSE2? requires GCC works on x86_32 and x86_64*/
+#ifdef LTC_GCM_TABLES
+/* #define LTC_GCM_TABLES_SSE2 */
+#endif
+
+#endif /* LTC_NO_MACS */
+
+
+/* --> Pseudo Random Number Generators <--- */
+#ifndef LTC_NO_PRNGS
+
+/* Yarrow */
+#define LTC_YARROW
+
+/* a PRNG that simply reads from an available system source */
+#define LTC_SPRNG
+
+/* The RC4 stream cipher based PRNG */
+#define LTC_RC4
+
+/* The ChaCha20 stream cipher based PRNG */
+#define LTC_CHACHA20_PRNG
+
+/* Fortuna PRNG */
+#define LTC_FORTUNA
+
+/* Greg's SOBER128 stream cipher based PRNG */
+#define LTC_SOBER128
+
+#if !defined(_WIN32) && !defined(_WIN32_WCE)
+/* the *nix style /dev/random device */
+#define LTC_DEVRANDOM
+/* try /dev/urandom before trying /dev/random
+ * are you sure you want to disable this? http://www.2uo.de/myths-about-urandom/ */
+#define LTC_TRY_URANDOM_FIRST
+#endif /* not Windows */
+
+/* rng_get_bytes() */
+#define LTC_RNG_GET_BYTES
+/* rng_make_prng() */
+#define LTC_RNG_MAKE_PRNG
+
+/* enable the ltc_rng hook to integrate e.g. embedded hardware RNG's easily */
+/* #define LTC_PRNG_ENABLE_LTC_RNG */
+
+#endif /* LTC_NO_PRNGS */
+
+#ifdef LTC_YARROW
+
+/* which descriptor of AES to use? */
+/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */
+#ifdef ENCRYPT_ONLY
+ #define LTC_YARROW_AES 0
+#else
+ #define LTC_YARROW_AES 2
+#endif
+
+#endif /* LTC_YARROW */
+
+#ifdef LTC_FORTUNA
+
+#if !defined(LTC_FORTUNA_RESEED_RATELIMIT_STATIC) && \
+ ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || defined(_WIN32))
+
+/* time-based rate limit of the reseeding */
+#define LTC_FORTUNA_RESEED_RATELIMIT_TIMED
+
+/* with non-glibc or glibc 2.17+ prefer clock_gettime over gettimeofday */
+#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+ #if __GLIBC_PREREQ(2, 17)
+ #define LTC_CLOCK_GETTIME
+ #endif
+#elif defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
+ #define LTC_CLOCK_GETTIME
+#endif
+
+#else
+
+#ifndef LTC_FORTUNA_WD
+/* reseed every N calls to the read function */
+#define LTC_FORTUNA_WD 10
+#endif
+
+#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED
+/* make sure only one of
+ * LTC_FORTUNA_RESEED_RATELIMIT_STATIC
+ * and
+ * LTC_FORTUNA_RESEED_RATELIMIT_TIMED
+ * is defined.
+ */
+#undef LTC_FORTUNA_RESEED_RATELIMIT_TIMED
+#warning "undef'ed LTC_FORTUNA_RESEED_RATELIMIT_TIMED, looks like your architecture doesn't support it"
+#endif
+
+#endif
+
+#ifndef LTC_FORTUNA_POOLS
+/* number of pools (4..32) can save a bit of ram by lowering the count */
+#define LTC_FORTUNA_POOLS 32
+#endif
+
+/* at compile time you can decide whether fortuna uses the regular AES APIs
+ * or whether it will use the 'encrypt_only' variants.
+ * This is useful for custom builds of libtomcrypt for size-constrained targets. */
+/* #define LTC_FORTUNA_USE_ENCRYPT_ONLY */
+
+#endif /* LTC_FORTUNA */
+
+
+/* ---> Public Key Crypto <--- */
+#ifndef LTC_NO_PK
+
+/* Include RSA support */
+#define LTC_MRSA
+
+/* Include Diffie-Hellman support */
+/* is_prime fails for GMP */
+#define LTC_MDH
+/* Supported Key Sizes */
+#define LTC_DH768
+#define LTC_DH1024
+#define LTC_DH1536
+#define LTC_DH2048
+
+#if defined(LTM_DESC) || defined(GMP_DESC)
+/* tfm has a problem in fp_isprime for larger key sizes */
+#define LTC_DH3072
+#define LTC_DH4096
+#define LTC_DH6144
+#define LTC_DH8192
+#endif
+
+/* Digital Signature Algorithm */
+#define LTC_MDSA
+
+/* Ed25519 & X25519 */
+#define LTC_CURVE25519
+
+/* ECC */
+#define LTC_MECC
+
+/* use Shamir's trick for point mul (speeds up signature verification) */
+#define LTC_ECC_SHAMIR
+
+#if defined(TFM_DESC) && defined(LTC_MECC)
+ #define LTC_MECC_ACCEL
+#endif
+
+/* do we want fixed point ECC */
+/* #define LTC_MECC_FP */
+
+#endif /* LTC_NO_PK */
+
+#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_BLINDING)
+/* Enable RSA blinding when doing private key operations by default */
+#define LTC_RSA_BLINDING
+#endif /* LTC_NO_RSA_BLINDING */
+
+#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_CRT_HARDENING)
+/* Enable RSA CRT hardening when doing private key operations by default */
+#define LTC_RSA_CRT_HARDENING
+#endif /* LTC_NO_RSA_CRT_HARDENING */
+
+#if defined(LTC_MECC) && !defined(LTC_NO_ECC_TIMING_RESISTANT)
+/* Enable ECC timing resistant version by default */
+#define LTC_ECC_TIMING_RESISTANT
+#endif
+
+/* PKCS #1 (RSA) and #5 (Password Handling) stuff */
+#ifndef LTC_NO_PKCS
+
+#define LTC_PKCS_1
+#define LTC_PKCS_5
+#define LTC_PKCS_8
+#define LTC_PKCS_12
+
+/* Include ASN.1 DER (required by DSA/RSA) */
+#define LTC_DER
+
+#endif /* LTC_NO_PKCS */
+
+/* misc stuff */
+#ifndef LTC_NO_MISC
+
+/* Various tidbits of modern neatoness */
+#define LTC_BASE64
+/* ... and it's URL safe version */
+#define LTC_BASE64_URL
+/* Base32 encoding/decoding */
+#define LTC_BASE32
+/* Base16/hex encoding/decoding */
+#define LTC_BASE16
+
+#define LTC_BCRYPT
+
+#ifndef LTC_BCRYPT_DEFAULT_ROUNDS
+#define LTC_BCRYPT_DEFAULT_ROUNDS 10
+#endif
+
+/* Keep LTC_NO_HKDF for compatibility reasons
+ * superseeded by LTC_NO_MISC*/
+#ifndef LTC_NO_HKDF
+/* HKDF Key Derivation/Expansion stuff */
+#define LTC_HKDF
+#endif /* LTC_NO_HKDF */
+
+#define LTC_ADLER32
+
+#define LTC_CRC32
+
+#define LTC_SSH
+
+#define LTC_PADDING
+
+#define LTC_PBES
+
+#define LTC_PEM
+
+#endif /* LTC_NO_MISC */
+
+/* cleanup */
+
+#ifdef LTC_MECC
+/* Supported ECC Key Sizes */
+#ifndef LTC_NO_CURVES
+ #define LTC_ECC_BRAINPOOLP160R1
+ #define LTC_ECC_BRAINPOOLP160T1
+ #define LTC_ECC_BRAINPOOLP192R1
+ #define LTC_ECC_BRAINPOOLP192T1
+ #define LTC_ECC_BRAINPOOLP224R1
+ #define LTC_ECC_BRAINPOOLP224T1
+ #define LTC_ECC_BRAINPOOLP256R1
+ #define LTC_ECC_BRAINPOOLP256T1
+ #define LTC_ECC_BRAINPOOLP320R1
+ #define LTC_ECC_BRAINPOOLP320T1
+ #define LTC_ECC_BRAINPOOLP384R1
+ #define LTC_ECC_BRAINPOOLP384T1
+ #define LTC_ECC_BRAINPOOLP512R1
+ #define LTC_ECC_BRAINPOOLP512T1
+ #define LTC_ECC_PRIME192V2
+ #define LTC_ECC_PRIME192V3
+ #define LTC_ECC_PRIME239V1
+ #define LTC_ECC_PRIME239V2
+ #define LTC_ECC_PRIME239V3
+ #define LTC_ECC_SECP112R1
+ #define LTC_ECC_SECP112R2
+ #define LTC_ECC_SECP128R1
+ #define LTC_ECC_SECP128R2
+ #define LTC_ECC_SECP160K1
+ #define LTC_ECC_SECP160R1
+ #define LTC_ECC_SECP160R2
+ #define LTC_ECC_SECP192K1
+ #define LTC_ECC_SECP192R1
+ #define LTC_ECC_SECP224K1
+ #define LTC_ECC_SECP224R1
+ #define LTC_ECC_SECP256K1
+ #define LTC_ECC_SECP256R1
+ #define LTC_ECC_SECP384R1
+ #define LTC_ECC_SECP521R1
+#endif
+#endif /* LTC_MECC */
+
+#ifndef LTC_NO_FILE
+ /* buffer size for reading from a file via fread(..) */
+ #ifndef LTC_FILE_READ_BUFSIZE
+ #define LTC_FILE_READ_BUFSIZE 8192
+ #endif
+#endif
+
+#if defined(LTC_PEM)
+ /* Size of the line-buffer */
+ #ifndef LTC_PEM_DECODE_BUFSZ
+ #define LTC_PEM_DECODE_BUFSZ 80
+ #elif LTC_PEM_DECODE_BUFSZ < 72
+ #error "LTC_PEM_DECODE_BUFSZ shall not be < 72 bytes"
+ #endif
+ /* Size of the decoded data buffer */
+ #ifndef LTC_PEM_READ_BUFSIZE
+ #ifdef LTC_FILE_READ_BUFSIZE
+ #define LTC_PEM_READ_BUFSIZE LTC_FILE_READ_BUFSIZE
+ #else
+ #define LTC_PEM_READ_BUFSIZE 4096
+ #endif
+ #endif
+ #if defined(LTC_SSH)
+ #define LTC_PEM_SSH
+ #endif
+#endif
+
+#if defined(LTC_DER)
+ #ifndef LTC_DER_MAX_RECURSION
+ /* Maximum recursion limit when processing nested ASN.1 types. */
+ #define LTC_DER_MAX_RECURSION 30
+ #endif
+#endif
+
+#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_SSH)
+ /* Include the MPI functionality? (required by the PK algorithms) */
+ #define LTC_MPI
+
+ #ifndef LTC_PK_MAX_RETRIES
+ /* iterations limit for retry-loops */
+ #define LTC_PK_MAX_RETRIES 20
+ #endif
+#endif
+
+#ifdef LTC_MRSA
+ #define LTC_PKCS_1
+#endif
+
+#if defined(LTC_MRSA) || defined(LTC_MECC)
+ #define LTC_PKCS_8
+#endif
+
+#ifdef LTC_PKCS_8
+ #define LTC_PADDING
+ #define LTC_PBES
+#endif
+
+#if defined(LTC_CLEAN_STACK)
+/* if you're sure that you want to use it, remove the line below */
+ #error LTC_CLEAN_STACK is considered as broken
+#endif
+
+#if defined(LTC_PBES) && !defined(LTC_PKCS_5)
+ #error LTC_PBES requires LTC_PKCS_5
+#endif
+
+#if defined(LTC_PBES) && !defined(LTC_PKCS_12)
+ #error LTC_PBES requires LTC_PKCS_12
+#endif
+
+#if defined(LTC_PKCS_5) && !defined(LTC_HMAC)
+ #error LTC_PKCS_5 requires LTC_HMAC
+#endif
+
+#if defined(LTC_PKCS_5) && !defined(LTC_HASH_HELPERS)
+ #error LTC_PKCS_5 requires LTC_HASH_HELPERS
+#endif
+
+#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL)
+ #error Pelican-MAC requires LTC_RIJNDAEL
+#endif
+
+#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC))
+ #error LTC_EAX_MODE requires CTR and LTC_OMAC mode
+#endif
+
+#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE)
+ #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined!
+#endif
+
+#if defined(LTC_DER) && !defined(LTC_MPI)
+ #error ASN.1 DER requires MPI functionality
+#endif
+
+#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC)) && !defined(LTC_DER)
+ #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled
+#endif
+
+#if defined(LTC_BCRYPT) && !defined(LTC_BLOWFISH)
+ #error LTC_BCRYPT requires LTC_BLOWFISH
+#endif
+
+#if defined(LTC_CHACHA20POLY1305_MODE) && (!defined(LTC_CHACHA) || !defined(LTC_POLY1305))
+ #error LTC_CHACHA20POLY1305_MODE requires LTC_CHACHA + LTC_POLY1305
+#endif
+
+#if defined(LTC_CHACHA20_PRNG) && !defined(LTC_CHACHA)
+ #error LTC_CHACHA20_PRNG requires LTC_CHACHA
+#endif
+
+#if defined(LTC_XSALSA20) && !defined(LTC_SALSA20)
+ #error LTC_XSALSA20 requires LTC_SALSA20
+#endif
+
+#if defined(LTC_RC4) && !defined(LTC_RC4_STREAM)
+ #error LTC_RC4 requires LTC_RC4_STREAM
+#endif
+
+#if defined(LTC_SOBER128) && !defined(LTC_SOBER128_STREAM)
+ #error LTC_SOBER128 requires LTC_SOBER128_STREAM
+#endif
+
+#if defined(LTC_BLAKE2SMAC) && !defined(LTC_BLAKE2S)
+ #error LTC_BLAKE2SMAC requires LTC_BLAKE2S
+#endif
+
+#if defined(LTC_BLAKE2BMAC) && !defined(LTC_BLAKE2B)
+ #error LTC_BLAKE2BMAC requires LTC_BLAKE2B
+#endif
+
+#if defined(LTC_SPRNG) && !defined(LTC_RNG_GET_BYTES)
+ #error LTC_SPRNG requires LTC_RNG_GET_BYTES
+#endif
+
+#if defined(LTC_NO_MATH) && (defined(LTM_DESC) || defined(TFM_DESC) || defined(GMP_DESC))
+ #error LTC_NO_MATH defined, but also a math descriptor
+#endif
+
+/* THREAD management */
+#ifdef LTC_PTHREAD
+
+#include
+
+#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
+#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x;
+#define LTC_MUTEX_TYPE(x) pthread_mutex_t x;
+#define LTC_MUTEX_INIT(x) LTC_ARGCHK(pthread_mutex_init(x, NULL) == 0);
+#define LTC_MUTEX_LOCK(x) LTC_ARGCHK(pthread_mutex_lock(x) == 0);
+#define LTC_MUTEX_UNLOCK(x) LTC_ARGCHK(pthread_mutex_unlock(x) == 0);
+#define LTC_MUTEX_DESTROY(x) LTC_ARGCHK(pthread_mutex_destroy(x) == 0);
+
+#else
+
+/* default no functions */
+#define LTC_MUTEX_GLOBAL(x)
+#define LTC_MUTEX_PROTO(x)
+#define LTC_MUTEX_TYPE(x)
+#define LTC_MUTEX_INIT(x)
+#define LTC_MUTEX_LOCK(x)
+#define LTC_MUTEX_UNLOCK(x)
+#define LTC_MUTEX_DESTROY(x)
+
+#endif /* LTC_PTHREAD */
+
+/* Debuggers */
+
+/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */
+/* #define LTC_VALGRIND */
+
+/* ECC backwards compatibility */
+#if !defined(LTC_ECC_SECP112R1) && defined(LTC_ECC112)
+#define LTC_ECC_SECP112R1
+#undef LTC_ECC112
+#endif
+#if !defined(LTC_ECC_SECP128R1) && defined(LTC_ECC128)
+#define LTC_ECC_SECP128R1
+#undef LTC_ECC128
+#endif
+#if !defined(LTC_ECC_SECP160R1) && defined(LTC_ECC160)
+#define LTC_ECC_SECP160R1
+#undef LTC_ECC160
+#endif
+#if !defined(LTC_ECC_SECP192R1) && defined(LTC_ECC192)
+#define LTC_ECC_SECP192R1
+#undef LTC_ECC192
+#endif
+#if !defined(LTC_ECC_SECP224R1) && defined(LTC_ECC224)
+#define LTC_ECC_SECP224R1
+#undef LTC_ECC224
+#endif
+#if !defined(LTC_ECC_SECP256R1) && defined(LTC_ECC256)
+#define LTC_ECC_SECP256R1
+#undef LTC_ECC256
+#endif
+#if !defined(LTC_ECC_SECP384R1) && defined(LTC_ECC384)
+#define LTC_ECC_SECP384R1
+#undef LTC_ECC384
+#endif
+#if !defined(LTC_ECC_SECP512R1) && defined(LTC_ECC521)
+#define LTC_ECC_SECP521R1
+#undef LTC_ECC521
+#endif
+
+#endif /* TOMCRYPT_CUSTOM_H_ */
diff --git a/Sources/libtomcrypt/include/tomcrypt_hash.h b/Sources/libtomcrypt/include/tomcrypt_hash.h
new file mode 100644
index 00000000..3ce3d223
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_hash.h
@@ -0,0 +1,514 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_HASH_H_
+#define TOMCRYPT_HASH_H_
+
+/* ---- HASH FUNCTIONS ---- */
+#if defined(LTC_SHA3) || defined(LTC_KECCAK)
+struct sha3_state {
+ ulong64 saved; /* the portion of the input message that we didn't consume yet */
+ ulong64 s[25];
+ unsigned char sb[25 * 8]; /* used for storing `ulong64 s[25]` as little-endian bytes */
+ unsigned short byte_index; /* 0..7--the next byte after the set one (starts from 0; 0--none are buffered) */
+ unsigned short word_index; /* 0..24--the next word to integrate input (starts from 0) */
+ unsigned short capacity_words; /* the double size of the hash output in words (e.g. 16 for Keccak 512) */
+ unsigned short xof_flag;
+};
+#endif
+
+#ifdef LTC_SHA512
+struct sha512_state {
+ ulong64 length, state[8];
+ unsigned long curlen;
+ unsigned char buf[128];
+};
+#endif
+
+#ifdef LTC_SHA256
+struct sha256_state {
+ ulong64 length;
+ ulong32 state[8], curlen;
+ unsigned char buf[64];
+};
+#endif
+
+#ifdef LTC_SHA1
+struct sha1_state {
+ ulong64 length;
+ ulong32 state[5], curlen;
+ unsigned char buf[64];
+};
+#endif
+
+#ifdef LTC_MD5
+struct md5_state {
+ ulong64 length;
+ ulong32 state[4], curlen;
+ unsigned char buf[64];
+};
+#endif
+
+#ifdef LTC_MD4
+struct md4_state {
+ ulong64 length;
+ ulong32 state[4], curlen;
+ unsigned char buf[64];
+};
+#endif
+
+#ifdef LTC_TIGER
+struct tiger_state {
+ ulong64 state[3], length;
+ unsigned long curlen, passes;
+ unsigned char buf[64], pad;
+};
+#endif
+
+#ifdef LTC_MD2
+struct md2_state {
+ unsigned char chksum[16], X[48], buf[16];
+ unsigned long curlen;
+};
+#endif
+
+#ifdef LTC_RIPEMD128
+struct rmd128_state {
+ ulong64 length;
+ unsigned char buf[64];
+ ulong32 curlen, state[4];
+};
+#endif
+
+#ifdef LTC_RIPEMD160
+struct rmd160_state {
+ ulong64 length;
+ unsigned char buf[64];
+ ulong32 curlen, state[5];
+};
+#endif
+
+#ifdef LTC_RIPEMD256
+struct rmd256_state {
+ ulong64 length;
+ unsigned char buf[64];
+ ulong32 curlen, state[8];
+};
+#endif
+
+#ifdef LTC_RIPEMD320
+struct rmd320_state {
+ ulong64 length;
+ unsigned char buf[64];
+ ulong32 curlen, state[10];
+};
+#endif
+
+#ifdef LTC_WHIRLPOOL
+struct whirlpool_state {
+ ulong64 length, state[8];
+ unsigned char buf[64];
+ ulong32 curlen;
+};
+#endif
+
+#ifdef LTC_CHC_HASH
+struct chc_state {
+ ulong64 length;
+ unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE];
+ ulong32 curlen;
+};
+#endif
+
+#ifdef LTC_BLAKE2S
+struct blake2s_state {
+ ulong32 h[8];
+ ulong32 t[2];
+ ulong32 f[2];
+ unsigned char buf[64];
+ unsigned long curlen;
+ unsigned long outlen;
+ unsigned char last_node;
+};
+#endif
+
+#ifdef LTC_BLAKE2B
+struct blake2b_state {
+ ulong64 h[8];
+ ulong64 t[2];
+ ulong64 f[2];
+ unsigned char buf[128];
+ unsigned long curlen;
+ unsigned long outlen;
+ unsigned char last_node;
+};
+#endif
+
+typedef union Hash_state {
+ char dummy[1];
+#ifdef LTC_CHC_HASH
+ struct chc_state chc;
+#endif
+#ifdef LTC_WHIRLPOOL
+ struct whirlpool_state whirlpool;
+#endif
+#if defined(LTC_SHA3) || defined(LTC_KECCAK)
+ struct sha3_state sha3;
+#endif
+#ifdef LTC_SHA512
+ struct sha512_state sha512;
+#endif
+#ifdef LTC_SHA256
+ struct sha256_state sha256;
+#endif
+#ifdef LTC_SHA1
+ struct sha1_state sha1;
+#endif
+#ifdef LTC_MD5
+ struct md5_state md5;
+#endif
+#ifdef LTC_MD4
+ struct md4_state md4;
+#endif
+#ifdef LTC_MD2
+ struct md2_state md2;
+#endif
+#ifdef LTC_TIGER
+ struct tiger_state tiger;
+#endif
+#ifdef LTC_RIPEMD128
+ struct rmd128_state rmd128;
+#endif
+#ifdef LTC_RIPEMD160
+ struct rmd160_state rmd160;
+#endif
+#ifdef LTC_RIPEMD256
+ struct rmd256_state rmd256;
+#endif
+#ifdef LTC_RIPEMD320
+ struct rmd320_state rmd320;
+#endif
+#ifdef LTC_BLAKE2S
+ struct blake2s_state blake2s;
+#endif
+#ifdef LTC_BLAKE2B
+ struct blake2b_state blake2b;
+#endif
+
+ void *data;
+} hash_state;
+
+/** hash descriptor */
+extern struct ltc_hash_descriptor {
+ /** name of hash */
+ const char *name;
+ /** internal ID */
+ unsigned char ID;
+ /** Size of digest in octets */
+ unsigned long hashsize;
+ /** Input block size in octets */
+ unsigned long blocksize;
+ /** ASN.1 OID */
+ unsigned long OID[16];
+ /** Length of DER encoding */
+ unsigned long OIDlen;
+
+ /** Init a hash state
+ @param hash The hash to initialize
+ @return CRYPT_OK if successful
+ */
+ int (*init)(hash_state *hash);
+ /** Process a block of data
+ @param hash The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+ */
+ int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen);
+ /** Produce the digest and store it
+ @param hash The hash state
+ @param out [out] The destination of the digest
+ @return CRYPT_OK if successful
+ */
+ int (*done)(hash_state *hash, unsigned char *out);
+ /** Self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+ */
+ int (*test)(void);
+
+ /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */
+ int (*hmac_block)(const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+} hash_descriptor[];
+
+#ifdef LTC_CHC_HASH
+int chc_register(int cipher);
+int chc_init(hash_state * md);
+int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int chc_done(hash_state * md, unsigned char *out);
+int chc_test(void);
+extern const struct ltc_hash_descriptor chc_desc;
+#endif
+
+#ifdef LTC_WHIRLPOOL
+int whirlpool_init(hash_state * md);
+int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int whirlpool_done(hash_state * md, unsigned char *out);
+int whirlpool_test(void);
+extern const struct ltc_hash_descriptor whirlpool_desc;
+#endif
+
+#if defined(LTC_SHA3) || defined(LTC_KECCAK)
+/* sha3_NNN_init are shared by SHA3 and KECCAK */
+int sha3_512_init(hash_state * md);
+int sha3_384_init(hash_state * md);
+int sha3_256_init(hash_state * md);
+int sha3_224_init(hash_state * md);
+/* sha3_process is the same for all variants of SHA3 + KECCAK */
+int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+#endif
+
+#ifdef LTC_SHA3
+int sha3_512_test(void);
+extern const struct ltc_hash_descriptor sha3_512_desc;
+int sha3_384_test(void);
+extern const struct ltc_hash_descriptor sha3_384_desc;
+int sha3_256_test(void);
+extern const struct ltc_hash_descriptor sha3_256_desc;
+int sha3_224_test(void);
+extern const struct ltc_hash_descriptor sha3_224_desc;
+int sha3_done(hash_state *md, unsigned char *out);
+/* SHAKE128 + SHAKE256 */
+int sha3_shake_init(hash_state *md, int num);
+#define sha3_shake_process(a,b,c) sha3_process(a,b,c)
+int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen);
+int sha3_shake_test(void);
+int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen);
+#endif
+
+#ifdef LTC_KECCAK
+#define keccak_512_init(a) sha3_512_init(a)
+#define keccak_384_init(a) sha3_384_init(a)
+#define keccak_256_init(a) sha3_256_init(a)
+#define keccak_224_init(a) sha3_224_init(a)
+#define keccak_process(a,b,c) sha3_process(a,b,c)
+extern const struct ltc_hash_descriptor keccak_512_desc;
+int keccak_512_test(void);
+extern const struct ltc_hash_descriptor keccak_384_desc;
+int keccak_384_test(void);
+extern const struct ltc_hash_descriptor keccak_256_desc;
+int keccak_256_test(void);
+extern const struct ltc_hash_descriptor keccak_224_desc;
+int keccak_224_test(void);
+int keccak_done(hash_state *md, unsigned char *out);
+#endif
+
+#ifdef LTC_SHA512
+int sha512_init(hash_state * md);
+int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha512_done(hash_state * md, unsigned char *out);
+int sha512_test(void);
+extern const struct ltc_hash_descriptor sha512_desc;
+#endif
+
+#ifdef LTC_SHA384
+#ifndef LTC_SHA512
+ #error LTC_SHA512 is required for LTC_SHA384
+#endif
+int sha384_init(hash_state * md);
+#define sha384_process sha512_process
+int sha384_done(hash_state * md, unsigned char *out);
+int sha384_test(void);
+extern const struct ltc_hash_descriptor sha384_desc;
+#endif
+
+#ifdef LTC_SHA512_256
+#ifndef LTC_SHA512
+ #error LTC_SHA512 is required for LTC_SHA512_256
+#endif
+int sha512_256_init(hash_state * md);
+#define sha512_256_process sha512_process
+int sha512_256_done(hash_state * md, unsigned char *out);
+int sha512_256_test(void);
+extern const struct ltc_hash_descriptor sha512_256_desc;
+#endif
+
+#ifdef LTC_SHA512_224
+#ifndef LTC_SHA512
+ #error LTC_SHA512 is required for LTC_SHA512_224
+#endif
+int sha512_224_init(hash_state * md);
+#define sha512_224_process sha512_process
+int sha512_224_done(hash_state * md, unsigned char *out);
+int sha512_224_test(void);
+extern const struct ltc_hash_descriptor sha512_224_desc;
+#endif
+
+#ifdef LTC_SHA256
+int sha256_init(hash_state * md);
+int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha256_done(hash_state * md, unsigned char *out);
+int sha256_test(void);
+extern const struct ltc_hash_descriptor sha256_desc;
+
+#ifdef LTC_SHA224
+#ifndef LTC_SHA256
+ #error LTC_SHA256 is required for LTC_SHA224
+#endif
+int sha224_init(hash_state * md);
+#define sha224_process sha256_process
+int sha224_done(hash_state * md, unsigned char *out);
+int sha224_test(void);
+extern const struct ltc_hash_descriptor sha224_desc;
+#endif
+#endif
+
+#ifdef LTC_SHA1
+int sha1_init(hash_state * md);
+int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha1_done(hash_state * md, unsigned char *out);
+int sha1_test(void);
+extern const struct ltc_hash_descriptor sha1_desc;
+#endif
+
+#ifdef LTC_BLAKE2S
+extern const struct ltc_hash_descriptor blake2s_256_desc;
+int blake2s_256_init(hash_state * md);
+int blake2s_256_test(void);
+
+extern const struct ltc_hash_descriptor blake2s_224_desc;
+int blake2s_224_init(hash_state * md);
+int blake2s_224_test(void);
+
+extern const struct ltc_hash_descriptor blake2s_160_desc;
+int blake2s_160_init(hash_state * md);
+int blake2s_160_test(void);
+
+extern const struct ltc_hash_descriptor blake2s_128_desc;
+int blake2s_128_init(hash_state * md);
+int blake2s_128_test(void);
+
+int blake2s_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen);
+int blake2s_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int blake2s_done(hash_state * md, unsigned char *out);
+#endif
+
+#ifdef LTC_BLAKE2B
+extern const struct ltc_hash_descriptor blake2b_512_desc;
+int blake2b_512_init(hash_state * md);
+int blake2b_512_test(void);
+
+extern const struct ltc_hash_descriptor blake2b_384_desc;
+int blake2b_384_init(hash_state * md);
+int blake2b_384_test(void);
+
+extern const struct ltc_hash_descriptor blake2b_256_desc;
+int blake2b_256_init(hash_state * md);
+int blake2b_256_test(void);
+
+extern const struct ltc_hash_descriptor blake2b_160_desc;
+int blake2b_160_init(hash_state * md);
+int blake2b_160_test(void);
+
+int blake2b_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen);
+int blake2b_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int blake2b_done(hash_state * md, unsigned char *out);
+#endif
+
+#ifdef LTC_MD5
+int md5_init(hash_state * md);
+int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int md5_done(hash_state * md, unsigned char *out);
+int md5_test(void);
+extern const struct ltc_hash_descriptor md5_desc;
+#endif
+
+#ifdef LTC_MD4
+int md4_init(hash_state * md);
+int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int md4_done(hash_state * md, unsigned char *out);
+int md4_test(void);
+extern const struct ltc_hash_descriptor md4_desc;
+#endif
+
+#ifdef LTC_MD2
+int md2_init(hash_state * md);
+int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int md2_done(hash_state * md, unsigned char *out);
+int md2_test(void);
+extern const struct ltc_hash_descriptor md2_desc;
+#endif
+
+#ifdef LTC_TIGER
+int tiger_init(hash_state * md);
+int tiger_init_ex(hash_state *md, unsigned long passes);
+int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int tiger_done(hash_state * md, unsigned char *out);
+int tiger_test(void);
+int tiger2_init(hash_state *md);
+int tiger2_init_ex(hash_state *md, unsigned long passes);
+#define tiger2_process(m, i, l) tiger_process(m, i, l)
+#define tiger2_done(m, o) tiger_done(m, o)
+int tiger2_test(void);
+extern const struct ltc_hash_descriptor tiger_desc, tiger2_desc;
+#endif
+
+#ifdef LTC_RIPEMD128
+int rmd128_init(hash_state * md);
+int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int rmd128_done(hash_state * md, unsigned char *out);
+int rmd128_test(void);
+extern const struct ltc_hash_descriptor rmd128_desc;
+#endif
+
+#ifdef LTC_RIPEMD160
+int rmd160_init(hash_state * md);
+int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int rmd160_done(hash_state * md, unsigned char *out);
+int rmd160_test(void);
+extern const struct ltc_hash_descriptor rmd160_desc;
+#endif
+
+#ifdef LTC_RIPEMD256
+int rmd256_init(hash_state * md);
+int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int rmd256_done(hash_state * md, unsigned char *out);
+int rmd256_test(void);
+extern const struct ltc_hash_descriptor rmd256_desc;
+#endif
+
+#ifdef LTC_RIPEMD320
+int rmd320_init(hash_state * md);
+int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int rmd320_done(hash_state * md, unsigned char *out);
+int rmd320_test(void);
+extern const struct ltc_hash_descriptor rmd320_desc;
+#endif
+
+
+int find_hash(const char *name);
+int find_hash_id(unsigned char ID);
+int find_hash_oid(const unsigned long *ID, unsigned long IDlen);
+int find_hash_any(const char *name, int digestlen);
+int register_hash(const struct ltc_hash_descriptor *hash);
+int unregister_hash(const struct ltc_hash_descriptor *hash);
+int register_all_hashes(void);
+int hash_is_valid(int idx);
+
+LTC_MUTEX_PROTO(ltc_hash_mutex)
+
+int hash_memory(int hash,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+ LTC_NULL_TERMINATED;
+
+#ifndef LTC_NO_FILE
+int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen);
+int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen);
+#endif
+
+#endif /* TOMCRYPT_HASH_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_mac.h b/Sources/libtomcrypt/include/tomcrypt_mac.h
new file mode 100644
index 00000000..3976d5a9
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_mac.h
@@ -0,0 +1,572 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_MAC_H_
+#define TOMCRYPT_MAC_H_
+
+#ifdef LTC_HMAC
+typedef struct Hmac_state {
+ hash_state md;
+ int hash;
+ unsigned char key[MAXBLOCKSIZE];
+} hmac_state;
+
+int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
+int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen);
+int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen);
+int hmac_test(void);
+int hmac_memory(int hash,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int hmac_memory_multi(int hash,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+ LTC_NULL_TERMINATED;
+int hmac_file(int hash, const char *fname, const unsigned char *key,
+ unsigned long keylen,
+ unsigned char *out, unsigned long *outlen);
+#endif
+
+#ifdef LTC_OMAC
+
+typedef struct {
+ int cipher_idx,
+ buflen,
+ blklen;
+ unsigned char block[MAXBLOCKSIZE],
+ prev[MAXBLOCKSIZE],
+ Lu[2][MAXBLOCKSIZE];
+ symmetric_key key;
+} omac_state;
+
+int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
+int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen);
+int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen);
+int omac_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int omac_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+ LTC_NULL_TERMINATED;
+int omac_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen);
+int omac_test(void);
+#endif /* LTC_OMAC */
+
+#ifdef LTC_PMAC
+
+typedef struct {
+ unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */
+ Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */
+ Lr[MAXBLOCKSIZE], /* L * x^-1 */
+ block[MAXBLOCKSIZE], /* currently accumulated block */
+ checksum[MAXBLOCKSIZE]; /* current checksum */
+
+ symmetric_key key; /* scheduled key for cipher */
+ unsigned long block_index; /* index # for current block */
+ int cipher_idx, /* cipher idx */
+ block_len, /* length of block */
+ buflen; /* number of bytes in the buffer */
+} pmac_state;
+
+int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen);
+int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen);
+int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen);
+
+int pmac_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+int pmac_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+ LTC_NULL_TERMINATED;
+
+int pmac_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen);
+
+int pmac_test(void);
+
+/* internal functions */
+int pmac_ntz(unsigned long x);
+void pmac_shift_xor(pmac_state *pmac);
+
+#endif /* PMAC */
+
+#ifdef LTC_POLY1305
+typedef struct {
+ ulong32 r[5];
+ ulong32 h[5];
+ ulong32 pad[4];
+ unsigned long leftover;
+ unsigned char buffer[16];
+ int final;
+} poly1305_state;
+
+int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen);
+int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen);
+int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen);
+int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen);
+int poly1305_memory_multi(const unsigned char *key, unsigned long keylen,
+ unsigned char *mac, unsigned long *maclen,
+ const unsigned char *in, unsigned long inlen, ...)
+ LTC_NULL_TERMINATED;
+int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen);
+int poly1305_test(void);
+#endif /* LTC_POLY1305 */
+
+#ifdef LTC_BLAKE2SMAC
+typedef hash_state blake2smac_state;
+int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen);
+int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen);
+int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen);
+int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen);
+int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen,
+ unsigned char *mac, unsigned long *maclen,
+ const unsigned char *in, unsigned long inlen, ...)
+ LTC_NULL_TERMINATED;
+int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen);
+int blake2smac_test(void);
+#endif /* LTC_BLAKE2SMAC */
+
+#ifdef LTC_BLAKE2BMAC
+typedef hash_state blake2bmac_state;
+int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen);
+int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen);
+int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen);
+int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen);
+int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen,
+ unsigned char *mac, unsigned long *maclen,
+ const unsigned char *in, unsigned long inlen, ...)
+ LTC_NULL_TERMINATED;
+int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen);
+int blake2bmac_test(void);
+#endif /* LTC_BLAKE2BMAC */
+
+
+#ifdef LTC_PELICAN
+
+typedef struct pelican_state
+{
+ symmetric_key K;
+ unsigned char state[16];
+ int buflen;
+} pelican_state;
+
+int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen);
+int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen);
+int pelican_done(pelican_state *pelmac, unsigned char *out);
+int pelican_test(void);
+
+int pelican_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out);
+
+#endif
+
+#ifdef LTC_XCBC
+
+/* add this to "keylen" to xcbc_init to use a pure three-key XCBC MAC */
+#define LTC_XCBC_PURE 0x8000UL
+
+typedef struct {
+ unsigned char K[3][MAXBLOCKSIZE],
+ IV[MAXBLOCKSIZE];
+
+ symmetric_key key;
+
+ int cipher,
+ buflen,
+ blocksize;
+} xcbc_state;
+
+int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen);
+int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen);
+int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen);
+int xcbc_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int xcbc_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+ LTC_NULL_TERMINATED;
+int xcbc_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen);
+int xcbc_test(void);
+
+#endif
+
+#ifdef LTC_F9_MODE
+
+typedef struct {
+ unsigned char akey[MAXBLOCKSIZE],
+ ACC[MAXBLOCKSIZE],
+ IV[MAXBLOCKSIZE];
+
+ symmetric_key key;
+
+ int cipher,
+ buflen,
+ keylen,
+ blocksize;
+} f9_state;
+
+int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen);
+int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen);
+int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen);
+int f9_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int f9_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+ LTC_NULL_TERMINATED;
+int f9_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *fname,
+ unsigned char *out, unsigned long *outlen);
+int f9_test(void);
+
+#endif
+
+/*
+ * ENC+AUTH modes
+ */
+
+#ifdef LTC_EAX_MODE
+
+#if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE))
+ #error LTC_EAX_MODE requires LTC_OMAC and CTR
+#endif
+
+typedef struct {
+ unsigned char N[MAXBLOCKSIZE];
+ symmetric_CTR ctr;
+ omac_state headeromac, ctomac;
+} eax_state;
+
+int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen);
+
+int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);
+int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length);
+int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length);
+int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen);
+
+int eax_encrypt_authenticate_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen);
+
+int eax_decrypt_verify_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen,
+ int *stat);
+
+ int eax_test(void);
+#endif /* EAX MODE */
+
+#ifdef LTC_OCB_MODE
+typedef struct {
+ unsigned char L[MAXBLOCKSIZE], /* L value */
+ Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */
+ Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */
+ Lr[MAXBLOCKSIZE], /* L * x^-1 */
+ R[MAXBLOCKSIZE], /* R value */
+ checksum[MAXBLOCKSIZE]; /* current checksum */
+
+ symmetric_key key; /* scheduled key for cipher */
+ unsigned long block_index; /* index # for current block */
+ int cipher, /* cipher idx */
+ block_len; /* length of block */
+} ocb_state;
+
+int ocb_init(ocb_state *ocb, int cipher,
+ const unsigned char *key, unsigned long keylen, const unsigned char *nonce);
+
+int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct);
+int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt);
+
+int ocb_done_encrypt(ocb_state *ocb,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen);
+
+int ocb_done_decrypt(ocb_state *ocb,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen, int *stat);
+
+int ocb_encrypt_authenticate_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen);
+
+int ocb_decrypt_verify_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen,
+ int *stat);
+
+int ocb_test(void);
+
+/* internal functions */
+void ocb_shift_xor(ocb_state *ocb, unsigned char *Z);
+int ocb_ntz(unsigned long x);
+int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode);
+
+#endif /* LTC_OCB_MODE */
+
+#ifdef LTC_OCB3_MODE
+typedef struct {
+ unsigned char Offset_0[MAXBLOCKSIZE], /* Offset_0 value */
+ Offset_current[MAXBLOCKSIZE], /* Offset_{current_block_index} value */
+ L_dollar[MAXBLOCKSIZE], /* L_$ value */
+ L_star[MAXBLOCKSIZE], /* L_* value */
+ L_[32][MAXBLOCKSIZE], /* L_{i} values */
+ tag_part[MAXBLOCKSIZE], /* intermediate result of tag calculation */
+ checksum[MAXBLOCKSIZE]; /* current checksum */
+
+ /* AAD related members */
+ unsigned char aSum_current[MAXBLOCKSIZE], /* AAD related helper variable */
+ aOffset_current[MAXBLOCKSIZE], /* AAD related helper variable */
+ adata_buffer[MAXBLOCKSIZE]; /* AAD buffer */
+
+ symmetric_key key; /* scheduled key for cipher */
+ int adata_buffer_bytes; /* bytes in AAD buffer */
+ unsigned long ablock_index; /* index # for current adata (AAD) block */
+ unsigned long block_index; /* index # for current data block */
+ int cipher, /* cipher idx */
+ tag_len, /* length of tag */
+ block_len; /* length of block */
+} ocb3_state;
+
+int ocb3_init(ocb3_state *ocb, int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ unsigned long taglen);
+
+int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct);
+int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt);
+int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct);
+int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt);
+int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen);
+int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen);
+
+int ocb3_encrypt_authenticate_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *adata, unsigned long adatalen,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen);
+
+int ocb3_decrypt_verify_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *adata, unsigned long adatalen,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen,
+ int *stat);
+
+int ocb3_test(void);
+
+#endif /* LTC_OCB3_MODE */
+
+#ifdef LTC_CCM_MODE
+
+#define CCM_ENCRYPT LTC_ENCRYPT
+#define CCM_DECRYPT LTC_DECRYPT
+
+typedef struct {
+ unsigned char PAD[16], /* flags | Nonce N | l(m) */
+ ctr[16],
+ CTRPAD[16];
+
+ symmetric_key K;
+
+ int cipher, /* which cipher */
+ taglen, /* length of the tag (encoded in M value) */
+ x; /* index in PAD */
+
+ unsigned long L, /* L value */
+ ptlen, /* length that will be enc / dec */
+ current_ptlen, /* current processed length */
+ aadlen, /* length of the aad */
+ current_aadlen, /* length of the currently provided add */
+ noncelen; /* length of the nonce */
+
+ unsigned char CTRlen;
+} ccm_state;
+
+int ccm_init(ccm_state *ccm, int cipher,
+ const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen);
+
+int ccm_reset(ccm_state *ccm);
+
+int ccm_add_nonce(ccm_state *ccm,
+ const unsigned char *nonce, unsigned long noncelen);
+
+int ccm_add_aad(ccm_state *ccm,
+ const unsigned char *adata, unsigned long adatalen);
+
+int ccm_process(ccm_state *ccm,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ int direction);
+
+int ccm_done(ccm_state *ccm,
+ unsigned char *tag, unsigned long *taglen);
+
+int ccm_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ symmetric_key *uskey,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction);
+
+int ccm_test(void);
+
+#endif /* LTC_CCM_MODE */
+
+#if defined(LRW_MODE) || defined(LTC_GCM_MODE)
+void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c);
+#endif
+
+
+/* table shared between GCM and LRW */
+#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST))
+extern const unsigned char gcm_shift_table[];
+#endif
+
+#ifdef LTC_GCM_MODE
+
+#define GCM_ENCRYPT LTC_ENCRYPT
+#define GCM_DECRYPT LTC_DECRYPT
+
+#define LTC_GCM_MODE_IV 0
+#define LTC_GCM_MODE_AAD 1
+#define LTC_GCM_MODE_TEXT 2
+
+typedef struct {
+ unsigned char H[16], /* multiplier */
+ X[16], /* accumulator */
+ Y[16], /* counter */
+ Y_0[16], /* initial counter */
+ buf[16]; /* buffer for stuff */
+
+#ifdef LTC_GCM_TABLES
+ unsigned char PC[16][256][16]; /* 16 tables of 8x128 */
+#endif
+
+ symmetric_key K;
+
+ int cipher, /* which cipher */
+ ivmode, /* Which mode is the IV in? */
+ mode, /* mode the GCM code is in */
+ buflen; /* length of data in buf */
+
+ ulong64 totlen, /* 64-bit counter used for IV and AAD */
+ pttotlen; /* 64-bit counter for the PT */
+} gcm_state;
+
+void gcm_mult_h(const gcm_state *gcm, unsigned char *I);
+
+int gcm_init(gcm_state *gcm, int cipher,
+ const unsigned char *key, int keylen);
+
+int gcm_reset(gcm_state *gcm);
+
+int gcm_add_iv(gcm_state *gcm,
+ const unsigned char *IV, unsigned long IVlen);
+
+int gcm_add_aad(gcm_state *gcm,
+ const unsigned char *adata, unsigned long adatalen);
+
+int gcm_process(gcm_state *gcm,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ int direction);
+
+int gcm_done(gcm_state *gcm,
+ unsigned char *tag, unsigned long *taglen);
+
+int gcm_memory( int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *IV, unsigned long IVlen,
+ const unsigned char *adata, unsigned long adatalen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction);
+int gcm_test(void);
+
+#endif /* LTC_GCM_MODE */
+
+#ifdef LTC_CHACHA20POLY1305_MODE
+
+typedef struct {
+ poly1305_state poly;
+ chacha_state chacha;
+ ulong64 aadlen;
+ ulong64 ctlen;
+ int aadflg, openssh_compat;
+} chacha20poly1305_state;
+
+#define CHACHA20POLY1305_ENCRYPT LTC_ENCRYPT
+#define CHACHA20POLY1305_DECRYPT LTC_DECRYPT
+#define CHACHA20POLY1305_OPENSSH_COMPAT 2
+
+int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen);
+int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen);
+int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number);
+int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen);
+int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
+int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
+int chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen);
+int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *aad, unsigned long aadlen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out,
+ unsigned char *tag, unsigned long *taglen,
+ int direction);
+int chacha20poly1305_test(void);
+
+#endif /* LTC_CHACHA20POLY1305_MODE */
+
+#endif /* TOMCRYPT_MAC_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_macros.h b/Sources/libtomcrypt/include/tomcrypt_macros.h
new file mode 100644
index 00000000..708f701c
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_macros.h
@@ -0,0 +1,463 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_MACROS_H_
+#define TOMCRYPT_MACROS_H_
+
+#define LTC_TMPVAR__(n, l) n ## l
+#define LTC_TMPVAR_(n, l) LTC_TMPVAR__(n, l)
+#define LTC_TMPVAR(n) LTC_TMPVAR_(LTC_ ## n ## _, __LINE__)
+
+/* ---- HELPER MACROS ---- */
+#ifdef ENDIAN_NEUTRAL
+
+#define STORE32L(x, y) \
+ do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD32L(x, y) \
+ do { x = ((ulong32)((y)[3] & 255)<<24) | \
+ ((ulong32)((y)[2] & 255)<<16) | \
+ ((ulong32)((y)[1] & 255)<<8) | \
+ ((ulong32)((y)[0] & 255)); } while(0)
+
+#define STORE64L(x, y) \
+ do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
+ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
+ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD64L(x, y) \
+ do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
+ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
+ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
+ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
+
+#define STORE32H(x, y) \
+ do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
+ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD32H(x, y) \
+ do { x = ((ulong32)((y)[0] & 255)<<24) | \
+ ((ulong32)((y)[1] & 255)<<16) | \
+ ((ulong32)((y)[2] & 255)<<8) | \
+ ((ulong32)((y)[3] & 255)); } while(0)
+
+#define STORE64H(x, y) \
+do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD64H(x, y) \
+do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
+ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
+ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
+ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0)
+
+
+#elif defined(ENDIAN_LITTLE)
+
+#ifdef LTC_HAVE_BSWAP_BUILTIN
+
+#define STORE32H(x, y) \
+do { ulong32 ttt = __builtin_bswap32 ((x)); \
+ XMEMCPY ((y), &ttt, 4); } while(0)
+
+#define LOAD32H(x, y) \
+do { XMEMCPY (&(x), (y), 4); \
+ (x) = __builtin_bswap32 ((x)); } while(0)
+
+#elif !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__))))
+
+#define STORE32H(x, y) \
+__asm__ volatile ( \
+ "bswapl %0 \n\t" \
+ "movl %0,(%1)\n\t" \
+ "bswapl %0 \n\t" \
+ ::"r"(x), "r"(y): "memory");
+
+#define LOAD32H(x, y) \
+__asm__ volatile ( \
+ "movl (%1),%0\n\t" \
+ "bswapl %0\n\t" \
+ :"=r"(x): "r"(y): "memory");
+
+#else
+
+#define STORE32H(x, y) \
+ do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
+ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD32H(x, y) \
+ do { x = ((ulong32)((y)[0] & 255)<<24) | \
+ ((ulong32)((y)[1] & 255)<<16) | \
+ ((ulong32)((y)[2] & 255)<<8) | \
+ ((ulong32)((y)[3] & 255)); } while(0)
+
+#endif
+
+#ifdef LTC_HAVE_BSWAP_BUILTIN
+
+#define STORE64H(x, y) \
+do { ulong64 ttt = __builtin_bswap64 ((x)); \
+ XMEMCPY ((y), &ttt, 8); } while(0)
+
+#define LOAD64H(x, y) \
+do { XMEMCPY (&(x), (y), 8); \
+ (x) = __builtin_bswap64 ((x)); } while(0)
+
+/* x86_64 processor */
+#elif !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__))
+
+#define STORE64H(x, y) \
+__asm__ volatile ( \
+ "bswapq %0 \n\t" \
+ "movq %0,(%1)\n\t" \
+ "bswapq %0 \n\t" \
+ ::"r"(x), "r"(y): "memory");
+
+#define LOAD64H(x, y) \
+__asm__ volatile ( \
+ "movq (%1),%0\n\t" \
+ "bswapq %0\n\t" \
+ :"=r"(x): "r"(y): "memory");
+
+#else
+
+#define STORE64H(x, y) \
+do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD64H(x, y) \
+do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
+ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
+ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
+ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0)
+
+#endif
+
+#ifdef ENDIAN_32BITWORD
+
+#define STORE32L(x, y) \
+ do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0)
+
+#define LOAD32L(x, y) \
+ do { XMEMCPY(&(x), y, 4); } while(0)
+
+#define STORE64L(x, y) \
+ do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
+ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
+ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD64L(x, y) \
+ do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
+ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
+ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
+ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
+
+#else /* 64-bit words then */
+
+#define STORE32L(x, y) \
+ do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0)
+
+#define LOAD32L(x, y) \
+ do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0)
+
+#define STORE64L(x, y) \
+ do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0)
+
+#define LOAD64L(x, y) \
+ do { XMEMCPY(&(x), y, 8); } while(0)
+
+#endif /* ENDIAN_64BITWORD */
+
+#elif defined(ENDIAN_BIG)
+
+#define STORE32L(x, y) \
+ do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD32L(x, y) \
+ do { x = ((ulong32)((y)[3] & 255)<<24) | \
+ ((ulong32)((y)[2] & 255)<<16) | \
+ ((ulong32)((y)[1] & 255)<<8) | \
+ ((ulong32)((y)[0] & 255)); } while(0)
+
+#define STORE64L(x, y) \
+do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
+ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
+ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD64L(x, y) \
+do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
+ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
+ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
+ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
+
+#ifdef ENDIAN_32BITWORD
+
+#define STORE32H(x, y) \
+ do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0)
+
+#define LOAD32H(x, y) \
+ do { XMEMCPY(&(x), y, 4); } while(0)
+
+#define STORE64H(x, y) \
+ do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
+
+#define LOAD64H(x, y) \
+ do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
+ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
+ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
+ (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } while(0)
+
+#else /* 64-bit words then */
+
+#define STORE32H(x, y) \
+ do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0)
+
+#define LOAD32H(x, y) \
+ do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0)
+
+#define STORE64H(x, y) \
+ do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0)
+
+#define LOAD64H(x, y) \
+ do { XMEMCPY(&(x), y, 8); } while(0)
+
+#endif /* ENDIAN_64BITWORD */
+#endif /* ENDIAN_BIG */
+
+#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
+ ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
+
+
+/* 32-bit Rotates */
+#if defined(_MSC_VER)
+#define LTC_ROx_BUILTIN
+
+/* instrinsic rotate */
+#include
+#pragma intrinsic(_rotr,_rotl)
+#define ROR(x,n) _rotr(x,n)
+#define ROL(x,n) _rotl(x,n)
+#define RORc(x,n) ROR(x,n)
+#define ROLc(x,n) ROL(x,n)
+
+#elif defined(LTC_HAVE_ROTATE_BUILTIN)
+#define LTC_ROx_BUILTIN
+
+#define ROR(x,n) __builtin_rotateright32(x,n)
+#define ROL(x,n) __builtin_rotateleft32(x,n)
+#define ROLc(x,n) ROL(x,n)
+#define RORc(x,n) ROR(x,n)
+
+#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
+#define LTC_ROx_ASM
+
+static inline ulong32 ROL(ulong32 word, int i)
+{
+ __asm__ ("roll %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+static inline ulong32 ROR(ulong32 word, int i)
+{
+ __asm__ ("rorl %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+#ifndef LTC_NO_ROLC
+
+#define ROLc(word,i) ({ \
+ ulong32 LTC_TMPVAR(ROLc) = (word); \
+ __asm__ ("roll %2, %0" : \
+ "=r" (LTC_TMPVAR(ROLc)) : \
+ "0" (LTC_TMPVAR(ROLc)), \
+ "I" (i)); \
+ LTC_TMPVAR(ROLc); \
+ })
+#define RORc(word,i) ({ \
+ ulong32 LTC_TMPVAR(RORc) = (word); \
+ __asm__ ("rorl %2, %0" : \
+ "=r" (LTC_TMPVAR(RORc)) : \
+ "0" (LTC_TMPVAR(RORc)), \
+ "I" (i)); \
+ LTC_TMPVAR(RORc); \
+ })
+
+#else
+
+#define ROLc ROL
+#define RORc ROR
+
+#endif
+
+#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
+#define LTC_ROx_ASM
+
+static inline ulong32 ROL(ulong32 word, int i)
+{
+ __asm__ ("rotlw %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"r" (i));
+ return word;
+}
+
+static inline ulong32 ROR(ulong32 word, int i)
+{
+ __asm__ ("rotlw %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"r" (32-i));
+ return word;
+}
+
+#ifndef LTC_NO_ROLC
+
+static inline ulong32 ROLc(ulong32 word, const int i)
+{
+ __asm__ ("rotlwi %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+static inline ulong32 RORc(ulong32 word, const int i)
+{
+ __asm__ ("rotrwi %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+#else
+
+#define ROLc ROL
+#define RORc ROR
+
+#endif
+
+
+#else
+
+/* rotates the hard way */
+#define ROL(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
+#define ROR(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
+#define ROLc(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
+#define RORc(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
+
+#endif
+
+
+/* 64-bit Rotates */
+#if defined(_MSC_VER)
+
+/* instrinsic rotate */
+#include
+#pragma intrinsic(_rotr64,_rotr64)
+#define ROR64(x,n) _rotr64(x,n)
+#define ROL64(x,n) _rotl64(x,n)
+#define ROR64c(x,n) ROR64(x,n)
+#define ROL64c(x,n) ROL64(x,n)
+
+#elif defined(LTC_HAVE_ROTATE_BUILTIN)
+
+#define ROR64(x,n) __builtin_rotateright64(x,n)
+#define ROL64(x,n) __builtin_rotateleft64(x,n)
+#define ROR64c(x,n) ROR64(x,n)
+#define ROL64c(x,n) ROL64(x,n)
+
+#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
+
+static inline ulong64 ROL64(ulong64 word, int i)
+{
+ __asm__("rolq %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+static inline ulong64 ROR64(ulong64 word, int i)
+{
+ __asm__("rorq %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+#ifndef LTC_NO_ROLC
+
+#define ROL64c(word,i) ({ \
+ ulong64 LTC_TMPVAR(ROL64c) = word; \
+ __asm__ ("rolq %2, %0" : \
+ "=r" (LTC_TMPVAR(ROL64c)) : \
+ "0" (LTC_TMPVAR(ROL64c)), \
+ "J" (i)); \
+ LTC_TMPVAR(ROL64c); \
+ })
+#define ROR64c(word,i) ({ \
+ ulong64 LTC_TMPVAR(ROR64c) = word; \
+ __asm__ ("rorq %2, %0" : \
+ "=r" (LTC_TMPVAR(ROR64c)) : \
+ "0" (LTC_TMPVAR(ROR64c)), \
+ "J" (i)); \
+ LTC_TMPVAR(ROR64c); \
+ })
+
+#else /* LTC_NO_ROLC */
+
+#define ROL64c ROL64
+#define ROR64c ROR64
+
+#endif
+
+#else /* Not x86_64 */
+
+#define ROL64(x, y) \
+ ( (((x)<<((ulong64)(y)&63)) | \
+ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROR64(x, y) \
+ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
+ ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROL64c(x, y) \
+ ( (((x)<<((ulong64)(y)&63)) | \
+ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROR64c(x, y) \
+ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
+ ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#endif
+
+#ifndef MAX
+ #define MAX(x, y) ( ((x)>(y))?(x):(y) )
+#endif
+
+#ifndef MIN
+ #define MIN(x, y) ( ((x)<(y))?(x):(y) )
+#endif
+
+#ifndef LTC_UNUSED_PARAM
+ #define LTC_UNUSED_PARAM(x) (void)(x)
+#endif
+
+/* there is no snprintf before Visual C++ 2015 */
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
+
+#endif /* TOMCRYPT_MACROS_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_math.h b/Sources/libtomcrypt/include/tomcrypt_math.h
new file mode 100644
index 00000000..20f5f930
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_math.h
@@ -0,0 +1,524 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_MATH_H_
+#define TOMCRYPT_MATH_H_
+
+/** math functions **/
+
+#define LTC_MP_LT -1
+#define LTC_MP_EQ 0
+#define LTC_MP_GT 1
+
+#define LTC_MP_NO 0
+#define LTC_MP_YES 1
+
+#ifndef LTC_MECC
+ typedef void ecc_point;
+#endif
+
+#ifndef LTC_MRSA
+ typedef void rsa_key;
+#endif
+
+#ifndef LTC_MILLER_RABIN_REPS
+ /* Number of rounds of the Miller-Rabin test
+ * "Reasonable values of reps are between 15 and 50." c.f. gmp doc of mpz_probab_prime_p()
+ * As of https://security.stackexchange.com/a/4546 we should use 40 rounds */
+ #define LTC_MILLER_RABIN_REPS 40
+#endif
+
+int radix_to_bin(const void *in, int radix, void *out, unsigned long *len);
+
+/** math descriptor */
+typedef struct {
+ /** Name of the math provider */
+ const char *name;
+
+ /** Bits per digit, amount of bits must fit in an unsigned long */
+ int bits_per_digit;
+
+/* ---- init/deinit functions ---- */
+
+ /** initialize a bignum
+ @param a The number to initialize
+ @return CRYPT_OK on success
+ */
+ int (*init)(void **a);
+
+ /** init copy
+ @param dst The number to initialize and write to
+ @param src The number to copy from
+ @return CRYPT_OK on success
+ */
+ int (*init_copy)(void **dst, void *src);
+
+ /** deinit
+ @param a The number to free
+ @return CRYPT_OK on success
+ */
+ void (*deinit)(void *a);
+
+/* ---- data movement ---- */
+
+ /** negate
+ @param src The number to negate
+ @param dst The destination
+ @return CRYPT_OK on success
+ */
+ int (*neg)(void *src, void *dst);
+
+ /** copy
+ @param src The number to copy from
+ @param dst The number to write to
+ @return CRYPT_OK on success
+ */
+ int (*copy)(void *src, void *dst);
+
+/* ---- trivial low level functions ---- */
+
+ /** set small constant
+ @param a Number to write to
+ @param n Source upto bits_per_digit (actually meant for very small constants)
+ @return CRYPT_OK on success
+ */
+ int (*set_int)(void *a, ltc_mp_digit n);
+
+ /** get small constant
+ @param a Small number to read,
+ only fetches up to bits_per_digit from the number
+ @return The lower bits_per_digit of the integer (unsigned)
+ */
+ unsigned long (*get_int)(void *a);
+
+ /** get digit n
+ @param a The number to read from
+ @param n The number of the digit to fetch
+ @return The bits_per_digit sized n'th digit of a
+ */
+ ltc_mp_digit (*get_digit)(void *a, int n);
+
+ /** Get the number of digits that represent the number
+ @param a The number to count
+ @return The number of digits used to represent the number
+ */
+ int (*get_digit_count)(void *a);
+
+ /** compare two integers
+ @param a The left side integer
+ @param b The right side integer
+ @return LTC_MP_LT if a < b,
+ LTC_MP_GT if a > b and
+ LTC_MP_EQ otherwise. (signed comparison)
+ */
+ int (*compare)(void *a, void *b);
+
+ /** compare against int
+ @param a The left side integer
+ @param b The right side integer (upto bits_per_digit)
+ @return LTC_MP_LT if a < b,
+ LTC_MP_GT if a > b and
+ LTC_MP_EQ otherwise. (signed comparison)
+ */
+ int (*compare_d)(void *a, ltc_mp_digit n);
+
+ /** Count the number of bits used to represent the integer
+ @param a The integer to count
+ @return The number of bits required to represent the integer
+ */
+ int (*count_bits)(void * a);
+
+ /** Count the number of LSB bits which are zero
+ @param a The integer to count
+ @return The number of contiguous zero LSB bits
+ */
+ int (*count_lsb_bits)(void *a);
+
+ /** Compute a power of two
+ @param a The integer to store the power in
+ @param n The power of two you want to store (a = 2^n)
+ @return CRYPT_OK on success
+ */
+ int (*twoexpt)(void *a , int n);
+
+/* ---- radix conversions ---- */
+
+ /** read ascii string
+ @param a The integer to store into
+ @param str The string to read
+ @param radix The radix the integer has been represented in (2-64)
+ @return CRYPT_OK on success
+ */
+ int (*read_radix)(void *a, const char *str, int radix);
+
+ /** write number to string
+ @param a The integer to store
+ @param str The destination for the string
+ @param radix The radix the integer is to be represented in (2-64)
+ @return CRYPT_OK on success
+ */
+ int (*write_radix)(void *a, char *str, int radix);
+
+ /** get size as unsigned char string
+ @param a The integer to get the size (when stored in array of octets)
+ @return The length of the integer in octets
+ */
+ unsigned long (*unsigned_size)(void *a);
+
+ /** store an integer as an array of octets
+ @param src The integer to store
+ @param dst The buffer to store the integer in
+ @return CRYPT_OK on success
+ */
+ int (*unsigned_write)(void *src, unsigned char *dst);
+
+ /** read an array of octets and store as integer
+ @param dst The integer to load
+ @param src The array of octets
+ @param len The number of octets
+ @return CRYPT_OK on success
+ */
+ int (*unsigned_read)( void *dst,
+ unsigned char *src,
+ unsigned long len);
+
+/* ---- basic math ---- */
+
+ /** add two integers
+ @param a The first source integer
+ @param b The second source integer
+ @param c The destination of "a + b"
+ @return CRYPT_OK on success
+ */
+ int (*add)(void *a, void *b, void *c);
+
+ /** add two integers
+ @param a The first source integer
+ @param b The second source integer
+ (single digit of upto bits_per_digit in length)
+ @param c The destination of "a + b"
+ @return CRYPT_OK on success
+ */
+ int (*addi)(void *a, ltc_mp_digit b, void *c);
+
+ /** subtract two integers
+ @param a The first source integer
+ @param b The second source integer
+ @param c The destination of "a - b"
+ @return CRYPT_OK on success
+ */
+ int (*sub)(void *a, void *b, void *c);
+
+ /** subtract two integers
+ @param a The first source integer
+ @param b The second source integer
+ (single digit of upto bits_per_digit in length)
+ @param c The destination of "a - b"
+ @return CRYPT_OK on success
+ */
+ int (*subi)(void *a, ltc_mp_digit b, void *c);
+
+ /** multiply two integers
+ @param a The first source integer
+ @param b The second source integer
+ (single digit of upto bits_per_digit in length)
+ @param c The destination of "a * b"
+ @return CRYPT_OK on success
+ */
+ int (*mul)(void *a, void *b, void *c);
+
+ /** multiply two integers
+ @param a The first source integer
+ @param b The second source integer
+ (single digit of upto bits_per_digit in length)
+ @param c The destination of "a * b"
+ @return CRYPT_OK on success
+ */
+ int (*muli)(void *a, ltc_mp_digit b, void *c);
+
+ /** Square an integer
+ @param a The integer to square
+ @param b The destination
+ @return CRYPT_OK on success
+ */
+ int (*sqr)(void *a, void *b);
+
+ /** Square root (mod prime)
+ @param a The integer to compute square root mod prime from
+ @param b The prime
+ @param c The destination
+ @return CRYPT_OK on success
+ */
+ int (*sqrtmod_prime)(void *a, void *b, void *c);
+
+ /** Divide an integer
+ @param a The dividend
+ @param b The divisor
+ @param c The quotient (can be NULL to signify don't care)
+ @param d The remainder (can be NULL to signify don't care)
+ @return CRYPT_OK on success
+ */
+ int (*mpdiv)(void *a, void *b, void *c, void *d);
+
+ /** divide by two
+ @param a The integer to divide (shift right)
+ @param b The destination
+ @return CRYPT_OK on success
+ */
+ int (*div_2)(void *a, void *b);
+
+ /** Get remainder (small value)
+ @param a The integer to reduce
+ @param b The modulus (upto bits_per_digit in length)
+ @param c The destination for the residue
+ @return CRYPT_OK on success
+ */
+ int (*modi)(void *a, ltc_mp_digit b, ltc_mp_digit *c);
+
+ /** gcd
+ @param a The first integer
+ @param b The second integer
+ @param c The destination for (a, b)
+ @return CRYPT_OK on success
+ */
+ int (*gcd)(void *a, void *b, void *c);
+
+ /** lcm
+ @param a The first integer
+ @param b The second integer
+ @param c The destination for [a, b]
+ @return CRYPT_OK on success
+ */
+ int (*lcm)(void *a, void *b, void *c);
+
+ /** Modular multiplication
+ @param a The first source
+ @param b The second source
+ @param c The modulus
+ @param d The destination (a*b mod c)
+ @return CRYPT_OK on success
+ */
+ int (*mulmod)(void *a, void *b, void *c, void *d);
+
+ /** Modular squaring
+ @param a The first source
+ @param b The modulus
+ @param c The destination (a*a mod b)
+ @return CRYPT_OK on success
+ */
+ int (*sqrmod)(void *a, void *b, void *c);
+
+ /** Modular inversion
+ @param a The value to invert
+ @param b The modulus
+ @param c The destination (1/a mod b)
+ @return CRYPT_OK on success
+ */
+ int (*invmod)(void *, void *, void *);
+
+/* ---- reduction ---- */
+
+ /** setup Montgomery
+ @param a The modulus
+ @param b The destination for the reduction digit
+ @return CRYPT_OK on success
+ */
+ int (*montgomery_setup)(void *a, void **b);
+
+ /** get normalization value
+ @param a The destination for the normalization value
+ @param b The modulus
+ @return CRYPT_OK on success
+ */
+ int (*montgomery_normalization)(void *a, void *b);
+
+ /** reduce a number
+ @param a The number [and dest] to reduce
+ @param b The modulus
+ @param c The value "b" from montgomery_setup()
+ @return CRYPT_OK on success
+ */
+ int (*montgomery_reduce)(void *a, void *b, void *c);
+
+ /** clean up (frees memory)
+ @param a The value "b" from montgomery_setup()
+ @return CRYPT_OK on success
+ */
+ void (*montgomery_deinit)(void *a);
+
+/* ---- exponentiation ---- */
+
+ /** Modular exponentiation
+ @param a The base integer
+ @param b The power (can be negative) integer
+ @param c The modulus integer
+ @param d The destination
+ @return CRYPT_OK on success
+ */
+ int (*exptmod)(void *a, void *b, void *c, void *d);
+
+ /** Primality testing
+ @param a The integer to test
+ @param b The number of Miller-Rabin tests that shall be executed
+ @param c The destination of the result (FP_YES if prime)
+ @return CRYPT_OK on success
+ */
+ int (*isprime)(void *a, int b, int *c);
+
+/* ---- (optional) ecc point math ---- */
+
+ /** ECC GF(p) point multiplication (from the NIST curves)
+ @param k The integer to multiply the point by
+ @param G The point to multiply
+ @param R The destination for kG
+ @param a ECC curve parameter a
+ @param modulus The modulus for the field
+ @param map Boolean indicated whether to map back to affine or not
+ (can be ignored if you work in affine only)
+ @return CRYPT_OK on success
+ */
+ int (*ecc_ptmul)( void *k,
+ const ecc_point *G,
+ ecc_point *R,
+ void *a,
+ void *modulus,
+ int map);
+
+ /** ECC GF(p) point addition
+ @param P The first point
+ @param Q The second point
+ @param R The destination of P + Q
+ @param ma The curve parameter "a" in montgomery form
+ @param modulus The modulus
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+ */
+ int (*ecc_ptadd)(const ecc_point *P,
+ const ecc_point *Q,
+ ecc_point *R,
+ void *ma,
+ void *modulus,
+ void *mp);
+
+ /** ECC GF(p) point double
+ @param P The first point
+ @param R The destination of 2P
+ @param ma The curve parameter "a" in montgomery form
+ @param modulus The modulus
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+ */
+ int (*ecc_ptdbl)(const ecc_point *P,
+ ecc_point *R,
+ void *ma,
+ void *modulus,
+ void *mp);
+
+ /** ECC mapping from projective to affine,
+ currently uses (x,y,z) => (x/z^2, y/z^3, 1)
+ @param P The point to map
+ @param modulus The modulus
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+ @remark The mapping can be different but keep in mind a
+ ecc_point only has three integers (x,y,z) so if
+ you use a different mapping you have to make it fit.
+ */
+ int (*ecc_map)(ecc_point *P, void *modulus, void *mp);
+
+ /** Computes kA*A + kB*B = C using Shamir's Trick
+ @param A First point to multiply
+ @param kA What to multiple A by
+ @param B Second point to multiply
+ @param kB What to multiple B by
+ @param C [out] Destination point (can overlap with A or B)
+ @param ma The curve parameter "a" in montgomery form
+ @param modulus Modulus for curve
+ @return CRYPT_OK on success
+ */
+ int (*ecc_mul2add)(const ecc_point *A, void *kA,
+ const ecc_point *B, void *kB,
+ ecc_point *C,
+ void *ma,
+ void *modulus);
+
+/* ---- (optional) rsa optimized math (for internal CRT) ---- */
+
+ /** RSA Key Generation
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param size The size of the key in octets
+ @param e The "e" value (public key).
+ e==65537 is a good choice
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful, upon error all allocated ram is freed
+ */
+ int (*rsa_keygen)(prng_state *prng,
+ int wprng,
+ int size,
+ long e,
+ rsa_key *key);
+
+ /** RSA exponentiation
+ @param in The octet array representing the base
+ @param inlen The length of the input
+ @param out The destination (to be stored in an octet array format)
+ @param outlen The length of the output buffer and the resulting size
+ (zero padded to the size of the modulus)
+ @param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA
+ @param key The RSA key to use
+ @return CRYPT_OK on success
+ */
+ int (*rsa_me)(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ const rsa_key *key);
+
+/* ---- basic math continued ---- */
+
+ /** Modular addition
+ @param a The first source
+ @param b The second source
+ @param c The modulus
+ @param d The destination (a + b mod c)
+ @return CRYPT_OK on success
+ */
+ int (*addmod)(void *a, void *b, void *c, void *d);
+
+ /** Modular substraction
+ @param a The first source
+ @param b The second source
+ @param c The modulus
+ @param d The destination (a - b mod c)
+ @return CRYPT_OK on success
+ */
+ int (*submod)(void *a, void *b, void *c, void *d);
+
+/* ---- misc stuff ---- */
+
+ /** Make a pseudo-random mpi
+ @param a The mpi to make random
+ @param size The desired length
+ @return CRYPT_OK on success
+ */
+ int (*rand)(void *a, int size);
+} ltc_math_descriptor;
+
+extern ltc_math_descriptor ltc_mp;
+
+int ltc_init_multi(void **a, ...) LTC_NULL_TERMINATED;
+void ltc_deinit_multi(void *a, ...) LTC_NULL_TERMINATED;
+void ltc_cleanup_multi(void **a, ...) LTC_NULL_TERMINATED;
+
+#ifdef LTM_DESC
+extern const ltc_math_descriptor ltm_desc;
+#endif
+
+#ifdef TFM_DESC
+extern const ltc_math_descriptor tfm_desc;
+#endif
+
+#ifdef GMP_DESC
+extern const ltc_math_descriptor gmp_desc;
+#endif
+
+#endif /* TOMCRYPT_MATH_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_misc.h b/Sources/libtomcrypt/include/tomcrypt_misc.h
new file mode 100644
index 00000000..98ef0f38
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_misc.h
@@ -0,0 +1,218 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_MISC_H_
+#define TOMCRYPT_MISC_H_
+
+/* ---- LTC_BASE64 Routines ---- */
+#ifdef LTC_BASE64
+int base64_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen);
+
+int base64_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int base64_strict_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int base64_sane_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+#endif
+
+#ifdef LTC_BASE64_URL
+int base64url_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen);
+int base64url_strict_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen);
+
+int base64url_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int base64url_strict_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int base64url_sane_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+#endif
+
+/* ---- BASE32 Routines ---- */
+#ifdef LTC_BASE32
+typedef enum {
+ BASE32_RFC4648 = 0,
+ BASE32_BASE32HEX = 1,
+ BASE32_ZBASE32 = 2,
+ BASE32_CROCKFORD = 3
+} base32_alphabet;
+int base32_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen,
+ base32_alphabet id);
+int base32_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ base32_alphabet id);
+#endif
+
+/* ---- BASE16 Routines ---- */
+#ifdef LTC_BASE16
+int base16_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen,
+ unsigned int options);
+int base16_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+#endif
+
+#ifdef LTC_BCRYPT
+int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len,
+ const unsigned char *salt, unsigned long salt_len,
+ unsigned int rounds, int hash_idx,
+ unsigned char *out, unsigned long *outlen);
+#endif
+
+/* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */
+#ifdef LTC_HKDF
+
+int hkdf_test(void);
+
+int hkdf_extract(int hash_idx,
+ const unsigned char *salt, unsigned long saltlen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+int hkdf_expand(int hash_idx,
+ const unsigned char *info, unsigned long infolen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long outlen);
+
+int hkdf(int hash_idx,
+ const unsigned char *salt, unsigned long saltlen,
+ const unsigned char *info, unsigned long infolen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long outlen);
+
+#endif /* LTC_HKDF */
+
+/* ---- MEM routines ---- */
+int mem_neq(const void *a, const void *b, size_t len);
+void zeromem(volatile void *out, size_t outlen);
+void burn_stack(unsigned long len);
+
+const char *error_to_string(int err);
+
+extern const char *crypt_build_settings;
+
+/* ---- HMM ---- */
+int crypt_fsa(void *mp, ...) LTC_NULL_TERMINATED;
+
+/* ---- Dynamic language support ---- */
+int crypt_get_constant(const char* namein, int *valueout);
+int crypt_list_all_constants(char *names_list, unsigned int *names_list_size);
+
+int crypt_get_size(const char* namein, unsigned int *sizeout);
+int crypt_list_all_sizes(char *names_list, unsigned int *names_list_size);
+
+#ifdef LTM_DESC
+LTC_DEPRECATED(crypt_mp_init) void init_LTM(void);
+#endif
+#ifdef TFM_DESC
+LTC_DEPRECATED(crypt_mp_init) void init_TFM(void);
+#endif
+#ifdef GMP_DESC
+LTC_DEPRECATED(crypt_mp_init) void init_GMP(void);
+#endif
+int crypt_mp_init(const char* mpi);
+
+#ifdef LTC_ADLER32
+typedef struct adler32_state_s
+{
+ unsigned short s[2];
+} adler32_state;
+
+void adler32_init(adler32_state *ctx);
+void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length);
+void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size);
+int adler32_test(void);
+#endif
+
+#ifdef LTC_CRC32
+typedef struct crc32_state_s
+{
+ ulong32 crc;
+} crc32_state;
+
+void crc32_init(crc32_state *ctx);
+void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length);
+void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size);
+int crc32_test(void);
+#endif
+
+
+#ifdef LTC_PADDING
+
+enum padding_type {
+ LTC_PAD_PKCS7 = 0x0000U,
+#ifdef LTC_RNG_GET_BYTES
+ LTC_PAD_ISO_10126 = 0x1000U,
+#endif
+ LTC_PAD_ANSI_X923 = 0x2000U,
+ LTC_PAD_SSH = 0x3000U,
+ /* The following padding modes don't contain the padding
+ * length as last byte of the padding.
+ */
+ LTC_PAD_ONE_AND_ZERO = 0x8000U,
+ LTC_PAD_ZERO = 0x9000U,
+ LTC_PAD_ZERO_ALWAYS = 0xA000U,
+};
+
+int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode);
+int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode);
+#endif /* LTC_PADDING */
+
+#ifdef LTC_PEM
+/* Buffer-based API */
+int pem_decode(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx);
+int pem_decode_pkcs(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx);
+
+#ifdef LTC_SSH
+/**
+ Callback function for each key in an `authorized_keys` file.
+
+ This function takes ownership of the `k` parameter passed.
+ `k` must be free'd by calling `pka_key_destroy(&k)`.
+
+ @param k Pointer to the PKA key.
+ @param comment Pointer to a string with the comment.
+ @param ctx The `ctx` pointer as passed to the read function.
+*/
+typedef int (*ssh_authorized_key_cb)(ltc_pka_key *k, const char *comment, void *ctx);
+
+int pem_decode_openssh(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx);
+int ssh_read_authorized_keys(const void *buf, unsigned long len, ssh_authorized_key_cb cb, void *ctx);
+#endif /* LTC_SSH */
+
+/* FILE*-based API */
+#ifndef LTC_NO_FILE
+int pem_decode_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx);
+int pem_decode_pkcs_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx);
+#ifdef LTC_SSH
+int pem_decode_openssh_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx);
+int ssh_read_authorized_keys_filehandle(FILE *f, ssh_authorized_key_cb cb, void *ctx);
+#endif /* LTC_SSH */
+#endif /* LTC_NO_FILE */
+
+#endif /* LTC_PEM */
+
+#ifdef LTC_SSH
+typedef enum ssh_data_type_ {
+ LTC_SSHDATA_EOL,
+ LTC_SSHDATA_BYTE,
+ LTC_SSHDATA_BOOLEAN,
+ LTC_SSHDATA_UINT32,
+ LTC_SSHDATA_UINT64,
+ LTC_SSHDATA_STRING,
+ LTC_SSHDATA_MPINT,
+ LTC_SSHDATA_NAMELIST,
+} ssh_data_type;
+
+/* VA list handy helpers with tuples of */
+int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED;
+int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) LTC_NULL_TERMINATED;
+#endif /* LTC_SSH */
+
+int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which);
+
+#endif /* TOMCRYPT_MISC_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_pk.h b/Sources/libtomcrypt/include/tomcrypt_pk.h
new file mode 100644
index 00000000..41795e42
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_pk.h
@@ -0,0 +1,881 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_PK_H_
+#define TOMCRYPT_PK_H_
+
+typedef struct password_ctx {
+ /**
+ Callback function that is called when a password is required.
+
+ Please be aware that the library takes ownership of the pointer that is
+ returned to the library via `str`.
+ The data will be zeroed and `free()`'d as soon as it isn't required anymore.
+ c.f. the documentation of the `free()` function pointer for details.
+
+ @param str Pointer to pointer where the password will be stored.
+ @param len Pointer to the length of the password.
+ @param userdata `userdata` that was passed in the `password_ctx` struct.
+ @return CRYPT_OK on success
+ */
+ int (*callback)(void **str, unsigned long *len, void *userdata);
+ /**
+ Optional free function to free the allocated buffer.
+
+ At the point where the value returned by `callback()` is not required
+ anymore the library will free it by either calling this `free()` function
+ or `XFREE()` in case this `free()` function is set to `NULL`.
+
+ @param str Pointer to the buffer to be free'd.
+ */
+ void (*free)(void *str);
+ /** Opaque `userdata` pointer passed when the callback is called */
+ void *userdata;
+} password_ctx;
+
+/* ---- NUMBER THEORY ---- */
+
+enum ltc_pka_id {
+ LTC_PKA_UNDEF = 0,
+ LTC_PKA_RSA,
+ LTC_PKA_DSA,
+ LTC_PKA_EC,
+ LTC_PKA_X25519,
+ LTC_PKA_ED25519,
+ LTC_PKA_DH,
+ LTC_PKA_NUM
+};
+
+enum public_key_type {
+ /* Refers to the public key */
+ PK_PUBLIC = 0x0000,
+ /* Refers to the private key */
+ PK_PRIVATE = 0x0001,
+
+ /* Indicates standard output formats that can be read e.g. by OpenSSL or GnuTLS */
+ PK_STD = 0x1000,
+ /* Indicates compressed public ECC key */
+ PK_COMPRESSED = 0x2000,
+ /* Indicates ECC key with the curve specified by OID */
+ PK_CURVEOID = 0x4000
+};
+
+int rand_prime(void *N, long len, prng_state *prng, int wprng);
+
+/* ---- RSA ---- */
+#ifdef LTC_MRSA
+
+/** RSA PKCS style key */
+typedef struct Rsa_key {
+ /** Type of key, PK_PRIVATE or PK_PUBLIC */
+ int type;
+ /** The public exponent */
+ void *e;
+ /** The private exponent */
+ void *d;
+ /** The modulus */
+ void *N;
+ /** The p factor of N */
+ void *p;
+ /** The q factor of N */
+ void *q;
+ /** The 1/q mod p CRT param */
+ void *qP;
+ /** The d mod (p - 1) CRT param */
+ void *dP;
+ /** The d mod (q - 1) CRT param */
+ void *dQ;
+} rsa_key;
+
+int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
+int rsa_make_key_ubin_e(prng_state *prng, int wprng, int size,
+ const unsigned char *e, unsigned long elen, rsa_key *key);
+int rsa_get_size(const rsa_key *key);
+
+int rsa_exptmod(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ const rsa_key *key);
+
+void rsa_free(rsa_key *key);
+
+/* These use PKCS #1 v2.0 padding */
+#define rsa_encrypt_key(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, key) \
+ rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, -1, LTC_PKCS_1_OAEP, key)
+
+#define rsa_decrypt_key(in, inlen, out, outlen, lparam, lparamlen, hash_idx, stat, key) \
+ rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, -1, LTC_PKCS_1_OAEP, stat, key)
+
+#define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \
+ rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key)
+
+#define rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen, stat, key) \
+ rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, saltlen, stat, key)
+
+#define rsa_sign_saltlen_get_max(hash_idx, key) \
+ rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key)
+
+/* These can be switched between PKCS #1 v2.x and PKCS #1 v1.5 paddings */
+int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ prng_state *prng, int prng_idx,
+ int mgf_hash, int lparam_hash,
+ int padding,
+ const rsa_key *key);
+
+int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ int mgf_hash, int lparam_hash,
+ int padding,
+ int *stat, const rsa_key *key);
+
+int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ int padding,
+ prng_state *prng, int prng_idx,
+ int hash_idx, unsigned long saltlen,
+ const rsa_key *key);
+
+int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int padding,
+ int hash_idx, unsigned long saltlen,
+ int *stat, const rsa_key *key);
+
+int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key);
+
+/* PKCS #1 import/export */
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_key *key);
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
+
+int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key);
+int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx, rsa_key *key);
+
+int rsa_set_key(const unsigned char *N, unsigned long Nlen,
+ const unsigned char *e, unsigned long elen,
+ const unsigned char *d, unsigned long dlen,
+ rsa_key *key);
+int rsa_set_factors(const unsigned char *p, unsigned long plen,
+ const unsigned char *q, unsigned long qlen,
+ rsa_key *key);
+int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen,
+ const unsigned char *dQ, unsigned long dQlen,
+ const unsigned char *qP, unsigned long qPlen,
+ rsa_key *key);
+#endif
+
+/* ---- DH Routines ---- */
+#ifdef LTC_MDH
+
+typedef struct {
+ int type;
+ void *x;
+ void *y;
+ void *base;
+ void *prime;
+} dh_key;
+
+int dh_get_groupsize(const dh_key *key);
+
+int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key);
+int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key);
+int dh_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx, dh_key *key);
+
+int dh_set_pg(const unsigned char *p, unsigned long plen,
+ const unsigned char *g, unsigned long glen,
+ dh_key *key);
+int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key);
+int dh_set_pg_groupsize(int groupsize, dh_key *key);
+
+int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key);
+int dh_generate_key(prng_state *prng, int wprng, dh_key *key);
+
+int dh_shared_secret(const dh_key *private_key, const dh_key *public_key,
+ unsigned char *out, unsigned long *outlen);
+
+void dh_free(dh_key *key);
+
+int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key);
+#endif /* LTC_MDH */
+
+
+/* ---- ECC Routines ---- */
+#ifdef LTC_MECC
+
+/* size of our temp buffers for exported keys */
+#define ECC_BUF_SIZE 256
+
+/* max private key size */
+#define ECC_MAXSIZE 66
+
+/** Structure defines a GF(p) curve */
+typedef struct {
+ /** The prime that defines the field the curve is in (encoded in hex) */
+ const char *prime;
+
+ /** The fields A param (hex) */
+ const char *A;
+
+ /** The fields B param (hex) */
+ const char *B;
+
+ /** The order of the curve (hex) */
+ const char *order;
+
+ /** The x co-ordinate of the base point on the curve (hex) */
+ const char *Gx;
+
+ /** The y co-ordinate of the base point on the curve (hex) */
+ const char *Gy;
+
+ /** The co-factor */
+ unsigned long cofactor;
+
+ /** The OID */
+ const char *OID;
+} ltc_ecc_curve;
+
+/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */
+typedef struct {
+ /** The x co-ordinate */
+ void *x;
+
+ /** The y co-ordinate */
+ void *y;
+
+ /** The z co-ordinate */
+ void *z;
+} ecc_point;
+
+/** ECC key's domain parameters */
+typedef struct {
+ /** The size of the curve in octets */
+ int size;
+ /** The prime that defines the field the curve is in */
+ void *prime;
+ /** The fields A param */
+ void *A;
+ /** The fields B param */
+ void *B;
+ /** The order of the curve */
+ void *order;
+ /** The base point G on the curve */
+ ecc_point base;
+ /** The co-factor */
+ unsigned long cofactor;
+ /** The OID */
+ unsigned long oid[16];
+ unsigned long oidlen;
+} ltc_ecc_dp;
+
+/** An ECC key */
+typedef struct {
+ /** Type of key, PK_PRIVATE or PK_PUBLIC */
+ int type;
+
+ /** Structure with domain parameters */
+ ltc_ecc_dp dp;
+
+ /** Structure with the public key */
+ ecc_point pubkey;
+
+ /** The private key */
+ void *k;
+} ecc_key;
+
+/** Formats of ECC signatures */
+typedef enum ecc_signature_type_ {
+ /* ASN.1 encoded, ANSI X9.62 */
+ LTC_ECCSIG_ANSIX962 = 0x0,
+ /* raw R, S values */
+ LTC_ECCSIG_RFC7518 = 0x1,
+ /* raw R, S, V (+27) values */
+ LTC_ECCSIG_ETH27 = 0x2,
+ /* SSH + ECDSA signature format defined by RFC5656 */
+ LTC_ECCSIG_RFC5656 = 0x3,
+} ecc_signature_type;
+
+/** the ECC params provided */
+extern const ltc_ecc_curve ltc_ecc_curves[];
+
+void ecc_sizes(int *low, int *high);
+int ecc_get_size(const ecc_key *key);
+
+int ecc_find_curve(const char* name_or_oid, const ltc_ecc_curve** cu);
+int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key);
+int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key);
+int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key);
+int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key);
+int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key);
+
+int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
+int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu);
+void ecc_free(ecc_key *key);
+
+int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key);
+int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
+int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu);
+
+int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen);
+int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
+int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu);
+
+int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key);
+int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key);
+int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const password_ctx *pw_ctx, ecc_key *key);
+int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key);
+
+int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key,
+ unsigned char *out, unsigned long *outlen);
+
+int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, int hash,
+ const ecc_key *key);
+
+int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const ecc_key *key);
+
+#define ecc_sign_hash_rfc7518(in_, inlen_, out_, outlen_, prng_, wprng_, key_) \
+ ecc_sign_hash_ex(in_, inlen_, out_, outlen_, prng_, wprng_, LTC_ECCSIG_RFC7518, NULL, key_)
+
+#define ecc_sign_hash(in_, inlen_, out_, outlen_, prng_, wprng_, key_) \
+ ecc_sign_hash_ex(in_, inlen_, out_, outlen_, prng_, wprng_, LTC_ECCSIG_ANSIX962, NULL, key_)
+
+#define ecc_verify_hash_rfc7518(sig_, siglen_, hash_, hashlen_, stat_, key_) \
+ ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_RFC7518, stat_, key_)
+
+#define ecc_verify_hash(sig_, siglen_, hash_, hashlen_, stat_, key_) \
+ ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_ANSIX962, stat_, key_)
+
+int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, ecc_signature_type sigformat,
+ int *recid, const ecc_key *key);
+
+int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ ecc_signature_type sigformat, int *stat, const ecc_key *key);
+
+int ecc_recover_key(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int recid, ecc_signature_type sigformat, ecc_key *key);
+
+#endif
+
+#ifdef LTC_CURVE25519
+
+typedef struct {
+ /** The key type, PK_PRIVATE or PK_PUBLIC */
+ enum public_key_type type;
+
+ /** The PK-algorithm, LTC_PKA_ED25519 or LTC_PKA_X25519 */
+ enum ltc_pka_id pka;
+
+ /** The private key */
+ unsigned char priv[32];
+
+ /** The public key */
+ unsigned char pub[32];
+} curve25519_key;
+
+
+/** Ed25519 Signature API */
+int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key);
+
+int ed25519_export( unsigned char *out, unsigned long *outlen,
+ int which,
+ const curve25519_key *key);
+
+int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key);
+int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key);
+int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key);
+int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ curve25519_key *key);
+
+int ed25519_sign(const unsigned char *msg, unsigned long msglen,
+ unsigned char *sig, unsigned long *siglen,
+ const curve25519_key *private_key);
+int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
+ unsigned char *sig, unsigned long *siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ const curve25519_key *private_key);
+int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
+ unsigned char *sig, unsigned long *siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ const curve25519_key *private_key);
+int ed25519_verify(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *sig, unsigned long siglen,
+ int *stat,
+ const curve25519_key *public_key);
+int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *sig, unsigned long siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ int *stat,
+ const curve25519_key *public_key);
+int ed25519ph_verify(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *sig, unsigned long siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ int *stat,
+ const curve25519_key *public_key);
+
+/** X25519 Key-Exchange API */
+int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key);
+
+int x25519_export( unsigned char *out, unsigned long *outlen,
+ int which,
+ const curve25519_key *key);
+
+int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key);
+int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key);
+int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key);
+int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ curve25519_key *key);
+
+int x25519_shared_secret(const curve25519_key *private_key,
+ const curve25519_key *public_key,
+ unsigned char *out, unsigned long *outlen);
+
+#endif /* LTC_CURVE25519 */
+
+#ifdef LTC_MDSA
+
+/* Max diff between group and modulus size in bytes (max case: L=8192bits, N=256bits) */
+#define LTC_MDSA_DELTA 992
+
+/* Max DSA group size in bytes */
+#define LTC_MDSA_MAX_GROUP 64
+
+/* Max DSA modulus size in bytes (the actual DSA size, max 8192 bits) */
+#define LTC_MDSA_MAX_MODULUS 1024
+
+/** DSA key structure */
+typedef struct {
+ /** The key type, PK_PRIVATE or PK_PUBLIC */
+ int type;
+
+ /** The order of the sub-group used in octets */
+ int qord;
+
+ /** The generator */
+ void *g;
+
+ /** The prime used to generate the sub-group */
+ void *q;
+
+ /** The large prime that generats the field the contains the sub-group */
+ void *p;
+
+ /** The private key */
+ void *x;
+
+ /** The public key */
+ void *y;
+} dsa_key;
+
+int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
+
+int dsa_set_pqg(const unsigned char *p, unsigned long plen,
+ const unsigned char *q, unsigned long qlen,
+ const unsigned char *g, unsigned long glen,
+ dsa_key *key);
+int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, dsa_key *key);
+int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
+
+int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key);
+int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key);
+
+void dsa_free(dsa_key *key);
+
+int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ void *r, void *s,
+ prng_state *prng, int wprng, const dsa_key *key);
+
+int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, const dsa_key *key);
+
+int dsa_verify_hash_raw( void *r, void *s,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, const dsa_key *key);
+
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, const dsa_key *key);
+
+int dsa_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, int hash,
+ const dsa_key *key);
+
+int dsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const dsa_key *key);
+
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
+int dsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ dsa_key *key);
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_key *key);
+int dsa_verify_key(const dsa_key *key, int *stat);
+int dsa_shared_secret(void *private_key, void *base,
+ const dsa_key *public_key,
+ unsigned char *out, unsigned long *outlen);
+#endif /* LTC_MDSA */
+
+/*
+ * LibTomCrypt tagged-union for holding a Public Key
+ */
+
+typedef struct {
+ union {
+#ifdef LTC_CURVE25519
+ curve25519_key x25519;
+ curve25519_key ed25519;
+#endif
+#ifdef LTC_MDH
+ dh_key dh;
+#endif
+#ifdef LTC_MDSA
+ dsa_key dsa;
+#endif
+#ifdef LTC_MECC
+ ecc_key ecc;
+#endif
+#ifdef LTC_MRSA
+ rsa_key rsa;
+#endif
+ char dummy;
+ } u;
+ enum ltc_pka_id id;
+} ltc_pka_key;
+
+void pka_key_free(ltc_pka_key *key);
+void pka_key_destroy(ltc_pka_key **key);
+
+#ifdef LTC_DER
+/* DER handling */
+
+typedef enum ltc_asn1_type_ {
+ /* 0 */
+ LTC_ASN1_EOL,
+ LTC_ASN1_BOOLEAN,
+ LTC_ASN1_INTEGER,
+ LTC_ASN1_SHORT_INTEGER,
+ LTC_ASN1_BIT_STRING,
+ /* 5 */
+ LTC_ASN1_OCTET_STRING,
+ LTC_ASN1_NULL,
+ LTC_ASN1_OBJECT_IDENTIFIER,
+ LTC_ASN1_IA5_STRING,
+ LTC_ASN1_PRINTABLE_STRING,
+ /* 10 */
+ LTC_ASN1_UTF8_STRING,
+ LTC_ASN1_UTCTIME,
+ LTC_ASN1_CHOICE,
+ LTC_ASN1_SEQUENCE,
+ LTC_ASN1_SET,
+ /* 15 */
+ LTC_ASN1_SETOF,
+ LTC_ASN1_RAW_BIT_STRING,
+ LTC_ASN1_TELETEX_STRING,
+ LTC_ASN1_GENERALIZEDTIME,
+ LTC_ASN1_CUSTOM_TYPE,
+} ltc_asn1_type;
+
+typedef enum {
+ LTC_ASN1_CL_UNIVERSAL = 0x0,
+ LTC_ASN1_CL_APPLICATION = 0x1,
+ LTC_ASN1_CL_CONTEXT_SPECIFIC = 0x2,
+ LTC_ASN1_CL_PRIVATE = 0x3,
+} ltc_asn1_class;
+
+typedef enum {
+ LTC_ASN1_PC_PRIMITIVE = 0x0,
+ LTC_ASN1_PC_CONSTRUCTED = 0x1,
+} ltc_asn1_pc;
+
+/** A LTC ASN.1 list type */
+typedef struct ltc_asn1_list_ {
+ /** The LTC ASN.1 enumerated type identifier */
+ ltc_asn1_type type;
+ /** The data to encode or place for decoding */
+ void *data;
+ /** The size of the input or resulting output */
+ unsigned long size;
+ /** The used flag
+ * 1. This is used by the CHOICE ASN.1 type to indicate which choice was made
+ * 2. This is used by the ASN.1 decoder to indicate if an element is used
+ * 3. This is used by the flexi-decoder to indicate the first byte of the identifier */
+ int used;
+ /** Flag used to indicate optional items in ASN.1 sequences */
+ int optional;
+ /** ASN.1 identifier */
+ ltc_asn1_class klass;
+ ltc_asn1_pc pc;
+ ulong64 tag;
+ /** prev/next entry in the list */
+ struct ltc_asn1_list_ *prev, *next, *child, *parent;
+} ltc_asn1_list;
+
+#define LTC_SET_ASN1(list, index, Type, Data, Size) \
+ do { \
+ int LTC_TMPVAR(SA) = (index); \
+ ltc_asn1_list *LTC_TMPVAR(SA_list) = (list); \
+ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].type = (Type); \
+ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].data = (void*)(Data); \
+ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].size = (Size); \
+ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].used = 0; \
+ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].optional = 0; \
+ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].klass = 0; \
+ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].pc = 0; \
+ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].tag = 0; \
+ } while (0)
+
+#define LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \
+ do { \
+ int LTC_TMPVAR(SAI) = (index); \
+ ltc_asn1_list *LTC_TMPVAR(SAI_list) = (list); \
+ LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].type = LTC_ASN1_CUSTOM_TYPE; \
+ LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].klass = (Class); \
+ LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].pc = (Pc); \
+ LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].tag = (Tag); \
+ } while (0)
+
+#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \
+ do { \
+ int LTC_TMPVAR(SACC) = (index); \
+ LTC_SET_ASN1(list, LTC_TMPVAR(SACC), LTC_ASN1_CUSTOM_TYPE, Data, 1); \
+ LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACC), Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \
+ } while (0)
+
+#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \
+ do { \
+ int LTC_TMPVAR(SACP) = (index); \
+ LTC_SET_ASN1(list, LTC_TMPVAR(SACP), LTC_ASN1_CUSTOM_TYPE, Data, Size); \
+ LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACP), Class, LTC_ASN1_PC_PRIMITIVE, Tag); \
+ list[LTC_TMPVAR(SACP)].used = (int)(Type); \
+ } while (0)
+
+extern const char* der_asn1_class_to_string_map[];
+extern const unsigned long der_asn1_class_to_string_map_sz;
+
+extern const char* der_asn1_pc_to_string_map[];
+extern const unsigned long der_asn1_pc_to_string_map_sz;
+
+extern const char* der_asn1_tag_to_string_map[];
+extern const unsigned long der_asn1_tag_to_string_map_sz;
+
+/* SEQUENCE */
+int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int type_of);
+
+#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE)
+
+/** The supported bitmap for all the
+ * decoders with a `flags` argument.
+ */
+enum ltc_der_seq {
+ LTC_DER_SEQ_ZERO = 0x0u,
+
+ /** Bit0 - [0]=Unordered (SET or SETOF)
+ * [1]=Ordered (SEQUENCE) */
+ LTC_DER_SEQ_UNORDERED = LTC_DER_SEQ_ZERO,
+ LTC_DER_SEQ_ORDERED = 0x1u,
+
+ /** Bit1 - [0]=Relaxed
+ * [1]=Strict */
+ LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO,
+ LTC_DER_SEQ_STRICT = 0x2u,
+
+ /** Alternative naming */
+ LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED,
+ LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED,
+};
+
+int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *list, unsigned long outlen, unsigned int flags);
+
+#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED)
+#define der_decode_sequence_strict(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT)
+
+int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen);
+
+
+/* Custom-types */
+int der_encode_custom_type(const ltc_asn1_list *root,
+ unsigned char *out, unsigned long *outlen);
+
+int der_decode_custom_type(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root);
+
+int der_length_custom_type(const ltc_asn1_list *root,
+ unsigned long *outlen,
+ unsigned long *payloadlen);
+
+/* SET */
+#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SET)
+#define der_length_set der_length_sequence
+int der_encode_set(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+int der_encode_setof(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+/* VA list handy helpers with triplets of */
+int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED;
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED;
+
+/* FLEXI DECODER handle unknown list decoder */
+int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out);
+#define der_free_sequence_flexi der_sequence_free
+void der_sequence_free(ltc_asn1_list *in);
+void der_sequence_shrink(ltc_asn1_list *in);
+
+/* BOOLEAN */
+int der_length_boolean(unsigned long *outlen);
+int der_encode_boolean(int in,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_boolean(const unsigned char *in, unsigned long inlen,
+ int *out);
+/* INTEGER */
+int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen);
+int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num);
+int der_length_integer(void *num, unsigned long *outlen);
+
+/* INTEGER -- handy for 0..2^32-1 values */
+int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num);
+int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen);
+int der_length_short_integer(unsigned long num, unsigned long *outlen);
+
+/* BIT STRING */
+int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_bit_string(unsigned long nbits, unsigned long *outlen);
+
+/* OCTET STRING */
+int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_octet_string(unsigned long noctets, unsigned long *outlen);
+
+/* OBJECT IDENTIFIER */
+int der_encode_object_identifier(const unsigned long *words, unsigned long nwords,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
+ unsigned long *words, unsigned long *outlen);
+int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen);
+unsigned long der_object_identifier_bits(unsigned long x);
+
+/* IA5 STRING */
+int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
+
+int der_ia5_char_encode(int c);
+int der_ia5_value_decode(int v);
+
+/* TELETEX STRING */
+int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
+
+/* PRINTABLE STRING */
+int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
+
+int der_printable_char_encode(int c);
+int der_printable_value_decode(int v);
+
+/* UTF-8 */
+#if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(__WCHAR_MAX__) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR)
+ #if defined(__WCHAR_MAX__)
+ #define LTC_WCHAR_MAX __WCHAR_MAX__
+ #else
+ #include
+ #define LTC_WCHAR_MAX WCHAR_MAX
+ #endif
+/* please note that it might happen that LTC_WCHAR_MAX is undefined */
+#else
+ typedef ulong32 wchar_t;
+ #define LTC_WCHAR_MAX 0xFFFFFFFF
+#endif
+
+int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
+ wchar_t *out, unsigned long *outlen);
+unsigned long der_utf8_charsize(const wchar_t c);
+int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen);
+
+
+/* CHOICE */
+int der_decode_choice(const unsigned char *in, unsigned long *inlen,
+ ltc_asn1_list *list, unsigned long outlen);
+
+/* UTCTime */
+typedef struct {
+ unsigned YY, /* year */
+ MM, /* month */
+ DD, /* day */
+ hh, /* hour */
+ mm, /* minute */
+ ss, /* second */
+ off_dir, /* timezone offset direction 0 == +, 1 == - */
+ off_hh, /* timezone offset hours */
+ off_mm; /* timezone offset minutes */
+} ltc_utctime;
+
+int der_encode_utctime(const ltc_utctime *utctime,
+ unsigned char *out, unsigned long *outlen);
+
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+ ltc_utctime *out);
+
+int der_length_utctime(const ltc_utctime *utctime, unsigned long *outlen);
+
+/* GeneralizedTime */
+typedef struct {
+ unsigned YYYY, /* year */
+ MM, /* month */
+ DD, /* day */
+ hh, /* hour */
+ mm, /* minute */
+ ss, /* second */
+ fs, /* fractional seconds */
+ off_dir, /* timezone offset direction 0 == +, 1 == - */
+ off_hh, /* timezone offset hours */
+ off_mm; /* timezone offset minutes */
+} ltc_generalizedtime;
+
+int der_encode_generalizedtime(const ltc_generalizedtime *gtime,
+ unsigned char *out, unsigned long *outlen);
+
+int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen,
+ ltc_generalizedtime *out);
+
+int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen);
+
+#endif
+
+#endif /* TOMCRYPT_PK_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_pkcs.h b/Sources/libtomcrypt/include/tomcrypt_pkcs.h
new file mode 100644
index 00000000..0ca63b0a
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_pkcs.h
@@ -0,0 +1,105 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_PKCS_H_
+#define TOMCRYPT_PKCS_H_
+
+/* PKCS Header Info */
+
+/* ===> PKCS #1 -- RSA Cryptography <=== */
+#ifdef LTC_PKCS_1
+
+enum ltc_pkcs_1_v1_5_blocks
+{
+ LTC_PKCS_1_EMSA = 1, /* Block type 1 (PKCS #1 v1.5 signature padding) */
+ LTC_PKCS_1_EME = 2 /* Block type 2 (PKCS #1 v1.5 encryption padding) */
+};
+
+enum ltc_pkcs_1_paddings
+{
+ LTC_PKCS_1_V1_5 = 1, /* PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */
+ LTC_PKCS_1_OAEP = 2, /* PKCS #1 v2.0 encryption padding */
+ LTC_PKCS_1_PSS = 3, /* PKCS #1 v2.1 signature padding */
+ LTC_PKCS_1_V1_5_NA1 = 4 /* PKCS #1 v1.5 padding - No ASN.1 (\sa ltc_pkcs_1_v1_5_blocks) */
+};
+
+int pkcs_1_mgf1( int hash_idx,
+ const unsigned char *seed, unsigned long seedlen,
+ unsigned char *mask, unsigned long masklen);
+
+int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out);
+int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen);
+
+/* *** v1.5 padding */
+int pkcs_1_v1_5_encode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ prng_state *prng,
+ int prng_idx,
+ unsigned char *out,
+ unsigned long *outlen);
+
+int pkcs_1_v1_5_decode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen,
+ int *is_valid);
+
+/* *** v2.1 padding */
+int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, prng_state *prng,
+ int prng_idx,
+ int mgf_hash, int lparam_hash,
+ unsigned char *out, unsigned long *outlen);
+
+int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen,
+ int mgf_hash, int lparam_hash,
+ unsigned char *out, unsigned long *outlen,
+ int *res);
+
+int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
+ unsigned long saltlen, prng_state *prng,
+ int prng_idx, int hash_idx,
+ unsigned long modulus_bitlen,
+ unsigned char *out, unsigned long *outlen);
+
+int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
+ const unsigned char *sig, unsigned long siglen,
+ unsigned long saltlen, int hash_idx,
+ unsigned long modulus_bitlen, int *res);
+
+#endif /* LTC_PKCS_1 */
+
+/* ===> PKCS #5 -- Password Based Cryptography <=== */
+#ifdef LTC_PKCS_5
+
+/* Algorithm #1 (PBKDF1) */
+int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
+ const unsigned char *salt,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen);
+
+/* Algorithm #1 (PBKDF1) - OpenSSL-compatible variant for arbitrarily-long keys.
+ Compatible with EVP_BytesToKey() */
+int pkcs_5_alg1_openssl(const unsigned char *password,
+ unsigned long password_len,
+ const unsigned char *salt,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen);
+
+/* Algorithm #2 (PBKDF2) */
+int pkcs_5_alg2(const unsigned char *password, unsigned long password_len,
+ const unsigned char *salt, unsigned long salt_len,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen);
+
+int pkcs_5_test (void);
+#endif /* LTC_PKCS_5 */
+
+#endif /* TOMCRYPT_PKCS_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_private.h b/Sources/libtomcrypt/include/tomcrypt_private.h
new file mode 100644
index 00000000..8b66b1dc
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_private.h
@@ -0,0 +1,696 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_PRIVATE_H_
+#define TOMCRYPT_PRIVATE_H_
+
+#include "tomcrypt.h"
+
+/*
+ * Internal Macros
+ */
+/* Static assertion */
+#define LTC_STATIC_ASSERT(msg, cond) typedef char ltc_static_assert_##msg[(cond) ? 1 : -1];
+
+#define LTC_PAD_MASK (0xF000U)
+
+#if defined(ENDIAN_64BITWORD)
+ #define CONSTPTR(n) CONST64(n)
+#else
+ #define CONSTPTR(n) n ## uL
+#endif
+
+LTC_STATIC_ASSERT(correct_CONSTPTR_size, sizeof(CONSTPTR(1)) == sizeof(void*))
+
+/* Poor-man's `uintptr_t` since we can't use stdint.h
+ * c.f. https://github.com/DCIT/perl-CryptX/issues/95#issuecomment-1745280962 */
+typedef size_t ltc_uintptr;
+
+LTC_STATIC_ASSERT(correct_ltc_uintptr_size, sizeof(ltc_uintptr) == sizeof(void*))
+
+/* Aligns a `unsigned char` buffer `buf` to `n` bytes and returns that aligned address.
+ * Make sure that the buffer that is passed is huge enough.
+ */
+#define LTC_ALIGN_BUF(buf, n) ((void*)((ltc_uintptr)&((unsigned char*)(buf))[n - 1] & (~(CONSTPTR(n) - CONSTPTR(1)))))
+
+#define LTC_OID_MAX_STRLEN 256
+
+/* `NULL` as defined by the standard is not guaranteed to be of a pointer
+ * type. In order to make sure that in vararg API's a pointer type is used,
+ * define our own version and use that one internally.
+ */
+#ifndef LTC_NULL
+ #define LTC_NULL ((void *)0)
+#endif
+
+/*
+ * Internal Enums
+ */
+
+enum ltc_oid_id {
+ LTC_OID_UNDEF,
+ LTC_OID_RSA,
+ LTC_OID_DSA,
+ LTC_OID_EC,
+ LTC_OID_EC_PRIMEF,
+ LTC_OID_X25519,
+ LTC_OID_ED25519,
+ LTC_OID_DH,
+ LTC_OID_NUM
+};
+
+/*
+ * Internal Types
+ */
+
+typedef struct {
+ int size;
+ const char *name, *base, *prime;
+} ltc_dh_set_type;
+
+
+struct password {
+ /* usually a `char*` but could also contain binary data
+ * so use a `void*` + length to be on the safe side.
+ */
+ void *pw;
+ unsigned long l;
+};
+
+typedef int (*fn_kdf_t)(const struct password *pwd,
+ const unsigned char *salt, unsigned long salt_len,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen);
+
+typedef struct {
+ /* KDF */
+ fn_kdf_t kdf;
+ /* Hash or HMAC */
+ const char* h;
+ /* cipher */
+ const char* c;
+ unsigned long keylen;
+ /* not used for pbkdf2 */
+ unsigned long blocklen;
+} pbes_properties;
+
+typedef struct
+{
+ pbes_properties type;
+ struct password pw;
+ ltc_asn1_list *enc_data;
+ ltc_asn1_list *salt;
+ ltc_asn1_list *iv;
+ unsigned long iterations;
+ /* only used for RC2 */
+ unsigned long key_bits;
+} pbes_arg;
+
+/*
+ * Internal functions
+ */
+
+
+/* tomcrypt_cipher.h */
+
+void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey);
+int blowfish_expand(const unsigned char *key, int keylen,
+ const unsigned char *data, int datalen,
+ symmetric_key *skey);
+int blowfish_setup_with_data(const unsigned char *key, int keylen,
+ const unsigned char *data, int datalen,
+ symmetric_key *skey);
+
+/* tomcrypt_hash.h */
+
+/* a simple macro for making hash "process" functions */
+#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \
+int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \
+{ \
+ unsigned long n; \
+ int err; \
+ LTC_ARGCHK(md != NULL); \
+ LTC_ARGCHK(in != NULL); \
+ if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \
+ return CRYPT_INVALID_ARG; \
+ } \
+ if (((md-> state_var .length + inlen * 8) < md-> state_var .length) \
+ || ((inlen * 8) < inlen)) { \
+ return CRYPT_HASH_OVERFLOW; \
+ } \
+ while (inlen > 0) { \
+ if (md-> state_var .curlen == 0 && inlen >= block_size) { \
+ if ((err = compress_name (md, in)) != CRYPT_OK) { \
+ return err; \
+ } \
+ md-> state_var .length += block_size * 8; \
+ in += block_size; \
+ inlen -= block_size; \
+ } else { \
+ n = MIN(inlen, (block_size - md-> state_var .curlen)); \
+ XMEMCPY(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \
+ md-> state_var .curlen += n; \
+ in += n; \
+ inlen -= n; \
+ if (md-> state_var .curlen == block_size) { \
+ if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \
+ return err; \
+ } \
+ md-> state_var .length += 8*block_size; \
+ md-> state_var .curlen = 0; \
+ } \
+ } \
+ } \
+ return CRYPT_OK; \
+}
+
+
+/* tomcrypt_mac.h */
+
+int ocb3_int_ntz(unsigned long x);
+void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len);
+
+
+/* tomcrypt_math.h */
+
+#if !defined(DESC_DEF_ONLY)
+
+#define MP_DIGIT_BIT ltc_mp.bits_per_digit
+
+/* some handy macros */
+#define mp_init(a) ltc_mp.init(a)
+#define mp_init_multi ltc_init_multi
+#define mp_clear(a) ltc_mp.deinit(a)
+#define mp_clear_multi ltc_deinit_multi
+#define mp_cleanup_multi ltc_cleanup_multi
+#define mp_init_copy(a, b) ltc_mp.init_copy(a, b)
+
+#define mp_neg(a, b) ltc_mp.neg(a, b)
+#define mp_copy(a, b) ltc_mp.copy(a, b)
+
+#define mp_set(a, b) ltc_mp.set_int(a, b)
+#define mp_set_int(a, b) ltc_mp.set_int(a, b)
+#define mp_get_int(a) ltc_mp.get_int(a)
+#define mp_get_digit(a, n) ltc_mp.get_digit(a, n)
+#define mp_get_digit_count(a) ltc_mp.get_digit_count(a)
+#define mp_cmp(a, b) ltc_mp.compare(a, b)
+#define mp_cmp_d(a, b) ltc_mp.compare_d(a, b)
+#define mp_count_bits(a) ltc_mp.count_bits(a)
+#define mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a)
+#define mp_2expt(a, b) ltc_mp.twoexpt(a, b)
+
+#define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c)
+#define mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c)
+#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a)
+#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b)
+#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
+
+#define mp_add(a, b, c) ltc_mp.add(a, b, c)
+#define mp_add_d(a, b, c) ltc_mp.addi(a, b, c)
+#define mp_sub(a, b, c) ltc_mp.sub(a, b, c)
+#define mp_sub_d(a, b, c) ltc_mp.subi(a, b, c)
+#define mp_mul(a, b, c) ltc_mp.mul(a, b, c)
+#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c)
+#define mp_sqr(a, b) ltc_mp.sqr(a, b)
+#define mp_sqrtmod_prime(a, b, c) ltc_mp.sqrtmod_prime(a, b, c)
+#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d)
+#define mp_div_2(a, b) ltc_mp.div_2(a, b)
+#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c)
+#define mp_mod_d(a, b, c) ltc_mp.modi(a, b, c)
+#define mp_gcd(a, b, c) ltc_mp.gcd(a, b, c)
+#define mp_lcm(a, b, c) ltc_mp.lcm(a, b, c)
+
+#define mp_addmod(a, b, c, d) ltc_mp.addmod(a, b, c, d)
+#define mp_submod(a, b, c, d) ltc_mp.submod(a, b, c, d)
+#define mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d)
+#define mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c)
+#define mp_invmod(a, b, c) ltc_mp.invmod(a, b, c)
+
+#define mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b)
+#define mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b)
+#define mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c)
+#define mp_montgomery_free(a) ltc_mp.montgomery_deinit(a)
+
+#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d)
+#define mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, b, c)
+
+#define mp_iszero(a) (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO)
+#define mp_isodd(a) (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO)
+#define mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0)
+
+#define mp_tohex(a, b) mp_toradix(a, b, 16)
+
+#define mp_rand(a, b) ltc_mp.rand(a, b)
+
+#endif
+
+
+/* tomcrypt_misc.h */
+
+typedef enum {
+ /** Use `\r\n` as line separator */
+ BASE64_PEM_CRLF = 1,
+ /** Create output with 72 chars line length */
+ BASE64_PEM_SSH = 2,
+} base64_pem_flags;
+
+int base64_encode_pem(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen,
+ unsigned int flags);
+
+/* PEM related */
+
+#ifdef LTC_PEM
+enum cipher_mode {
+ cm_modes = 0x00ff,
+ cm_flags = 0xff00,
+ /* Flags */
+ cm_openssh = 0x0100,
+ cm_1bit = 0x0200,
+ cm_8bit = 0x0400,
+ /* Modes */
+ cm_none = 0x0000,
+ cm_cbc = 0x0001,
+ cm_cfb = 0x0002,
+ cm_ctr = 0x0003,
+ cm_ofb = 0x0004,
+ cm_stream = 0x0005,
+ cm_gcm = 0x0006,
+ cm_cfb1 = cm_cfb | cm_1bit,
+ cm_cfb8 = cm_cfb | cm_8bit,
+ cm_stream_openssh = cm_stream | cm_openssh,
+};
+
+struct blockcipher_info {
+ const char *name;
+ const char *algo;
+ unsigned long keylen;
+ enum cipher_mode mode;
+ /* should use `MAXBLOCKSIZE` here, but all supported
+ * blockciphers require max 16 bytes IV */
+ char iv[16 * 2 + 1];
+};
+
+struct str {
+ char *p;
+ unsigned long len;
+};
+
+#define SET_STR(n, s) n.p = s, n.len = XSTRLEN(s)
+#define SET_CSTR(n, s) n.p = (char*)s, n.len = (sizeof s) - 1
+#define COPY_STR(n, s, l) do { XMEMCPY(n.p, s, l); n.len = l; } while(0)
+#define RESET_STR(n) do { n.p = NULL; n.len = 0; } while(0)
+
+enum more_headers {
+ no,
+ yes,
+ maybe
+};
+
+enum pem_flags {
+ pf_encrypted = 0x01u,
+ pf_pkcs8 = 0x02u,
+ pf_public = 0x04u,
+ pf_x509 = 0x08u,
+ pf_encrypted_pkcs8 = pf_encrypted | pf_pkcs8,
+};
+
+struct pem_header_id {
+ struct str start, end;
+ enum more_headers has_more_headers;
+ enum pem_flags flags;
+ enum ltc_pka_id pka;
+ int (*decrypt)(void *, unsigned long *, void *);
+};
+
+struct pem_headers {
+ const struct pem_header_id *id;
+ int encrypted;
+ struct blockcipher_info info;
+ struct password *pw;
+};
+
+struct bufp {
+ /* `end` points to one byte after the last
+ * element of the allocated buffer
+ */
+ char *start, *work, *end;
+};
+
+#define SET_BUFP(n, d, l) n.start = (char*)d, n.work = (char*)d, n.end = (char*)d + l + 1
+
+struct get_char {
+ int (*get)(struct get_char*);
+ union {
+#ifndef LTC_NO_FILE
+ FILE *f;
+#endif /* LTC_NO_FILE */
+ struct bufp buf;
+ } data;
+ struct str unget_buf;
+ char unget_buf_[LTC_PEM_DECODE_BUFSZ];
+};
+#endif
+
+/* others */
+
+void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz);
+void password_free(struct password *pw, const struct password_ctx *ctx);
+
+int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size);
+
+int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res);
+int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res);
+
+int pem_decrypt(unsigned char *data, unsigned long *datalen,
+ unsigned char *key, unsigned long keylen,
+ unsigned char *iv, unsigned long ivlen,
+ unsigned char *tag, unsigned long taglen,
+ const struct blockcipher_info *info,
+ enum padding_type padding);
+#ifndef LTC_NO_FILE
+int pem_get_char_from_file(struct get_char *g);
+#endif /* LTC_NO_FILE */
+int pem_get_char_from_buf(struct get_char *g);
+int pem_read(void *pem, unsigned long *w, struct pem_headers *hdr, struct get_char *g);
+
+/* tomcrypt_pk.h */
+
+int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng);
+int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng);
+
+int pk_get_oid(enum ltc_oid_id id, const char **st);
+int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka);
+int pk_get_oid_id(enum ltc_pka_id pka, enum ltc_oid_id *oid);
+int pk_get_oid_from_asn1(const ltc_asn1_list *oid, enum ltc_oid_id *id);
+int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen);
+int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen);
+
+/* ---- DH Routines ---- */
+#ifdef LTC_MRSA
+int rsa_init(rsa_key *key);
+void rsa_shrink_key(rsa_key *key);
+int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e,
+ rsa_key *key); /* used by op-tee */
+int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key);
+int rsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, rsa_key *key);
+#endif /* LTC_MRSA */
+
+/* ---- DH Routines ---- */
+#ifdef LTC_MDH
+extern const ltc_dh_set_type ltc_dh_sets[];
+
+int dh_init(dh_key *key);
+int dh_check_pubkey(const dh_key *key);
+int dh_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dh_key *key);
+#endif /* LTC_MDH */
+
+/* ---- ECC Routines ---- */
+#ifdef LTC_MECC
+int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key);
+int ecc_copy_curve(const ecc_key *srckey, ecc_key *key);
+int ecc_set_curve_by_size(int size, ecc_key *key);
+int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key);
+int ecc_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, ecc_key *key);
+int ecc_import_with_curve(const unsigned char *in, unsigned long inlen, int type, ecc_key *key);
+int ecc_import_with_oid(const unsigned char *in, unsigned long inlen, unsigned long *oid, unsigned long oid_len, int type, ecc_key *key);
+
+#ifdef LTC_SSH
+int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key);
+#endif
+
+/* low level functions */
+ecc_point *ltc_ecc_new_point(void);
+void ltc_ecc_del_point(ecc_point *p);
+int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p);
+int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst);
+int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y);
+int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval);
+int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y);
+int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed);
+int ltc_ecc_verify_key(const ecc_key *key);
+
+/* point ops (mp == montgomery digit) */
+#if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC)
+/* R = 2P */
+int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp);
+
+/* R = P + Q */
+int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp);
+#endif
+
+#if defined(LTC_MECC_FP)
+/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */
+int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map);
+
+/* functions for saving/loading/freeing/adding to fixed point cache */
+int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen);
+int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen);
+void ltc_ecc_fp_free(void);
+int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock);
+
+/* lock/unlock all points currently in fixed point cache */
+void ltc_ecc_fp_tablelock(int lock);
+#endif
+
+/* R = kG */
+int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map);
+
+#ifdef LTC_ECC_SHAMIR
+/* kA*A + kB*B = C */
+int ltc_ecc_mul2add(const ecc_point *A, void *kA,
+ const ecc_point *B, void *kB,
+ ecc_point *C,
+ void *ma,
+ void *modulus);
+
+#ifdef LTC_MECC_FP
+/* Shamir's trick with optimized point multiplication using fixed point cache */
+int ltc_ecc_fp_mul2add(const ecc_point *A, void *kA,
+ const ecc_point *B, void *kB,
+ ecc_point *C,
+ void *ma,
+ void *modulus);
+#endif
+
+#endif
+
+
+/* map P to affine from projective */
+int ltc_ecc_map(ecc_point *P, void *modulus, void *mp);
+#endif /* LTC_MECC */
+
+#ifdef LTC_MDSA
+int dsa_int_init(dsa_key *key);
+int dsa_int_validate(const dsa_key *key, int *stat);
+int dsa_int_validate_xy(const dsa_key *key, int *stat);
+int dsa_int_validate_pqg(const dsa_key *key, int *stat);
+int dsa_int_validate_primes(const dsa_key *key, int *stat);
+int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key);
+int dsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dsa_key *key);
+#endif /* LTC_MDSA */
+
+
+#ifdef LTC_CURVE25519
+
+int tweetnacl_crypto_sign(
+ unsigned char *sm,unsigned long long *smlen,
+ const unsigned char *m,unsigned long long mlen,
+ const unsigned char *sk,const unsigned char *pk,
+ const unsigned char *ctx,unsigned long long cs);
+int tweetnacl_crypto_sign_open(
+ int *stat,
+ unsigned char *m,unsigned long long *mlen,
+ const unsigned char *sm,unsigned long long smlen,
+ const unsigned char *ctx, unsigned long long cs,
+ const unsigned char *pk);
+int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, unsigned char *pk,unsigned char *sk);
+int tweetnacl_crypto_sk_to_pk(unsigned char *pk, const unsigned char *sk);
+int tweetnacl_crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p);
+int tweetnacl_crypto_scalarmult_base(unsigned char *q,const unsigned char *n);
+int tweetnacl_crypto_ph(unsigned char *out, const unsigned char *msg, unsigned long long msglen);
+
+int ed25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
+ curve25519_key *key);
+int x25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
+ curve25519_key *key);
+
+int ec25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
+ enum ltc_oid_id id,
+ curve25519_key *key);
+int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ enum ltc_oid_id id,
+ curve25519_key *key);
+int ec25519_export( unsigned char *out, unsigned long *outlen,
+ int which,
+ const curve25519_key *key);
+int ec25519_crypto_ctx( unsigned char *out, unsigned long *outlen,
+ unsigned char flag,
+ const unsigned char *ctx, unsigned long ctxlen);
+#endif /* LTC_CURVE25519 */
+
+#ifdef LTC_DER
+
+#define LTC_ASN1_IS_TYPE(e, t) (((e) != NULL) && ((e)->type == (t)))
+
+/* DER handling */
+int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root,
+ ltc_asn1_list *list, unsigned long outlen, unsigned int flags);
+
+int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen);
+int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id);
+int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen);
+
+int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen);
+int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen);
+int der_length_asn1_length(unsigned long len, unsigned long *outlen);
+
+int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen, unsigned long *payloadlen);
+
+typedef struct {
+ ltc_asn1_type t;
+ ltc_asn1_list **pp;
+} der_flexi_check;
+
+#define LTC_SET_DER_FLEXI_CHECK(list, index, Type, P) \
+ do { \
+ int LTC_SDFC_temp##__LINE__ = (index); \
+ list[LTC_SDFC_temp##__LINE__].t = Type; \
+ list[LTC_SDFC_temp##__LINE__].pp = P; \
+ } while (0)
+
+
+extern const ltc_asn1_type der_asn1_tag_to_type_map[];
+extern const unsigned long der_asn1_tag_to_type_map_sz;
+
+extern const int der_asn1_type_to_identifier_map[];
+extern const unsigned long der_asn1_type_to_identifier_map_sz;
+
+int der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check);
+
+int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...)
+ LTC_NULL_TERMINATED;
+
+int der_teletex_char_encode(int c);
+int der_teletex_value_decode(int v);
+
+int der_utf8_valid_char(const wchar_t c);
+
+typedef int (*public_key_decode_cb)(const unsigned char *in, unsigned long inlen, void *ctx);
+
+int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen,
+ enum ltc_oid_id algorithm, ltc_asn1_type param_type,
+ ltc_asn1_list* parameters, unsigned long *parameters_len,
+ public_key_decode_cb callback, void *ctx);
+int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki);
+
+/* SUBJECT PUBLIC KEY INFO */
+int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
+ enum ltc_oid_id algorithm, const void* public_key, unsigned long public_key_len,
+ ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len);
+
+int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
+ enum ltc_oid_id algorithm, void *public_key, unsigned long *public_key_len,
+ ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len);
+
+int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size);
+int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2);
+
+#endif /* LTC_DER */
+
+/* tomcrypt_pkcs.h */
+
+#ifdef LTC_PKCS_8
+
+/* Public-Key Cryptography Standards (PKCS) #8:
+ * Private-Key Information Syntax Specification Version 1.2
+ * https://tools.ietf.org/html/rfc5208
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes [0] IMPLICIT Attributes OPTIONAL }
+ * where:
+ * - Version ::= INTEGER
+ * - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ * - PrivateKey ::= OCTET STRING
+ * - Attributes ::= SET OF Attribute
+ *
+ * EncryptedPrivateKeyInfo ::= SEQUENCE {
+ * encryptionAlgorithm EncryptionAlgorithmIdentifier,
+ * encryptedData EncryptedData }
+ * where:
+ * - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ * - EncryptedData ::= OCTET STRING
+ */
+
+int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ ltc_asn1_list **decoded_list);
+
+int pkcs8_get_children(const ltc_asn1_list *decoded_list, enum ltc_oid_id *pka,
+ ltc_asn1_list **alg_id, ltc_asn1_list **priv_key);
+
+#endif /* LTC_PKCS_8 */
+
+
+#ifdef LTC_PKCS_12
+
+int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+int pkcs12_kdf( int hash_id,
+ const unsigned char *pw, unsigned long pwlen,
+ const unsigned char *salt, unsigned long saltlen,
+ unsigned int iterations, unsigned char purpose,
+ unsigned char *out, unsigned long outlen);
+
+#endif /* LTC_PKCS_12 */
+
+/* tomcrypt_prng.h */
+
+#define LTC_PRNG_EXPORT(which) \
+int which ## _export(unsigned char *out, unsigned long *outlen, prng_state *prng) \
+{ \
+ unsigned long len = which ## _desc.export_size; \
+ \
+ LTC_ARGCHK(prng != NULL); \
+ LTC_ARGCHK(out != NULL); \
+ LTC_ARGCHK(outlen != NULL); \
+ \
+ if (*outlen < len) { \
+ *outlen = len; \
+ return CRYPT_BUFFER_OVERFLOW; \
+ } \
+ \
+ if (which ## _read(out, len, prng) != len) { \
+ return CRYPT_ERROR_READPRNG; \
+ } \
+ \
+ *outlen = len; \
+ return CRYPT_OK; \
+}
+
+/* extract a byte portably */
+#ifdef _MSC_VER
+ #define LTC_BYTE(x, n) ((unsigned char)((x) >> (8 * (n))))
+#else
+ #define LTC_BYTE(x, n) (((x) >> (8 * (n))) & 255)
+#endif
+
+/*
+ * On Windows, choose whether to use CryptGenRandom() [older Windows versions]
+ * or BCryptGenRandom() [newer Windows versions].
+ * If CryptGenRandom() is desired, define LTC_NO_WIN32_BCRYPT when building.
+ */
+#if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
+ #if !defined(LTC_NO_WIN32_BCRYPT)
+ #define LTC_WIN32_BCRYPT
+ #endif
+#endif
+
+#endif /* TOMCRYPT_PRIVATE_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/include/tomcrypt_prng.h b/Sources/libtomcrypt/include/tomcrypt_prng.h
new file mode 100644
index 00000000..156ce209
--- /dev/null
+++ b/Sources/libtomcrypt/include/tomcrypt_prng.h
@@ -0,0 +1,227 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#ifndef TOMCRYPT_PRNG_H_
+#define TOMCRYPT_PRNG_H_
+
+/* ---- PRNG Stuff ---- */
+#ifdef LTC_YARROW
+struct yarrow_prng {
+ int cipher, hash;
+ unsigned char pool[MAXBLOCKSIZE];
+ symmetric_CTR ctr;
+};
+#endif
+
+#ifdef LTC_RC4
+struct rc4_prng {
+ rc4_state s;
+};
+#endif
+
+#ifdef LTC_CHACHA20_PRNG
+struct chacha20_prng {
+ chacha_state s; /* chacha state */
+ unsigned char ent[40]; /* entropy buffer */
+ unsigned long idx; /* entropy counter */
+};
+#endif
+
+#ifdef LTC_FORTUNA
+struct fortuna_prng {
+ hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */
+
+ symmetric_key skey;
+
+ unsigned char K[32], /* the current key */
+ IV[16]; /* IV for CTR mode */
+
+ unsigned long pool_idx, /* current pool we will add to */
+ pool0_len; /* length of 0'th pool */
+ ulong64 wd;
+ ulong64 reset_cnt; /* number of times we have reseeded */
+};
+#endif
+
+#ifdef LTC_SOBER128
+struct sober128_prng {
+ sober128_state s; /* sober128 state */
+ unsigned char ent[40]; /* entropy buffer */
+ unsigned long idx; /* entropy counter */
+};
+#endif
+
+typedef struct {
+ union {
+ char dummy[1];
+#ifdef LTC_YARROW
+ struct yarrow_prng yarrow;
+#endif
+#ifdef LTC_RC4
+ struct rc4_prng rc4;
+#endif
+#ifdef LTC_CHACHA20_PRNG
+ struct chacha20_prng chacha;
+#endif
+#ifdef LTC_FORTUNA
+ struct fortuna_prng fortuna;
+#endif
+#ifdef LTC_SOBER128
+ struct sober128_prng sober128;
+#endif
+ } u;
+ short ready; /* ready flag 0-1 */
+ LTC_MUTEX_TYPE(lock) /* lock */
+} prng_state;
+
+/** PRNG descriptor */
+extern struct ltc_prng_descriptor {
+ /** Name of the PRNG */
+ const char *name;
+ /** size in bytes of exported state */
+ int export_size;
+ /** Start a PRNG state
+ @param prng [out] The state to initialize
+ @return CRYPT_OK if successful
+ */
+ int (*start)(prng_state *prng);
+ /** Add entropy to the PRNG
+ @param in The entropy
+ @param inlen Length of the entropy (octets)\
+ @param prng The PRNG state
+ @return CRYPT_OK if successful
+ */
+ int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ /** Ready a PRNG state to read from
+ @param prng The PRNG state to ready
+ @return CRYPT_OK if successful
+ */
+ int (*ready)(prng_state *prng);
+ /** Read from the PRNG
+ @param out [out] Where to store the data
+ @param outlen Length of data desired (octets)
+ @param prng The PRNG state to read from
+ @return Number of octets read
+ */
+ unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng);
+ /** Terminate a PRNG state
+ @param prng The PRNG state to terminate
+ @return CRYPT_OK if successful
+ */
+ int (*done)(prng_state *prng);
+ /** Export a PRNG state
+ @param out [out] The destination for the state
+ @param outlen [in/out] The max size and resulting size of the PRNG state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+ */
+ int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng);
+ /** Import a PRNG state
+ @param in The data to import
+ @param inlen The length of the data to import (octets)
+ @param prng The PRNG to initialize/import
+ @return CRYPT_OK if successful
+ */
+ int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ /** Self-test the PRNG
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+ */
+ int (*test)(void);
+} prng_descriptor[];
+
+#ifdef LTC_YARROW
+int yarrow_start(prng_state *prng);
+int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int yarrow_ready(prng_state *prng);
+unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int yarrow_done(prng_state *prng);
+int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int yarrow_test(void);
+extern const struct ltc_prng_descriptor yarrow_desc;
+#endif
+
+#ifdef LTC_FORTUNA
+int fortuna_start(prng_state *prng);
+int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng);
+int fortuna_ready(prng_state *prng);
+unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int fortuna_done(prng_state *prng);
+int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int fortuna_test(void);
+extern const struct ltc_prng_descriptor fortuna_desc;
+#endif
+
+#ifdef LTC_RC4
+int rc4_start(prng_state *prng);
+int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int rc4_ready(prng_state *prng);
+unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int rc4_done(prng_state *prng);
+int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int rc4_test(void);
+extern const struct ltc_prng_descriptor rc4_desc;
+#endif
+
+#ifdef LTC_CHACHA20_PRNG
+int chacha20_prng_start(prng_state *prng);
+int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int chacha20_prng_ready(prng_state *prng);
+unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int chacha20_prng_done(prng_state *prng);
+int chacha20_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int chacha20_prng_test(void);
+extern const struct ltc_prng_descriptor chacha20_prng_desc;
+#endif
+
+#ifdef LTC_SPRNG
+int sprng_start(prng_state *prng);
+int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int sprng_ready(prng_state *prng);
+unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int sprng_done(prng_state *prng);
+int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int sprng_test(void);
+extern const struct ltc_prng_descriptor sprng_desc;
+#endif
+
+#ifdef LTC_SOBER128
+int sober128_start(prng_state *prng);
+int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int sober128_ready(prng_state *prng);
+unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int sober128_done(prng_state *prng);
+int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int sober128_test(void);
+extern const struct ltc_prng_descriptor sober128_desc;
+#endif
+
+int find_prng(const char *name);
+int register_prng(const struct ltc_prng_descriptor *prng);
+int unregister_prng(const struct ltc_prng_descriptor *prng);
+int register_all_prngs(void);
+int prng_is_valid(int idx);
+LTC_MUTEX_PROTO(ltc_prng_mutex)
+
+/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this
+ * might not work on all platforms as planned
+ */
+unsigned long rng_get_bytes(unsigned char *out,
+ unsigned long outlen,
+ void (*callback)(void));
+
+int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));
+
+#ifdef LTC_PRNG_ENABLE_LTC_RNG
+extern unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen,
+ void (*callback)(void));
+#endif
+
+#endif /* TOMCRYPT_PRNG_H_ */
\ No newline at end of file
diff --git a/Sources/libtomcrypt/mac/blake2/blake2bmac.c b/Sources/libtomcrypt/mac/blake2/blake2bmac.c
new file mode 100644
index 00000000..ac26e106
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2bmac.c
@@ -0,0 +1,56 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2BMAC
+
+/**
+ Initialize an BLAKE2B MAC context.
+ @param st The BLAKE2B MAC state
+ @param outlen The size of the MAC output (octets)
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @return CRYPT_OK if successful
+*/
+int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen)
+{
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ return blake2b_init(st, outlen, key, keylen);
+}
+
+/**
+ Process data through BLAKE2B MAC
+ @param st The BLAKE2B MAC state
+ @param in The data to send through HMAC
+ @param inlen The length of the data to HMAC (octets)
+ @return CRYPT_OK if successful
+*/
+int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen)
+{
+ if (inlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ return blake2b_process(st, in, inlen);
+}
+
+/**
+ Terminate a BLAKE2B MAC session
+ @param st The BLAKE2B MAC state
+ @param mac [out] The destination of the BLAKE2B MAC authentication tag
+ @param maclen [in/out] The max size and resulting size of the BLAKE2B MAC authentication tag
+ @return CRYPT_OK if successful
+*/
+int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen)
+{
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+ LTC_ARGCHK(*maclen >= st->blake2b.outlen);
+
+ *maclen = st->blake2b.outlen;
+ return blake2b_done(st, mac);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/blake2/blake2bmac_file.c b/Sources/libtomcrypt/mac/blake2/blake2bmac_file.c
new file mode 100644
index 00000000..831e845d
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2bmac_file.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2BMAC
+
+/**
+ BLAKE2B MAC a file
+ @param fname The name of the file you wish to BLAKE2B MAC
+ @param key The secret key
+ @param keylen The length of the secret key
+ @param mac [out] The BLAKE2B MAC authentication tag
+ @param maclen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen)
+{
+#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(mac);
+ LTC_UNUSED_PARAM(maclen);
+ return CRYPT_NOP;
+#else
+ blake2bmac_state st;
+ FILE *in;
+ unsigned char *buf;
+ size_t x;
+ int err;
+
+ LTC_ARGCHK(fname != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+
+ if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ in = fopen(fname, "rb");
+ if (in == NULL) {
+ err = CRYPT_FILE_NOTFOUND;
+ goto LBL_ERR;
+ }
+
+ do {
+ x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+ if ((err = blake2bmac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) {
+ fclose(in);
+ goto LBL_CLEANBUF;
+ }
+ } while (x == LTC_FILE_READ_BUFSIZE);
+
+ if (fclose(in) != 0) {
+ err = CRYPT_ERROR;
+ goto LBL_CLEANBUF;
+ }
+
+ err = blake2bmac_done(&st, mac, maclen);
+
+LBL_CLEANBUF:
+ zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(blake2bmac_state));
+#endif
+ XFREE(buf);
+ return err;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/blake2/blake2bmac_memory.c b/Sources/libtomcrypt/mac/blake2/blake2bmac_memory.c
new file mode 100644
index 00000000..3f5e309a
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2bmac_memory.c
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2BMAC
+
+/**
+ BLAKE2B MAC a block of memory to produce the authentication tag
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param in The data to BLAKE2B MAC
+ @param inlen The length of the data to BLAKE2B MAC (octets)
+ @param mac [out] Destination of the authentication tag
+ @param maclen [in/out] Max size and resulting size of authentication tag
+ @return CRYPT_OK if successful
+*/
+int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen)
+{
+ blake2bmac_state st;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+
+ if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = blake2bmac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
+ err = blake2bmac_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(blake2bmac_state));
+#endif
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/blake2/blake2bmac_memory_multi.c b/Sources/libtomcrypt/mac/blake2/blake2bmac_memory_multi.c
new file mode 100644
index 00000000..403fba35
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2bmac_memory_multi.c
@@ -0,0 +1,52 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+#include
+
+#ifdef LTC_BLAKE2BMAC
+
+/**
+ BLAKE2B MAC multiple blocks of memory to produce the authentication tag
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param mac [out] Destination of the authentication tag
+ @param maclen [in/out] Max size and resulting size of authentication tag
+ @param in The data to BLAKE2B MAC
+ @param inlen The length of the data to BLAKE2B MAC (octets)
+ @param ... tuples of (data,len) pairs to BLAKE2B MAC, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...)
+{
+ blake2bmac_state st;
+ int err;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; }
+ for (;;) {
+ if ((err = blake2bmac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; }
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) break;
+ curlen = va_arg(args, unsigned long);
+ }
+ err = blake2bmac_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(blake2bmac_state));
+#endif
+ va_end(args);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/blake2/blake2bmac_test.c b/Sources/libtomcrypt/mac/blake2/blake2bmac_test.c
new file mode 100644
index 00000000..b2651cc7
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2bmac_test.c
@@ -0,0 +1,304 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2BMAC
+
+int blake2bmac_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const unsigned char tests[256][64] = {
+ /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt */
+ { 0x10, 0xeb, 0xb6, 0x77, 0x00, 0xb1, 0x86, 0x8e, 0xfb, 0x44, 0x17, 0x98, 0x7a, 0xcf, 0x46, 0x90, 0xae, 0x9d, 0x97, 0x2f, 0xb7, 0xa5, 0x90, 0xc2, 0xf0, 0x28, 0x71, 0x79, 0x9a, 0xaa, 0x47, 0x86, 0xb5, 0xe9, 0x96, 0xe8, 0xf0, 0xf4, 0xeb, 0x98, 0x1f, 0xc2, 0x14, 0xb0, 0x05, 0xf4, 0x2d, 0x2f, 0xf4, 0x23, 0x34, 0x99, 0x39, 0x16, 0x53, 0xdf, 0x7a, 0xef, 0xcb, 0xc1, 0x3f, 0xc5, 0x15, 0x68 },
+ { 0x96, 0x1f, 0x6d, 0xd1, 0xe4, 0xdd, 0x30, 0xf6, 0x39, 0x01, 0x69, 0x0c, 0x51, 0x2e, 0x78, 0xe4, 0xb4, 0x5e, 0x47, 0x42, 0xed, 0x19, 0x7c, 0x3c, 0x5e, 0x45, 0xc5, 0x49, 0xfd, 0x25, 0xf2, 0xe4, 0x18, 0x7b, 0x0b, 0xc9, 0xfe, 0x30, 0x49, 0x2b, 0x16, 0xb0, 0xd0, 0xbc, 0x4e, 0xf9, 0xb0, 0xf3, 0x4c, 0x70, 0x03, 0xfa, 0xc0, 0x9a, 0x5e, 0xf1, 0x53, 0x2e, 0x69, 0x43, 0x02, 0x34, 0xce, 0xbd },
+ { 0xda, 0x2c, 0xfb, 0xe2, 0xd8, 0x40, 0x9a, 0x0f, 0x38, 0x02, 0x61, 0x13, 0x88, 0x4f, 0x84, 0xb5, 0x01, 0x56, 0x37, 0x1a, 0xe3, 0x04, 0xc4, 0x43, 0x01, 0x73, 0xd0, 0x8a, 0x99, 0xd9, 0xfb, 0x1b, 0x98, 0x31, 0x64, 0xa3, 0x77, 0x07, 0x06, 0xd5, 0x37, 0xf4, 0x9e, 0x0c, 0x91, 0x6d, 0x9f, 0x32, 0xb9, 0x5c, 0xc3, 0x7a, 0x95, 0xb9, 0x9d, 0x85, 0x74, 0x36, 0xf0, 0x23, 0x2c, 0x88, 0xa9, 0x65 },
+ { 0x33, 0xd0, 0x82, 0x5d, 0xdd, 0xf7, 0xad, 0xa9, 0x9b, 0x0e, 0x7e, 0x30, 0x71, 0x04, 0xad, 0x07, 0xca, 0x9c, 0xfd, 0x96, 0x92, 0x21, 0x4f, 0x15, 0x61, 0x35, 0x63, 0x15, 0xe7, 0x84, 0xf3, 0xe5, 0xa1, 0x7e, 0x36, 0x4a, 0xe9, 0xdb, 0xb1, 0x4c, 0xb2, 0x03, 0x6d, 0xf9, 0x32, 0xb7, 0x7f, 0x4b, 0x29, 0x27, 0x61, 0x36, 0x5f, 0xb3, 0x28, 0xde, 0x7a, 0xfd, 0xc6, 0xd8, 0x99, 0x8f, 0x5f, 0xc1 },
+ { 0xbe, 0xaa, 0x5a, 0x3d, 0x08, 0xf3, 0x80, 0x71, 0x43, 0xcf, 0x62, 0x1d, 0x95, 0xcd, 0x69, 0x05, 0x14, 0xd0, 0xb4, 0x9e, 0xff, 0xf9, 0xc9, 0x1d, 0x24, 0xb5, 0x92, 0x41, 0xec, 0x0e, 0xef, 0xa5, 0xf6, 0x01, 0x96, 0xd4, 0x07, 0x04, 0x8b, 0xba, 0x8d, 0x21, 0x46, 0x82, 0x8e, 0xbc, 0xb0, 0x48, 0x8d, 0x88, 0x42, 0xfd, 0x56, 0xbb, 0x4f, 0x6d, 0xf8, 0xe1, 0x9c, 0x4b, 0x4d, 0xaa, 0xb8, 0xac },
+ { 0x09, 0x80, 0x84, 0xb5, 0x1f, 0xd1, 0x3d, 0xea, 0xe5, 0xf4, 0x32, 0x0d, 0xe9, 0x4a, 0x68, 0x8e, 0xe0, 0x7b, 0xae, 0xa2, 0x80, 0x04, 0x86, 0x68, 0x9a, 0x86, 0x36, 0x11, 0x7b, 0x46, 0xc1, 0xf4, 0xc1, 0xf6, 0xaf, 0x7f, 0x74, 0xae, 0x7c, 0x85, 0x76, 0x00, 0x45, 0x6a, 0x58, 0xa3, 0xaf, 0x25, 0x1d, 0xc4, 0x72, 0x3a, 0x64, 0xcc, 0x7c, 0x0a, 0x5a, 0xb6, 0xd9, 0xca, 0xc9, 0x1c, 0x20, 0xbb },
+ { 0x60, 0x44, 0x54, 0x0d, 0x56, 0x08, 0x53, 0xeb, 0x1c, 0x57, 0xdf, 0x00, 0x77, 0xdd, 0x38, 0x10, 0x94, 0x78, 0x1c, 0xdb, 0x90, 0x73, 0xe5, 0xb1, 0xb3, 0xd3, 0xf6, 0xc7, 0x82, 0x9e, 0x12, 0x06, 0x6b, 0xba, 0xca, 0x96, 0xd9, 0x89, 0xa6, 0x90, 0xde, 0x72, 0xca, 0x31, 0x33, 0xa8, 0x36, 0x52, 0xba, 0x28, 0x4a, 0x6d, 0x62, 0x94, 0x2b, 0x27, 0x1f, 0xfa, 0x26, 0x20, 0xc9, 0xe7, 0x5b, 0x1f },
+ { 0x7a, 0x8c, 0xfe, 0x9b, 0x90, 0xf7, 0x5f, 0x7e, 0xcb, 0x3a, 0xcc, 0x05, 0x3a, 0xae, 0xd6, 0x19, 0x31, 0x12, 0xb6, 0xf6, 0xa4, 0xae, 0xeb, 0x3f, 0x65, 0xd3, 0xde, 0x54, 0x19, 0x42, 0xde, 0xb9, 0xe2, 0x22, 0x81, 0x52, 0xa3, 0xc4, 0xbb, 0xbe, 0x72, 0xfc, 0x3b, 0x12, 0x62, 0x95, 0x28, 0xcf, 0xbb, 0x09, 0xfe, 0x63, 0x0f, 0x04, 0x74, 0x33, 0x9f, 0x54, 0xab, 0xf4, 0x53, 0xe2, 0xed, 0x52 },
+ { 0x38, 0x0b, 0xea, 0xf6, 0xea, 0x7c, 0xc9, 0x36, 0x5e, 0x27, 0x0e, 0xf0, 0xe6, 0xf3, 0xa6, 0x4f, 0xb9, 0x02, 0xac, 0xae, 0x51, 0xdd, 0x55, 0x12, 0xf8, 0x42, 0x59, 0xad, 0x2c, 0x91, 0xf4, 0xbc, 0x41, 0x08, 0xdb, 0x73, 0x19, 0x2a, 0x5b, 0xbf, 0xb0, 0xcb, 0xcf, 0x71, 0xe4, 0x6c, 0x3e, 0x21, 0xae, 0xe1, 0xc5, 0xe8, 0x60, 0xdc, 0x96, 0xe8, 0xeb, 0x0b, 0x7b, 0x84, 0x26, 0xe6, 0xab, 0xe9 },
+ { 0x60, 0xfe, 0x3c, 0x45, 0x35, 0xe1, 0xb5, 0x9d, 0x9a, 0x61, 0xea, 0x85, 0x00, 0xbf, 0xac, 0x41, 0xa6, 0x9d, 0xff, 0xb1, 0xce, 0xad, 0xd9, 0xac, 0xa3, 0x23, 0xe9, 0xa6, 0x25, 0xb6, 0x4d, 0xa5, 0x76, 0x3b, 0xad, 0x72, 0x26, 0xda, 0x02, 0xb9, 0xc8, 0xc4, 0xf1, 0xa5, 0xde, 0x14, 0x0a, 0xc5, 0xa6, 0xc1, 0x12, 0x4e, 0x4f, 0x71, 0x8c, 0xe0, 0xb2, 0x8e, 0xa4, 0x73, 0x93, 0xaa, 0x66, 0x37 },
+ { 0x4f, 0xe1, 0x81, 0xf5, 0x4a, 0xd6, 0x3a, 0x29, 0x83, 0xfe, 0xaa, 0xf7, 0x7d, 0x1e, 0x72, 0x35, 0xc2, 0xbe, 0xb1, 0x7f, 0xa3, 0x28, 0xb6, 0xd9, 0x50, 0x5b, 0xda, 0x32, 0x7d, 0xf1, 0x9f, 0xc3, 0x7f, 0x02, 0xc4, 0xb6, 0xf0, 0x36, 0x8c, 0xe2, 0x31, 0x47, 0x31, 0x3a, 0x8e, 0x57, 0x38, 0xb5, 0xfa, 0x2a, 0x95, 0xb2, 0x9d, 0xe1, 0xc7, 0xf8, 0x26, 0x4e, 0xb7, 0x7b, 0x69, 0xf5, 0x85, 0xcd },
+ { 0xf2, 0x28, 0x77, 0x3c, 0xe3, 0xf3, 0xa4, 0x2b, 0x5f, 0x14, 0x4d, 0x63, 0x23, 0x7a, 0x72, 0xd9, 0x96, 0x93, 0xad, 0xb8, 0x83, 0x7d, 0x0e, 0x11, 0x2a, 0x8a, 0x0f, 0x8f, 0xff, 0xf2, 0xc3, 0x62, 0x85, 0x7a, 0xc4, 0x9c, 0x11, 0xec, 0x74, 0x0d, 0x15, 0x00, 0x74, 0x9d, 0xac, 0x9b, 0x1f, 0x45, 0x48, 0x10, 0x8b, 0xf3, 0x15, 0x57, 0x94, 0xdc, 0xc9, 0xe4, 0x08, 0x28, 0x49, 0xe2, 0xb8, 0x5b },
+ { 0x96, 0x24, 0x52, 0xa8, 0x45, 0x5c, 0xc5, 0x6c, 0x85, 0x11, 0x31, 0x7e, 0x3b, 0x1f, 0x3b, 0x2c, 0x37, 0xdf, 0x75, 0xf5, 0x88, 0xe9, 0x43, 0x25, 0xfd, 0xd7, 0x70, 0x70, 0x35, 0x9c, 0xf6, 0x3a, 0x9a, 0xe6, 0xe9, 0x30, 0x93, 0x6f, 0xdf, 0x8e, 0x1e, 0x08, 0xff, 0xca, 0x44, 0x0c, 0xfb, 0x72, 0xc2, 0x8f, 0x06, 0xd8, 0x9a, 0x21, 0x51, 0xd1, 0xc4, 0x6c, 0xd5, 0xb2, 0x68, 0xef, 0x85, 0x63 },
+ { 0x43, 0xd4, 0x4b, 0xfa, 0x18, 0x76, 0x8c, 0x59, 0x89, 0x6b, 0xf7, 0xed, 0x17, 0x65, 0xcb, 0x2d, 0x14, 0xaf, 0x8c, 0x26, 0x02, 0x66, 0x03, 0x90, 0x99, 0xb2, 0x5a, 0x60, 0x3e, 0x4d, 0xdc, 0x50, 0x39, 0xd6, 0xef, 0x3a, 0x91, 0x84, 0x7d, 0x10, 0x88, 0xd4, 0x01, 0xc0, 0xc7, 0xe8, 0x47, 0x78, 0x1a, 0x8a, 0x59, 0x0d, 0x33, 0xa3, 0xc6, 0xcb, 0x4d, 0xf0, 0xfa, 0xb1, 0xc2, 0xf2, 0x23, 0x55 },
+ { 0xdc, 0xff, 0xa9, 0xd5, 0x8c, 0x2a, 0x4c, 0xa2, 0xcd, 0xbb, 0x0c, 0x7a, 0xa4, 0xc4, 0xc1, 0xd4, 0x51, 0x65, 0x19, 0x00, 0x89, 0xf4, 0xe9, 0x83, 0xbb, 0x1c, 0x2c, 0xab, 0x4a, 0xae, 0xff, 0x1f, 0xa2, 0xb5, 0xee, 0x51, 0x6f, 0xec, 0xd7, 0x80, 0x54, 0x02, 0x40, 0xbf, 0x37, 0xe5, 0x6c, 0x8b, 0xcc, 0xa7, 0xfa, 0xb9, 0x80, 0xe1, 0xe6, 0x1c, 0x94, 0x00, 0xd8, 0xa9, 0xa5, 0xb1, 0x4a, 0xc6 },
+ { 0x6f, 0xbf, 0x31, 0xb4, 0x5a, 0xb0, 0xc0, 0xb8, 0xda, 0xd1, 0xc0, 0xf5, 0xf4, 0x06, 0x13, 0x79, 0x91, 0x2d, 0xde, 0x5a, 0xa9, 0x22, 0x09, 0x9a, 0x03, 0x0b, 0x72, 0x5c, 0x73, 0x34, 0x6c, 0x52, 0x42, 0x91, 0xad, 0xef, 0x89, 0xd2, 0xf6, 0xfd, 0x8d, 0xfc, 0xda, 0x6d, 0x07, 0xda, 0xd8, 0x11, 0xa9, 0x31, 0x45, 0x36, 0xc2, 0x91, 0x5e, 0xd4, 0x5d, 0xa3, 0x49, 0x47, 0xe8, 0x3d, 0xe3, 0x4e },
+ { 0xa0, 0xc6, 0x5b, 0xdd, 0xde, 0x8a, 0xde, 0xf5, 0x72, 0x82, 0xb0, 0x4b, 0x11, 0xe7, 0xbc, 0x8a, 0xab, 0x10, 0x5b, 0x99, 0x23, 0x1b, 0x75, 0x0c, 0x02, 0x1f, 0x4a, 0x73, 0x5c, 0xb1, 0xbc, 0xfa, 0xb8, 0x75, 0x53, 0xbb, 0xa3, 0xab, 0xb0, 0xc3, 0xe6, 0x4a, 0x0b, 0x69, 0x55, 0x28, 0x51, 0x85, 0xa0, 0xbd, 0x35, 0xfb, 0x8c, 0xfd, 0xe5, 0x57, 0x32, 0x9b, 0xeb, 0xb1, 0xf6, 0x29, 0xee, 0x93 },
+ { 0xf9, 0x9d, 0x81, 0x55, 0x50, 0x55, 0x8e, 0x81, 0xec, 0xa2, 0xf9, 0x67, 0x18, 0xae, 0xd1, 0x0d, 0x86, 0xf3, 0xf1, 0xcf, 0xb6, 0x75, 0xcc, 0xe0, 0x6b, 0x0e, 0xff, 0x02, 0xf6, 0x17, 0xc5, 0xa4, 0x2c, 0x5a, 0xa7, 0x60, 0x27, 0x0f, 0x26, 0x79, 0xda, 0x26, 0x77, 0xc5, 0xae, 0xb9, 0x4f, 0x11, 0x42, 0x27, 0x7f, 0x21, 0xc7, 0xf7, 0x9f, 0x3c, 0x4f, 0x0c, 0xce, 0x4e, 0xd8, 0xee, 0x62, 0xb1 },
+ { 0x95, 0x39, 0x1d, 0xa8, 0xfc, 0x7b, 0x91, 0x7a, 0x20, 0x44, 0xb3, 0xd6, 0xf5, 0x37, 0x4e, 0x1c, 0xa0, 0x72, 0xb4, 0x14, 0x54, 0xd5, 0x72, 0xc7, 0x35, 0x6c, 0x05, 0xfd, 0x4b, 0xc1, 0xe0, 0xf4, 0x0b, 0x8b, 0xb8, 0xb4, 0xa9, 0xf6, 0xbc, 0xe9, 0xbe, 0x2c, 0x46, 0x23, 0xc3, 0x99, 0xb0, 0xdc, 0xa0, 0xda, 0xb0, 0x5c, 0xb7, 0x28, 0x1b, 0x71, 0xa2, 0x1b, 0x0e, 0xbc, 0xd9, 0xe5, 0x56, 0x70 },
+ { 0x04, 0xb9, 0xcd, 0x3d, 0x20, 0xd2, 0x21, 0xc0, 0x9a, 0xc8, 0x69, 0x13, 0xd3, 0xdc, 0x63, 0x04, 0x19, 0x89, 0xa9, 0xa1, 0xe6, 0x94, 0xf1, 0xe6, 0x39, 0xa3, 0xba, 0x7e, 0x45, 0x18, 0x40, 0xf7, 0x50, 0xc2, 0xfc, 0x19, 0x1d, 0x56, 0xad, 0x61, 0xf2, 0xe7, 0x93, 0x6b, 0xc0, 0xac, 0x8e, 0x09, 0x4b, 0x60, 0xca, 0xee, 0xd8, 0x78, 0xc1, 0x87, 0x99, 0x04, 0x54, 0x02, 0xd6, 0x1c, 0xea, 0xf9 },
+ { 0xec, 0x0e, 0x0e, 0xf7, 0x07, 0xe4, 0xed, 0x6c, 0x0c, 0x66, 0xf9, 0xe0, 0x89, 0xe4, 0x95, 0x4b, 0x05, 0x80, 0x30, 0xd2, 0xdd, 0x86, 0x39, 0x8f, 0xe8, 0x40, 0x59, 0x63, 0x1f, 0x9e, 0xe5, 0x91, 0xd9, 0xd7, 0x73, 0x75, 0x35, 0x51, 0x49, 0x17, 0x8c, 0x0c, 0xf8, 0xf8, 0xe7, 0xc4, 0x9e, 0xd2, 0xa5, 0xe4, 0xf9, 0x54, 0x88, 0xa2, 0x24, 0x70, 0x67, 0xc2, 0x08, 0x51, 0x0f, 0xad, 0xc4, 0x4c },
+ { 0x9a, 0x37, 0xcc, 0xe2, 0x73, 0xb7, 0x9c, 0x09, 0x91, 0x36, 0x77, 0x51, 0x0e, 0xaf, 0x76, 0x88, 0xe8, 0x9b, 0x33, 0x14, 0xd3, 0x53, 0x2f, 0xd2, 0x76, 0x4c, 0x39, 0xde, 0x02, 0x2a, 0x29, 0x45, 0xb5, 0x71, 0x0d, 0x13, 0x51, 0x7a, 0xf8, 0xdd, 0xc0, 0x31, 0x66, 0x24, 0xe7, 0x3b, 0xec, 0x1c, 0xe6, 0x7d, 0xf1, 0x52, 0x28, 0x30, 0x20, 0x36, 0xf3, 0x30, 0xab, 0x0c, 0xb4, 0xd2, 0x18, 0xdd },
+ { 0x4c, 0xf9, 0xbb, 0x8f, 0xb3, 0xd4, 0xde, 0x8b, 0x38, 0xb2, 0xf2, 0x62, 0xd3, 0xc4, 0x0f, 0x46, 0xdf, 0xe7, 0x47, 0xe8, 0xfc, 0x0a, 0x41, 0x4c, 0x19, 0x3d, 0x9f, 0xcf, 0x75, 0x31, 0x06, 0xce, 0x47, 0xa1, 0x8f, 0x17, 0x2f, 0x12, 0xe8, 0xa2, 0xf1, 0xc2, 0x67, 0x26, 0x54, 0x53, 0x58, 0xe5, 0xee, 0x28, 0xc9, 0xe2, 0x21, 0x3a, 0x87, 0x87, 0xaa, 0xfb, 0xc5, 0x16, 0xd2, 0x34, 0x31, 0x52 },
+ { 0x64, 0xe0, 0xc6, 0x3a, 0xf9, 0xc8, 0x08, 0xfd, 0x89, 0x31, 0x37, 0x12, 0x98, 0x67, 0xfd, 0x91, 0x93, 0x9d, 0x53, 0xf2, 0xaf, 0x04, 0xbe, 0x4f, 0xa2, 0x68, 0x00, 0x61, 0x00, 0x06, 0x9b, 0x2d, 0x69, 0xda, 0xa5, 0xc5, 0xd8, 0xed, 0x7f, 0xdd, 0xcb, 0x2a, 0x70, 0xee, 0xec, 0xdf, 0x2b, 0x10, 0x5d, 0xd4, 0x6a, 0x1e, 0x3b, 0x73, 0x11, 0x72, 0x8f, 0x63, 0x9a, 0xb4, 0x89, 0x32, 0x6b, 0xc9 },
+ { 0x5e, 0x9c, 0x93, 0x15, 0x8d, 0x65, 0x9b, 0x2d, 0xef, 0x06, 0xb0, 0xc3, 0xc7, 0x56, 0x50, 0x45, 0x54, 0x26, 0x62, 0xd6, 0xee, 0xe8, 0xa9, 0x6a, 0x89, 0xb7, 0x8a, 0xde, 0x09, 0xfe, 0x8b, 0x3d, 0xcc, 0x09, 0x6d, 0x4f, 0xe4, 0x88, 0x15, 0xd8, 0x8d, 0x8f, 0x82, 0x62, 0x01, 0x56, 0x60, 0x2a, 0xf5, 0x41, 0x95, 0x5e, 0x1f, 0x6c, 0xa3, 0x0d, 0xce, 0x14, 0xe2, 0x54, 0xc3, 0x26, 0xb8, 0x8f },
+ { 0x77, 0x75, 0xdf, 0xf8, 0x89, 0x45, 0x8d, 0xd1, 0x1a, 0xef, 0x41, 0x72, 0x76, 0x85, 0x3e, 0x21, 0x33, 0x5e, 0xb8, 0x8e, 0x4d, 0xec, 0x9c, 0xfb, 0x4e, 0x9e, 0xdb, 0x49, 0x82, 0x00, 0x88, 0x55, 0x1a, 0x2c, 0xa6, 0x03, 0x39, 0xf1, 0x20, 0x66, 0x10, 0x11, 0x69, 0xf0, 0xdf, 0xe8, 0x4b, 0x09, 0x8f, 0xdd, 0xb1, 0x48, 0xd9, 0xda, 0x6b, 0x3d, 0x61, 0x3d, 0xf2, 0x63, 0x88, 0x9a, 0xd6, 0x4b },
+ { 0xf0, 0xd2, 0x80, 0x5a, 0xfb, 0xb9, 0x1f, 0x74, 0x39, 0x51, 0x35, 0x1a, 0x6d, 0x02, 0x4f, 0x93, 0x53, 0xa2, 0x3c, 0x7c, 0xe1, 0xfc, 0x2b, 0x05, 0x1b, 0x3a, 0x8b, 0x96, 0x8c, 0x23, 0x3f, 0x46, 0xf5, 0x0f, 0x80, 0x6e, 0xcb, 0x15, 0x68, 0xff, 0xaa, 0x0b, 0x60, 0x66, 0x1e, 0x33, 0x4b, 0x21, 0xdd, 0xe0, 0x4f, 0x8f, 0xa1, 0x55, 0xac, 0x74, 0x0e, 0xeb, 0x42, 0xe2, 0x0b, 0x60, 0xd7, 0x64 },
+ { 0x86, 0xa2, 0xaf, 0x31, 0x6e, 0x7d, 0x77, 0x54, 0x20, 0x1b, 0x94, 0x2e, 0x27, 0x53, 0x64, 0xac, 0x12, 0xea, 0x89, 0x62, 0xab, 0x5b, 0xd8, 0xd7, 0xfb, 0x27, 0x6d, 0xc5, 0xfb, 0xff, 0xc8, 0xf9, 0xa2, 0x8c, 0xae, 0x4e, 0x48, 0x67, 0xdf, 0x67, 0x80, 0xd9, 0xb7, 0x25, 0x24, 0x16, 0x09, 0x27, 0xc8, 0x55, 0xda, 0x5b, 0x60, 0x78, 0xe0, 0xb5, 0x54, 0xaa, 0x91, 0xe3, 0x1c, 0xb9, 0xca, 0x1d },
+ { 0x10, 0xbd, 0xf0, 0xca, 0xa0, 0x80, 0x27, 0x05, 0xe7, 0x06, 0x36, 0x9b, 0xaf, 0x8a, 0x3f, 0x79, 0xd7, 0x2c, 0x0a, 0x03, 0xa8, 0x06, 0x75, 0xa7, 0xbb, 0xb0, 0x0b, 0xe3, 0xa4, 0x5e, 0x51, 0x64, 0x24, 0xd1, 0xee, 0x88, 0xef, 0xb5, 0x6f, 0x6d, 0x57, 0x77, 0x54, 0x5a, 0xe6, 0xe2, 0x77, 0x65, 0xc3, 0xa8, 0xf5, 0xe4, 0x93, 0xfc, 0x30, 0x89, 0x15, 0x63, 0x89, 0x33, 0xa1, 0xdf, 0xee, 0x55 },
+ { 0xb0, 0x17, 0x81, 0x09, 0x2b, 0x17, 0x48, 0x45, 0x9e, 0x2e, 0x4e, 0xc1, 0x78, 0x69, 0x66, 0x27, 0xbf, 0x4e, 0xba, 0xfe, 0xbb, 0xa7, 0x74, 0xec, 0xf0, 0x18, 0xb7, 0x9a, 0x68, 0xae, 0xb8, 0x49, 0x17, 0xbf, 0x0b, 0x84, 0xbb, 0x79, 0xd1, 0x7b, 0x74, 0x31, 0x51, 0x14, 0x4c, 0xd6, 0x6b, 0x7b, 0x33, 0xa4, 0xb9, 0xe5, 0x2c, 0x76, 0xc4, 0xe1, 0x12, 0x05, 0x0f, 0xf5, 0x38, 0x5b, 0x7f, 0x0b },
+ { 0xc6, 0xdb, 0xc6, 0x1d, 0xec, 0x6e, 0xae, 0xac, 0x81, 0xe3, 0xd5, 0xf7, 0x55, 0x20, 0x3c, 0x8e, 0x22, 0x05, 0x51, 0x53, 0x4a, 0x0b, 0x2f, 0xd1, 0x05, 0xa9, 0x18, 0x89, 0x94, 0x5a, 0x63, 0x85, 0x50, 0x20, 0x4f, 0x44, 0x09, 0x3d, 0xd9, 0x98, 0xc0, 0x76, 0x20, 0x5d, 0xff, 0xad, 0x70, 0x3a, 0x0e, 0x5c, 0xd3, 0xc7, 0xf4, 0x38, 0xa7, 0xe6, 0x34, 0xcd, 0x59, 0xfe, 0xde, 0xdb, 0x53, 0x9e },
+ { 0xeb, 0xa5, 0x1a, 0xcf, 0xfb, 0x4c, 0xea, 0x31, 0xdb, 0x4b, 0x8d, 0x87, 0xe9, 0xbf, 0x7d, 0xd4, 0x8f, 0xe9, 0x7b, 0x02, 0x53, 0xae, 0x67, 0xaa, 0x58, 0x0f, 0x9a, 0xc4, 0xa9, 0xd9, 0x41, 0xf2, 0xbe, 0xa5, 0x18, 0xee, 0x28, 0x68, 0x18, 0xcc, 0x9f, 0x63, 0x3f, 0x2a, 0x3b, 0x9f, 0xb6, 0x8e, 0x59, 0x4b, 0x48, 0xcd, 0xd6, 0xd5, 0x15, 0xbf, 0x1d, 0x52, 0xba, 0x6c, 0x85, 0xa2, 0x03, 0xa7 },
+ { 0x86, 0x22, 0x1f, 0x3a, 0xda, 0x52, 0x03, 0x7b, 0x72, 0x22, 0x4f, 0x10, 0x5d, 0x79, 0x99, 0x23, 0x1c, 0x5e, 0x55, 0x34, 0xd0, 0x3d, 0xa9, 0xd9, 0xc0, 0xa1, 0x2a, 0xcb, 0x68, 0x46, 0x0c, 0xd3, 0x75, 0xda, 0xf8, 0xe2, 0x43, 0x86, 0x28, 0x6f, 0x96, 0x68, 0xf7, 0x23, 0x26, 0xdb, 0xf9, 0x9b, 0xa0, 0x94, 0x39, 0x24, 0x37, 0xd3, 0x98, 0xe9, 0x5b, 0xb8, 0x16, 0x1d, 0x71, 0x7f, 0x89, 0x91 },
+ { 0x55, 0x95, 0xe0, 0x5c, 0x13, 0xa7, 0xec, 0x4d, 0xc8, 0xf4, 0x1f, 0xb7, 0x0c, 0xb5, 0x0a, 0x71, 0xbc, 0xe1, 0x7c, 0x02, 0x4f, 0xf6, 0xde, 0x7a, 0xf6, 0x18, 0xd0, 0xcc, 0x4e, 0x9c, 0x32, 0xd9, 0x57, 0x0d, 0x6d, 0x3e, 0xa4, 0x5b, 0x86, 0x52, 0x54, 0x91, 0x03, 0x0c, 0x0d, 0x8f, 0x2b, 0x18, 0x36, 0xd5, 0x77, 0x8c, 0x1c, 0xe7, 0x35, 0xc1, 0x77, 0x07, 0xdf, 0x36, 0x4d, 0x05, 0x43, 0x47 },
+ { 0xce, 0x0f, 0x4f, 0x6a, 0xca, 0x89, 0x59, 0x0a, 0x37, 0xfe, 0x03, 0x4d, 0xd7, 0x4d, 0xd5, 0xfa, 0x65, 0xeb, 0x1c, 0xbd, 0x0a, 0x41, 0x50, 0x8a, 0xad, 0xdc, 0x09, 0x35, 0x1a, 0x3c, 0xea, 0x6d, 0x18, 0xcb, 0x21, 0x89, 0xc5, 0x4b, 0x70, 0x0c, 0x00, 0x9f, 0x4c, 0xbf, 0x05, 0x21, 0xc7, 0xea, 0x01, 0xbe, 0x61, 0xc5, 0xae, 0x09, 0xcb, 0x54, 0xf2, 0x7b, 0xc1, 0xb4, 0x4d, 0x65, 0x8c, 0x82 },
+ { 0x7e, 0xe8, 0x0b, 0x06, 0xa2, 0x15, 0xa3, 0xbc, 0xa9, 0x70, 0xc7, 0x7c, 0xda, 0x87, 0x61, 0x82, 0x2b, 0xc1, 0x03, 0xd4, 0x4f, 0xa4, 0xb3, 0x3f, 0x4d, 0x07, 0xdc, 0xb9, 0x97, 0xe3, 0x6d, 0x55, 0x29, 0x8b, 0xce, 0xae, 0x12, 0x24, 0x1b, 0x3f, 0xa0, 0x7f, 0xa6, 0x3b, 0xe5, 0x57, 0x60, 0x68, 0xda, 0x38, 0x7b, 0x8d, 0x58, 0x59, 0xae, 0xab, 0x70, 0x13, 0x69, 0x84, 0x8b, 0x17, 0x6d, 0x42 },
+ { 0x94, 0x0a, 0x84, 0xb6, 0xa8, 0x4d, 0x10, 0x9a, 0xab, 0x20, 0x8c, 0x02, 0x4c, 0x6c, 0xe9, 0x64, 0x76, 0x76, 0xba, 0x0a, 0xaa, 0x11, 0xf8, 0x6d, 0xbb, 0x70, 0x18, 0xf9, 0xfd, 0x22, 0x20, 0xa6, 0xd9, 0x01, 0xa9, 0x02, 0x7f, 0x9a, 0xbc, 0xf9, 0x35, 0x37, 0x27, 0x27, 0xcb, 0xf0, 0x9e, 0xbd, 0x61, 0xa2, 0xa2, 0xee, 0xb8, 0x76, 0x53, 0xe8, 0xec, 0xad, 0x1b, 0xab, 0x85, 0xdc, 0x83, 0x27 },
+ { 0x20, 0x20, 0xb7, 0x82, 0x64, 0xa8, 0x2d, 0x9f, 0x41, 0x51, 0x14, 0x1a, 0xdb, 0xa8, 0xd4, 0x4b, 0xf2, 0x0c, 0x5e, 0xc0, 0x62, 0xee, 0xe9, 0xb5, 0x95, 0xa1, 0x1f, 0x9e, 0x84, 0x90, 0x1b, 0xf1, 0x48, 0xf2, 0x98, 0xe0, 0xc9, 0xf8, 0x77, 0x7d, 0xcd, 0xbc, 0x7c, 0xc4, 0x67, 0x0a, 0xac, 0x35, 0x6c, 0xc2, 0xad, 0x8c, 0xcb, 0x16, 0x29, 0xf1, 0x6f, 0x6a, 0x76, 0xbc, 0xef, 0xbe, 0xe7, 0x60 },
+ { 0xd1, 0xb8, 0x97, 0xb0, 0xe0, 0x75, 0xba, 0x68, 0xab, 0x57, 0x2a, 0xdf, 0x9d, 0x9c, 0x43, 0x66, 0x63, 0xe4, 0x3e, 0xb3, 0xd8, 0xe6, 0x2d, 0x92, 0xfc, 0x49, 0xc9, 0xbe, 0x21, 0x4e, 0x6f, 0x27, 0x87, 0x3f, 0xe2, 0x15, 0xa6, 0x51, 0x70, 0xe6, 0xbe, 0xa9, 0x02, 0x40, 0x8a, 0x25, 0xb4, 0x95, 0x06, 0xf4, 0x7b, 0xab, 0xd0, 0x7c, 0xec, 0xf7, 0x11, 0x3e, 0xc1, 0x0c, 0x5d, 0xd3, 0x12, 0x52 },
+ { 0xb1, 0x4d, 0x0c, 0x62, 0xab, 0xfa, 0x46, 0x9a, 0x35, 0x71, 0x77, 0xe5, 0x94, 0xc1, 0x0c, 0x19, 0x42, 0x43, 0xed, 0x20, 0x25, 0xab, 0x8a, 0xa5, 0xad, 0x2f, 0xa4, 0x1a, 0xd3, 0x18, 0xe0, 0xff, 0x48, 0xcd, 0x5e, 0x60, 0xbe, 0xc0, 0x7b, 0x13, 0x63, 0x4a, 0x71, 0x1d, 0x23, 0x26, 0xe4, 0x88, 0xa9, 0x85, 0xf3, 0x1e, 0x31, 0x15, 0x33, 0x99, 0xe7, 0x30, 0x88, 0xef, 0xc8, 0x6a, 0x5c, 0x55 },
+ { 0x41, 0x69, 0xc5, 0xcc, 0x80, 0x8d, 0x26, 0x97, 0xdc, 0x2a, 0x82, 0x43, 0x0d, 0xc2, 0x3e, 0x3c, 0xd3, 0x56, 0xdc, 0x70, 0xa9, 0x45, 0x66, 0x81, 0x05, 0x02, 0xb8, 0xd6, 0x55, 0xb3, 0x9a, 0xbf, 0x9e, 0x7f, 0x90, 0x2f, 0xe7, 0x17, 0xe0, 0x38, 0x92, 0x19, 0x85, 0x9e, 0x19, 0x45, 0xdf, 0x1a, 0xf6, 0xad, 0xa4, 0x2e, 0x4c, 0xcd, 0xa5, 0x5a, 0x19, 0x7b, 0x71, 0x00, 0xa3, 0x0c, 0x30, 0xa1 },
+ { 0x25, 0x8a, 0x4e, 0xdb, 0x11, 0x3d, 0x66, 0xc8, 0x39, 0xc8, 0xb1, 0xc9, 0x1f, 0x15, 0xf3, 0x5a, 0xde, 0x60, 0x9f, 0x11, 0xcd, 0x7f, 0x86, 0x81, 0xa4, 0x04, 0x5b, 0x9f, 0xef, 0x7b, 0x0b, 0x24, 0xc8, 0x2c, 0xda, 0x06, 0xa5, 0xf2, 0x06, 0x7b, 0x36, 0x88, 0x25, 0xe3, 0x91, 0x4e, 0x53, 0xd6, 0x94, 0x8e, 0xde, 0x92, 0xef, 0xd6, 0xe8, 0x38, 0x7f, 0xa2, 0xe5, 0x37, 0x23, 0x9b, 0x5b, 0xee },
+ { 0x79, 0xd2, 0xd8, 0x69, 0x6d, 0x30, 0xf3, 0x0f, 0xb3, 0x46, 0x57, 0x76, 0x11, 0x71, 0xa1, 0x1e, 0x6c, 0x3f, 0x1e, 0x64, 0xcb, 0xe7, 0xbe, 0xbe, 0xe1, 0x59, 0xcb, 0x95, 0xbf, 0xaf, 0x81, 0x2b, 0x4f, 0x41, 0x1e, 0x2f, 0x26, 0xd9, 0xc4, 0x21, 0xdc, 0x2c, 0x28, 0x4a, 0x33, 0x42, 0xd8, 0x23, 0xec, 0x29, 0x38, 0x49, 0xe4, 0x2d, 0x1e, 0x46, 0xb0, 0xa4, 0xac, 0x1e, 0x3c, 0x86, 0xab, 0xaa },
+ { 0x8b, 0x94, 0x36, 0x01, 0x0d, 0xc5, 0xde, 0xe9, 0x92, 0xae, 0x38, 0xae, 0xa9, 0x7f, 0x2c, 0xd6, 0x3b, 0x94, 0x6d, 0x94, 0xfe, 0xdd, 0x2e, 0xc9, 0x67, 0x1d, 0xcd, 0xe3, 0xbd, 0x4c, 0xe9, 0x56, 0x4d, 0x55, 0x5c, 0x66, 0xc1, 0x5b, 0xb2, 0xb9, 0x00, 0xdf, 0x72, 0xed, 0xb6, 0xb8, 0x91, 0xeb, 0xca, 0xdf, 0xef, 0xf6, 0x3c, 0x9e, 0xa4, 0x03, 0x6a, 0x99, 0x8b, 0xe7, 0x97, 0x39, 0x81, 0xe7 },
+ { 0xc8, 0xf6, 0x8e, 0x69, 0x6e, 0xd2, 0x82, 0x42, 0xbf, 0x99, 0x7f, 0x5b, 0x3b, 0x34, 0x95, 0x95, 0x08, 0xe4, 0x2d, 0x61, 0x38, 0x10, 0xf1, 0xe2, 0xa4, 0x35, 0xc9, 0x6e, 0xd2, 0xff, 0x56, 0x0c, 0x70, 0x22, 0xf3, 0x61, 0xa9, 0x23, 0x4b, 0x98, 0x37, 0xfe, 0xee, 0x90, 0xbf, 0x47, 0x92, 0x2e, 0xe0, 0xfd, 0x5f, 0x8d, 0xdf, 0x82, 0x37, 0x18, 0xd8, 0x6d, 0x1e, 0x16, 0xc6, 0x09, 0x00, 0x71 },
+ { 0xb0, 0x2d, 0x3e, 0xee, 0x48, 0x60, 0xd5, 0x86, 0x8b, 0x2c, 0x39, 0xce, 0x39, 0xbf, 0xe8, 0x10, 0x11, 0x29, 0x05, 0x64, 0xdd, 0x67, 0x8c, 0x85, 0xe8, 0x78, 0x3f, 0x29, 0x30, 0x2d, 0xfc, 0x13, 0x99, 0xba, 0x95, 0xb6, 0xb5, 0x3c, 0xd9, 0xeb, 0xbf, 0x40, 0x0c, 0xca, 0x1d, 0xb0, 0xab, 0x67, 0xe1, 0x9a, 0x32, 0x5f, 0x2d, 0x11, 0x58, 0x12, 0xd2, 0x5d, 0x00, 0x97, 0x8a, 0xd1, 0xbc, 0xa4 },
+ { 0x76, 0x93, 0xea, 0x73, 0xaf, 0x3a, 0xc4, 0xda, 0xd2, 0x1c, 0xa0, 0xd8, 0xda, 0x85, 0xb3, 0x11, 0x8a, 0x7d, 0x1c, 0x60, 0x24, 0xcf, 0xaf, 0x55, 0x76, 0x99, 0x86, 0x82, 0x17, 0xbc, 0x0c, 0x2f, 0x44, 0xa1, 0x99, 0xbc, 0x6c, 0x0e, 0xdd, 0x51, 0x97, 0x98, 0xba, 0x05, 0xbd, 0x5b, 0x1b, 0x44, 0x84, 0x34, 0x6a, 0x47, 0xc2, 0xca, 0xdf, 0x6b, 0xf3, 0x0b, 0x78, 0x5c, 0xc8, 0x8b, 0x2b, 0xaf },
+ { 0xa0, 0xe5, 0xc1, 0xc0, 0x03, 0x1c, 0x02, 0xe4, 0x8b, 0x7f, 0x09, 0xa5, 0xe8, 0x96, 0xee, 0x9a, 0xef, 0x2f, 0x17, 0xfc, 0x9e, 0x18, 0xe9, 0x97, 0xd7, 0xf6, 0xca, 0xc7, 0xae, 0x31, 0x64, 0x22, 0xc2, 0xb1, 0xe7, 0x79, 0x84, 0xe5, 0xf3, 0xa7, 0x3c, 0xb4, 0x5d, 0xee, 0xd5, 0xd3, 0xf8, 0x46, 0x00, 0x10, 0x5e, 0x6e, 0xe3, 0x8f, 0x2d, 0x09, 0x0c, 0x7d, 0x04, 0x42, 0xea, 0x34, 0xc4, 0x6d },
+ { 0x41, 0xda, 0xa6, 0xad, 0xcf, 0xdb, 0x69, 0xf1, 0x44, 0x0c, 0x37, 0xb5, 0x96, 0x44, 0x01, 0x65, 0xc1, 0x5a, 0xda, 0x59, 0x68, 0x13, 0xe2, 0xe2, 0x2f, 0x06, 0x0f, 0xcd, 0x55, 0x1f, 0x24, 0xde, 0xe8, 0xe0, 0x4b, 0xa6, 0x89, 0x03, 0x87, 0x88, 0x6c, 0xee, 0xc4, 0xa7, 0xa0, 0xd7, 0xfc, 0x6b, 0x44, 0x50, 0x63, 0x92, 0xec, 0x38, 0x22, 0xc0, 0xd8, 0xc1, 0xac, 0xfc, 0x7d, 0x5a, 0xeb, 0xe8 },
+ { 0x14, 0xd4, 0xd4, 0x0d, 0x59, 0x84, 0xd8, 0x4c, 0x5c, 0xf7, 0x52, 0x3b, 0x77, 0x98, 0xb2, 0x54, 0xe2, 0x75, 0xa3, 0xa8, 0xcc, 0x0a, 0x1b, 0xd0, 0x6e, 0xbc, 0x0b, 0xee, 0x72, 0x68, 0x56, 0xac, 0xc3, 0xcb, 0xf5, 0x16, 0xff, 0x66, 0x7c, 0xda, 0x20, 0x58, 0xad, 0x5c, 0x34, 0x12, 0x25, 0x44, 0x60, 0xa8, 0x2c, 0x92, 0x18, 0x70, 0x41, 0x36, 0x3c, 0xc7, 0x7a, 0x4d, 0xc2, 0x15, 0xe4, 0x87 },
+ { 0xd0, 0xe7, 0xa1, 0xe2, 0xb9, 0xa4, 0x47, 0xfe, 0xe8, 0x3e, 0x22, 0x77, 0xe9, 0xff, 0x80, 0x10, 0xc2, 0xf3, 0x75, 0xae, 0x12, 0xfa, 0x7a, 0xaa, 0x8c, 0xa5, 0xa6, 0x31, 0x78, 0x68, 0xa2, 0x6a, 0x36, 0x7a, 0x0b, 0x69, 0xfb, 0xc1, 0xcf, 0x32, 0xa5, 0x5d, 0x34, 0xeb, 0x37, 0x06, 0x63, 0x01, 0x6f, 0x3d, 0x21, 0x10, 0x23, 0x0e, 0xba, 0x75, 0x40, 0x28, 0xa5, 0x6f, 0x54, 0xac, 0xf5, 0x7c },
+ { 0xe7, 0x71, 0xaa, 0x8d, 0xb5, 0xa3, 0xe0, 0x43, 0xe8, 0x17, 0x8f, 0x39, 0xa0, 0x85, 0x7b, 0xa0, 0x4a, 0x3f, 0x18, 0xe4, 0xaa, 0x05, 0x74, 0x3c, 0xf8, 0xd2, 0x22, 0xb0, 0xb0, 0x95, 0x82, 0x53, 0x50, 0xba, 0x42, 0x2f, 0x63, 0x38, 0x2a, 0x23, 0xd9, 0x2e, 0x41, 0x49, 0x07, 0x4e, 0x81, 0x6a, 0x36, 0xc1, 0xcd, 0x28, 0x28, 0x4d, 0x14, 0x62, 0x67, 0x94, 0x0b, 0x31, 0xf8, 0x81, 0x8e, 0xa2 },
+ { 0xfe, 0xb4, 0xfd, 0x6f, 0x9e, 0x87, 0xa5, 0x6b, 0xef, 0x39, 0x8b, 0x32, 0x84, 0xd2, 0xbd, 0xa5, 0xb5, 0xb0, 0xe1, 0x66, 0x58, 0x3a, 0x66, 0xb6, 0x1e, 0x53, 0x84, 0x57, 0xff, 0x05, 0x84, 0x87, 0x2c, 0x21, 0xa3, 0x29, 0x62, 0xb9, 0x92, 0x8f, 0xfa, 0xb5, 0x8d, 0xe4, 0xaf, 0x2e, 0xdd, 0x4e, 0x15, 0xd8, 0xb3, 0x55, 0x70, 0x52, 0x32, 0x07, 0xff, 0x4e, 0x2a, 0x5a, 0xa7, 0x75, 0x4c, 0xaa },
+ { 0x46, 0x2f, 0x17, 0xbf, 0x00, 0x5f, 0xb1, 0xc1, 0xb9, 0xe6, 0x71, 0x77, 0x9f, 0x66, 0x52, 0x09, 0xec, 0x28, 0x73, 0xe3, 0xe4, 0x11, 0xf9, 0x8d, 0xab, 0xf2, 0x40, 0xa1, 0xd5, 0xec, 0x3f, 0x95, 0xce, 0x67, 0x96, 0xb6, 0xfc, 0x23, 0xfe, 0x17, 0x19, 0x03, 0xb5, 0x02, 0x02, 0x34, 0x67, 0xde, 0xc7, 0x27, 0x3f, 0xf7, 0x48, 0x79, 0xb9, 0x29, 0x67, 0xa2, 0xa4, 0x3a, 0x5a, 0x18, 0x3d, 0x33 },
+ { 0xd3, 0x33, 0x81, 0x93, 0xb6, 0x45, 0x53, 0xdb, 0xd3, 0x8d, 0x14, 0x4b, 0xea, 0x71, 0xc5, 0x91, 0x5b, 0xb1, 0x10, 0xe2, 0xd8, 0x81, 0x80, 0xdb, 0xc5, 0xdb, 0x36, 0x4f, 0xd6, 0x17, 0x1d, 0xf3, 0x17, 0xfc, 0x72, 0x68, 0x83, 0x1b, 0x5a, 0xef, 0x75, 0xe4, 0x34, 0x2b, 0x2f, 0xad, 0x87, 0x97, 0xba, 0x39, 0xed, 0xdc, 0xef, 0x80, 0xe6, 0xec, 0x08, 0x15, 0x93, 0x50, 0xb1, 0xad, 0x69, 0x6d },
+ { 0xe1, 0x59, 0x0d, 0x58, 0x5a, 0x3d, 0x39, 0xf7, 0xcb, 0x59, 0x9a, 0xbd, 0x47, 0x90, 0x70, 0x96, 0x64, 0x09, 0xa6, 0x84, 0x6d, 0x43, 0x77, 0xac, 0xf4, 0x47, 0x1d, 0x06, 0x5d, 0x5d, 0xb9, 0x41, 0x29, 0xcc, 0x9b, 0xe9, 0x25, 0x73, 0xb0, 0x5e, 0xd2, 0x26, 0xbe, 0x1e, 0x9b, 0x7c, 0xb0, 0xca, 0xbe, 0x87, 0x91, 0x85, 0x89, 0xf8, 0x0d, 0xad, 0xd4, 0xef, 0x5e, 0xf2, 0x5a, 0x93, 0xd2, 0x8e },
+ { 0xf8, 0xf3, 0x72, 0x6a, 0xc5, 0xa2, 0x6c, 0xc8, 0x01, 0x32, 0x49, 0x3a, 0x6f, 0xed, 0xcb, 0x0e, 0x60, 0x76, 0x0c, 0x09, 0xcf, 0xc8, 0x4c, 0xad, 0x17, 0x81, 0x75, 0x98, 0x68, 0x19, 0x66, 0x5e, 0x76, 0x84, 0x2d, 0x7b, 0x9f, 0xed, 0xf7, 0x6d, 0xdd, 0xeb, 0xf5, 0xd3, 0xf5, 0x6f, 0xaa, 0xad, 0x44, 0x77, 0x58, 0x7a, 0xf2, 0x16, 0x06, 0xd3, 0x96, 0xae, 0x57, 0x0d, 0x8e, 0x71, 0x9a, 0xf2 },
+ { 0x30, 0x18, 0x60, 0x55, 0xc0, 0x79, 0x49, 0x94, 0x81, 0x83, 0xc8, 0x50, 0xe9, 0xa7, 0x56, 0xcc, 0x09, 0x93, 0x7e, 0x24, 0x7d, 0x9d, 0x92, 0x8e, 0x86, 0x9e, 0x20, 0xba, 0xfc, 0x3c, 0xd9, 0x72, 0x17, 0x19, 0xd3, 0x4e, 0x04, 0xa0, 0x89, 0x9b, 0x92, 0xc7, 0x36, 0x08, 0x45, 0x50, 0x18, 0x68, 0x86, 0xef, 0xba, 0x2e, 0x79, 0x0d, 0x8b, 0xe6, 0xeb, 0xf0, 0x40, 0xb2, 0x09, 0xc4, 0x39, 0xa4 },
+ { 0xf3, 0xc4, 0x27, 0x6c, 0xb8, 0x63, 0x63, 0x77, 0x12, 0xc2, 0x41, 0xc4, 0x44, 0xc5, 0xcc, 0x1e, 0x35, 0x54, 0xe0, 0xfd, 0xdb, 0x17, 0x4d, 0x03, 0x58, 0x19, 0xdd, 0x83, 0xeb, 0x70, 0x0b, 0x4c, 0xe8, 0x8d, 0xf3, 0xab, 0x38, 0x41, 0xba, 0x02, 0x08, 0x5e, 0x1a, 0x99, 0xb4, 0xe1, 0x73, 0x10, 0xc5, 0x34, 0x10, 0x75, 0xc0, 0x45, 0x8b, 0xa3, 0x76, 0xc9, 0x5a, 0x68, 0x18, 0xfb, 0xb3, 0xe2 },
+ { 0x0a, 0xa0, 0x07, 0xc4, 0xdd, 0x9d, 0x58, 0x32, 0x39, 0x30, 0x40, 0xa1, 0x58, 0x3c, 0x93, 0x0b, 0xca, 0x7d, 0xc5, 0xe7, 0x7e, 0xa5, 0x3a, 0xdd, 0x7e, 0x2b, 0x3f, 0x7c, 0x8e, 0x23, 0x13, 0x68, 0x04, 0x35, 0x20, 0xd4, 0xa3, 0xef, 0x53, 0xc9, 0x69, 0xb6, 0xbb, 0xfd, 0x02, 0x59, 0x46, 0xf6, 0x32, 0xbd, 0x7f, 0x76, 0x5d, 0x53, 0xc2, 0x10, 0x03, 0xb8, 0xf9, 0x83, 0xf7, 0x5e, 0x2a, 0x6a },
+ { 0x08, 0xe9, 0x46, 0x47, 0x20, 0x53, 0x3b, 0x23, 0xa0, 0x4e, 0xc2, 0x4f, 0x7a, 0xe8, 0xc1, 0x03, 0x14, 0x5f, 0x76, 0x53, 0x87, 0xd7, 0x38, 0x77, 0x7d, 0x3d, 0x34, 0x34, 0x77, 0xfd, 0x1c, 0x58, 0xdb, 0x05, 0x21, 0x42, 0xca, 0xb7, 0x54, 0xea, 0x67, 0x43, 0x78, 0xe1, 0x87, 0x66, 0xc5, 0x35, 0x42, 0xf7, 0x19, 0x70, 0x17, 0x1c, 0xc4, 0xf8, 0x16, 0x94, 0x24, 0x6b, 0x71, 0x7d, 0x75, 0x64 },
+ { 0xd3, 0x7f, 0xf7, 0xad, 0x29, 0x79, 0x93, 0xe7, 0xec, 0x21, 0xe0, 0xf1, 0xb4, 0xb5, 0xae, 0x71, 0x9c, 0xdc, 0x83, 0xc5, 0xdb, 0x68, 0x75, 0x27, 0xf2, 0x75, 0x16, 0xcb, 0xff, 0xa8, 0x22, 0x88, 0x8a, 0x68, 0x10, 0xee, 0x5c, 0x1c, 0xa7, 0xbf, 0xe3, 0x32, 0x11, 0x19, 0xbe, 0x1a, 0xb7, 0xbf, 0xa0, 0xa5, 0x02, 0x67, 0x1c, 0x83, 0x29, 0x49, 0x4d, 0xf7, 0xad, 0x6f, 0x52, 0x2d, 0x44, 0x0f },
+ { 0xdd, 0x90, 0x42, 0xf6, 0xe4, 0x64, 0xdc, 0xf8, 0x6b, 0x12, 0x62, 0xf6, 0xac, 0xcf, 0xaf, 0xbd, 0x8c, 0xfd, 0x90, 0x2e, 0xd3, 0xed, 0x89, 0xab, 0xf7, 0x8f, 0xfa, 0x48, 0x2d, 0xbd, 0xee, 0xb6, 0x96, 0x98, 0x42, 0x39, 0x4c, 0x9a, 0x11, 0x68, 0xae, 0x3d, 0x48, 0x1a, 0x01, 0x78, 0x42, 0xf6, 0x60, 0x00, 0x2d, 0x42, 0x44, 0x7c, 0x6b, 0x22, 0xf7, 0xb7, 0x2f, 0x21, 0xaa, 0xe0, 0x21, 0xc9 },
+ { 0xbd, 0x96, 0x5b, 0xf3, 0x1e, 0x87, 0xd7, 0x03, 0x27, 0x53, 0x6f, 0x2a, 0x34, 0x1c, 0xeb, 0xc4, 0x76, 0x8e, 0xca, 0x27, 0x5f, 0xa0, 0x5e, 0xf9, 0x8f, 0x7f, 0x1b, 0x71, 0xa0, 0x35, 0x12, 0x98, 0xde, 0x00, 0x6f, 0xba, 0x73, 0xfe, 0x67, 0x33, 0xed, 0x01, 0xd7, 0x58, 0x01, 0xb4, 0xa9, 0x28, 0xe5, 0x42, 0x31, 0xb3, 0x8e, 0x38, 0xc5, 0x62, 0xb2, 0xe3, 0x3e, 0xa1, 0x28, 0x49, 0x92, 0xfa },
+ { 0x65, 0x67, 0x6d, 0x80, 0x06, 0x17, 0x97, 0x2f, 0xbd, 0x87, 0xe4, 0xb9, 0x51, 0x4e, 0x1c, 0x67, 0x40, 0x2b, 0x7a, 0x33, 0x10, 0x96, 0xd3, 0xbf, 0xac, 0x22, 0xf1, 0xab, 0xb9, 0x53, 0x74, 0xab, 0xc9, 0x42, 0xf1, 0x6e, 0x9a, 0xb0, 0xea, 0xd3, 0x3b, 0x87, 0xc9, 0x19, 0x68, 0xa6, 0xe5, 0x09, 0xe1, 0x19, 0xff, 0x07, 0x78, 0x7b, 0x3e, 0xf4, 0x83, 0xe1, 0xdc, 0xdc, 0xcf, 0x6e, 0x30, 0x22 },
+ { 0x93, 0x9f, 0xa1, 0x89, 0x69, 0x9c, 0x5d, 0x2c, 0x81, 0xdd, 0xd1, 0xff, 0xc1, 0xfa, 0x20, 0x7c, 0x97, 0x0b, 0x6a, 0x36, 0x85, 0xbb, 0x29, 0xce, 0x1d, 0x3e, 0x99, 0xd4, 0x2f, 0x2f, 0x74, 0x42, 0xda, 0x53, 0xe9, 0x5a, 0x72, 0x90, 0x73, 0x14, 0xf4, 0x58, 0x83, 0x99, 0xa3, 0xff, 0x5b, 0x0a, 0x92, 0xbe, 0xb3, 0xf6, 0xbe, 0x26, 0x94, 0xf9, 0xf8, 0x6e, 0xcf, 0x29, 0x52, 0xd5, 0xb4, 0x1c },
+ { 0xc5, 0x16, 0x54, 0x17, 0x01, 0x86, 0x3f, 0x91, 0x00, 0x5f, 0x31, 0x41, 0x08, 0xce, 0xec, 0xe3, 0xc6, 0x43, 0xe0, 0x4f, 0xc8, 0xc4, 0x2f, 0xd2, 0xff, 0x55, 0x62, 0x20, 0xe6, 0x16, 0xaa, 0xa6, 0xa4, 0x8a, 0xeb, 0x97, 0xa8, 0x4b, 0xad, 0x74, 0x78, 0x2e, 0x8d, 0xff, 0x96, 0xa1, 0xa2, 0xfa, 0x94, 0x93, 0x39, 0xd7, 0x22, 0xed, 0xca, 0xa3, 0x2b, 0x57, 0x06, 0x70, 0x41, 0xdf, 0x88, 0xcc },
+ { 0x98, 0x7f, 0xd6, 0xe0, 0xd6, 0x85, 0x7c, 0x55, 0x3e, 0xae, 0xbb, 0x3d, 0x34, 0x97, 0x0a, 0x2c, 0x2f, 0x6e, 0x89, 0xa3, 0x54, 0x8f, 0x49, 0x25, 0x21, 0x72, 0x2b, 0x80, 0xa1, 0xc2, 0x1a, 0x15, 0x38, 0x92, 0x34, 0x6d, 0x2c, 0xba, 0x64, 0x44, 0x21, 0x2d, 0x56, 0xda, 0x9a, 0x26, 0xe3, 0x24, 0xdc, 0xcb, 0xc0, 0xdc, 0xde, 0x85, 0xd4, 0xd2, 0xee, 0x43, 0x99, 0xee, 0xc5, 0xa6, 0x4e, 0x8f },
+ { 0xae, 0x56, 0xde, 0xb1, 0xc2, 0x32, 0x8d, 0x9c, 0x40, 0x17, 0x70, 0x6b, 0xce, 0x6e, 0x99, 0xd4, 0x13, 0x49, 0x05, 0x3b, 0xa9, 0xd3, 0x36, 0xd6, 0x77, 0xc4, 0xc2, 0x7d, 0x9f, 0xd5, 0x0a, 0xe6, 0xae, 0xe1, 0x7e, 0x85, 0x31, 0x54, 0xe1, 0xf4, 0xfe, 0x76, 0x72, 0x34, 0x6d, 0xa2, 0xea, 0xa3, 0x1e, 0xea, 0x53, 0xfc, 0xf2, 0x4a, 0x22, 0x80, 0x4f, 0x11, 0xd0, 0x3d, 0xa6, 0xab, 0xfc, 0x2b },
+ { 0x49, 0xd6, 0xa6, 0x08, 0xc9, 0xbd, 0xe4, 0x49, 0x18, 0x70, 0x49, 0x85, 0x72, 0xac, 0x31, 0xaa, 0xc3, 0xfa, 0x40, 0x93, 0x8b, 0x38, 0xa7, 0x81, 0x8f, 0x72, 0x38, 0x3e, 0xb0, 0x40, 0xad, 0x39, 0x53, 0x2b, 0xc0, 0x65, 0x71, 0xe1, 0x3d, 0x76, 0x7e, 0x69, 0x45, 0xab, 0x77, 0xc0, 0xbd, 0xc3, 0xb0, 0x28, 0x42, 0x53, 0x34, 0x3f, 0x9f, 0x6c, 0x12, 0x44, 0xeb, 0xf2, 0xff, 0x0d, 0xf8, 0x66 },
+ { 0xda, 0x58, 0x2a, 0xd8, 0xc5, 0x37, 0x0b, 0x44, 0x69, 0xaf, 0x86, 0x2a, 0xa6, 0x46, 0x7a, 0x22, 0x93, 0xb2, 0xb2, 0x8b, 0xd8, 0x0a, 0xe0, 0xe9, 0x1f, 0x42, 0x5a, 0xd3, 0xd4, 0x72, 0x49, 0xfd, 0xf9, 0x88, 0x25, 0xcc, 0x86, 0xf1, 0x40, 0x28, 0xc3, 0x30, 0x8c, 0x98, 0x04, 0xc7, 0x8b, 0xfe, 0xee, 0xee, 0x46, 0x14, 0x44, 0xce, 0x24, 0x36, 0x87, 0xe1, 0xa5, 0x05, 0x22, 0x45, 0x6a, 0x1d },
+ { 0xd5, 0x26, 0x6a, 0xa3, 0x33, 0x11, 0x94, 0xae, 0xf8, 0x52, 0xee, 0xd8, 0x6d, 0x7b, 0x5b, 0x26, 0x33, 0xa0, 0xaf, 0x1c, 0x73, 0x59, 0x06, 0xf2, 0xe1, 0x32, 0x79, 0xf1, 0x49, 0x31, 0xa9, 0xfc, 0x3b, 0x0e, 0xac, 0x5c, 0xe9, 0x24, 0x52, 0x73, 0xbd, 0x1a, 0xa9, 0x29, 0x05, 0xab, 0xe1, 0x62, 0x78, 0xef, 0x7e, 0xfd, 0x47, 0x69, 0x47, 0x89, 0xa7, 0x28, 0x3b, 0x77, 0xda, 0x3c, 0x70, 0xf8 },
+ { 0x29, 0x62, 0x73, 0x4c, 0x28, 0x25, 0x21, 0x86, 0xa9, 0xa1, 0x11, 0x1c, 0x73, 0x2a, 0xd4, 0xde, 0x45, 0x06, 0xd4, 0xb4, 0x48, 0x09, 0x16, 0x30, 0x3e, 0xb7, 0x99, 0x1d, 0x65, 0x9c, 0xcd, 0xa0, 0x7a, 0x99, 0x11, 0x91, 0x4b, 0xc7, 0x5c, 0x41, 0x8a, 0xb7, 0xa4, 0x54, 0x17, 0x57, 0xad, 0x05, 0x47, 0x96, 0xe2, 0x67, 0x97, 0xfe, 0xaf, 0x36, 0xe9, 0xf6, 0xad, 0x43, 0xf1, 0x4b, 0x35, 0xa4 },
+ { 0xe8, 0xb7, 0x9e, 0xc5, 0xd0, 0x6e, 0x11, 0x1b, 0xdf, 0xaf, 0xd7, 0x1e, 0x9f, 0x57, 0x60, 0xf0, 0x0a, 0xc8, 0xac, 0x5d, 0x8b, 0xf7, 0x68, 0xf9, 0xff, 0x6f, 0x08, 0xb8, 0xf0, 0x26, 0x09, 0x6b, 0x1c, 0xc3, 0xa4, 0xc9, 0x73, 0x33, 0x30, 0x19, 0xf1, 0xe3, 0x55, 0x3e, 0x77, 0xda, 0x3f, 0x98, 0xcb, 0x9f, 0x54, 0x2e, 0x0a, 0x90, 0xe5, 0xf8, 0xa9, 0x40, 0xcc, 0x58, 0xe5, 0x98, 0x44, 0xb3 },
+ { 0xdf, 0xb3, 0x20, 0xc4, 0x4f, 0x9d, 0x41, 0xd1, 0xef, 0xdc, 0xc0, 0x15, 0xf0, 0x8d, 0xd5, 0x53, 0x9e, 0x52, 0x6e, 0x39, 0xc8, 0x7d, 0x50, 0x9a, 0xe6, 0x81, 0x2a, 0x96, 0x9e, 0x54, 0x31, 0xbf, 0x4f, 0xa7, 0xd9, 0x1f, 0xfd, 0x03, 0xb9, 0x81, 0xe0, 0xd5, 0x44, 0xcf, 0x72, 0xd7, 0xb1, 0xc0, 0x37, 0x4f, 0x88, 0x01, 0x48, 0x2e, 0x6d, 0xea, 0x2e, 0xf9, 0x03, 0x87, 0x7e, 0xba, 0x67, 0x5e },
+ { 0xd8, 0x86, 0x75, 0x11, 0x8f, 0xdb, 0x55, 0xa5, 0xfb, 0x36, 0x5a, 0xc2, 0xaf, 0x1d, 0x21, 0x7b, 0xf5, 0x26, 0xce, 0x1e, 0xe9, 0xc9, 0x4b, 0x2f, 0x00, 0x90, 0xb2, 0xc5, 0x8a, 0x06, 0xca, 0x58, 0x18, 0x7d, 0x7f, 0xe5, 0x7c, 0x7b, 0xed, 0x9d, 0x26, 0xfc, 0xa0, 0x67, 0xb4, 0x11, 0x0e, 0xef, 0xcd, 0x9a, 0x0a, 0x34, 0x5d, 0xe8, 0x72, 0xab, 0xe2, 0x0d, 0xe3, 0x68, 0x00, 0x1b, 0x07, 0x45 },
+ { 0xb8, 0x93, 0xf2, 0xfc, 0x41, 0xf7, 0xb0, 0xdd, 0x6e, 0x2f, 0x6a, 0xa2, 0xe0, 0x37, 0x0c, 0x0c, 0xff, 0x7d, 0xf0, 0x9e, 0x3a, 0xcf, 0xcc, 0x0e, 0x92, 0x0b, 0x6e, 0x6f, 0xad, 0x0e, 0xf7, 0x47, 0xc4, 0x06, 0x68, 0x41, 0x7d, 0x34, 0x2b, 0x80, 0xd2, 0x35, 0x1e, 0x8c, 0x17, 0x5f, 0x20, 0x89, 0x7a, 0x06, 0x2e, 0x97, 0x65, 0xe6, 0xc6, 0x7b, 0x53, 0x9b, 0x6b, 0xa8, 0xb9, 0x17, 0x05, 0x45 },
+ { 0x6c, 0x67, 0xec, 0x56, 0x97, 0xac, 0xcd, 0x23, 0x5c, 0x59, 0xb4, 0x86, 0xd7, 0xb7, 0x0b, 0xae, 0xed, 0xcb, 0xd4, 0xaa, 0x64, 0xeb, 0xd4, 0xee, 0xf3, 0xc7, 0xea, 0xc1, 0x89, 0x56, 0x1a, 0x72, 0x62, 0x50, 0xae, 0xc4, 0xd4, 0x8c, 0xad, 0xca, 0xfb, 0xbe, 0x2c, 0xe3, 0xc1, 0x6c, 0xe2, 0xd6, 0x91, 0xa8, 0xcc, 0xe0, 0x6e, 0x88, 0x79, 0x55, 0x6d, 0x44, 0x83, 0xed, 0x71, 0x65, 0xc0, 0x63 },
+ { 0xf1, 0xaa, 0x2b, 0x04, 0x4f, 0x8f, 0x0c, 0x63, 0x8a, 0x3f, 0x36, 0x2e, 0x67, 0x7b, 0x5d, 0x89, 0x1d, 0x6f, 0xd2, 0xab, 0x07, 0x65, 0xf6, 0xee, 0x1e, 0x49, 0x87, 0xde, 0x05, 0x7e, 0xad, 0x35, 0x78, 0x83, 0xd9, 0xb4, 0x05, 0xb9, 0xd6, 0x09, 0xee, 0xa1, 0xb8, 0x69, 0xd9, 0x7f, 0xb1, 0x6d, 0x9b, 0x51, 0x01, 0x7c, 0x55, 0x3f, 0x3b, 0x93, 0xc0, 0xa1, 0xe0, 0xf1, 0x29, 0x6f, 0xed, 0xcd },
+ { 0xcb, 0xaa, 0x25, 0x95, 0x72, 0xd4, 0xae, 0xbf, 0xc1, 0x91, 0x7a, 0xcd, 0xdc, 0x58, 0x2b, 0x9f, 0x8d, 0xfa, 0xa9, 0x28, 0xa1, 0x98, 0xca, 0x7a, 0xcd, 0x0f, 0x2a, 0xa7, 0x6a, 0x13, 0x4a, 0x90, 0x25, 0x2e, 0x62, 0x98, 0xa6, 0x5b, 0x08, 0x18, 0x6a, 0x35, 0x0d, 0x5b, 0x76, 0x26, 0x69, 0x9f, 0x8c, 0xb7, 0x21, 0xa3, 0xea, 0x59, 0x21, 0xb7, 0x53, 0xae, 0x3a, 0x2d, 0xce, 0x24, 0xba, 0x3a },
+ { 0xfa, 0x15, 0x49, 0xc9, 0x79, 0x6c, 0xd4, 0xd3, 0x03, 0xdc, 0xf4, 0x52, 0xc1, 0xfb, 0xd5, 0x74, 0x4f, 0xd9, 0xb9, 0xb4, 0x70, 0x03, 0xd9, 0x20, 0xb9, 0x2d, 0xe3, 0x48, 0x39, 0xd0, 0x7e, 0xf2, 0xa2, 0x9d, 0xed, 0x68, 0xf6, 0xfc, 0x9e, 0x6c, 0x45, 0xe0, 0x71, 0xa2, 0xe4, 0x8b, 0xd5, 0x0c, 0x50, 0x84, 0xe9, 0x6b, 0x65, 0x7d, 0xd0, 0x40, 0x40, 0x45, 0xa1, 0xdd, 0xef, 0xe2, 0x82, 0xed },
+ { 0x5c, 0xf2, 0xac, 0x89, 0x7a, 0xb4, 0x44, 0xdc, 0xb5, 0xc8, 0xd8, 0x7c, 0x49, 0x5d, 0xbd, 0xb3, 0x4e, 0x18, 0x38, 0xb6, 0xb6, 0x29, 0x42, 0x7c, 0xaa, 0x51, 0x70, 0x2a, 0xd0, 0xf9, 0x68, 0x85, 0x25, 0xf1, 0x3b, 0xec, 0x50, 0x3a, 0x3c, 0x3a, 0x2c, 0x80, 0xa6, 0x5e, 0x0b, 0x57, 0x15, 0xe8, 0xaf, 0xab, 0x00, 0xff, 0xa5, 0x6e, 0xc4, 0x55, 0xa4, 0x9a, 0x1a, 0xd3, 0x0a, 0xa2, 0x4f, 0xcd },
+ { 0x9a, 0xaf, 0x80, 0x20, 0x7b, 0xac, 0xe1, 0x7b, 0xb7, 0xab, 0x14, 0x57, 0x57, 0xd5, 0x69, 0x6b, 0xde, 0x32, 0x40, 0x6e, 0xf2, 0x2b, 0x44, 0x29, 0x2e, 0xf6, 0x5d, 0x45, 0x19, 0xc3, 0xbb, 0x2a, 0xd4, 0x1a, 0x59, 0xb6, 0x2c, 0xc3, 0xe9, 0x4b, 0x6f, 0xa9, 0x6d, 0x32, 0xa7, 0xfa, 0xad, 0xae, 0x28, 0xaf, 0x7d, 0x35, 0x09, 0x72, 0x19, 0xaa, 0x3f, 0xd8, 0xcd, 0xa3, 0x1e, 0x40, 0xc2, 0x75 },
+ { 0xaf, 0x88, 0xb1, 0x63, 0x40, 0x2c, 0x86, 0x74, 0x5c, 0xb6, 0x50, 0xc2, 0x98, 0x8f, 0xb9, 0x52, 0x11, 0xb9, 0x4b, 0x03, 0xef, 0x29, 0x0e, 0xed, 0x96, 0x62, 0x03, 0x42, 0x41, 0xfd, 0x51, 0xcf, 0x39, 0x8f, 0x80, 0x73, 0xe3, 0x69, 0x35, 0x4c, 0x43, 0xea, 0xe1, 0x05, 0x2f, 0x9b, 0x63, 0xb0, 0x81, 0x91, 0xca, 0xa1, 0x38, 0xaa, 0x54, 0xfe, 0xa8, 0x89, 0xcc, 0x70, 0x24, 0x23, 0x68, 0x97 },
+ { 0x48, 0xfa, 0x7d, 0x64, 0xe1, 0xce, 0xee, 0x27, 0xb9, 0x86, 0x4d, 0xb5, 0xad, 0xa4, 0xb5, 0x3d, 0x00, 0xc9, 0xbc, 0x76, 0x26, 0x55, 0x58, 0x13, 0xd3, 0xcd, 0x67, 0x30, 0xab, 0x3c, 0xc0, 0x6f, 0xf3, 0x42, 0xd7, 0x27, 0x90, 0x5e, 0x33, 0x17, 0x1b, 0xde, 0x6e, 0x84, 0x76, 0xe7, 0x7f, 0xb1, 0x72, 0x08, 0x61, 0xe9, 0x4b, 0x73, 0xa2, 0xc5, 0x38, 0xd2, 0x54, 0x74, 0x62, 0x85, 0xf4, 0x30 },
+ { 0x0e, 0x6f, 0xd9, 0x7a, 0x85, 0xe9, 0x04, 0xf8, 0x7b, 0xfe, 0x85, 0xbb, 0xeb, 0x34, 0xf6, 0x9e, 0x1f, 0x18, 0x10, 0x5c, 0xf4, 0xed, 0x4f, 0x87, 0xae, 0xc3, 0x6c, 0x6e, 0x8b, 0x5f, 0x68, 0xbd, 0x2a, 0x6f, 0x3d, 0xc8, 0xa9, 0xec, 0xb2, 0xb6, 0x1d, 0xb4, 0xee, 0xdb, 0x6b, 0x2e, 0xa1, 0x0b, 0xf9, 0xcb, 0x02, 0x51, 0xfb, 0x0f, 0x8b, 0x34, 0x4a, 0xbf, 0x7f, 0x36, 0x6b, 0x6d, 0xe5, 0xab },
+ { 0x06, 0x62, 0x2d, 0xa5, 0x78, 0x71, 0x76, 0x28, 0x7f, 0xdc, 0x8f, 0xed, 0x44, 0x0b, 0xad, 0x18, 0x7d, 0x83, 0x00, 0x99, 0xc9, 0x4e, 0x6d, 0x04, 0xc8, 0xe9, 0xc9, 0x54, 0xcd, 0xa7, 0x0c, 0x8b, 0xb9, 0xe1, 0xfc, 0x4a, 0x6d, 0x0b, 0xaa, 0x83, 0x1b, 0x9b, 0x78, 0xef, 0x66, 0x48, 0x68, 0x1a, 0x48, 0x67, 0xa1, 0x1d, 0xa9, 0x3e, 0xe3, 0x6e, 0x5e, 0x6a, 0x37, 0xd8, 0x7f, 0xc6, 0x3f, 0x6f },
+ { 0x1d, 0xa6, 0x77, 0x2b, 0x58, 0xfa, 0xbf, 0x9c, 0x61, 0xf6, 0x8d, 0x41, 0x2c, 0x82, 0xf1, 0x82, 0xc0, 0x23, 0x6d, 0x7d, 0x57, 0x5e, 0xf0, 0xb5, 0x8d, 0xd2, 0x24, 0x58, 0xd6, 0x43, 0xcd, 0x1d, 0xfc, 0x93, 0xb0, 0x38, 0x71, 0xc3, 0x16, 0xd8, 0x43, 0x0d, 0x31, 0x29, 0x95, 0xd4, 0x19, 0x7f, 0x08, 0x74, 0xc9, 0x91, 0x72, 0xba, 0x00, 0x4a, 0x01, 0xee, 0x29, 0x5a, 0xba, 0xc2, 0x4e, 0x46 },
+ { 0x3c, 0xd2, 0xd9, 0x32, 0x0b, 0x7b, 0x1d, 0x5f, 0xb9, 0xaa, 0xb9, 0x51, 0xa7, 0x60, 0x23, 0xfa, 0x66, 0x7b, 0xe1, 0x4a, 0x91, 0x24, 0xe3, 0x94, 0x51, 0x39, 0x18, 0xa3, 0xf4, 0x40, 0x96, 0xae, 0x49, 0x04, 0xba, 0x0f, 0xfc, 0x15, 0x0b, 0x63, 0xbc, 0x7a, 0xb1, 0xee, 0xb9, 0xa6, 0xe2, 0x57, 0xe5, 0xc8, 0xf0, 0x00, 0xa7, 0x03, 0x94, 0xa5, 0xaf, 0xd8, 0x42, 0x71, 0x5d, 0xe1, 0x5f, 0x29 },
+ { 0x04, 0xcd, 0xc1, 0x4f, 0x74, 0x34, 0xe0, 0xb4, 0xbe, 0x70, 0xcb, 0x41, 0xdb, 0x4c, 0x77, 0x9a, 0x88, 0xea, 0xef, 0x6a, 0xcc, 0xeb, 0xcb, 0x41, 0xf2, 0xd4, 0x2f, 0xff, 0xe7, 0xf3, 0x2a, 0x8e, 0x28, 0x1b, 0x5c, 0x10, 0x3a, 0x27, 0x02, 0x1d, 0x0d, 0x08, 0x36, 0x22, 0x50, 0x75, 0x3c, 0xdf, 0x70, 0x29, 0x21, 0x95, 0xa5, 0x3a, 0x48, 0x72, 0x8c, 0xeb, 0x58, 0x44, 0xc2, 0xd9, 0x8b, 0xab },
+ { 0x90, 0x71, 0xb7, 0xa8, 0xa0, 0x75, 0xd0, 0x09, 0x5b, 0x8f, 0xb3, 0xae, 0x51, 0x13, 0x78, 0x57, 0x35, 0xab, 0x98, 0xe2, 0xb5, 0x2f, 0xaf, 0x91, 0xd5, 0xb8, 0x9e, 0x44, 0xaa, 0xc5, 0xb5, 0xd4, 0xeb, 0xbf, 0x91, 0x22, 0x3b, 0x0f, 0xf4, 0xc7, 0x19, 0x05, 0xda, 0x55, 0x34, 0x2e, 0x64, 0x65, 0x5d, 0x6e, 0xf8, 0xc8, 0x9a, 0x47, 0x68, 0xc3, 0xf9, 0x3a, 0x6d, 0xc0, 0x36, 0x6b, 0x5b, 0xc8 },
+ { 0xeb, 0xb3, 0x02, 0x40, 0xdd, 0x96, 0xc7, 0xbc, 0x8d, 0x0a, 0xbe, 0x49, 0xaa, 0x4e, 0xdc, 0xbb, 0x4a, 0xfd, 0xc5, 0x1f, 0xf9, 0xaa, 0xf7, 0x20, 0xd3, 0xf9, 0xe7, 0xfb, 0xb0, 0xf9, 0xc6, 0xd6, 0x57, 0x13, 0x50, 0x50, 0x17, 0x69, 0xfc, 0x4e, 0xbd, 0x0b, 0x21, 0x41, 0x24, 0x7f, 0xf4, 0x00, 0xd4, 0xfd, 0x4b, 0xe4, 0x14, 0xed, 0xf3, 0x77, 0x57, 0xbb, 0x90, 0xa3, 0x2a, 0xc5, 0xc6, 0x5a },
+ { 0x85, 0x32, 0xc5, 0x8b, 0xf3, 0xc8, 0x01, 0x5d, 0x9d, 0x1c, 0xbe, 0x00, 0xee, 0xf1, 0xf5, 0x08, 0x2f, 0x8f, 0x36, 0x32, 0xfb, 0xe9, 0xf1, 0xed, 0x4f, 0x9d, 0xfb, 0x1f, 0xa7, 0x9e, 0x82, 0x83, 0x06, 0x6d, 0x77, 0xc4, 0x4c, 0x4a, 0xf9, 0x43, 0xd7, 0x6b, 0x30, 0x03, 0x64, 0xae, 0xcb, 0xd0, 0x64, 0x8c, 0x8a, 0x89, 0x39, 0xbd, 0x20, 0x41, 0x23, 0xf4, 0xb5, 0x62, 0x60, 0x42, 0x2d, 0xec },
+ { 0xfe, 0x98, 0x46, 0xd6, 0x4f, 0x7c, 0x77, 0x08, 0x69, 0x6f, 0x84, 0x0e, 0x2d, 0x76, 0xcb, 0x44, 0x08, 0xb6, 0x59, 0x5c, 0x2f, 0x81, 0xec, 0x6a, 0x28, 0xa7, 0xf2, 0xf2, 0x0c, 0xb8, 0x8c, 0xfe, 0x6a, 0xc0, 0xb9, 0xe9, 0xb8, 0x24, 0x4f, 0x08, 0xbd, 0x70, 0x95, 0xc3, 0x50, 0xc1, 0xd0, 0x84, 0x2f, 0x64, 0xfb, 0x01, 0xbb, 0x7f, 0x53, 0x2d, 0xfc, 0xd4, 0x73, 0x71, 0xb0, 0xae, 0xeb, 0x79 },
+ { 0x28, 0xf1, 0x7e, 0xa6, 0xfb, 0x6c, 0x42, 0x09, 0x2d, 0xc2, 0x64, 0x25, 0x7e, 0x29, 0x74, 0x63, 0x21, 0xfb, 0x5b, 0xda, 0xea, 0x98, 0x73, 0xc2, 0xa7, 0xfa, 0x9d, 0x8f, 0x53, 0x81, 0x8e, 0x89, 0x9e, 0x16, 0x1b, 0xc7, 0x7d, 0xfe, 0x80, 0x90, 0xaf, 0xd8, 0x2b, 0xf2, 0x26, 0x6c, 0x5c, 0x1b, 0xc9, 0x30, 0xa8, 0xd1, 0x54, 0x76, 0x24, 0x43, 0x9e, 0x66, 0x2e, 0xf6, 0x95, 0xf2, 0x6f, 0x24 },
+ { 0xec, 0x6b, 0x7d, 0x7f, 0x03, 0x0d, 0x48, 0x50, 0xac, 0xae, 0x3c, 0xb6, 0x15, 0xc2, 0x1d, 0xd2, 0x52, 0x06, 0xd6, 0x3e, 0x84, 0xd1, 0xdb, 0x8d, 0x95, 0x73, 0x70, 0x73, 0x7b, 0xa0, 0xe9, 0x84, 0x67, 0xea, 0x0c, 0xe2, 0x74, 0xc6, 0x61, 0x99, 0x90, 0x1e, 0xae, 0xc1, 0x8a, 0x08, 0x52, 0x57, 0x15, 0xf5, 0x3b, 0xfd, 0xb0, 0xaa, 0xcb, 0x61, 0x3d, 0x34, 0x2e, 0xbd, 0xce, 0xed, 0xdc, 0x3b },
+ { 0xb4, 0x03, 0xd3, 0x69, 0x1c, 0x03, 0xb0, 0xd3, 0x41, 0x8d, 0xf3, 0x27, 0xd5, 0x86, 0x0d, 0x34, 0xbb, 0xfc, 0xc4, 0x51, 0x9b, 0xfb, 0xce, 0x36, 0xbf, 0x33, 0xb2, 0x08, 0x38, 0x5f, 0xad, 0xb9, 0x18, 0x6b, 0xc7, 0x8a, 0x76, 0xc4, 0x89, 0xd8, 0x9f, 0xd5, 0x7e, 0x7d, 0xc7, 0x54, 0x12, 0xd2, 0x3b, 0xcd, 0x1d, 0xae, 0x84, 0x70, 0xce, 0x92, 0x74, 0x75, 0x4b, 0xb8, 0x58, 0x5b, 0x13, 0xc5 },
+ { 0x31, 0xfc, 0x79, 0x73, 0x8b, 0x87, 0x72, 0xb3, 0xf5, 0x5c, 0xd8, 0x17, 0x88, 0x13, 0xb3, 0xb5, 0x2d, 0x0d, 0xb5, 0xa4, 0x19, 0xd3, 0x0b, 0xa9, 0x49, 0x5c, 0x4b, 0x9d, 0xa0, 0x21, 0x9f, 0xac, 0x6d, 0xf8, 0xe7, 0xc2, 0x3a, 0x81, 0x15, 0x51, 0xa6, 0x2b, 0x82, 0x7f, 0x25, 0x6e, 0xcd, 0xb8, 0x12, 0x4a, 0xc8, 0xa6, 0x79, 0x2c, 0xcf, 0xec, 0xc3, 0xb3, 0x01, 0x27, 0x22, 0xe9, 0x44, 0x63 },
+ { 0xbb, 0x20, 0x39, 0xec, 0x28, 0x70, 0x91, 0xbc, 0xc9, 0x64, 0x2f, 0xc9, 0x00, 0x49, 0xe7, 0x37, 0x32, 0xe0, 0x2e, 0x57, 0x7e, 0x28, 0x62, 0xb3, 0x22, 0x16, 0xae, 0x9b, 0xed, 0xcd, 0x73, 0x0c, 0x4c, 0x28, 0x4e, 0xf3, 0x96, 0x8c, 0x36, 0x8b, 0x7d, 0x37, 0x58, 0x4f, 0x97, 0xbd, 0x4b, 0x4d, 0xc6, 0xef, 0x61, 0x27, 0xac, 0xfe, 0x2e, 0x6a, 0xe2, 0x50, 0x91, 0x24, 0xe6, 0x6c, 0x8a, 0xf4 },
+ { 0xf5, 0x3d, 0x68, 0xd1, 0x3f, 0x45, 0xed, 0xfc, 0xb9, 0xbd, 0x41, 0x5e, 0x28, 0x31, 0xe9, 0x38, 0x35, 0x0d, 0x53, 0x80, 0xd3, 0x43, 0x22, 0x78, 0xfc, 0x1c, 0x0c, 0x38, 0x1f, 0xcb, 0x7c, 0x65, 0xc8, 0x2d, 0xaf, 0xe0, 0x51, 0xd8, 0xc8, 0xb0, 0xd4, 0x4e, 0x09, 0x74, 0xa0, 0xe5, 0x9e, 0xc7, 0xbf, 0x7e, 0xd0, 0x45, 0x9f, 0x86, 0xe9, 0x6f, 0x32, 0x9f, 0xc7, 0x97, 0x52, 0x51, 0x0f, 0xd3 },
+ { 0x8d, 0x56, 0x8c, 0x79, 0x84, 0xf0, 0xec, 0xdf, 0x76, 0x40, 0xfb, 0xc4, 0x83, 0xb5, 0xd8, 0xc9, 0xf8, 0x66, 0x34, 0xf6, 0xf4, 0x32, 0x91, 0x84, 0x1b, 0x30, 0x9a, 0x35, 0x0a, 0xb9, 0xc1, 0x13, 0x7d, 0x24, 0x06, 0x6b, 0x09, 0xda, 0x99, 0x44, 0xba, 0xc5, 0x4d, 0x5b, 0xb6, 0x58, 0x0d, 0x83, 0x60, 0x47, 0xaa, 0xc7, 0x4a, 0xb7, 0x24, 0xb8, 0x87, 0xeb, 0xf9, 0x3d, 0x4b, 0x32, 0xec, 0xa9 },
+ { 0xc0, 0xb6, 0x5c, 0xe5, 0xa9, 0x6f, 0xf7, 0x74, 0xc4, 0x56, 0xca, 0xc3, 0xb5, 0xf2, 0xc4, 0xcd, 0x35, 0x9b, 0x4f, 0xf5, 0x3e, 0xf9, 0x3a, 0x3d, 0xa0, 0x77, 0x8b, 0xe4, 0x90, 0x0d, 0x1e, 0x8d, 0xa1, 0x60, 0x1e, 0x76, 0x9e, 0x8f, 0x1b, 0x02, 0xd2, 0xa2, 0xf8, 0xc5, 0xb9, 0xfa, 0x10, 0xb4, 0x4f, 0x1c, 0x18, 0x69, 0x85, 0x46, 0x8f, 0xee, 0xb0, 0x08, 0x73, 0x02, 0x83, 0xa6, 0x65, 0x7d },
+ { 0x49, 0x00, 0xbb, 0xa6, 0xf5, 0xfb, 0x10, 0x3e, 0xce, 0x8e, 0xc9, 0x6a, 0xda, 0x13, 0xa5, 0xc3, 0xc8, 0x54, 0x88, 0xe0, 0x55, 0x51, 0xda, 0x6b, 0x6b, 0x33, 0xd9, 0x88, 0xe6, 0x11, 0xec, 0x0f, 0xe2, 0xe3, 0xc2, 0xaa, 0x48, 0xea, 0x6a, 0xe8, 0x98, 0x6a, 0x3a, 0x23, 0x1b, 0x22, 0x3c, 0x5d, 0x27, 0xce, 0xc2, 0xea, 0xdd, 0xe9, 0x1c, 0xe0, 0x79, 0x81, 0xee, 0x65, 0x28, 0x62, 0xd1, 0xe4 },
+ { 0xc7, 0xf5, 0xc3, 0x7c, 0x72, 0x85, 0xf9, 0x27, 0xf7, 0x64, 0x43, 0x41, 0x4d, 0x43, 0x57, 0xff, 0x78, 0x96, 0x47, 0xd7, 0xa0, 0x05, 0xa5, 0xa7, 0x87, 0xe0, 0x3c, 0x34, 0x6b, 0x57, 0xf4, 0x9f, 0x21, 0xb6, 0x4f, 0xa9, 0xcf, 0x4b, 0x7e, 0x45, 0x57, 0x3e, 0x23, 0x04, 0x90, 0x17, 0x56, 0x71, 0x21, 0xa9, 0xc3, 0xd4, 0xb2, 0xb7, 0x3e, 0xc5, 0xe9, 0x41, 0x35, 0x77, 0x52, 0x5d, 0xb4, 0x5a },
+ { 0xec, 0x70, 0x96, 0x33, 0x07, 0x36, 0xfd, 0xb2, 0xd6, 0x4b, 0x56, 0x53, 0xe7, 0x47, 0x5d, 0xa7, 0x46, 0xc2, 0x3a, 0x46, 0x13, 0xa8, 0x26, 0x87, 0xa2, 0x80, 0x62, 0xd3, 0x23, 0x63, 0x64, 0x28, 0x4a, 0xc0, 0x17, 0x20, 0xff, 0xb4, 0x06, 0xcf, 0xe2, 0x65, 0xc0, 0xdf, 0x62, 0x6a, 0x18, 0x8c, 0x9e, 0x59, 0x63, 0xac, 0xe5, 0xd3, 0xd5, 0xbb, 0x36, 0x3e, 0x32, 0xc3, 0x8c, 0x21, 0x90, 0xa6 },
+ { 0x82, 0xe7, 0x44, 0xc7, 0x5f, 0x46, 0x49, 0xec, 0x52, 0xb8, 0x07, 0x71, 0xa7, 0x7d, 0x47, 0x5a, 0x3b, 0xc0, 0x91, 0x98, 0x95, 0x56, 0x96, 0x0e, 0x27, 0x6a, 0x5f, 0x9e, 0xad, 0x92, 0xa0, 0x3f, 0x71, 0x87, 0x42, 0xcd, 0xcf, 0xea, 0xee, 0x5c, 0xb8, 0x5c, 0x44, 0xaf, 0x19, 0x8a, 0xdc, 0x43, 0xa4, 0xa4, 0x28, 0xf5, 0xf0, 0xc2, 0xdd, 0xb0, 0xbe, 0x36, 0x05, 0x9f, 0x06, 0xd7, 0xdf, 0x73 },
+ { 0x28, 0x34, 0xb7, 0xa7, 0x17, 0x0f, 0x1f, 0x5b, 0x68, 0x55, 0x9a, 0xb7, 0x8c, 0x10, 0x50, 0xec, 0x21, 0xc9, 0x19, 0x74, 0x0b, 0x78, 0x4a, 0x90, 0x72, 0xf6, 0xe5, 0xd6, 0x9f, 0x82, 0x8d, 0x70, 0xc9, 0x19, 0xc5, 0x03, 0x9f, 0xb1, 0x48, 0xe3, 0x9e, 0x2c, 0x8a, 0x52, 0x11, 0x83, 0x78, 0xb0, 0x64, 0xca, 0x8d, 0x50, 0x01, 0xcd, 0x10, 0xa5, 0x47, 0x83, 0x87, 0xb9, 0x66, 0x71, 0x5e, 0xd6 },
+ { 0x16, 0xb4, 0xad, 0xa8, 0x83, 0xf7, 0x2f, 0x85, 0x3b, 0xb7, 0xef, 0x25, 0x3e, 0xfc, 0xab, 0x0c, 0x3e, 0x21, 0x61, 0x68, 0x7a, 0xd6, 0x15, 0x43, 0xa0, 0xd2, 0x82, 0x4f, 0x91, 0xc1, 0xf8, 0x13, 0x47, 0xd8, 0x6b, 0xe7, 0x09, 0xb1, 0x69, 0x96, 0xe1, 0x7f, 0x2d, 0xd4, 0x86, 0x92, 0x7b, 0x02, 0x88, 0xad, 0x38, 0xd1, 0x30, 0x63, 0xc4, 0xa9, 0x67, 0x2c, 0x39, 0x39, 0x7d, 0x37, 0x89, 0xb6 },
+ { 0x78, 0xd0, 0x48, 0xf3, 0xa6, 0x9d, 0x8b, 0x54, 0xae, 0x0e, 0xd6, 0x3a, 0x57, 0x3a, 0xe3, 0x50, 0xd8, 0x9f, 0x7c, 0x6c, 0xf1, 0xf3, 0x68, 0x89, 0x30, 0xde, 0x89, 0x9a, 0xfa, 0x03, 0x76, 0x97, 0x62, 0x9b, 0x31, 0x4e, 0x5c, 0xd3, 0x03, 0xaa, 0x62, 0xfe, 0xea, 0x72, 0xa2, 0x5b, 0xf4, 0x2b, 0x30, 0x4b, 0x6c, 0x6b, 0xcb, 0x27, 0xfa, 0xe2, 0x1c, 0x16, 0xd9, 0x25, 0xe1, 0xfb, 0xda, 0xc3 },
+ { 0x0f, 0x74, 0x6a, 0x48, 0x74, 0x92, 0x87, 0xad, 0xa7, 0x7a, 0x82, 0x96, 0x1f, 0x05, 0xa4, 0xda, 0x4a, 0xbd, 0xb7, 0xd7, 0x7b, 0x12, 0x20, 0xf8, 0x36, 0xd0, 0x9e, 0xc8, 0x14, 0x35, 0x9c, 0x0e, 0xc0, 0x23, 0x9b, 0x8c, 0x7b, 0x9f, 0xf9, 0xe0, 0x2f, 0x56, 0x9d, 0x1b, 0x30, 0x1e, 0xf6, 0x7c, 0x46, 0x12, 0xd1, 0xde, 0x4f, 0x73, 0x0f, 0x81, 0xc1, 0x2c, 0x40, 0xcc, 0x06, 0x3c, 0x5c, 0xaa },
+ { 0xf0, 0xfc, 0x85, 0x9d, 0x3b, 0xd1, 0x95, 0xfb, 0xdc, 0x2d, 0x59, 0x1e, 0x4c, 0xda, 0xc1, 0x51, 0x79, 0xec, 0x0f, 0x1d, 0xc8, 0x21, 0xc1, 0x1d, 0xf1, 0xf0, 0xc1, 0xd2, 0x6e, 0x62, 0x60, 0xaa, 0xa6, 0x5b, 0x79, 0xfa, 0xfa, 0xca, 0xfd, 0x7d, 0x3a, 0xd6, 0x1e, 0x60, 0x0f, 0x25, 0x09, 0x05, 0xf5, 0x87, 0x8c, 0x87, 0x45, 0x28, 0x97, 0x64, 0x7a, 0x35, 0xb9, 0x95, 0xbc, 0xad, 0xc3, 0xa3 },
+ { 0x26, 0x20, 0xf6, 0x87, 0xe8, 0x62, 0x5f, 0x6a, 0x41, 0x24, 0x60, 0xb4, 0x2e, 0x2c, 0xef, 0x67, 0x63, 0x42, 0x08, 0xce, 0x10, 0xa0, 0xcb, 0xd4, 0xdf, 0xf7, 0x04, 0x4a, 0x41, 0xb7, 0x88, 0x00, 0x77, 0xe9, 0xf8, 0xdc, 0x3b, 0x8d, 0x12, 0x16, 0xd3, 0x37, 0x6a, 0x21, 0xe0, 0x15, 0xb5, 0x8f, 0xb2, 0x79, 0xb5, 0x21, 0xd8, 0x3f, 0x93, 0x88, 0xc7, 0x38, 0x2c, 0x85, 0x05, 0x59, 0x0b, 0x9b },
+ { 0x22, 0x7e, 0x3a, 0xed, 0x8d, 0x2c, 0xb1, 0x0b, 0x91, 0x8f, 0xcb, 0x04, 0xf9, 0xde, 0x3e, 0x6d, 0x0a, 0x57, 0xe0, 0x84, 0x76, 0xd9, 0x37, 0x59, 0xcd, 0x7b, 0x2e, 0xd5, 0x4a, 0x1c, 0xbf, 0x02, 0x39, 0xc5, 0x28, 0xfb, 0x04, 0xbb, 0xf2, 0x88, 0x25, 0x3e, 0x60, 0x1d, 0x3b, 0xc3, 0x8b, 0x21, 0x79, 0x4a, 0xfe, 0xf9, 0x0b, 0x17, 0x09, 0x4a, 0x18, 0x2c, 0xac, 0x55, 0x77, 0x45, 0xe7, 0x5f },
+ { 0x1a, 0x92, 0x99, 0x01, 0xb0, 0x9c, 0x25, 0xf2, 0x7d, 0x6b, 0x35, 0xbe, 0x7b, 0x2f, 0x1c, 0x47, 0x45, 0x13, 0x1f, 0xde, 0xbc, 0xa7, 0xf3, 0xe2, 0x45, 0x19, 0x26, 0x72, 0x04, 0x34, 0xe0, 0xdb, 0x6e, 0x74, 0xfd, 0x69, 0x3a, 0xd2, 0x9b, 0x77, 0x7d, 0xc3, 0x35, 0x5c, 0x59, 0x2a, 0x36, 0x1c, 0x48, 0x73, 0xb0, 0x11, 0x33, 0xa5, 0x7c, 0x2e, 0x3b, 0x70, 0x75, 0xcb, 0xdb, 0x86, 0xf4, 0xfc },
+ { 0x5f, 0xd7, 0x96, 0x8b, 0xc2, 0xfe, 0x34, 0xf2, 0x20, 0xb5, 0xe3, 0xdc, 0x5a, 0xf9, 0x57, 0x17, 0x42, 0xd7, 0x3b, 0x7d, 0x60, 0x81, 0x9f, 0x28, 0x88, 0xb6, 0x29, 0x07, 0x2b, 0x96, 0xa9, 0xd8, 0xab, 0x2d, 0x91, 0xb8, 0x2d, 0x0a, 0x9a, 0xab, 0xa6, 0x1b, 0xbd, 0x39, 0x95, 0x81, 0x32, 0xfc, 0xc4, 0x25, 0x70, 0x23, 0xd1, 0xec, 0xa5, 0x91, 0xb3, 0x05, 0x4e, 0x2d, 0xc8, 0x1c, 0x82, 0x00 },
+ { 0xdf, 0xcc, 0xe8, 0xcf, 0x32, 0x87, 0x0c, 0xc6, 0xa5, 0x03, 0xea, 0xda, 0xfc, 0x87, 0xfd, 0x6f, 0x78, 0x91, 0x8b, 0x9b, 0x4d, 0x07, 0x37, 0xdb, 0x68, 0x10, 0xbe, 0x99, 0x6b, 0x54, 0x97, 0xe7, 0xe5, 0xcc, 0x80, 0xe3, 0x12, 0xf6, 0x1e, 0x71, 0xff, 0x3e, 0x96, 0x24, 0x43, 0x60, 0x73, 0x15, 0x64, 0x03, 0xf7, 0x35, 0xf5, 0x6b, 0x0b, 0x01, 0x84, 0x5c, 0x18, 0xf6, 0xca, 0xf7, 0x72, 0xe6 },
+ { 0x02, 0xf7, 0xef, 0x3a, 0x9c, 0xe0, 0xff, 0xf9, 0x60, 0xf6, 0x70, 0x32, 0xb2, 0x96, 0xef, 0xca, 0x30, 0x61, 0xf4, 0x93, 0x4d, 0x69, 0x07, 0x49, 0xf2, 0xd0, 0x1c, 0x35, 0xc8, 0x1c, 0x14, 0xf3, 0x9a, 0x67, 0xfa, 0x35, 0x0b, 0xc8, 0xa0, 0x35, 0x9b, 0xf1, 0x72, 0x4b, 0xff, 0xc3, 0xbc, 0xa6, 0xd7, 0xc7, 0xbb, 0xa4, 0x79, 0x1f, 0xd5, 0x22, 0xa3, 0xad, 0x35, 0x3c, 0x02, 0xec, 0x5a, 0xa8 },
+ { 0x64, 0xbe, 0x5c, 0x6a, 0xba, 0x65, 0xd5, 0x94, 0x84, 0x4a, 0xe7, 0x8b, 0xb0, 0x22, 0xe5, 0xbe, 0xbe, 0x12, 0x7f, 0xd6, 0xb6, 0xff, 0xa5, 0xa1, 0x37, 0x03, 0x85, 0x5a, 0xb6, 0x3b, 0x62, 0x4d, 0xcd, 0x1a, 0x36, 0x3f, 0x99, 0x20, 0x3f, 0x63, 0x2e, 0xc3, 0x86, 0xf3, 0xea, 0x76, 0x7f, 0xc9, 0x92, 0xe8, 0xed, 0x96, 0x86, 0x58, 0x6a, 0xa2, 0x75, 0x55, 0xa8, 0x59, 0x9d, 0x5b, 0x80, 0x8f },
+ { 0xf7, 0x85, 0x85, 0x50, 0x5c, 0x4e, 0xaa, 0x54, 0xa8, 0xb5, 0xbe, 0x70, 0xa6, 0x1e, 0x73, 0x5e, 0x0f, 0xf9, 0x7a, 0xf9, 0x44, 0xdd, 0xb3, 0x00, 0x1e, 0x35, 0xd8, 0x6c, 0x4e, 0x21, 0x99, 0xd9, 0x76, 0x10, 0x4b, 0x6a, 0xe3, 0x17, 0x50, 0xa3, 0x6a, 0x72, 0x6e, 0xd2, 0x85, 0x06, 0x4f, 0x59, 0x81, 0xb5, 0x03, 0x88, 0x9f, 0xef, 0x82, 0x2f, 0xcd, 0xc2, 0x89, 0x8d, 0xdd, 0xb7, 0x88, 0x9a },
+ { 0xe4, 0xb5, 0x56, 0x60, 0x33, 0x86, 0x95, 0x72, 0xed, 0xfd, 0x87, 0x47, 0x9a, 0x5b, 0xb7, 0x3c, 0x80, 0xe8, 0x75, 0x9b, 0x91, 0x23, 0x28, 0x79, 0xd9, 0x6b, 0x1d, 0xda, 0x36, 0xc0, 0x12, 0x07, 0x6e, 0xe5, 0xa2, 0xed, 0x7a, 0xe2, 0xde, 0x63, 0xef, 0x84, 0x06, 0xa0, 0x6a, 0xea, 0x82, 0xc1, 0x88, 0x03, 0x1b, 0x56, 0x0b, 0xea, 0xfb, 0x58, 0x3f, 0xb3, 0xde, 0x9e, 0x57, 0x95, 0x2a, 0x7e },
+ { 0xe1, 0xb3, 0xe7, 0xed, 0x86, 0x7f, 0x6c, 0x94, 0x84, 0xa2, 0xa9, 0x7f, 0x77, 0x15, 0xf2, 0x5e, 0x25, 0x29, 0x4e, 0x99, 0x2e, 0x41, 0xf6, 0xa7, 0xc1, 0x61, 0xff, 0xc2, 0xad, 0xc6, 0xda, 0xae, 0xb7, 0x11, 0x31, 0x02, 0xd5, 0xe6, 0x09, 0x02, 0x87, 0xfe, 0x6a, 0xd9, 0x4c, 0xe5, 0xd6, 0xb7, 0x39, 0xc6, 0xca, 0x24, 0x0b, 0x05, 0xc7, 0x6f, 0xb7, 0x3f, 0x25, 0xdd, 0x02, 0x4b, 0xf9, 0x35 },
+ { 0x85, 0xfd, 0x08, 0x5f, 0xdc, 0x12, 0xa0, 0x80, 0x98, 0x3d, 0xf0, 0x7b, 0xd7, 0x01, 0x2b, 0x0d, 0x40, 0x2a, 0x0f, 0x40, 0x43, 0xfc, 0xb2, 0x77, 0x5a, 0xdf, 0x0b, 0xad, 0x17, 0x4f, 0x9b, 0x08, 0xd1, 0x67, 0x6e, 0x47, 0x69, 0x85, 0x78, 0x5c, 0x0a, 0x5d, 0xcc, 0x41, 0xdb, 0xff, 0x6d, 0x95, 0xef, 0x4d, 0x66, 0xa3, 0xfb, 0xdc, 0x4a, 0x74, 0xb8, 0x2b, 0xa5, 0x2d, 0xa0, 0x51, 0x2b, 0x74 },
+ { 0xae, 0xd8, 0xfa, 0x76, 0x4b, 0x0f, 0xbf, 0xf8, 0x21, 0xe0, 0x52, 0x33, 0xd2, 0xf7, 0xb0, 0x90, 0x0e, 0xc4, 0x4d, 0x82, 0x6f, 0x95, 0xe9, 0x3c, 0x34, 0x3c, 0x1b, 0xc3, 0xba, 0x5a, 0x24, 0x37, 0x4b, 0x1d, 0x61, 0x6e, 0x7e, 0x7a, 0xba, 0x45, 0x3a, 0x0a, 0xda, 0x5e, 0x4f, 0xab, 0x53, 0x82, 0x40, 0x9e, 0x0d, 0x42, 0xce, 0x9c, 0x2b, 0xc7, 0xfb, 0x39, 0xa9, 0x9c, 0x34, 0x0c, 0x20, 0xf0 },
+ { 0x7b, 0xa3, 0xb2, 0xe2, 0x97, 0x23, 0x35, 0x22, 0xee, 0xb3, 0x43, 0xbd, 0x3e, 0xbc, 0xfd, 0x83, 0x5a, 0x04, 0x00, 0x77, 0x35, 0xe8, 0x7f, 0x0c, 0xa3, 0x00, 0xcb, 0xee, 0x6d, 0x41, 0x65, 0x65, 0x16, 0x21, 0x71, 0x58, 0x1e, 0x40, 0x20, 0xff, 0x4c, 0xf1, 0x76, 0x45, 0x0f, 0x12, 0x91, 0xea, 0x22, 0x85, 0xcb, 0x9e, 0xbf, 0xfe, 0x4c, 0x56, 0x66, 0x06, 0x27, 0x68, 0x51, 0x45, 0x05, 0x1c },
+ { 0xde, 0x74, 0x8b, 0xcf, 0x89, 0xec, 0x88, 0x08, 0x47, 0x21, 0xe1, 0x6b, 0x85, 0xf3, 0x0a, 0xdb, 0x1a, 0x61, 0x34, 0xd6, 0x64, 0xb5, 0x84, 0x35, 0x69, 0xba, 0xbc, 0x5b, 0xbd, 0x1a, 0x15, 0xca, 0x9b, 0x61, 0x80, 0x3c, 0x90, 0x1a, 0x4f, 0xef, 0x32, 0x96, 0x5a, 0x17, 0x49, 0xc9, 0xf3, 0xa4, 0xe2, 0x43, 0xe1, 0x73, 0x93, 0x9d, 0xc5, 0xa8, 0xdc, 0x49, 0x5c, 0x67, 0x1a, 0xb5, 0x21, 0x45 },
+ { 0xaa, 0xf4, 0xd2, 0xbd, 0xf2, 0x00, 0xa9, 0x19, 0x70, 0x6d, 0x98, 0x42, 0xdc, 0xe1, 0x6c, 0x98, 0x14, 0x0d, 0x34, 0xbc, 0x43, 0x3d, 0xf3, 0x20, 0xab, 0xa9, 0xbd, 0x42, 0x9e, 0x54, 0x9a, 0xa7, 0xa3, 0x39, 0x76, 0x52, 0xa4, 0xd7, 0x68, 0x27, 0x77, 0x86, 0xcf, 0x99, 0x3c, 0xde, 0x23, 0x38, 0x67, 0x3e, 0xd2, 0xe6, 0xb6, 0x6c, 0x96, 0x1f, 0xef, 0xb8, 0x2c, 0xd2, 0x0c, 0x93, 0x33, 0x8f },
+ { 0xc4, 0x08, 0x21, 0x89, 0x68, 0xb7, 0x88, 0xbf, 0x86, 0x4f, 0x09, 0x97, 0xe6, 0xbc, 0x4c, 0x3d, 0xba, 0x68, 0xb2, 0x76, 0xe2, 0x12, 0x5a, 0x48, 0x43, 0x29, 0x60, 0x52, 0xff, 0x93, 0xbf, 0x57, 0x67, 0xb8, 0xcd, 0xce, 0x71, 0x31, 0xf0, 0x87, 0x64, 0x30, 0xc1, 0x16, 0x5f, 0xec, 0x6c, 0x4f, 0x47, 0xad, 0xaa, 0x4f, 0xd8, 0xbc, 0xfa, 0xce, 0xf4, 0x63, 0xb5, 0xd3, 0xd0, 0xfa, 0x61, 0xa0 },
+ { 0x76, 0xd2, 0xd8, 0x19, 0xc9, 0x2b, 0xce, 0x55, 0xfa, 0x8e, 0x09, 0x2a, 0xb1, 0xbf, 0x9b, 0x9e, 0xab, 0x23, 0x7a, 0x25, 0x26, 0x79, 0x86, 0xca, 0xcf, 0x2b, 0x8e, 0xe1, 0x4d, 0x21, 0x4d, 0x73, 0x0d, 0xc9, 0xa5, 0xaa, 0x2d, 0x7b, 0x59, 0x6e, 0x86, 0xa1, 0xfd, 0x8f, 0xa0, 0x80, 0x4c, 0x77, 0x40, 0x2d, 0x2f, 0xcd, 0x45, 0x08, 0x36, 0x88, 0xb2, 0x18, 0xb1, 0xcd, 0xfa, 0x0d, 0xcb, 0xcb },
+ { 0x72, 0x06, 0x5e, 0xe4, 0xdd, 0x91, 0xc2, 0xd8, 0x50, 0x9f, 0xa1, 0xfc, 0x28, 0xa3, 0x7c, 0x7f, 0xc9, 0xfa, 0x7d, 0x5b, 0x3f, 0x8a, 0xd3, 0xd0, 0xd7, 0xa2, 0x56, 0x26, 0xb5, 0x7b, 0x1b, 0x44, 0x78, 0x8d, 0x4c, 0xaf, 0x80, 0x62, 0x90, 0x42, 0x5f, 0x98, 0x90, 0xa3, 0xa2, 0xa3, 0x5a, 0x90, 0x5a, 0xb4, 0xb3, 0x7a, 0xcf, 0xd0, 0xda, 0x6e, 0x45, 0x17, 0xb2, 0x52, 0x5c, 0x96, 0x51, 0xe4 },
+ { 0x64, 0x47, 0x5d, 0xfe, 0x76, 0x00, 0xd7, 0x17, 0x1b, 0xea, 0x0b, 0x39, 0x4e, 0x27, 0xc9, 0xb0, 0x0d, 0x8e, 0x74, 0xdd, 0x1e, 0x41, 0x6a, 0x79, 0x47, 0x36, 0x82, 0xad, 0x3d, 0xfd, 0xbb, 0x70, 0x66, 0x31, 0x55, 0x80, 0x55, 0xcf, 0xc8, 0xa4, 0x0e, 0x07, 0xbd, 0x01, 0x5a, 0x45, 0x40, 0xdc, 0xde, 0xa1, 0x58, 0x83, 0xcb, 0xbf, 0x31, 0x41, 0x2d, 0xf1, 0xde, 0x1c, 0xd4, 0x15, 0x2b, 0x91 },
+ { 0x12, 0xcd, 0x16, 0x74, 0xa4, 0x48, 0x8a, 0x5d, 0x7c, 0x2b, 0x31, 0x60, 0xd2, 0xe2, 0xc4, 0xb5, 0x83, 0x71, 0xbe, 0xda, 0xd7, 0x93, 0x41, 0x8d, 0x6f, 0x19, 0xc6, 0xee, 0x38, 0x5d, 0x70, 0xb3, 0xe0, 0x67, 0x39, 0x36, 0x9d, 0x4d, 0xf9, 0x10, 0xed, 0xb0, 0xb0, 0xa5, 0x4c, 0xbf, 0xf4, 0x3d, 0x54, 0x54, 0x4c, 0xd3, 0x7a, 0xb3, 0xa0, 0x6c, 0xfa, 0x0a, 0x3d, 0xda, 0xc8, 0xb6, 0x6c, 0x89 },
+ { 0x60, 0x75, 0x69, 0x66, 0x47, 0x9d, 0xed, 0xc6, 0xdd, 0x4b, 0xcf, 0xf8, 0xea, 0x7d, 0x1d, 0x4c, 0xe4, 0xd4, 0xaf, 0x2e, 0x7b, 0x09, 0x7e, 0x32, 0xe3, 0x76, 0x35, 0x18, 0x44, 0x11, 0x47, 0xcc, 0x12, 0xb3, 0xc0, 0xee, 0x6d, 0x2e, 0xca, 0xbf, 0x11, 0x98, 0xce, 0xc9, 0x2e, 0x86, 0xa3, 0x61, 0x6f, 0xba, 0x4f, 0x4e, 0x87, 0x2f, 0x58, 0x25, 0x33, 0x0a, 0xdb, 0xb4, 0xc1, 0xde, 0xe4, 0x44 },
+ { 0xa7, 0x80, 0x3b, 0xcb, 0x71, 0xbc, 0x1d, 0x0f, 0x43, 0x83, 0xdd, 0xe1, 0xe0, 0x61, 0x2e, 0x04, 0xf8, 0x72, 0xb7, 0x15, 0xad, 0x30, 0x81, 0x5c, 0x22, 0x49, 0xcf, 0x34, 0xab, 0xb8, 0xb0, 0x24, 0x91, 0x5c, 0xb2, 0xfc, 0x9f, 0x4e, 0x7c, 0xc4, 0xc8, 0xcf, 0xd4, 0x5b, 0xe2, 0xd5, 0xa9, 0x1e, 0xab, 0x09, 0x41, 0xc7, 0xd2, 0x70, 0xe2, 0xda, 0x4c, 0xa4, 0xa9, 0xf7, 0xac, 0x68, 0x66, 0x3a },
+ { 0xb8, 0x4e, 0xf6, 0xa7, 0x22, 0x9a, 0x34, 0xa7, 0x50, 0xd9, 0xa9, 0x8e, 0xe2, 0x52, 0x98, 0x71, 0x81, 0x6b, 0x87, 0xfb, 0xe3, 0xbc, 0x45, 0xb4, 0x5f, 0xa5, 0xae, 0x82, 0xd5, 0x14, 0x15, 0x40, 0x21, 0x11, 0x65, 0xc3, 0xc5, 0xd7, 0xa7, 0x47, 0x6b, 0xa5, 0xa4, 0xaa, 0x06, 0xd6, 0x64, 0x76, 0xf0, 0xd9, 0xdc, 0x49, 0xa3, 0xf1, 0xee, 0x72, 0xc3, 0xac, 0xab, 0xd4, 0x98, 0x96, 0x74, 0x14 },
+ { 0xfa, 0xe4, 0xb6, 0xd8, 0xef, 0xc3, 0xf8, 0xc8, 0xe6, 0x4d, 0x00, 0x1d, 0xab, 0xec, 0x3a, 0x21, 0xf5, 0x44, 0xe8, 0x27, 0x14, 0x74, 0x52, 0x51, 0xb2, 0xb4, 0xb3, 0x93, 0xf2, 0xf4, 0x3e, 0x0d, 0xa3, 0xd4, 0x03, 0xc6, 0x4d, 0xb9, 0x5a, 0x2c, 0xb6, 0xe2, 0x3e, 0xbb, 0x7b, 0x9e, 0x94, 0xcd, 0xd5, 0xdd, 0xac, 0x54, 0xf0, 0x7c, 0x4a, 0x61, 0xbd, 0x3c, 0xb1, 0x0a, 0xa6, 0xf9, 0x3b, 0x49 },
+ { 0x34, 0xf7, 0x28, 0x66, 0x05, 0xa1, 0x22, 0x36, 0x95, 0x40, 0x14, 0x1d, 0xed, 0x79, 0xb8, 0x95, 0x72, 0x55, 0xda, 0x2d, 0x41, 0x55, 0xab, 0xbf, 0x5a, 0x8d, 0xbb, 0x89, 0xc8, 0xeb, 0x7e, 0xde, 0x8e, 0xee, 0xf1, 0xda, 0xa4, 0x6d, 0xc2, 0x9d, 0x75, 0x1d, 0x04, 0x5d, 0xc3, 0xb1, 0xd6, 0x58, 0xbb, 0x64, 0xb8, 0x0f, 0xf8, 0x58, 0x9e, 0xdd, 0xb3, 0x82, 0x4b, 0x13, 0xda, 0x23, 0x5a, 0x6b },
+ { 0x3b, 0x3b, 0x48, 0x43, 0x4b, 0xe2, 0x7b, 0x9e, 0xab, 0xab, 0xba, 0x43, 0xbf, 0x6b, 0x35, 0xf1, 0x4b, 0x30, 0xf6, 0xa8, 0x8d, 0xc2, 0xe7, 0x50, 0xc3, 0x58, 0x47, 0x0d, 0x6b, 0x3a, 0xa3, 0xc1, 0x8e, 0x47, 0xdb, 0x40, 0x17, 0xfa, 0x55, 0x10, 0x6d, 0x82, 0x52, 0xf0, 0x16, 0x37, 0x1a, 0x00, 0xf5, 0xf8, 0xb0, 0x70, 0xb7, 0x4b, 0xa5, 0xf2, 0x3c, 0xff, 0xc5, 0x51, 0x1c, 0x9f, 0x09, 0xf0 },
+ { 0xba, 0x28, 0x9e, 0xbd, 0x65, 0x62, 0xc4, 0x8c, 0x3e, 0x10, 0xa8, 0xad, 0x6c, 0xe0, 0x2e, 0x73, 0x43, 0x3d, 0x1e, 0x93, 0xd7, 0xc9, 0x27, 0x9d, 0x4d, 0x60, 0xa7, 0xe8, 0x79, 0xee, 0x11, 0xf4, 0x41, 0xa0, 0x00, 0xf4, 0x8e, 0xd9, 0xf7, 0xc4, 0xed, 0x87, 0xa4, 0x51, 0x36, 0xd7, 0xdc, 0xcd, 0xca, 0x48, 0x21, 0x09, 0xc7, 0x8a, 0x51, 0x06, 0x2b, 0x3b, 0xa4, 0x04, 0x4a, 0xda, 0x24, 0x69 },
+ { 0x02, 0x29, 0x39, 0xe2, 0x38, 0x6c, 0x5a, 0x37, 0x04, 0x98, 0x56, 0xc8, 0x50, 0xa2, 0xbb, 0x10, 0xa1, 0x3d, 0xfe, 0xa4, 0x21, 0x2b, 0x4c, 0x73, 0x2a, 0x88, 0x40, 0xa9, 0xff, 0xa5, 0xfa, 0xf5, 0x48, 0x75, 0xc5, 0x44, 0x88, 0x16, 0xb2, 0x78, 0x5a, 0x00, 0x7d, 0xa8, 0xa8, 0xd2, 0xbc, 0x7d, 0x71, 0xa5, 0x4e, 0x4e, 0x65, 0x71, 0xf1, 0x0b, 0x60, 0x0c, 0xbd, 0xb2, 0x5d, 0x13, 0xed, 0xe3 },
+ { 0xe6, 0xfe, 0xc1, 0x9d, 0x89, 0xce, 0x87, 0x17, 0xb1, 0xa0, 0x87, 0x02, 0x46, 0x70, 0xfe, 0x02, 0x6f, 0x6c, 0x7c, 0xbd, 0xa1, 0x1c, 0xae, 0xf9, 0x59, 0xbb, 0x2d, 0x35, 0x1b, 0xf8, 0x56, 0xf8, 0x05, 0x5d, 0x1c, 0x0e, 0xbd, 0xaa, 0xa9, 0xd1, 0xb1, 0x78, 0x86, 0xfc, 0x2c, 0x56, 0x2b, 0x5e, 0x99, 0x64, 0x2f, 0xc0, 0x64, 0x71, 0x0c, 0x0d, 0x34, 0x88, 0xa0, 0x2b, 0x5e, 0xd7, 0xf6, 0xfd },
+ { 0x94, 0xc9, 0x6f, 0x02, 0xa8, 0xf5, 0x76, 0xac, 0xa3, 0x2b, 0xa6, 0x1c, 0x2b, 0x20, 0x6f, 0x90, 0x72, 0x85, 0xd9, 0x29, 0x9b, 0x83, 0xac, 0x17, 0x5c, 0x20, 0x9a, 0x8d, 0x43, 0xd5, 0x3b, 0xfe, 0x68, 0x3d, 0xd1, 0xd8, 0x3e, 0x75, 0x49, 0xcb, 0x90, 0x6c, 0x28, 0xf5, 0x9a, 0xb7, 0xc4, 0x6f, 0x87, 0x51, 0x36, 0x6a, 0x28, 0xc3, 0x9d, 0xd5, 0xfe, 0x26, 0x93, 0xc9, 0x01, 0x96, 0x66, 0xc8 },
+ { 0x31, 0xa0, 0xcd, 0x21, 0x5e, 0xbd, 0x2c, 0xb6, 0x1d, 0xe5, 0xb9, 0xed, 0xc9, 0x1e, 0x61, 0x95, 0xe3, 0x1c, 0x59, 0xa5, 0x64, 0x8d, 0x5c, 0x9f, 0x73, 0x7e, 0x12, 0x5b, 0x26, 0x05, 0x70, 0x8f, 0x2e, 0x32, 0x5a, 0xb3, 0x38, 0x1c, 0x8d, 0xce, 0x1a, 0x3e, 0x95, 0x88, 0x86, 0xf1, 0xec, 0xdc, 0x60, 0x31, 0x8f, 0x88, 0x2c, 0xfe, 0x20, 0xa2, 0x41, 0x91, 0x35, 0x2e, 0x61, 0x7b, 0x0f, 0x21 },
+ { 0x91, 0xab, 0x50, 0x4a, 0x52, 0x2d, 0xce, 0x78, 0x77, 0x9f, 0x4c, 0x6c, 0x6b, 0xa2, 0xe6, 0xb6, 0xdb, 0x55, 0x65, 0xc7, 0x6d, 0x3e, 0x7e, 0x7c, 0x92, 0x0c, 0xaf, 0x7f, 0x75, 0x7e, 0xf9, 0xdb, 0x7c, 0x8f, 0xcf, 0x10, 0xe5, 0x7f, 0x03, 0x37, 0x9e, 0xa9, 0xbf, 0x75, 0xeb, 0x59, 0x89, 0x5d, 0x96, 0xe1, 0x49, 0x80, 0x0b, 0x6a, 0xae, 0x01, 0xdb, 0x77, 0x8b, 0xb9, 0x0a, 0xfb, 0xc9, 0x89 },
+ { 0xd8, 0x5c, 0xab, 0xc6, 0xbd, 0x5b, 0x1a, 0x01, 0xa5, 0xaf, 0xd8, 0xc6, 0x73, 0x47, 0x40, 0xda, 0x9f, 0xd1, 0xc1, 0xac, 0xc6, 0xdb, 0x29, 0xbf, 0xc8, 0xa2, 0xe5, 0xb6, 0x68, 0xb0, 0x28, 0xb6, 0xb3, 0x15, 0x4b, 0xfb, 0x87, 0x03, 0xfa, 0x31, 0x80, 0x25, 0x1d, 0x58, 0x9a, 0xd3, 0x80, 0x40, 0xce, 0xb7, 0x07, 0xc4, 0xba, 0xd1, 0xb5, 0x34, 0x3c, 0xb4, 0x26, 0xb6, 0x1e, 0xaa, 0x49, 0xc1 },
+ { 0xd6, 0x2e, 0xfb, 0xec, 0x2c, 0xa9, 0xc1, 0xf8, 0xbd, 0x66, 0xce, 0x8b, 0x3f, 0x6a, 0x89, 0x8c, 0xb3, 0xf7, 0x56, 0x6b, 0xa6, 0x56, 0x8c, 0x61, 0x8a, 0xd1, 0xfe, 0xb2, 0xb6, 0x5b, 0x76, 0xc3, 0xce, 0x1d, 0xd2, 0x0f, 0x73, 0x95, 0x37, 0x2f, 0xaf, 0x28, 0x42, 0x7f, 0x61, 0xc9, 0x27, 0x80, 0x49, 0xcf, 0x01, 0x40, 0xdf, 0x43, 0x4f, 0x56, 0x33, 0x04, 0x8c, 0x86, 0xb8, 0x1e, 0x03, 0x99 },
+ { 0x7c, 0x8f, 0xdc, 0x61, 0x75, 0x43, 0x9e, 0x2c, 0x3d, 0xb1, 0x5b, 0xaf, 0xa7, 0xfb, 0x06, 0x14, 0x3a, 0x6a, 0x23, 0xbc, 0x90, 0xf4, 0x49, 0xe7, 0x9d, 0xee, 0xf7, 0x3c, 0x3d, 0x49, 0x2a, 0x67, 0x17, 0x15, 0xc1, 0x93, 0xb6, 0xfe, 0xa9, 0xf0, 0x36, 0x05, 0x0b, 0x94, 0x60, 0x69, 0x85, 0x6b, 0x89, 0x7e, 0x08, 0xc0, 0x07, 0x68, 0xf5, 0xee, 0x5d, 0xdc, 0xf7, 0x0b, 0x7c, 0xd6, 0xd0, 0xe0 },
+ { 0x58, 0x60, 0x2e, 0xe7, 0x46, 0x8e, 0x6b, 0xc9, 0xdf, 0x21, 0xbd, 0x51, 0xb2, 0x3c, 0x00, 0x5f, 0x72, 0xd6, 0xcb, 0x01, 0x3f, 0x0a, 0x1b, 0x48, 0xcb, 0xec, 0x5e, 0xca, 0x29, 0x92, 0x99, 0xf9, 0x7f, 0x09, 0xf5, 0x4a, 0x9a, 0x01, 0x48, 0x3e, 0xae, 0xb3, 0x15, 0xa6, 0x47, 0x8b, 0xad, 0x37, 0xba, 0x47, 0xca, 0x13, 0x47, 0xc7, 0xc8, 0xfc, 0x9e, 0x66, 0x95, 0x59, 0x2c, 0x91, 0xd7, 0x23 },
+ { 0x27, 0xf5, 0xb7, 0x9e, 0xd2, 0x56, 0xb0, 0x50, 0x99, 0x3d, 0x79, 0x34, 0x96, 0xed, 0xf4, 0x80, 0x7c, 0x1d, 0x85, 0xa7, 0xb0, 0xa6, 0x7c, 0x9c, 0x4f, 0xa9, 0x98, 0x60, 0x75, 0x0b, 0x0a, 0xe6, 0x69, 0x89, 0x67, 0x0a, 0x8f, 0xfd, 0x78, 0x56, 0xd7, 0xce, 0x41, 0x15, 0x99, 0xe5, 0x8c, 0x4d, 0x77, 0xb2, 0x32, 0xa6, 0x2b, 0xef, 0x64, 0xd1, 0x52, 0x75, 0xbe, 0x46, 0xa6, 0x82, 0x35, 0xff },
+ { 0x39, 0x57, 0xa9, 0x76, 0xb9, 0xf1, 0x88, 0x7b, 0xf0, 0x04, 0xa8, 0xdc, 0xa9, 0x42, 0xc9, 0x2d, 0x2b, 0x37, 0xea, 0x52, 0x60, 0x0f, 0x25, 0xe0, 0xc9, 0xbc, 0x57, 0x07, 0xd0, 0x27, 0x9c, 0x00, 0xc6, 0xe8, 0x5a, 0x83, 0x9b, 0x0d, 0x2d, 0x8e, 0xb5, 0x9c, 0x51, 0xd9, 0x47, 0x88, 0xeb, 0xe6, 0x24, 0x74, 0xa7, 0x91, 0xca, 0xdf, 0x52, 0xcc, 0xcf, 0x20, 0xf5, 0x07, 0x0b, 0x65, 0x73, 0xfc },
+ { 0xea, 0xa2, 0x37, 0x6d, 0x55, 0x38, 0x0b, 0xf7, 0x72, 0xec, 0xca, 0x9c, 0xb0, 0xaa, 0x46, 0x68, 0xc9, 0x5c, 0x70, 0x71, 0x62, 0xfa, 0x86, 0xd5, 0x18, 0xc8, 0xce, 0x0c, 0xa9, 0xbf, 0x73, 0x62, 0xb9, 0xf2, 0xa0, 0xad, 0xc3, 0xff, 0x59, 0x92, 0x2d, 0xf9, 0x21, 0xb9, 0x45, 0x67, 0xe8, 0x1e, 0x45, 0x2f, 0x6c, 0x1a, 0x07, 0xfc, 0x81, 0x7c, 0xeb, 0xe9, 0x96, 0x04, 0xb3, 0x50, 0x5d, 0x38 },
+ { 0xc1, 0xe2, 0xc7, 0x8b, 0x6b, 0x27, 0x34, 0xe2, 0x48, 0x0e, 0xc5, 0x50, 0x43, 0x4c, 0xb5, 0xd6, 0x13, 0x11, 0x1a, 0xdc, 0xc2, 0x1d, 0x47, 0x55, 0x45, 0xc3, 0xb1, 0xb7, 0xe6, 0xff, 0x12, 0x44, 0x44, 0x76, 0xe5, 0xc0, 0x55, 0x13, 0x2e, 0x22, 0x29, 0xdc, 0x0f, 0x80, 0x70, 0x44, 0xbb, 0x91, 0x9b, 0x1a, 0x56, 0x62, 0xdd, 0x38, 0xa9, 0xee, 0x65, 0xe2, 0x43, 0xa3, 0x91, 0x1a, 0xed, 0x1a },
+ { 0x8a, 0xb4, 0x87, 0x13, 0x38, 0x9d, 0xd0, 0xfc, 0xf9, 0xf9, 0x65, 0xd3, 0xce, 0x66, 0xb1, 0xe5, 0x59, 0xa1, 0xf8, 0xc5, 0x87, 0x41, 0xd6, 0x76, 0x83, 0xcd, 0x97, 0x13, 0x54, 0xf4, 0x52, 0xe6, 0x2d, 0x02, 0x07, 0xa6, 0x5e, 0x43, 0x6c, 0x5d, 0x5d, 0x8f, 0x8e, 0xe7, 0x1c, 0x6a, 0xbf, 0xe5, 0x0e, 0x66, 0x90, 0x04, 0xc3, 0x02, 0xb3, 0x1a, 0x7e, 0xa8, 0x31, 0x1d, 0x4a, 0x91, 0x60, 0x51 },
+ { 0x24, 0xce, 0x0a, 0xdd, 0xaa, 0x4c, 0x65, 0x03, 0x8b, 0xd1, 0xb1, 0xc0, 0xf1, 0x45, 0x2a, 0x0b, 0x12, 0x87, 0x77, 0xaa, 0xbc, 0x94, 0xa2, 0x9d, 0xf2, 0xfd, 0x6c, 0x7e, 0x2f, 0x85, 0xf8, 0xab, 0x9a, 0xc7, 0xef, 0xf5, 0x16, 0xb0, 0xe0, 0xa8, 0x25, 0xc8, 0x4a, 0x24, 0xcf, 0xe4, 0x92, 0xea, 0xad, 0x0a, 0x63, 0x08, 0xe4, 0x6d, 0xd4, 0x2f, 0xe8, 0x33, 0x3a, 0xb9, 0x71, 0xbb, 0x30, 0xca },
+ { 0x51, 0x54, 0xf9, 0x29, 0xee, 0x03, 0x04, 0x5b, 0x6b, 0x0c, 0x00, 0x04, 0xfa, 0x77, 0x8e, 0xde, 0xe1, 0xd1, 0x39, 0x89, 0x32, 0x67, 0xcc, 0x84, 0x82, 0x5a, 0xd7, 0xb3, 0x6c, 0x63, 0xde, 0x32, 0x79, 0x8e, 0x4a, 0x16, 0x6d, 0x24, 0x68, 0x65, 0x61, 0x35, 0x4f, 0x63, 0xb0, 0x07, 0x09, 0xa1, 0x36, 0x4b, 0x3c, 0x24, 0x1d, 0xe3, 0xfe, 0xbf, 0x07, 0x54, 0x04, 0x58, 0x97, 0x46, 0x7c, 0xd4 },
+ { 0xe7, 0x4e, 0x90, 0x79, 0x20, 0xfd, 0x87, 0xbd, 0x5a, 0xd6, 0x36, 0xdd, 0x11, 0x08, 0x5e, 0x50, 0xee, 0x70, 0x45, 0x9c, 0x44, 0x3e, 0x1c, 0xe5, 0x80, 0x9a, 0xf2, 0xbc, 0x2e, 0xba, 0x39, 0xf9, 0xe6, 0xd7, 0x12, 0x8e, 0x0e, 0x37, 0x12, 0xc3, 0x16, 0xda, 0x06, 0xf4, 0x70, 0x5d, 0x78, 0xa4, 0x83, 0x8e, 0x28, 0x12, 0x1d, 0x43, 0x44, 0xa2, 0xc7, 0x9c, 0x5e, 0x0d, 0xb3, 0x07, 0xa6, 0x77 },
+ { 0xbf, 0x91, 0xa2, 0x23, 0x34, 0xba, 0xc2, 0x0f, 0x3f, 0xd8, 0x06, 0x63, 0xb3, 0xcd, 0x06, 0xc4, 0xe8, 0x80, 0x2f, 0x30, 0xe6, 0xb5, 0x9f, 0x90, 0xd3, 0x03, 0x5c, 0xc9, 0x79, 0x8a, 0x21, 0x7e, 0xd5, 0xa3, 0x1a, 0xbb, 0xda, 0x7f, 0xa6, 0x84, 0x28, 0x27, 0xbd, 0xf2, 0xa7, 0xa1, 0xc2, 0x1f, 0x6f, 0xcf, 0xcc, 0xbb, 0x54, 0xc6, 0xc5, 0x29, 0x26, 0xf3, 0x2d, 0xa8, 0x16, 0x26, 0x9b, 0xe1 },
+ { 0xd9, 0xd5, 0xc7, 0x4b, 0xe5, 0x12, 0x1b, 0x0b, 0xd7, 0x42, 0xf2, 0x6b, 0xff, 0xb8, 0xc8, 0x9f, 0x89, 0x17, 0x1f, 0x3f, 0x93, 0x49, 0x13, 0x49, 0x2b, 0x09, 0x03, 0xc2, 0x71, 0xbb, 0xe2, 0xb3, 0x39, 0x5e, 0xf2, 0x59, 0x66, 0x9b, 0xef, 0x43, 0xb5, 0x7f, 0x7f, 0xcc, 0x30, 0x27, 0xdb, 0x01, 0x82, 0x3f, 0x6b, 0xae, 0xe6, 0x6e, 0x4f, 0x9f, 0xea, 0xd4, 0xd6, 0x72, 0x6c, 0x74, 0x1f, 0xce },
+ { 0x50, 0xc8, 0xb8, 0xcf, 0x34, 0xcd, 0x87, 0x9f, 0x80, 0xe2, 0xfa, 0xab, 0x32, 0x30, 0xb0, 0xc0, 0xe1, 0xcc, 0x3e, 0x9d, 0xca, 0xde, 0xb1, 0xb9, 0xd9, 0x7a, 0xb9, 0x23, 0x41, 0x5d, 0xd9, 0xa1, 0xfe, 0x38, 0xad, 0xdd, 0x5c, 0x11, 0x75, 0x6c, 0x67, 0x99, 0x0b, 0x25, 0x6e, 0x95, 0xad, 0x6d, 0x8f, 0x9f, 0xed, 0xce, 0x10, 0xbf, 0x1c, 0x90, 0x67, 0x9c, 0xde, 0x0e, 0xcf, 0x1b, 0xe3, 0x47 },
+ { 0x0a, 0x38, 0x6e, 0x7c, 0xd5, 0xdd, 0x9b, 0x77, 0xa0, 0x35, 0xe0, 0x9f, 0xe6, 0xfe, 0xe2, 0xc8, 0xce, 0x61, 0xb5, 0x38, 0x3c, 0x87, 0xea, 0x43, 0x20, 0x50, 0x59, 0xc5, 0xe4, 0xcd, 0x4f, 0x44, 0x08, 0x31, 0x9b, 0xb0, 0xa8, 0x23, 0x60, 0xf6, 0xa5, 0x8e, 0x6c, 0x9c, 0xe3, 0xf4, 0x87, 0xc4, 0x46, 0x06, 0x3b, 0xf8, 0x13, 0xbc, 0x6b, 0xa5, 0x35, 0xe1, 0x7f, 0xc1, 0x82, 0x6c, 0xfc, 0x91 },
+ { 0x1f, 0x14, 0x59, 0xcb, 0x6b, 0x61, 0xcb, 0xac, 0x5f, 0x0e, 0xfe, 0x8f, 0xc4, 0x87, 0x53, 0x8f, 0x42, 0x54, 0x89, 0x87, 0xfc, 0xd5, 0x62, 0x21, 0xcf, 0xa7, 0xbe, 0xb2, 0x25, 0x04, 0x76, 0x9e, 0x79, 0x2c, 0x45, 0xad, 0xfb, 0x1d, 0x6b, 0x3d, 0x60, 0xd7, 0xb7, 0x49, 0xc8, 0xa7, 0x5b, 0x0b, 0xdf, 0x14, 0xe8, 0xea, 0x72, 0x1b, 0x95, 0xdc, 0xa5, 0x38, 0xca, 0x6e, 0x25, 0x71, 0x12, 0x09 },
+ { 0xe5, 0x8b, 0x38, 0x36, 0xb7, 0xd8, 0xfe, 0xdb, 0xb5, 0x0c, 0xa5, 0x72, 0x5c, 0x65, 0x71, 0xe7, 0x4c, 0x07, 0x85, 0xe9, 0x78, 0x21, 0xda, 0xb8, 0xb6, 0x29, 0x8c, 0x10, 0xe4, 0xc0, 0x79, 0xd4, 0xa6, 0xcd, 0xf2, 0x2f, 0x0f, 0xed, 0xb5, 0x50, 0x32, 0x92, 0x5c, 0x16, 0x74, 0x81, 0x15, 0xf0, 0x1a, 0x10, 0x5e, 0x77, 0xe0, 0x0c, 0xee, 0x3d, 0x07, 0x92, 0x4d, 0xc0, 0xd8, 0xf9, 0x06, 0x59 },
+ { 0xb9, 0x29, 0xcc, 0x65, 0x05, 0xf0, 0x20, 0x15, 0x86, 0x72, 0xde, 0xda, 0x56, 0xd0, 0xdb, 0x08, 0x1a, 0x2e, 0xe3, 0x4c, 0x00, 0xc1, 0x10, 0x00, 0x29, 0xbd, 0xf8, 0xea, 0x98, 0x03, 0x4f, 0xa4, 0xbf, 0x3e, 0x86, 0x55, 0xec, 0x69, 0x7f, 0xe3, 0x6f, 0x40, 0x55, 0x3c, 0x5b, 0xb4, 0x68, 0x01, 0x64, 0x4a, 0x62, 0x7d, 0x33, 0x42, 0xf4, 0xfc, 0x92, 0xb6, 0x1f, 0x03, 0x29, 0x0f, 0xb3, 0x81 },
+ { 0x72, 0xd3, 0x53, 0x99, 0x4b, 0x49, 0xd3, 0xe0, 0x31, 0x53, 0x92, 0x9a, 0x1e, 0x4d, 0x4f, 0x18, 0x8e, 0xe5, 0x8a, 0xb9, 0xe7, 0x2e, 0xe8, 0xe5, 0x12, 0xf2, 0x9b, 0xc7, 0x73, 0x91, 0x38, 0x19, 0xce, 0x05, 0x7d, 0xdd, 0x70, 0x02, 0xc0, 0x43, 0x3e, 0xe0, 0xa1, 0x61, 0x14, 0xe3, 0xd1, 0x56, 0xdd, 0x2c, 0x4a, 0x7e, 0x80, 0xee, 0x53, 0x37, 0x8b, 0x86, 0x70, 0xf2, 0x3e, 0x33, 0xef, 0x56 },
+ { 0xc7, 0x0e, 0xf9, 0xbf, 0xd7, 0x75, 0xd4, 0x08, 0x17, 0x67, 0x37, 0xa0, 0x73, 0x6d, 0x68, 0x51, 0x7c, 0xe1, 0xaa, 0xad, 0x7e, 0x81, 0xa9, 0x3c, 0x8c, 0x1e, 0xd9, 0x67, 0xea, 0x21, 0x4f, 0x56, 0xc8, 0xa3, 0x77, 0xb1, 0x76, 0x3e, 0x67, 0x66, 0x15, 0xb6, 0x0f, 0x39, 0x88, 0x24, 0x1e, 0xae, 0x6e, 0xab, 0x96, 0x85, 0xa5, 0x12, 0x49, 0x29, 0xd2, 0x81, 0x88, 0xf2, 0x9e, 0xab, 0x06, 0xf7 },
+ { 0xc2, 0x30, 0xf0, 0x80, 0x26, 0x79, 0xcb, 0x33, 0x82, 0x2e, 0xf8, 0xb3, 0xb2, 0x1b, 0xf7, 0xa9, 0xa2, 0x89, 0x42, 0x09, 0x29, 0x01, 0xd7, 0xda, 0xc3, 0x76, 0x03, 0x00, 0x83, 0x10, 0x26, 0xcf, 0x35, 0x4c, 0x92, 0x32, 0xdf, 0x3e, 0x08, 0x4d, 0x99, 0x03, 0x13, 0x0c, 0x60, 0x1f, 0x63, 0xc1, 0xf4, 0xa4, 0xa4, 0xb8, 0x10, 0x6e, 0x46, 0x8c, 0xd4, 0x43, 0xbb, 0xe5, 0xa7, 0x34, 0xf4, 0x5f },
+ { 0x6f, 0x43, 0x09, 0x4c, 0xaf, 0xb5, 0xeb, 0xf1, 0xf7, 0xa4, 0x93, 0x7e, 0xc5, 0x0f, 0x56, 0xa4, 0xc9, 0xda, 0x30, 0x3c, 0xbb, 0x55, 0xac, 0x1f, 0x27, 0xf1, 0xf1, 0x97, 0x6c, 0xd9, 0x6b, 0xed, 0xa9, 0x46, 0x4f, 0x0e, 0x7b, 0x9c, 0x54, 0x62, 0x0b, 0x8a, 0x9f, 0xba, 0x98, 0x31, 0x64, 0xb8, 0xbe, 0x35, 0x78, 0x42, 0x5a, 0x02, 0x4f, 0x5f, 0xe1, 0x99, 0xc3, 0x63, 0x56, 0xb8, 0x89, 0x72 },
+ { 0x37, 0x45, 0x27, 0x3f, 0x4c, 0x38, 0x22, 0x5d, 0xb2, 0x33, 0x73, 0x81, 0x87, 0x1a, 0x0c, 0x6a, 0xaf, 0xd3, 0xaf, 0x9b, 0x01, 0x8c, 0x88, 0xaa, 0x02, 0x02, 0x58, 0x50, 0xa5, 0xdc, 0x3a, 0x42, 0xa1, 0xa3, 0xe0, 0x3e, 0x56, 0xcb, 0xf1, 0xb0, 0x87, 0x6d, 0x63, 0xa4, 0x41, 0xf1, 0xd2, 0x85, 0x6a, 0x39, 0xb8, 0x80, 0x1e, 0xb5, 0xaf, 0x32, 0x52, 0x01, 0xc4, 0x15, 0xd6, 0x5e, 0x97, 0xfe },
+ { 0xc5, 0x0c, 0x44, 0xcc, 0xa3, 0xec, 0x3e, 0xda, 0xae, 0x77, 0x9a, 0x7e, 0x17, 0x94, 0x50, 0xeb, 0xdd, 0xa2, 0xf9, 0x70, 0x67, 0xc6, 0x90, 0xaa, 0x6c, 0x5a, 0x4a, 0xc7, 0xc3, 0x01, 0x39, 0xbb, 0x27, 0xc0, 0xdf, 0x4d, 0xb3, 0x22, 0x0e, 0x63, 0xcb, 0x11, 0x0d, 0x64, 0xf3, 0x7f, 0xfe, 0x07, 0x8d, 0xb7, 0x26, 0x53, 0xe2, 0xda, 0xac, 0xf9, 0x3a, 0xe3, 0xf0, 0xa2, 0xd1, 0xa7, 0xeb, 0x2e },
+ { 0x8a, 0xef, 0x26, 0x3e, 0x38, 0x5c, 0xbc, 0x61, 0xe1, 0x9b, 0x28, 0x91, 0x42, 0x43, 0x26, 0x2a, 0xf5, 0xaf, 0xe8, 0x72, 0x6a, 0xf3, 0xce, 0x39, 0xa7, 0x9c, 0x27, 0x02, 0x8c, 0xf3, 0xec, 0xd3, 0xf8, 0xd2, 0xdf, 0xd9, 0xcf, 0xc9, 0xad, 0x91, 0xb5, 0x8f, 0x6f, 0x20, 0x77, 0x8f, 0xd5, 0xf0, 0x28, 0x94, 0xa3, 0xd9, 0x1c, 0x7d, 0x57, 0xd1, 0xe4, 0xb8, 0x66, 0xa7, 0xf3, 0x64, 0xb6, 0xbe },
+ { 0x28, 0x69, 0x61, 0x41, 0xde, 0x6e, 0x2d, 0x9b, 0xcb, 0x32, 0x35, 0x57, 0x8a, 0x66, 0x16, 0x6c, 0x14, 0x48, 0xd3, 0xe9, 0x05, 0xa1, 0xb4, 0x82, 0xd4, 0x23, 0xbe, 0x4b, 0xc5, 0x36, 0x9b, 0xc8, 0xc7, 0x4d, 0xae, 0x0a, 0xcc, 0x9c, 0xc1, 0x23, 0xe1, 0xd8, 0xdd, 0xce, 0x9f, 0x97, 0x91, 0x7e, 0x8c, 0x01, 0x9c, 0x55, 0x2d, 0xa3, 0x2d, 0x39, 0xd2, 0x21, 0x9b, 0x9a, 0xbf, 0x0f, 0xa8, 0xc8 },
+ { 0x2f, 0xb9, 0xeb, 0x20, 0x85, 0x83, 0x01, 0x81, 0x90, 0x3a, 0x9d, 0xaf, 0xe3, 0xdb, 0x42, 0x8e, 0xe1, 0x5b, 0xe7, 0x66, 0x22, 0x24, 0xef, 0xd6, 0x43, 0x37, 0x1f, 0xb2, 0x56, 0x46, 0xae, 0xe7, 0x16, 0xe5, 0x31, 0xec, 0xa6, 0x9b, 0x2b, 0xdc, 0x82, 0x33, 0xf1, 0xa8, 0x08, 0x1f, 0xa4, 0x3d, 0xa1, 0x50, 0x03, 0x02, 0x97, 0x5a, 0x77, 0xf4, 0x2f, 0xa5, 0x92, 0x13, 0x67, 0x10, 0xe9, 0xdc },
+ { 0x66, 0xf9, 0xa7, 0x14, 0x3f, 0x7a, 0x33, 0x14, 0xa6, 0x69, 0xbf, 0x2e, 0x24, 0xbb, 0xb3, 0x50, 0x14, 0x26, 0x1d, 0x63, 0x9f, 0x49, 0x5b, 0x6c, 0x9c, 0x1f, 0x10, 0x4f, 0xe8, 0xe3, 0x20, 0xac, 0xa6, 0x0d, 0x45, 0x50, 0xd6, 0x9d, 0x52, 0xed, 0xbd, 0x5a, 0x3c, 0xde, 0xb4, 0x01, 0x4a, 0xe6, 0x5b, 0x1d, 0x87, 0xaa, 0x77, 0x0b, 0x69, 0xae, 0x5c, 0x15, 0xf4, 0x33, 0x0b, 0x0b, 0x0a, 0xd8 },
+ { 0xf4, 0xc4, 0xdd, 0x1d, 0x59, 0x4c, 0x35, 0x65, 0xe3, 0xe2, 0x5c, 0xa4, 0x3d, 0xad, 0x82, 0xf6, 0x2a, 0xbe, 0xa4, 0x83, 0x5e, 0xd4, 0xcd, 0x81, 0x1b, 0xcd, 0x97, 0x5e, 0x46, 0x27, 0x98, 0x28, 0xd4, 0x4d, 0x4c, 0x62, 0xc3, 0x67, 0x9f, 0x1b, 0x7f, 0x7b, 0x9d, 0xd4, 0x57, 0x1d, 0x7b, 0x49, 0x55, 0x73, 0x47, 0xb8, 0xc5, 0x46, 0x0c, 0xbd, 0xc1, 0xbe, 0xf6, 0x90, 0xfb, 0x2a, 0x08, 0xc0 },
+ { 0x8f, 0x1d, 0xc9, 0x64, 0x9c, 0x3a, 0x84, 0x55, 0x1f, 0x8f, 0x6e, 0x91, 0xca, 0xc6, 0x82, 0x42, 0xa4, 0x3b, 0x1f, 0x8f, 0x32, 0x8e, 0xe9, 0x22, 0x80, 0x25, 0x73, 0x87, 0xfa, 0x75, 0x59, 0xaa, 0x6d, 0xb1, 0x2e, 0x4a, 0xea, 0xdc, 0x2d, 0x26, 0x09, 0x91, 0x78, 0x74, 0x9c, 0x68, 0x64, 0xb3, 0x57, 0xf3, 0xf8, 0x3b, 0x2f, 0xb3, 0xef, 0xa8, 0xd2, 0xa8, 0xdb, 0x05, 0x6b, 0xed, 0x6b, 0xcc },
+ { 0x31, 0x39, 0xc1, 0xa7, 0xf9, 0x7a, 0xfd, 0x16, 0x75, 0xd4, 0x60, 0xeb, 0xbc, 0x07, 0xf2, 0x72, 0x8a, 0xa1, 0x50, 0xdf, 0x84, 0x96, 0x24, 0x51, 0x1e, 0xe0, 0x4b, 0x74, 0x3b, 0xa0, 0xa8, 0x33, 0x09, 0x2f, 0x18, 0xc1, 0x2d, 0xc9, 0x1b, 0x4d, 0xd2, 0x43, 0xf3, 0x33, 0x40, 0x2f, 0x59, 0xfe, 0x28, 0xab, 0xdb, 0xbb, 0xae, 0x30, 0x1e, 0x7b, 0x65, 0x9c, 0x7a, 0x26, 0xd5, 0xc0, 0xf9, 0x79 },
+ { 0x06, 0xf9, 0x4a, 0x29, 0x96, 0x15, 0x8a, 0x81, 0x9f, 0xe3, 0x4c, 0x40, 0xde, 0x3c, 0xf0, 0x37, 0x9f, 0xd9, 0xfb, 0x85, 0xb3, 0xe3, 0x63, 0xba, 0x39, 0x26, 0xa0, 0xe7, 0xd9, 0x60, 0xe3, 0xf4, 0xc2, 0xe0, 0xc7, 0x0c, 0x7c, 0xe0, 0xcc, 0xb2, 0xa6, 0x4f, 0xc2, 0x98, 0x69, 0xf6, 0xe7, 0xab, 0x12, 0xbd, 0x4d, 0x3f, 0x14, 0xfc, 0xe9, 0x43, 0x27, 0x90, 0x27, 0xe7, 0x85, 0xfb, 0x5c, 0x29 },
+ { 0xc2, 0x9c, 0x39, 0x9e, 0xf3, 0xee, 0xe8, 0x96, 0x1e, 0x87, 0x56, 0x5c, 0x1c, 0xe2, 0x63, 0x92, 0x5f, 0xc3, 0xd0, 0xce, 0x26, 0x7d, 0x13, 0xe4, 0x8d, 0xd9, 0xe7, 0x32, 0xee, 0x67, 0xb0, 0xf6, 0x9f, 0xad, 0x56, 0x40, 0x1b, 0x0f, 0x10, 0xfc, 0xaa, 0xc1, 0x19, 0x20, 0x10, 0x46, 0xcc, 0xa2, 0x8c, 0x5b, 0x14, 0xab, 0xde, 0xa3, 0x21, 0x2a, 0xe6, 0x55, 0x62, 0xf7, 0xf1, 0x38, 0xdb, 0x3d },
+ { 0x4c, 0xec, 0x4c, 0x9d, 0xf5, 0x2e, 0xef, 0x05, 0xc3, 0xf6, 0xfa, 0xaa, 0x97, 0x91, 0xbc, 0x74, 0x45, 0x93, 0x71, 0x83, 0x22, 0x4e, 0xcc, 0x37, 0xa1, 0xe5, 0x8d, 0x01, 0x32, 0xd3, 0x56, 0x17, 0x53, 0x1d, 0x7e, 0x79, 0x5f, 0x52, 0xaf, 0x7b, 0x1e, 0xb9, 0xd1, 0x47, 0xde, 0x12, 0x92, 0xd3, 0x45, 0xfe, 0x34, 0x18, 0x23, 0xf8, 0xe6, 0xbc, 0x1e, 0x5b, 0xad, 0xca, 0x5c, 0x65, 0x61, 0x08 },
+ { 0x89, 0x8b, 0xfb, 0xae, 0x93, 0xb3, 0xe1, 0x8d, 0x00, 0x69, 0x7e, 0xab, 0x7d, 0x97, 0x04, 0xfa, 0x36, 0xec, 0x33, 0x9d, 0x07, 0x61, 0x31, 0xce, 0xfd, 0xf3, 0x0e, 0xdb, 0xe8, 0xd9, 0xcc, 0x81, 0xc3, 0xa8, 0x0b, 0x12, 0x96, 0x59, 0xb1, 0x63, 0xa3, 0x23, 0xba, 0xb9, 0x79, 0x3d, 0x4f, 0xee, 0xd9, 0x2d, 0x54, 0xda, 0xe9, 0x66, 0xc7, 0x75, 0x29, 0x76, 0x4a, 0x09, 0xbe, 0x88, 0xdb, 0x45 },
+ { 0xee, 0x9b, 0xd0, 0x46, 0x9d, 0x3a, 0xaf, 0x4f, 0x14, 0x03, 0x5b, 0xe4, 0x8a, 0x2c, 0x3b, 0x84, 0xd9, 0xb4, 0xb1, 0xff, 0xf1, 0xd9, 0x45, 0xe1, 0xf1, 0xc1, 0xd3, 0x89, 0x80, 0xa9, 0x51, 0xbe, 0x19, 0x7b, 0x25, 0xfe, 0x22, 0xc7, 0x31, 0xf2, 0x0a, 0xea, 0xcc, 0x93, 0x0b, 0xa9, 0xc4, 0xa1, 0xf4, 0x76, 0x22, 0x27, 0x61, 0x7a, 0xd3, 0x50, 0xfd, 0xab, 0xb4, 0xe8, 0x02, 0x73, 0xa0, 0xf4 },
+ { 0x3d, 0x4d, 0x31, 0x13, 0x30, 0x05, 0x81, 0xcd, 0x96, 0xac, 0xbf, 0x09, 0x1c, 0x3d, 0x0f, 0x3c, 0x31, 0x01, 0x38, 0xcd, 0x69, 0x79, 0xe6, 0x02, 0x6c, 0xde, 0x62, 0x3e, 0x2d, 0xd1, 0xb2, 0x4d, 0x4a, 0x86, 0x38, 0xbe, 0xd1, 0x07, 0x33, 0x44, 0x78, 0x3a, 0xd0, 0x64, 0x9c, 0xc6, 0x30, 0x5c, 0xce, 0xc0, 0x4b, 0xeb, 0x49, 0xf3, 0x1c, 0x63, 0x30, 0x88, 0xa9, 0x9b, 0x65, 0x13, 0x02, 0x67 },
+ { 0x95, 0xc0, 0x59, 0x1a, 0xd9, 0x1f, 0x92, 0x1a, 0xc7, 0xbe, 0x6d, 0x9c, 0xe3, 0x7e, 0x06, 0x63, 0xed, 0x80, 0x11, 0xc1, 0xcf, 0xd6, 0xd0, 0x16, 0x2a, 0x55, 0x72, 0xe9, 0x43, 0x68, 0xba, 0xc0, 0x20, 0x24, 0x48, 0x5e, 0x6a, 0x39, 0x85, 0x4a, 0xa4, 0x6f, 0xe3, 0x8e, 0x97, 0xd6, 0xc6, 0xb1, 0x94, 0x7c, 0xd2, 0x72, 0xd8, 0x6b, 0x06, 0xbb, 0x5b, 0x2f, 0x78, 0xb9, 0xb6, 0x8d, 0x55, 0x9d },
+ { 0x22, 0x7b, 0x79, 0xde, 0xd3, 0x68, 0x15, 0x3b, 0xf4, 0x6c, 0x0a, 0x3c, 0xa9, 0x78, 0xbf, 0xdb, 0xef, 0x31, 0xf3, 0x02, 0x4a, 0x56, 0x65, 0x84, 0x24, 0x68, 0x49, 0x0b, 0x0f, 0xf7, 0x48, 0xae, 0x04, 0xe7, 0x83, 0x2e, 0xd4, 0xc9, 0xf4, 0x9d, 0xe9, 0xb1, 0x70, 0x67, 0x09, 0xd6, 0x23, 0xe5, 0xc8, 0xc1, 0x5e, 0x3c, 0xae, 0xca, 0xe8, 0xd5, 0xe4, 0x33, 0x43, 0x0f, 0xf7, 0x2f, 0x20, 0xeb },
+ { 0x5d, 0x34, 0xf3, 0x95, 0x2f, 0x01, 0x05, 0xee, 0xf8, 0x8a, 0xe8, 0xb6, 0x4c, 0x6c, 0xe9, 0x5e, 0xbf, 0xad, 0xe0, 0xe0, 0x2c, 0x69, 0xb0, 0x87, 0x62, 0xa8, 0x71, 0x2d, 0x2e, 0x49, 0x11, 0xad, 0x3f, 0x94, 0x1f, 0xc4, 0x03, 0x4d, 0xc9, 0xb2, 0xe4, 0x79, 0xfd, 0xbc, 0xd2, 0x79, 0xb9, 0x02, 0xfa, 0xf5, 0xd8, 0x38, 0xbb, 0x2e, 0x0c, 0x64, 0x95, 0xd3, 0x72, 0xb5, 0xb7, 0x02, 0x98, 0x13 },
+ { 0x7f, 0x93, 0x9b, 0xf8, 0x35, 0x3a, 0xbc, 0xe4, 0x9e, 0x77, 0xf1, 0x4f, 0x37, 0x50, 0xaf, 0x20, 0xb7, 0xb0, 0x39, 0x02, 0xe1, 0xa1, 0xe7, 0xfb, 0x6a, 0xaf, 0x76, 0xd0, 0x25, 0x9c, 0xd4, 0x01, 0xa8, 0x31, 0x90, 0xf1, 0x56, 0x40, 0xe7, 0x4f, 0x3e, 0x6c, 0x5a, 0x90, 0xe8, 0x39, 0xc7, 0x82, 0x1f, 0x64, 0x74, 0x75, 0x7f, 0x75, 0xc7, 0xbf, 0x90, 0x02, 0x08, 0x4d, 0xdc, 0x7a, 0x62, 0xdc },
+ { 0x06, 0x2b, 0x61, 0xa2, 0xf9, 0xa3, 0x3a, 0x71, 0xd7, 0xd0, 0xa0, 0x61, 0x19, 0x64, 0x4c, 0x70, 0xb0, 0x71, 0x6a, 0x50, 0x4d, 0xe7, 0xe5, 0xe1, 0xbe, 0x49, 0xbd, 0x7b, 0x86, 0xe7, 0xed, 0x68, 0x17, 0x71, 0x4f, 0x9f, 0x0f, 0xc3, 0x13, 0xd0, 0x61, 0x29, 0x59, 0x7e, 0x9a, 0x22, 0x35, 0xec, 0x85, 0x21, 0xde, 0x36, 0xf7, 0x29, 0x0a, 0x90, 0xcc, 0xfc, 0x1f, 0xfa, 0x6d, 0x0a, 0xee, 0x29 },
+ { 0xf2, 0x9e, 0x01, 0xee, 0xae, 0x64, 0x31, 0x1e, 0xb7, 0xf1, 0xc6, 0x42, 0x2f, 0x94, 0x6b, 0xf7, 0xbe, 0xa3, 0x63, 0x79, 0x52, 0x3e, 0x7b, 0x2b, 0xba, 0xba, 0x7d, 0x1d, 0x34, 0xa2, 0x2d, 0x5e, 0xa5, 0xf1, 0xc5, 0xa0, 0x9d, 0x5c, 0xe1, 0xfe, 0x68, 0x2c, 0xce, 0xd9, 0xa4, 0x79, 0x8d, 0x1a, 0x05, 0xb4, 0x6c, 0xd7, 0x2d, 0xff, 0x5c, 0x1b, 0x35, 0x54, 0x40, 0xb2, 0xa2, 0xd4, 0x76, 0xbc },
+ { 0xec, 0x38, 0xcd, 0x3b, 0xba, 0xb3, 0xef, 0x35, 0xd7, 0xcb, 0x6d, 0x5c, 0x91, 0x42, 0x98, 0x35, 0x1d, 0x8a, 0x9d, 0xc9, 0x7f, 0xce, 0xe0, 0x51, 0xa8, 0xa0, 0x2f, 0x58, 0xe3, 0xed, 0x61, 0x84, 0xd0, 0xb7, 0x81, 0x0a, 0x56, 0x15, 0x41, 0x1a, 0xb1, 0xb9, 0x52, 0x09, 0xc3, 0xc8, 0x10, 0x11, 0x4f, 0xde, 0xb2, 0x24, 0x52, 0x08, 0x4e, 0x77, 0xf3, 0xf8, 0x47, 0xc6, 0xdb, 0xaa, 0xfe, 0x16 },
+ { 0xc2, 0xae, 0xf5, 0xe0, 0xca, 0x43, 0xe8, 0x26, 0x41, 0x56, 0x5b, 0x8c, 0xb9, 0x43, 0xaa, 0x8b, 0xa5, 0x35, 0x50, 0xca, 0xef, 0x79, 0x3b, 0x65, 0x32, 0xfa, 0xfa, 0xd9, 0x4b, 0x81, 0x60, 0x82, 0xf0, 0x11, 0x3a, 0x3e, 0xa2, 0xf6, 0x36, 0x08, 0xab, 0x40, 0x43, 0x7e, 0xcc, 0x0f, 0x02, 0x29, 0xcb, 0x8f, 0xa2, 0x24, 0xdc, 0xf1, 0xc4, 0x78, 0xa6, 0x7d, 0x9b, 0x64, 0x16, 0x2b, 0x92, 0xd1 },
+ { 0x15, 0xf5, 0x34, 0xef, 0xff, 0x71, 0x05, 0xcd, 0x1c, 0x25, 0x4d, 0x07, 0x4e, 0x27, 0xd5, 0x89, 0x8b, 0x89, 0x31, 0x3b, 0x7d, 0x36, 0x6d, 0xc2, 0xd7, 0xd8, 0x71, 0x13, 0xfa, 0x7d, 0x53, 0xaa, 0xe1, 0x3f, 0x6d, 0xba, 0x48, 0x7a, 0xd8, 0x10, 0x3d, 0x5e, 0x85, 0x4c, 0x91, 0xfd, 0xb6, 0xe1, 0xe7, 0x4b, 0x2e, 0xf6, 0xd1, 0x43, 0x17, 0x69, 0xc3, 0x07, 0x67, 0xdd, 0xe0, 0x67, 0xa3, 0x5c },
+ { 0x89, 0xac, 0xbc, 0xa0, 0xb1, 0x69, 0x89, 0x7a, 0x0a, 0x27, 0x14, 0xc2, 0xdf, 0x8c, 0x95, 0xb5, 0xb7, 0x9c, 0xb6, 0x93, 0x90, 0x14, 0x2b, 0x7d, 0x60, 0x18, 0xbb, 0x3e, 0x30, 0x76, 0xb0, 0x99, 0xb7, 0x9a, 0x96, 0x41, 0x52, 0xa9, 0xd9, 0x12, 0xb1, 0xb8, 0x64, 0x12, 0xb7, 0xe3, 0x72, 0xe9, 0xce, 0xca, 0xd7, 0xf2, 0x5d, 0x4c, 0xba, 0xb8, 0xa3, 0x17, 0xbe, 0x36, 0x49, 0x2a, 0x67, 0xd7 },
+ { 0xe3, 0xc0, 0x73, 0x91, 0x90, 0xed, 0x84, 0x9c, 0x9c, 0x96, 0x2f, 0xd9, 0xdb, 0xb5, 0x5e, 0x20, 0x7e, 0x62, 0x4f, 0xca, 0xc1, 0xeb, 0x41, 0x76, 0x91, 0x51, 0x54, 0x99, 0xee, 0xa8, 0xd8, 0x26, 0x7b, 0x7e, 0x8f, 0x12, 0x87, 0xa6, 0x36, 0x33, 0xaf, 0x50, 0x11, 0xfd, 0xe8, 0xc4, 0xdd, 0xf5, 0x5b, 0xfd, 0xf7, 0x22, 0xed, 0xf8, 0x88, 0x31, 0x41, 0x4f, 0x2c, 0xfa, 0xed, 0x59, 0xcb, 0x9a },
+ { 0x8d, 0x6c, 0xf8, 0x7c, 0x08, 0x38, 0x0d, 0x2d, 0x15, 0x06, 0xee, 0xe4, 0x6f, 0xd4, 0x22, 0x2d, 0x21, 0xd8, 0xc0, 0x4e, 0x58, 0x5f, 0xbf, 0xd0, 0x82, 0x69, 0xc9, 0x8f, 0x70, 0x28, 0x33, 0xa1, 0x56, 0x32, 0x6a, 0x07, 0x24, 0x65, 0x64, 0x00, 0xee, 0x09, 0x35, 0x1d, 0x57, 0xb4, 0x40, 0x17, 0x5e, 0x2a, 0x5d, 0xe9, 0x3c, 0xc5, 0xf8, 0x0d, 0xb6, 0xda, 0xf8, 0x35, 0x76, 0xcf, 0x75, 0xfa },
+ { 0xda, 0x24, 0xbe, 0xde, 0x38, 0x36, 0x66, 0xd5, 0x63, 0xee, 0xed, 0x37, 0xf6, 0x31, 0x9b, 0xaf, 0x20, 0xd5, 0xc7, 0x5d, 0x16, 0x35, 0xa6, 0xba, 0x5e, 0xf4, 0xcf, 0xa1, 0xac, 0x95, 0x48, 0x7e, 0x96, 0xf8, 0xc0, 0x8a, 0xf6, 0x00, 0xaa, 0xb8, 0x7c, 0x98, 0x6e, 0xba, 0xd4, 0x9f, 0xc7, 0x0a, 0x58, 0xb4, 0x89, 0x0b, 0x9c, 0x87, 0x6e, 0x09, 0x10, 0x16, 0xda, 0xf4, 0x9e, 0x1d, 0x32, 0x2e },
+ { 0xf9, 0xd1, 0xd1, 0xb1, 0xe8, 0x7e, 0xa7, 0xae, 0x75, 0x3a, 0x02, 0x97, 0x50, 0xcc, 0x1c, 0xf3, 0xd0, 0x15, 0x7d, 0x41, 0x80, 0x5e, 0x24, 0x5c, 0x56, 0x17, 0xbb, 0x93, 0x4e, 0x73, 0x2f, 0x0a, 0xe3, 0x18, 0x0b, 0x78, 0xe0, 0x5b, 0xfe, 0x76, 0xc7, 0xc3, 0x05, 0x1e, 0x3e, 0x3a, 0xc7, 0x8b, 0x9b, 0x50, 0xc0, 0x51, 0x42, 0x65, 0x7e, 0x1e, 0x03, 0x21, 0x5d, 0x6e, 0xc7, 0xbf, 0xd0, 0xfc },
+ { 0x11, 0xb7, 0xbc, 0x16, 0x68, 0x03, 0x20, 0x48, 0xaa, 0x43, 0x34, 0x3d, 0xe4, 0x76, 0x39, 0x5e, 0x81, 0x4b, 0xbb, 0xc2, 0x23, 0x67, 0x8d, 0xb9, 0x51, 0xa1, 0xb0, 0x3a, 0x02, 0x1e, 0xfa, 0xc9, 0x48, 0xcf, 0xbe, 0x21, 0x5f, 0x97, 0xfe, 0x9a, 0x72, 0xa2, 0xf6, 0xbc, 0x03, 0x9e, 0x39, 0x56, 0xbf, 0xa4, 0x17, 0xc1, 0xa9, 0xf1, 0x0d, 0x6d, 0x7b, 0xa5, 0xd3, 0xd3, 0x2f, 0xf3, 0x23, 0xe5 },
+ { 0xb8, 0xd9, 0x00, 0x0e, 0x4f, 0xc2, 0xb0, 0x66, 0xed, 0xb9, 0x1a, 0xfe, 0xe8, 0xe7, 0xeb, 0x0f, 0x24, 0xe3, 0xa2, 0x01, 0xdb, 0x8b, 0x67, 0x93, 0xc0, 0x60, 0x85, 0x81, 0xe6, 0x28, 0xed, 0x0b, 0xcc, 0x4e, 0x5a, 0xa6, 0x78, 0x79, 0x92, 0xa4, 0xbc, 0xc4, 0x4e, 0x28, 0x80, 0x93, 0xe6, 0x3e, 0xe8, 0x3a, 0xbd, 0x0b, 0xc3, 0xec, 0x6d, 0x09, 0x34, 0xa6, 0x74, 0xa4, 0xda, 0x13, 0x83, 0x8a },
+ { 0xce, 0x32, 0x5e, 0x29, 0x4f, 0x9b, 0x67, 0x19, 0xd6, 0xb6, 0x12, 0x78, 0x27, 0x6a, 0xe0, 0x6a, 0x25, 0x64, 0xc0, 0x3b, 0xb0, 0xb7, 0x83, 0xfa, 0xfe, 0x78, 0x5b, 0xdf, 0x89, 0xc7, 0xd5, 0xac, 0xd8, 0x3e, 0x78, 0x75, 0x6d, 0x30, 0x1b, 0x44, 0x56, 0x99, 0x02, 0x4e, 0xae, 0xb7, 0x7b, 0x54, 0xd4, 0x77, 0x33, 0x6e, 0xc2, 0xa4, 0xf3, 0x32, 0xf2, 0xb3, 0xf8, 0x87, 0x65, 0xdd, 0xb0, 0xc3 },
+ { 0x29, 0xac, 0xc3, 0x0e, 0x96, 0x03, 0xae, 0x2f, 0xcc, 0xf9, 0x0b, 0xf9, 0x7e, 0x6c, 0xc4, 0x63, 0xeb, 0xe2, 0x8c, 0x1b, 0x2f, 0x9b, 0x4b, 0x76, 0x5e, 0x70, 0x53, 0x7c, 0x25, 0xc7, 0x02, 0xa2, 0x9d, 0xcb, 0xfb, 0xf1, 0x4c, 0x99, 0xc5, 0x43, 0x45, 0xba, 0x2b, 0x51, 0xf1, 0x7b, 0x77, 0xb5, 0xf1, 0x5d, 0xb9, 0x2b, 0xba, 0xd8, 0xfa, 0x95, 0xc4, 0x71, 0xf5, 0xd0, 0x70, 0xa1, 0x37, 0xcc },
+ { 0x33, 0x79, 0xcb, 0xaa, 0xe5, 0x62, 0xa8, 0x7b, 0x4c, 0x04, 0x25, 0x55, 0x0f, 0xfd, 0xd6, 0xbf, 0xe1, 0x20, 0x3f, 0x0d, 0x66, 0x6c, 0xc7, 0xea, 0x09, 0x5b, 0xe4, 0x07, 0xa5, 0xdf, 0xe6, 0x1e, 0xe9, 0x14, 0x41, 0xcd, 0x51, 0x54, 0xb3, 0xe5, 0x3b, 0x4f, 0x5f, 0xb3, 0x1a, 0xd4, 0xc7, 0xa9, 0xad, 0x5c, 0x7a, 0xf4, 0xae, 0x67, 0x9a, 0xa5, 0x1a, 0x54, 0x00, 0x3a, 0x54, 0xca, 0x6b, 0x2d },
+ { 0x30, 0x95, 0xa3, 0x49, 0xd2, 0x45, 0x70, 0x8c, 0x7c, 0xf5, 0x50, 0x11, 0x87, 0x03, 0xd7, 0x30, 0x2c, 0x27, 0xb6, 0x0a, 0xf5, 0xd4, 0xe6, 0x7f, 0xc9, 0x78, 0xf8, 0xa4, 0xe6, 0x09, 0x53, 0xc7, 0xa0, 0x4f, 0x92, 0xfc, 0xf4, 0x1a, 0xee, 0x64, 0x32, 0x1c, 0xcb, 0x70, 0x7a, 0x89, 0x58, 0x51, 0x55, 0x2b, 0x1e, 0x37, 0xb0, 0x0b, 0xc5, 0xe6, 0xb7, 0x2f, 0xa5, 0xbc, 0xef, 0x9e, 0x3f, 0xff },
+ { 0x07, 0x26, 0x2d, 0x73, 0x8b, 0x09, 0x32, 0x1f, 0x4d, 0xbc, 0xce, 0xc4, 0xbb, 0x26, 0xf4, 0x8c, 0xb0, 0xf0, 0xed, 0x24, 0x6c, 0xe0, 0xb3, 0x1b, 0x9a, 0x6e, 0x7b, 0xc6, 0x83, 0x04, 0x9f, 0x1f, 0x3e, 0x55, 0x45, 0xf2, 0x8c, 0xe9, 0x32, 0xdd, 0x98, 0x5c, 0x5a, 0xb0, 0xf4, 0x3b, 0xd6, 0xde, 0x07, 0x70, 0x56, 0x0a, 0xf3, 0x29, 0x06, 0x5e, 0xd2, 0xe4, 0x9d, 0x34, 0x62, 0x4c, 0x2c, 0xbb },
+ { 0xb6, 0x40, 0x5e, 0xca, 0x8e, 0xe3, 0x31, 0x6c, 0x87, 0x06, 0x1c, 0xc6, 0xec, 0x18, 0xdb, 0xa5, 0x3e, 0x6c, 0x25, 0x0c, 0x63, 0xba, 0x1f, 0x3b, 0xae, 0x9e, 0x55, 0xdd, 0x34, 0x98, 0x03, 0x6a, 0xf0, 0x8c, 0xd2, 0x72, 0xaa, 0x24, 0xd7, 0x13, 0xc6, 0x02, 0x0d, 0x77, 0xab, 0x2f, 0x39, 0x19, 0xaf, 0x1a, 0x32, 0xf3, 0x07, 0x42, 0x06, 0x18, 0xab, 0x97, 0xe7, 0x39, 0x53, 0x99, 0x4f, 0xb4 },
+ { 0x7e, 0xe6, 0x82, 0xf6, 0x31, 0x48, 0xee, 0x45, 0xf6, 0xe5, 0x31, 0x5d, 0xa8, 0x1e, 0x5c, 0x6e, 0x55, 0x7c, 0x2c, 0x34, 0x64, 0x1f, 0xc5, 0x09, 0xc7, 0xa5, 0x70, 0x10, 0x88, 0xc3, 0x8a, 0x74, 0x75, 0x61, 0x68, 0xe2, 0xcd, 0x8d, 0x35, 0x1e, 0x88, 0xfd, 0x1a, 0x45, 0x1f, 0x36, 0x0a, 0x01, 0xf5, 0xb2, 0x58, 0x0f, 0x9b, 0x5a, 0x2e, 0x8c, 0xfc, 0x13, 0x8f, 0x3d, 0xd5, 0x9a, 0x3f, 0xfc },
+ { 0x1d, 0x26, 0x3c, 0x17, 0x9d, 0x6b, 0x26, 0x8f, 0x6f, 0xa0, 0x16, 0xf3, 0xa4, 0xf2, 0x9e, 0x94, 0x38, 0x91, 0x12, 0x5e, 0xd8, 0x59, 0x3c, 0x81, 0x25, 0x60, 0x59, 0xf5, 0xa7, 0xb4, 0x4a, 0xf2, 0xdc, 0xb2, 0x03, 0x0d, 0x17, 0x5c, 0x00, 0xe6, 0x2e, 0xca, 0xf7, 0xee, 0x96, 0x68, 0x2a, 0xa0, 0x7a, 0xb2, 0x0a, 0x61, 0x10, 0x24, 0xa2, 0x85, 0x32, 0xb1, 0xc2, 0x5b, 0x86, 0x65, 0x79, 0x02 },
+ { 0x10, 0x6d, 0x13, 0x2c, 0xbd, 0xb4, 0xcd, 0x25, 0x97, 0x81, 0x28, 0x46, 0xe2, 0xbc, 0x1b, 0xf7, 0x32, 0xfe, 0xc5, 0xf0, 0xa5, 0xf6, 0x5d, 0xbb, 0x39, 0xec, 0x4e, 0x6d, 0xc6, 0x4a, 0xb2, 0xce, 0x6d, 0x24, 0x63, 0x0d, 0x0f, 0x15, 0xa8, 0x05, 0xc3, 0x54, 0x00, 0x25, 0xd8, 0x4a, 0xfa, 0x98, 0xe3, 0x67, 0x03, 0xc3, 0xdb, 0xee, 0x71, 0x3e, 0x72, 0xdd, 0xe8, 0x46, 0x5b, 0xc1, 0xbe, 0x7e },
+ { 0x0e, 0x79, 0x96, 0x82, 0x26, 0x65, 0x06, 0x67, 0xa8, 0xd8, 0x62, 0xea, 0x8d, 0xa4, 0x89, 0x1a, 0xf5, 0x6a, 0x4e, 0x3a, 0x8b, 0x6d, 0x17, 0x50, 0xe3, 0x94, 0xf0, 0xde, 0xa7, 0x6d, 0x64, 0x0d, 0x85, 0x07, 0x7b, 0xce, 0xc2, 0xcc, 0x86, 0x88, 0x6e, 0x50, 0x67, 0x51, 0xb4, 0xf6, 0xa5, 0x83, 0x8f, 0x7f, 0x0b, 0x5f, 0xef, 0x76, 0x5d, 0x9d, 0xc9, 0x0d, 0xcd, 0xcb, 0xaf, 0x07, 0x9f, 0x08 },
+ { 0x52, 0x11, 0x56, 0xa8, 0x2a, 0xb0, 0xc4, 0xe5, 0x66, 0xe5, 0x84, 0x4d, 0x5e, 0x31, 0xad, 0x9a, 0xaf, 0x14, 0x4b, 0xbd, 0x5a, 0x46, 0x4f, 0xdc, 0xa3, 0x4d, 0xbd, 0x57, 0x17, 0xe8, 0xff, 0x71, 0x1d, 0x3f, 0xfe, 0xbb, 0xfa, 0x08, 0x5d, 0x67, 0xfe, 0x99, 0x6a, 0x34, 0xf6, 0xd3, 0xe4, 0xe6, 0x0b, 0x13, 0x96, 0xbf, 0x4b, 0x16, 0x10, 0xc2, 0x63, 0xbd, 0xbb, 0x83, 0x4d, 0x56, 0x08, 0x16 },
+ { 0x1a, 0xba, 0x88, 0xbe, 0xfc, 0x55, 0xbc, 0x25, 0xef, 0xbc, 0xe0, 0x2d, 0xb8, 0xb9, 0x93, 0x3e, 0x46, 0xf5, 0x76, 0x61, 0xba, 0xea, 0xbe, 0xb2, 0x1c, 0xc2, 0x57, 0x4d, 0x2a, 0x51, 0x8a, 0x3c, 0xba, 0x5d, 0xc5, 0xa3, 0x8e, 0x49, 0x71, 0x34, 0x40, 0xb2, 0x5f, 0x9c, 0x74, 0x4e, 0x75, 0xf6, 0xb8, 0x5c, 0x9d, 0x8f, 0x46, 0x81, 0xf6, 0x76, 0x16, 0x0f, 0x61, 0x05, 0x35, 0x7b, 0x84, 0x06 },
+ { 0x5a, 0x99, 0x49, 0xfc, 0xb2, 0xc4, 0x73, 0xcd, 0xa9, 0x68, 0xac, 0x1b, 0x5d, 0x08, 0x56, 0x6d, 0xc2, 0xd8, 0x16, 0xd9, 0x60, 0xf5, 0x7e, 0x63, 0xb8, 0x98, 0xfa, 0x70, 0x1c, 0xf8, 0xeb, 0xd3, 0xf5, 0x9b, 0x12, 0x4d, 0x95, 0xbf, 0xbb, 0xed, 0xc5, 0xf1, 0xcf, 0x0e, 0x17, 0xd5, 0xea, 0xed, 0x0c, 0x02, 0xc5, 0x0b, 0x69, 0xd8, 0xa4, 0x02, 0xca, 0xbc, 0xca, 0x44, 0x33, 0xb5, 0x1f, 0xd4 },
+ { 0xb0, 0xce, 0xad, 0x09, 0x80, 0x7c, 0x67, 0x2a, 0xf2, 0xeb, 0x2b, 0x0f, 0x06, 0xdd, 0xe4, 0x6c, 0xf5, 0x37, 0x0e, 0x15, 0xa4, 0x09, 0x6b, 0x1a, 0x7d, 0x7c, 0xbb, 0x36, 0xec, 0x31, 0xc2, 0x05, 0xfb, 0xef, 0xca, 0x00, 0xb7, 0xa4, 0x16, 0x2f, 0xa8, 0x9f, 0xb4, 0xfb, 0x3e, 0xb7, 0x8d, 0x79, 0x77, 0x0c, 0x23, 0xf4, 0x4e, 0x72, 0x06, 0x66, 0x4c, 0xe3, 0xcd, 0x93, 0x1c, 0x29, 0x1e, 0x5d },
+ { 0xbb, 0x66, 0x64, 0x93, 0x1e, 0xc9, 0x70, 0x44, 0xe4, 0x5b, 0x2a, 0xe4, 0x20, 0xae, 0x1c, 0x55, 0x1a, 0x88, 0x74, 0xbc, 0x93, 0x7d, 0x08, 0xe9, 0x69, 0x39, 0x9c, 0x39, 0x64, 0xeb, 0xdb, 0xa8, 0x34, 0x6c, 0xdd, 0x5d, 0x09, 0xca, 0xaf, 0xe4, 0xc2, 0x8b, 0xa7, 0xec, 0x78, 0x81, 0x91, 0xce, 0xca, 0x65, 0xdd, 0xd6, 0xf9, 0x5f, 0x18, 0x58, 0x3e, 0x04, 0x0d, 0x0f, 0x30, 0xd0, 0x36, 0x4d },
+ { 0x65, 0xbc, 0x77, 0x0a, 0x5f, 0xaa, 0x37, 0x92, 0x36, 0x98, 0x03, 0x68, 0x3e, 0x84, 0x4b, 0x0b, 0xe7, 0xee, 0x96, 0xf2, 0x9f, 0x6d, 0x6a, 0x35, 0x56, 0x80, 0x06, 0xbd, 0x55, 0x90, 0xf9, 0xa4, 0xef, 0x63, 0x9b, 0x7a, 0x80, 0x61, 0xc7, 0xb0, 0x42, 0x4b, 0x66, 0xb6, 0x0a, 0xc3, 0x4a, 0xf3, 0x11, 0x99, 0x05, 0xf3, 0x3a, 0x9d, 0x8c, 0x3a, 0xe1, 0x83, 0x82, 0xca, 0x9b, 0x68, 0x99, 0x00 },
+ { 0xea, 0x9b, 0x4d, 0xca, 0x33, 0x33, 0x36, 0xaa, 0xf8, 0x39, 0xa4, 0x5c, 0x6e, 0xaa, 0x48, 0xb8, 0xcb, 0x4c, 0x7d, 0xda, 0xbf, 0xfe, 0xa4, 0xf6, 0x43, 0xd6, 0x35, 0x7e, 0xa6, 0x62, 0x8a, 0x48, 0x0a, 0x5b, 0x45, 0xf2, 0xb0, 0x52, 0xc1, 0xb0, 0x7d, 0x1f, 0xed, 0xca, 0x91, 0x8b, 0x6f, 0x11, 0x39, 0xd8, 0x0f, 0x74, 0xc2, 0x45, 0x10, 0xdc, 0xba, 0xa4, 0xbe, 0x70, 0xea, 0xcc, 0x1b, 0x06 },
+ { 0xe6, 0x34, 0x2f, 0xb4, 0xa7, 0x80, 0xad, 0x97, 0x5d, 0x0e, 0x24, 0xbc, 0xe1, 0x49, 0x98, 0x9b, 0x91, 0xd3, 0x60, 0x55, 0x7e, 0x87, 0x99, 0x4f, 0x6b, 0x45, 0x7b, 0x89, 0x55, 0x75, 0xcc, 0x02, 0xd0, 0xc1, 0x5b, 0xad, 0x3c, 0xe7, 0x57, 0x7f, 0x4c, 0x63, 0x92, 0x7f, 0xf1, 0x3f, 0x3e, 0x38, 0x1f, 0xf7, 0xe7, 0x2b, 0xdb, 0xe7, 0x45, 0x32, 0x48, 0x44, 0xa9, 0xd2, 0x7e, 0x3f, 0x1c, 0x01 },
+ { 0x3e, 0x20, 0x9c, 0x9b, 0x33, 0xe8, 0xe4, 0x61, 0x17, 0x8a, 0xb4, 0x6b, 0x1c, 0x64, 0xb4, 0x9a, 0x07, 0xfb, 0x74, 0x5f, 0x1c, 0x8b, 0xc9, 0x5f, 0xbf, 0xb9, 0x4c, 0x6b, 0x87, 0xc6, 0x95, 0x16, 0x65, 0x1b, 0x26, 0x4e, 0xf9, 0x80, 0x93, 0x7f, 0xad, 0x41, 0x23, 0x8b, 0x91, 0xdd, 0xc0, 0x11, 0xa5, 0xdd, 0x77, 0x7c, 0x7e, 0xfd, 0x44, 0x94, 0xb4, 0xb6, 0xec, 0xd3, 0xa9, 0xc2, 0x2a, 0xc0 },
+ { 0xfd, 0x6a, 0x3d, 0x5b, 0x18, 0x75, 0xd8, 0x04, 0x86, 0xd6, 0xe6, 0x96, 0x94, 0xa5, 0x6d, 0xbb, 0x04, 0xa9, 0x9a, 0x4d, 0x05, 0x1f, 0x15, 0xdb, 0x26, 0x89, 0x77, 0x6b, 0xa1, 0xc4, 0x88, 0x2e, 0x6d, 0x46, 0x2a, 0x60, 0x3b, 0x70, 0x15, 0xdc, 0x9f, 0x4b, 0x74, 0x50, 0xf0, 0x53, 0x94, 0x30, 0x3b, 0x86, 0x52, 0xcf, 0xb4, 0x04, 0xa2, 0x66, 0x96, 0x2c, 0x41, 0xba, 0xe6, 0xe1, 0x8a, 0x94 },
+ { 0x95, 0x1e, 0x27, 0x51, 0x7e, 0x6b, 0xad, 0x9e, 0x41, 0x95, 0xfc, 0x86, 0x71, 0xde, 0xe3, 0xe7, 0xe9, 0xbe, 0x69, 0xce, 0xe1, 0x42, 0x2c, 0xb9, 0xfe, 0xcf, 0xce, 0x0d, 0xba, 0x87, 0x5f, 0x7b, 0x31, 0x0b, 0x93, 0xee, 0x3a, 0x3d, 0x55, 0x8f, 0x94, 0x1f, 0x63, 0x5f, 0x66, 0x8f, 0xf8, 0x32, 0xd2, 0xc1, 0xd0, 0x33, 0xc5, 0xe2, 0xf0, 0x99, 0x7e, 0x4c, 0x66, 0xf1, 0x47, 0x34, 0x4e, 0x02 },
+ { 0x8e, 0xba, 0x2f, 0x87, 0x4f, 0x1a, 0xe8, 0x40, 0x41, 0x90, 0x3c, 0x7c, 0x42, 0x53, 0xc8, 0x22, 0x92, 0x53, 0x0f, 0xc8, 0x50, 0x95, 0x50, 0xbf, 0xdc, 0x34, 0xc9, 0x5c, 0x7e, 0x28, 0x89, 0xd5, 0x65, 0x0b, 0x0a, 0xd8, 0xcb, 0x98, 0x8e, 0x5c, 0x48, 0x94, 0xcb, 0x87, 0xfb, 0xfb, 0xb1, 0x96, 0x12, 0xea, 0x93, 0xcc, 0xc4, 0xc5, 0xca, 0xd1, 0x71, 0x58, 0xb9, 0x76, 0x34, 0x64, 0xb4, 0x92 },
+ { 0x16, 0xf7, 0x12, 0xea, 0xa1, 0xb7, 0xc6, 0x35, 0x47, 0x19, 0xa8, 0xe7, 0xdb, 0xdf, 0xaf, 0x55, 0xe4, 0x06, 0x3a, 0x4d, 0x27, 0x7d, 0x94, 0x75, 0x50, 0x01, 0x9b, 0x38, 0xdf, 0xb5, 0x64, 0x83, 0x09, 0x11, 0x05, 0x7d, 0x50, 0x50, 0x61, 0x36, 0xe2, 0x39, 0x4c, 0x3b, 0x28, 0x94, 0x5c, 0xc9, 0x64, 0x96, 0x7d, 0x54, 0xe3, 0x00, 0x0c, 0x21, 0x81, 0x62, 0x6c, 0xfb, 0x9b, 0x73, 0xef, 0xd2 },
+ { 0xc3, 0x96, 0x39, 0xe7, 0xd5, 0xc7, 0xfb, 0x8c, 0xdd, 0x0f, 0xd3, 0xe6, 0xa5, 0x20, 0x96, 0x03, 0x94, 0x37, 0x12, 0x2f, 0x21, 0xc7, 0x8f, 0x16, 0x79, 0xce, 0xa9, 0xd7, 0x8a, 0x73, 0x4c, 0x56, 0xec, 0xbe, 0xb2, 0x86, 0x54, 0xb4, 0xf1, 0x8e, 0x34, 0x2c, 0x33, 0x1f, 0x6f, 0x72, 0x29, 0xec, 0x4b, 0x4b, 0xc2, 0x81, 0xb2, 0xd8, 0x0a, 0x6e, 0xb5, 0x00, 0x43, 0xf3, 0x17, 0x96, 0xc8, 0x8c },
+ { 0x72, 0xd0, 0x81, 0xaf, 0x99, 0xf8, 0xa1, 0x73, 0xdc, 0xc9, 0xa0, 0xac, 0x4e, 0xb3, 0x55, 0x74, 0x05, 0x63, 0x9a, 0x29, 0x08, 0x4b, 0x54, 0xa4, 0x01, 0x72, 0x91, 0x2a, 0x2f, 0x8a, 0x39, 0x51, 0x29, 0xd5, 0x53, 0x6f, 0x09, 0x18, 0xe9, 0x02, 0xf9, 0xe8, 0xfa, 0x60, 0x00, 0x99, 0x5f, 0x41, 0x68, 0xdd, 0xc5, 0xf8, 0x93, 0x01, 0x1b, 0xe6, 0xa0, 0xdb, 0xc9, 0xb8, 0xa1, 0xa3, 0xf5, 0xbb },
+ { 0xc1, 0x1a, 0xa8, 0x1e, 0x5e, 0xfd, 0x24, 0xd5, 0xfc, 0x27, 0xee, 0x58, 0x6c, 0xfd, 0x88, 0x47, 0xfb, 0xb0, 0xe2, 0x76, 0x01, 0xcc, 0xec, 0xe5, 0xec, 0xca, 0x01, 0x98, 0xe3, 0xc7, 0x76, 0x53, 0x93, 0xbb, 0x74, 0x45, 0x7c, 0x7e, 0x7a, 0x27, 0xeb, 0x91, 0x70, 0x35, 0x0e, 0x1f, 0xb5, 0x38, 0x57, 0x17, 0x75, 0x06, 0xbe, 0x3e, 0x76, 0x2c, 0xc0, 0xf1, 0x4d, 0x8c, 0x3a, 0xfe, 0x90, 0x77 },
+ { 0xc2, 0x8f, 0x21, 0x50, 0xb4, 0x52, 0xe6, 0xc0, 0xc4, 0x24, 0xbc, 0xde, 0x6f, 0x8d, 0x72, 0x00, 0x7f, 0x93, 0x10, 0xfe, 0xd7, 0xf2, 0xf8, 0x7d, 0xe0, 0xdb, 0xb6, 0x4f, 0x44, 0x79, 0xd6, 0xc1, 0x44, 0x1b, 0xa6, 0x6f, 0x44, 0xb2, 0xac, 0xce, 0xe6, 0x16, 0x09, 0x17, 0x7e, 0xd3, 0x40, 0x12, 0x8b, 0x40, 0x7e, 0xce, 0xc7, 0xc6, 0x4b, 0xbe, 0x50, 0xd6, 0x3d, 0x22, 0xd8, 0x62, 0x77, 0x27 },
+ { 0xf6, 0x3d, 0x88, 0x12, 0x28, 0x77, 0xec, 0x30, 0xb8, 0xc8, 0xb0, 0x0d, 0x22, 0xe8, 0x90, 0x00, 0xa9, 0x66, 0x42, 0x61, 0x12, 0xbd, 0x44, 0x16, 0x6e, 0x2f, 0x52, 0x5b, 0x76, 0x9c, 0xcb, 0xe9, 0xb2, 0x86, 0xd4, 0x37, 0xa0, 0x12, 0x91, 0x30, 0xdd, 0xe1, 0xa8, 0x6c, 0x43, 0xe0, 0x4b, 0xed, 0xb5, 0x94, 0xe6, 0x71, 0xd9, 0x82, 0x83, 0xaf, 0xe6, 0x4c, 0xe3, 0x31, 0xde, 0x98, 0x28, 0xfd },
+ { 0x34, 0x8b, 0x05, 0x32, 0x88, 0x0b, 0x88, 0xa6, 0x61, 0x4a, 0x8d, 0x74, 0x08, 0xc3, 0xf9, 0x13, 0x35, 0x7f, 0xbb, 0x60, 0xe9, 0x95, 0xc6, 0x02, 0x05, 0xbe, 0x91, 0x39, 0xe7, 0x49, 0x98, 0xae, 0xde, 0x7f, 0x45, 0x81, 0xe4, 0x2f, 0x6b, 0x52, 0x69, 0x8f, 0x7f, 0xa1, 0x21, 0x97, 0x08, 0xc1, 0x44, 0x98, 0x06, 0x7f, 0xd1, 0xe0, 0x95, 0x02, 0xde, 0x83, 0xa7, 0x7d, 0xd2, 0x81, 0x15, 0x0c },
+ { 0x51, 0x33, 0xdc, 0x8b, 0xef, 0x72, 0x53, 0x59, 0xdf, 0xf5, 0x97, 0x92, 0xd8, 0x5e, 0xaf, 0x75, 0xb7, 0xe1, 0xdc, 0xd1, 0x97, 0x8b, 0x01, 0xc3, 0x5b, 0x1b, 0x85, 0xfc, 0xeb, 0xc6, 0x33, 0x88, 0xad, 0x99, 0xa1, 0x7b, 0x63, 0x46, 0xa2, 0x17, 0xdc, 0x1a, 0x96, 0x22, 0xeb, 0xd1, 0x22, 0xec, 0xf6, 0x91, 0x3c, 0x4d, 0x31, 0xa6, 0xb5, 0x2a, 0x69, 0x5b, 0x86, 0xaf, 0x00, 0xd7, 0x41, 0xa0 },
+ { 0x27, 0x53, 0xc4, 0xc0, 0xe9, 0x8e, 0xca, 0xd8, 0x06, 0xe8, 0x87, 0x80, 0xec, 0x27, 0xfc, 0xcd, 0x0f, 0x5c, 0x1a, 0xb5, 0x47, 0xf9, 0xe4, 0xbf, 0x16, 0x59, 0xd1, 0x92, 0xc2, 0x3a, 0xa2, 0xcc, 0x97, 0x1b, 0x58, 0xb6, 0x80, 0x25, 0x80, 0xba, 0xef, 0x8a, 0xdc, 0x3b, 0x77, 0x6e, 0xf7, 0x08, 0x6b, 0x25, 0x45, 0xc2, 0x98, 0x7f, 0x34, 0x8e, 0xe3, 0x71, 0x9c, 0xde, 0xf2, 0x58, 0xc4, 0x03 },
+ { 0xb1, 0x66, 0x35, 0x73, 0xce, 0x4b, 0x9d, 0x8c, 0xae, 0xfc, 0x86, 0x50, 0x12, 0xf3, 0xe3, 0x97, 0x14, 0xb9, 0x89, 0x8a, 0x5d, 0xa6, 0xce, 0x17, 0xc2, 0x5a, 0x6a, 0x47, 0x93, 0x1a, 0x9d, 0xdb, 0x9b, 0xbe, 0x98, 0xad, 0xaa, 0x55, 0x3b, 0xee, 0xd4, 0x36, 0xe8, 0x95, 0x78, 0x45, 0x54, 0x16, 0xc2, 0xa5, 0x2a, 0x52, 0x5c, 0xf2, 0x86, 0x2b, 0x8d, 0x1d, 0x49, 0xa2, 0x53, 0x1b, 0x73, 0x91 },
+ { 0x64, 0xf5, 0x8b, 0xd6, 0xbf, 0xc8, 0x56, 0xf5, 0xe8, 0x73, 0xb2, 0xa2, 0x95, 0x6e, 0xa0, 0xed, 0xa0, 0xd6, 0xdb, 0x0d, 0xa3, 0x9c, 0x8c, 0x7f, 0xc6, 0x7c, 0x9f, 0x9f, 0xee, 0xfc, 0xff, 0x30, 0x72, 0xcd, 0xf9, 0xe6, 0xea, 0x37, 0xf6, 0x9a, 0x44, 0xf0, 0xc6, 0x1a, 0xa0, 0xda, 0x36, 0x93, 0xc2, 0xdb, 0x5b, 0x54, 0x96, 0x0c, 0x02, 0x81, 0xa0, 0x88, 0x15, 0x1d, 0xb4, 0x2b, 0x11, 0xe8 },
+ { 0x07, 0x64, 0xc7, 0xbe, 0x28, 0x12, 0x5d, 0x90, 0x65, 0xc4, 0xb9, 0x8a, 0x69, 0xd6, 0x0a, 0xed, 0xe7, 0x03, 0x54, 0x7c, 0x66, 0xa1, 0x2e, 0x17, 0xe1, 0xc6, 0x18, 0x99, 0x41, 0x32, 0xf5, 0xef, 0x82, 0x48, 0x2c, 0x1e, 0x3f, 0xe3, 0x14, 0x6c, 0xc6, 0x53, 0x76, 0xcc, 0x10, 0x9f, 0x01, 0x38, 0xed, 0x9a, 0x80, 0xe4, 0x9f, 0x1f, 0x3c, 0x7d, 0x61, 0x0d, 0x2f, 0x24, 0x32, 0xf2, 0x06, 0x05 },
+ { 0xf7, 0x48, 0x78, 0x43, 0x98, 0xa2, 0xff, 0x03, 0xeb, 0xeb, 0x07, 0xe1, 0x55, 0xe6, 0x61, 0x16, 0xa8, 0x39, 0x74, 0x1a, 0x33, 0x6e, 0x32, 0xda, 0x71, 0xec, 0x69, 0x60, 0x01, 0xf0, 0xad, 0x1b, 0x25, 0xcd, 0x48, 0xc6, 0x9c, 0xfc, 0xa7, 0x26, 0x5e, 0xca, 0x1d, 0xd7, 0x19, 0x04, 0xa0, 0xce, 0x74, 0x8a, 0xc4, 0x12, 0x4f, 0x35, 0x71, 0x07, 0x6d, 0xfa, 0x71, 0x16, 0xa9, 0xcf, 0x00, 0xe9 },
+ { 0x3f, 0x0d, 0xbc, 0x01, 0x86, 0xbc, 0xeb, 0x6b, 0x78, 0x5b, 0xa7, 0x8d, 0x2a, 0x2a, 0x01, 0x3c, 0x91, 0x0b, 0xe1, 0x57, 0xbd, 0xaf, 0xfa, 0xe8, 0x1b, 0xb6, 0x66, 0x3b, 0x1a, 0x73, 0x72, 0x2f, 0x7f, 0x12, 0x28, 0x79, 0x5f, 0x3e, 0xca, 0xda, 0x87, 0xcf, 0x6e, 0xf0, 0x07, 0x84, 0x74, 0xaf, 0x73, 0xf3, 0x1e, 0xca, 0x0c, 0xc2, 0x00, 0xed, 0x97, 0x5b, 0x68, 0x93, 0xf7, 0x61, 0xcb, 0x6d },
+ { 0xd4, 0x76, 0x2c, 0xd4, 0x59, 0x98, 0x76, 0xca, 0x75, 0xb2, 0xb8, 0xfe, 0x24, 0x99, 0x44, 0xdb, 0xd2, 0x7a, 0xce, 0x74, 0x1f, 0xda, 0xb9, 0x36, 0x16, 0xcb, 0xc6, 0xe4, 0x25, 0x46, 0x0f, 0xeb, 0x51, 0xd4, 0xe7, 0xad, 0xcc, 0x38, 0x18, 0x0e, 0x7f, 0xc4, 0x7c, 0x89, 0x02, 0x4a, 0x7f, 0x56, 0x19, 0x1a, 0xdb, 0x87, 0x8d, 0xfd, 0xe4, 0xea, 0xd6, 0x22, 0x23, 0xf5, 0xa2, 0x61, 0x0e, 0xfe },
+ { 0xcd, 0x36, 0xb3, 0xd5, 0xb4, 0xc9, 0x1b, 0x90, 0xfc, 0xbb, 0xa7, 0x95, 0x13, 0xcf, 0xee, 0x19, 0x07, 0xd8, 0x64, 0x5a, 0x16, 0x2a, 0xfd, 0x0c, 0xd4, 0xcf, 0x41, 0x92, 0xd4, 0xa5, 0xf4, 0xc8, 0x92, 0x18, 0x3a, 0x8e, 0xac, 0xdb, 0x2b, 0x6b, 0x6a, 0x9d, 0x9a, 0xa8, 0xc1, 0x1a, 0xc1, 0xb2, 0x61, 0xb3, 0x80, 0xdb, 0xee, 0x24, 0xca, 0x46, 0x8f, 0x1b, 0xfd, 0x04, 0x3c, 0x58, 0xee, 0xfe },
+ { 0x98, 0x59, 0x34, 0x52, 0x28, 0x16, 0x61, 0xa5, 0x3c, 0x48, 0xa9, 0xd8, 0xcd, 0x79, 0x08, 0x26, 0xc1, 0xa1, 0xce, 0x56, 0x77, 0x38, 0x05, 0x3d, 0x0b, 0xee, 0x4a, 0x91, 0xa3, 0xd5, 0xbd, 0x92, 0xee, 0xfd, 0xba, 0xbe, 0xbe, 0x32, 0x04, 0xf2, 0x03, 0x1c, 0xa5, 0xf7, 0x81, 0xbd, 0xa9, 0x9e, 0xf5, 0xd8, 0xae, 0x56, 0xe5, 0xb0, 0x4a, 0x9e, 0x1e, 0xcd, 0x21, 0xb0, 0xeb, 0x05, 0xd3, 0xe1 },
+ { 0x77, 0x1f, 0x57, 0xdd, 0x27, 0x75, 0xcc, 0xda, 0xb5, 0x59, 0x21, 0xd3, 0xe8, 0xe3, 0x0c, 0xcf, 0x48, 0x4d, 0x61, 0xfe, 0x1c, 0x1b, 0x9c, 0x2a, 0xe8, 0x19, 0xd0, 0xfb, 0x2a, 0x12, 0xfa, 0xb9, 0xbe, 0x70, 0xc4, 0xa7, 0xa1, 0x38, 0xda, 0x84, 0xe8, 0x28, 0x04, 0x35, 0xda, 0xad, 0xe5, 0xbb, 0xe6, 0x6a, 0xf0, 0x83, 0x6a, 0x15, 0x4f, 0x81, 0x7f, 0xb1, 0x7f, 0x33, 0x97, 0xe7, 0x25, 0xa3 },
+ { 0xc6, 0x08, 0x97, 0xc6, 0xf8, 0x28, 0xe2, 0x1f, 0x16, 0xfb, 0xb5, 0xf1, 0x5b, 0x32, 0x3f, 0x87, 0xb6, 0xc8, 0x95, 0x5e, 0xab, 0xf1, 0xd3, 0x80, 0x61, 0xf7, 0x07, 0xf6, 0x08, 0xab, 0xdd, 0x99, 0x3f, 0xac, 0x30, 0x70, 0x63, 0x3e, 0x28, 0x6c, 0xf8, 0x33, 0x9c, 0xe2, 0x95, 0xdd, 0x35, 0x2d, 0xf4, 0xb4, 0xb4, 0x0b, 0x2f, 0x29, 0xda, 0x1d, 0xd5, 0x0b, 0x3a, 0x05, 0xd0, 0x79, 0xe6, 0xbb },
+ { 0x82, 0x10, 0xcd, 0x2c, 0x2d, 0x3b, 0x13, 0x5c, 0x2c, 0xf0, 0x7f, 0xa0, 0xd1, 0x43, 0x3c, 0xd7, 0x71, 0xf3, 0x25, 0xd0, 0x75, 0xc6, 0x46, 0x9d, 0x9c, 0x7f, 0x1b, 0xa0, 0x94, 0x3c, 0xd4, 0xab, 0x09, 0x80, 0x8c, 0xab, 0xf4, 0xac, 0xb9, 0xce, 0x5b, 0xb8, 0x8b, 0x49, 0x89, 0x29, 0xb4, 0xb8, 0x47, 0xf6, 0x81, 0xad, 0x2c, 0x49, 0x0d, 0x04, 0x2d, 0xb2, 0xae, 0xc9, 0x42, 0x14, 0xb0, 0x6b },
+ { 0x1d, 0x4e, 0xdf, 0xff, 0xd8, 0xfd, 0x80, 0xf7, 0xe4, 0x10, 0x78, 0x40, 0xfa, 0x3a, 0xa3, 0x1e, 0x32, 0x59, 0x84, 0x91, 0xe4, 0xaf, 0x70, 0x13, 0xc1, 0x97, 0xa6, 0x5b, 0x7f, 0x36, 0xdd, 0x3a, 0xc4, 0xb4, 0x78, 0x45, 0x61, 0x11, 0xcd, 0x43, 0x09, 0xd9, 0x24, 0x35, 0x10, 0x78, 0x2f, 0xa3, 0x1b, 0x7c, 0x4c, 0x95, 0xfa, 0x95, 0x15, 0x20, 0xd0, 0x20, 0xeb, 0x7e, 0x5c, 0x36, 0xe4, 0xef },
+ { 0xaf, 0x8e, 0x6e, 0x91, 0xfa, 0xb4, 0x6c, 0xe4, 0x87, 0x3e, 0x1a, 0x50, 0xa8, 0xef, 0x44, 0x8c, 0xc2, 0x91, 0x21, 0xf7, 0xf7, 0x4d, 0xee, 0xf3, 0x4a, 0x71, 0xef, 0x89, 0xcc, 0x00, 0xd9, 0x27, 0x4b, 0xc6, 0xc2, 0x45, 0x4b, 0xbb, 0x32, 0x30, 0xd8, 0xb2, 0xec, 0x94, 0xc6, 0x2b, 0x1d, 0xec, 0x85, 0xf3, 0x59, 0x3b, 0xfa, 0x30, 0xea, 0x6f, 0x7a, 0x44, 0xd7, 0xc0, 0x94, 0x65, 0xa2, 0x53 },
+ { 0x29, 0xfd, 0x38, 0x4e, 0xd4, 0x90, 0x6f, 0x2d, 0x13, 0xaa, 0x9f, 0xe7, 0xaf, 0x90, 0x59, 0x90, 0x93, 0x8b, 0xed, 0x80, 0x7f, 0x18, 0x32, 0x45, 0x4a, 0x37, 0x2a, 0xb4, 0x12, 0xee, 0xa1, 0xf5, 0x62, 0x5a, 0x1f, 0xcc, 0x9a, 0xc8, 0x34, 0x3b, 0x7c, 0x67, 0xc5, 0xab, 0xa6, 0xe0, 0xb1, 0xcc, 0x46, 0x44, 0x65, 0x49, 0x13, 0x69, 0x2c, 0x6b, 0x39, 0xeb, 0x91, 0x87, 0xce, 0xac, 0xd3, 0xec },
+ { 0xa2, 0x68, 0xc7, 0x88, 0x5d, 0x98, 0x74, 0xa5, 0x1c, 0x44, 0xdf, 0xfe, 0xd8, 0xea, 0x53, 0xe9, 0x4f, 0x78, 0x45, 0x6e, 0x0b, 0x2e, 0xd9, 0x9f, 0xf5, 0xa3, 0x92, 0x47, 0x60, 0x81, 0x38, 0x26, 0xd9, 0x60, 0xa1, 0x5e, 0xdb, 0xed, 0xbb, 0x5d, 0xe5, 0x22, 0x6b, 0xa4, 0xb0, 0x74, 0xe7, 0x1b, 0x05, 0xc5, 0x5b, 0x97, 0x56, 0xbb, 0x79, 0xe5, 0x5c, 0x02, 0x75, 0x4c, 0x2c, 0x7b, 0x6c, 0x8a },
+ { 0x0c, 0xf8, 0x54, 0x54, 0x88, 0xd5, 0x6a, 0x86, 0x81, 0x7c, 0xd7, 0xec, 0xb1, 0x0f, 0x71, 0x16, 0xb7, 0xea, 0x53, 0x0a, 0x45, 0xb6, 0xea, 0x49, 0x7b, 0x6c, 0x72, 0xc9, 0x97, 0xe0, 0x9e, 0x3d, 0x0d, 0xa8, 0x69, 0x8f, 0x46, 0xbb, 0x00, 0x6f, 0xc9, 0x77, 0xc2, 0xcd, 0x3d, 0x11, 0x77, 0x46, 0x3a, 0xc9, 0x05, 0x7f, 0xdd, 0x16, 0x62, 0xc8, 0x5d, 0x0c, 0x12, 0x64, 0x43, 0xc1, 0x04, 0x73 },
+ { 0xb3, 0x96, 0x14, 0x26, 0x8f, 0xdd, 0x87, 0x81, 0x51, 0x5e, 0x2c, 0xfe, 0xbf, 0x89, 0xb4, 0xd5, 0x40, 0x2b, 0xab, 0x10, 0xc2, 0x26, 0xe6, 0x34, 0x4e, 0x6b, 0x9a, 0xe0, 0x00, 0xfb, 0x0d, 0x6c, 0x79, 0xcb, 0x2f, 0x3e, 0xc8, 0x0e, 0x80, 0xea, 0xeb, 0x19, 0x80, 0xd2, 0xf8, 0x69, 0x89, 0x16, 0xbd, 0x2e, 0x9f, 0x74, 0x72, 0x36, 0x65, 0x51, 0x16, 0x64, 0x9c, 0xd3, 0xca, 0x23, 0xa8, 0x37 },
+ { 0x74, 0xbe, 0xf0, 0x92, 0xfc, 0x6f, 0x1e, 0x5d, 0xba, 0x36, 0x63, 0xa3, 0xfb, 0x00, 0x3b, 0x2a, 0x5b, 0xa2, 0x57, 0x49, 0x65, 0x36, 0xd9, 0x9f, 0x62, 0xb9, 0xd7, 0x3f, 0x8f, 0x9e, 0xb3, 0xce, 0x9f, 0xf3, 0xee, 0xc7, 0x09, 0xeb, 0x88, 0x36, 0x55, 0xec, 0x9e, 0xb8, 0x96, 0xb9, 0x12, 0x8f, 0x2a, 0xfc, 0x89, 0xcf, 0x7d, 0x1a, 0xb5, 0x8a, 0x72, 0xf4, 0xa3, 0xbf, 0x03, 0x4d, 0x2b, 0x4a },
+ { 0x3a, 0x98, 0x8d, 0x38, 0xd7, 0x56, 0x11, 0xf3, 0xef, 0x38, 0xb8, 0x77, 0x49, 0x80, 0xb3, 0x3e, 0x57, 0x3b, 0x6c, 0x57, 0xbe, 0xe0, 0x46, 0x9b, 0xa5, 0xee, 0xd9, 0xb4, 0x4f, 0x29, 0x94, 0x5e, 0x73, 0x47, 0x96, 0x7f, 0xba, 0x2c, 0x16, 0x2e, 0x1c, 0x3b, 0xe7, 0xf3, 0x10, 0xf2, 0xf7, 0x5e, 0xe2, 0x38, 0x1e, 0x7b, 0xfd, 0x6b, 0x3f, 0x0b, 0xae, 0xa8, 0xd9, 0x5d, 0xfb, 0x1d, 0xaf, 0xb1 },
+ { 0x58, 0xae, 0xdf, 0xce, 0x6f, 0x67, 0xdd, 0xc8, 0x5a, 0x28, 0xc9, 0x92, 0xf1, 0xc0, 0xbd, 0x09, 0x69, 0xf0, 0x41, 0xe6, 0x6f, 0x1e, 0xe8, 0x80, 0x20, 0xa1, 0x25, 0xcb, 0xfc, 0xfe, 0xbc, 0xd6, 0x17, 0x09, 0xc9, 0xc4, 0xeb, 0xa1, 0x92, 0xc1, 0x5e, 0x69, 0xf0, 0x20, 0xd4, 0x62, 0x48, 0x60, 0x19, 0xfa, 0x8d, 0xea, 0x0c, 0xd7, 0xa4, 0x29, 0x21, 0xa1, 0x9d, 0x2f, 0xe5, 0x46, 0xd4, 0x3d },
+ { 0x93, 0x47, 0xbd, 0x29, 0x14, 0x73, 0xe6, 0xb4, 0xe3, 0x68, 0x43, 0x7b, 0x8e, 0x56, 0x1e, 0x06, 0x5f, 0x64, 0x9a, 0x6d, 0x8a, 0xda, 0x47, 0x9a, 0xd0, 0x9b, 0x19, 0x99, 0xa8, 0xf2, 0x6b, 0x91, 0xcf, 0x61, 0x20, 0xfd, 0x3b, 0xfe, 0x01, 0x4e, 0x83, 0xf2, 0x3a, 0xcf, 0xa4, 0xc0, 0xad, 0x7b, 0x37, 0x12, 0xb2, 0xc3, 0xc0, 0x73, 0x32, 0x70, 0x66, 0x31, 0x12, 0xcc, 0xd9, 0x28, 0x5c, 0xd9 },
+ { 0xb3, 0x21, 0x63, 0xe7, 0xc5, 0xdb, 0xb5, 0xf5, 0x1f, 0xdc, 0x11, 0xd2, 0xea, 0xc8, 0x75, 0xef, 0xbb, 0xcb, 0x7e, 0x76, 0x99, 0x09, 0x0a, 0x7e, 0x7f, 0xf8, 0xa8, 0xd5, 0x07, 0x95, 0xaf, 0x5d, 0x74, 0xd9, 0xff, 0x98, 0x54, 0x3e, 0xf8, 0xcd, 0xf8, 0x9a, 0xc1, 0x3d, 0x04, 0x85, 0x27, 0x87, 0x56, 0xe0, 0xef, 0x00, 0xc8, 0x17, 0x74, 0x56, 0x61, 0xe1, 0xd5, 0x9f, 0xe3, 0x8e, 0x75, 0x37 },
+ { 0x10, 0x85, 0xd7, 0x83, 0x07, 0xb1, 0xc4, 0xb0, 0x08, 0xc5, 0x7a, 0x2e, 0x7e, 0x5b, 0x23, 0x46, 0x58, 0xa0, 0xa8, 0x2e, 0x4f, 0xf1, 0xe4, 0xaa, 0xac, 0x72, 0xb3, 0x12, 0xfd, 0xa0, 0xfe, 0x27, 0xd2, 0x33, 0xbc, 0x5b, 0x10, 0xe9, 0xcc, 0x17, 0xfd, 0xc7, 0x69, 0x7b, 0x54, 0x0c, 0x7d, 0x95, 0xeb, 0x21, 0x5a, 0x19, 0xa1, 0xa0, 0xe2, 0x0e, 0x1a, 0xbf, 0xa1, 0x26, 0xef, 0xd5, 0x68, 0xc7 },
+ { 0x4e, 0x5c, 0x73, 0x4c, 0x7d, 0xde, 0x01, 0x1d, 0x83, 0xea, 0xc2, 0xb7, 0x34, 0x7b, 0x37, 0x35, 0x94, 0xf9, 0x2d, 0x70, 0x91, 0xb9, 0xca, 0x34, 0xcb, 0x9c, 0x6f, 0x39, 0xbd, 0xf5, 0xa8, 0xd2, 0xf1, 0x34, 0x37, 0x9e, 0x16, 0xd8, 0x22, 0xf6, 0x52, 0x21, 0x70, 0xcc, 0xf2, 0xdd, 0xd5, 0x5c, 0x84, 0xb9, 0xe6, 0xc6, 0x4f, 0xc9, 0x27, 0xac, 0x4c, 0xf8, 0xdf, 0xb2, 0xa1, 0x77, 0x01, 0xf2 },
+ { 0x69, 0x5d, 0x83, 0xbd, 0x99, 0x0a, 0x11, 0x17, 0xb3, 0xd0, 0xce, 0x06, 0xcc, 0x88, 0x80, 0x27, 0xd1, 0x2a, 0x05, 0x4c, 0x26, 0x77, 0xfd, 0x82, 0xf0, 0xd4, 0xfb, 0xfc, 0x93, 0x57, 0x55, 0x23, 0xe7, 0x99, 0x1a, 0x5e, 0x35, 0xa3, 0x75, 0x2e, 0x9b, 0x70, 0xce, 0x62, 0x99, 0x2e, 0x26, 0x8a, 0x87, 0x77, 0x44, 0xcd, 0xd4, 0x35, 0xf5, 0xf1, 0x30, 0x86, 0x9c, 0x9a, 0x20, 0x74, 0xb3, 0x38 },
+ { 0xa6, 0x21, 0x37, 0x43, 0x56, 0x8e, 0x3b, 0x31, 0x58, 0xb9, 0x18, 0x43, 0x01, 0xf3, 0x69, 0x08, 0x47, 0x55, 0x4c, 0x68, 0x45, 0x7c, 0xb4, 0x0f, 0xc9, 0xa4, 0xb8, 0xcf, 0xd8, 0xd4, 0xa1, 0x18, 0xc3, 0x01, 0xa0, 0x77, 0x37, 0xae, 0xda, 0x0f, 0x92, 0x9c, 0x68, 0x91, 0x3c, 0x5f, 0x51, 0xc8, 0x03, 0x94, 0xf5, 0x3b, 0xff, 0x1c, 0x3e, 0x83, 0xb2, 0xe4, 0x0c, 0xa9, 0x7e, 0xba, 0x9e, 0x15 },
+ { 0xd4, 0x44, 0xbf, 0xa2, 0x36, 0x2a, 0x96, 0xdf, 0x21, 0x3d, 0x07, 0x0e, 0x33, 0xfa, 0x84, 0x1f, 0x51, 0x33, 0x4e, 0x4e, 0x76, 0x86, 0x6b, 0x81, 0x39, 0xe8, 0xaf, 0x3b, 0xb3, 0x39, 0x8b, 0xe2, 0xdf, 0xad, 0xdc, 0xbc, 0x56, 0xb9, 0x14, 0x6d, 0xe9, 0xf6, 0x81, 0x18, 0xdc, 0x58, 0x29, 0xe7, 0x4b, 0x0c, 0x28, 0xd7, 0x71, 0x19, 0x07, 0xb1, 0x21, 0xf9, 0x16, 0x1c, 0xb9, 0x2b, 0x69, 0xa9 },
+ { 0x14, 0x27, 0x09, 0xd6, 0x2e, 0x28, 0xfc, 0xcc, 0xd0, 0xaf, 0x97, 0xfa, 0xd0, 0xf8, 0x46, 0x5b, 0x97, 0x1e, 0x82, 0x20, 0x1d, 0xc5, 0x10, 0x70, 0xfa, 0xa0, 0x37, 0x2a, 0xa4, 0x3e, 0x92, 0x48, 0x4b, 0xe1, 0xc1, 0xe7, 0x3b, 0xa1, 0x09, 0x06, 0xd5, 0xd1, 0x85, 0x3d, 0xb6, 0xa4, 0x10, 0x6e, 0x0a, 0x7b, 0xf9, 0x80, 0x0d, 0x37, 0x3d, 0x6d, 0xee, 0x2d, 0x46, 0xd6, 0x2e, 0xf2, 0xa4, 0x61 },
+ };
+ unsigned char inp[1000], out[1000];
+ unsigned char key[] = { 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, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f };
+ unsigned long ilen, klen = sizeof(key), mlen = 64;
+ blake2bmac_state st;
+
+ for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen;
+
+ for (ilen = 0; ilen < 256; ilen++) {
+ const unsigned char *mac = tests[ilen];
+ unsigned long olen = mlen;
+ /* process piece by piece */
+ if (ilen > 15) {
+ blake2bmac_init(&st, olen, key, klen);
+ blake2bmac_process(&st, (unsigned char*)inp, 5);
+ blake2bmac_process(&st, (unsigned char*)inp + 5, 4);
+ blake2bmac_process(&st, (unsigned char*)inp + 9, 3);
+ blake2bmac_process(&st, (unsigned char*)inp + 12, 2);
+ blake2bmac_process(&st, (unsigned char*)inp + 14, 1);
+ blake2bmac_process(&st, (unsigned char*)inp + 15, ilen - 15);
+ blake2bmac_done(&st, out, &olen);
+ if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ /* process in one go */
+ blake2bmac_init(&st, olen, key, klen);
+ blake2bmac_process(&st, (unsigned char*)inp, ilen);
+ blake2bmac_done(&st, out, &olen);
+ if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/blake2/blake2smac.c b/Sources/libtomcrypt/mac/blake2/blake2smac.c
new file mode 100644
index 00000000..f42c7aec
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2smac.c
@@ -0,0 +1,56 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2SMAC
+
+/**
+ Initialize an BLAKE2S MAC context.
+ @param st The BLAKE2S MAC state
+ @param outlen The size of the MAC output (octets)
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @return CRYPT_OK if successful
+*/
+int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen)
+{
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ return blake2s_init(st, outlen, key, keylen);
+}
+
+/**
+ Process data through BLAKE2S MAC
+ @param st The BLAKE2S MAC state
+ @param in The data to send through HMAC
+ @param inlen The length of the data to HMAC (octets)
+ @return CRYPT_OK if successful
+*/
+int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen)
+{
+ if (inlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ return blake2s_process(st, in, inlen);
+}
+
+/**
+ Terminate a BLAKE2S MAC session
+ @param st The BLAKE2S MAC state
+ @param mac [out] The destination of the BLAKE2S MAC authentication tag
+ @param maclen [in/out] The max size and resulting size of the BLAKE2S MAC authentication tag
+ @return CRYPT_OK if successful
+*/
+int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen)
+{
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+ LTC_ARGCHK(*maclen >= st->blake2s.outlen);
+
+ *maclen = st->blake2s.outlen;
+ return blake2s_done(st, mac);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/blake2/blake2smac_file.c b/Sources/libtomcrypt/mac/blake2/blake2smac_file.c
new file mode 100644
index 00000000..bcfbe062
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2smac_file.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2SMAC
+
+/**
+ BLAKE2S MAC a file
+ @param fname The name of the file you wish to BLAKE2S MAC
+ @param key The secret key
+ @param keylen The length of the secret key
+ @param mac [out] The BLAKE2S MAC authentication tag
+ @param maclen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen)
+{
+#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(mac);
+ LTC_UNUSED_PARAM(maclen);
+ return CRYPT_NOP;
+#else
+ blake2smac_state st;
+ FILE *in;
+ unsigned char *buf;
+ size_t x;
+ int err;
+
+ LTC_ARGCHK(fname != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+
+ if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ in = fopen(fname, "rb");
+ if (in == NULL) {
+ err = CRYPT_FILE_NOTFOUND;
+ goto LBL_ERR;
+ }
+
+ do {
+ x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+ if ((err = blake2smac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) {
+ fclose(in);
+ goto LBL_CLEANBUF;
+ }
+ } while (x == LTC_FILE_READ_BUFSIZE);
+
+ if (fclose(in) != 0) {
+ err = CRYPT_ERROR;
+ goto LBL_CLEANBUF;
+ }
+
+ err = blake2smac_done(&st, mac, maclen);
+
+LBL_CLEANBUF:
+ zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(blake2smac_state));
+#endif
+ XFREE(buf);
+ return err;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/blake2/blake2smac_memory.c b/Sources/libtomcrypt/mac/blake2/blake2smac_memory.c
new file mode 100644
index 00000000..755267b0
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2smac_memory.c
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2SMAC
+
+/**
+ BLAKE2S MAC a block of memory to produce the authentication tag
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param in The data to BLAKE2S MAC
+ @param inlen The length of the data to BLAKE2S MAC (octets)
+ @param mac [out] Destination of the authentication tag
+ @param maclen [in/out] Max size and resulting size of authentication tag
+ @return CRYPT_OK if successful
+*/
+int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen)
+{
+ blake2smac_state st;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+
+ if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = blake2smac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
+ err = blake2smac_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(blake2smac_state));
+#endif
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/blake2/blake2smac_memory_multi.c b/Sources/libtomcrypt/mac/blake2/blake2smac_memory_multi.c
new file mode 100644
index 00000000..34fb5e16
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2smac_memory_multi.c
@@ -0,0 +1,52 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+#include
+
+#ifdef LTC_BLAKE2SMAC
+
+/**
+ BLAKE2S MAC multiple blocks of memory to produce the authentication tag
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param mac [out] Destination of the authentication tag
+ @param maclen [in/out] Max size and resulting size of authentication tag
+ @param in The data to BLAKE2S MAC
+ @param inlen The length of the data to BLAKE2S MAC (octets)
+ @param ... tuples of (data,len) pairs to BLAKE2S MAC, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...)
+{
+ blake2smac_state st;
+ int err;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; }
+ for (;;) {
+ if ((err = blake2smac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; }
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) break;
+ curlen = va_arg(args, unsigned long);
+ }
+ err = blake2smac_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(blake2smac_state));
+#endif
+ va_end(args);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/blake2/blake2smac_test.c b/Sources/libtomcrypt/mac/blake2/blake2smac_test.c
new file mode 100644
index 00000000..acfb0305
--- /dev/null
+++ b/Sources/libtomcrypt/mac/blake2/blake2smac_test.c
@@ -0,0 +1,304 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BLAKE2SMAC
+
+int blake2smac_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const unsigned char tests[256][32] = {
+ /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2s-kat.txt */
+ { 0x48, 0xa8, 0x99, 0x7d, 0xa4, 0x07, 0x87, 0x6b, 0x3d, 0x79, 0xc0, 0xd9, 0x23, 0x25, 0xad, 0x3b, 0x89, 0xcb, 0xb7, 0x54, 0xd8, 0x6a, 0xb7, 0x1a, 0xee, 0x04, 0x7a, 0xd3, 0x45, 0xfd, 0x2c, 0x49 },
+ { 0x40, 0xd1, 0x5f, 0xee, 0x7c, 0x32, 0x88, 0x30, 0x16, 0x6a, 0xc3, 0xf9, 0x18, 0x65, 0x0f, 0x80, 0x7e, 0x7e, 0x01, 0xe1, 0x77, 0x25, 0x8c, 0xdc, 0x0a, 0x39, 0xb1, 0x1f, 0x59, 0x80, 0x66, 0xf1 },
+ { 0x6b, 0xb7, 0x13, 0x00, 0x64, 0x4c, 0xd3, 0x99, 0x1b, 0x26, 0xcc, 0xd4, 0xd2, 0x74, 0xac, 0xd1, 0xad, 0xea, 0xb8, 0xb1, 0xd7, 0x91, 0x45, 0x46, 0xc1, 0x19, 0x8b, 0xbe, 0x9f, 0xc9, 0xd8, 0x03 },
+ { 0x1d, 0x22, 0x0d, 0xbe, 0x2e, 0xe1, 0x34, 0x66, 0x1f, 0xdf, 0x6d, 0x9e, 0x74, 0xb4, 0x17, 0x04, 0x71, 0x05, 0x56, 0xf2, 0xf6, 0xe5, 0xa0, 0x91, 0xb2, 0x27, 0x69, 0x74, 0x45, 0xdb, 0xea, 0x6b },
+ { 0xf6, 0xc3, 0xfb, 0xad, 0xb4, 0xcc, 0x68, 0x7a, 0x00, 0x64, 0xa5, 0xbe, 0x6e, 0x79, 0x1b, 0xec, 0x63, 0xb8, 0x68, 0xad, 0x62, 0xfb, 0xa6, 0x1b, 0x37, 0x57, 0xef, 0x9c, 0xa5, 0x2e, 0x05, 0xb2 },
+ { 0x49, 0xc1, 0xf2, 0x11, 0x88, 0xdf, 0xd7, 0x69, 0xae, 0xa0, 0xe9, 0x11, 0xdd, 0x6b, 0x41, 0xf1, 0x4d, 0xab, 0x10, 0x9d, 0x2b, 0x85, 0x97, 0x7a, 0xa3, 0x08, 0x8b, 0x5c, 0x70, 0x7e, 0x85, 0x98 },
+ { 0xfd, 0xd8, 0x99, 0x3d, 0xcd, 0x43, 0xf6, 0x96, 0xd4, 0x4f, 0x3c, 0xea, 0x0f, 0xf3, 0x53, 0x45, 0x23, 0x4e, 0xc8, 0xee, 0x08, 0x3e, 0xb3, 0xca, 0xda, 0x01, 0x7c, 0x7f, 0x78, 0xc1, 0x71, 0x43 },
+ { 0xe6, 0xc8, 0x12, 0x56, 0x37, 0x43, 0x8d, 0x09, 0x05, 0xb7, 0x49, 0xf4, 0x65, 0x60, 0xac, 0x89, 0xfd, 0x47, 0x1c, 0xf8, 0x69, 0x2e, 0x28, 0xfa, 0xb9, 0x82, 0xf7, 0x3f, 0x01, 0x9b, 0x83, 0xa9 },
+ { 0x19, 0xfc, 0x8c, 0xa6, 0x97, 0x9d, 0x60, 0xe6, 0xed, 0xd3, 0xb4, 0x54, 0x1e, 0x2f, 0x96, 0x7c, 0xed, 0x74, 0x0d, 0xf6, 0xec, 0x1e, 0xae, 0xbb, 0xfe, 0x81, 0x38, 0x32, 0xe9, 0x6b, 0x29, 0x74 },
+ { 0xa6, 0xad, 0x77, 0x7c, 0xe8, 0x81, 0xb5, 0x2b, 0xb5, 0xa4, 0x42, 0x1a, 0xb6, 0xcd, 0xd2, 0xdf, 0xba, 0x13, 0xe9, 0x63, 0x65, 0x2d, 0x4d, 0x6d, 0x12, 0x2a, 0xee, 0x46, 0x54, 0x8c, 0x14, 0xa7 },
+ { 0xf5, 0xc4, 0xb2, 0xba, 0x1a, 0x00, 0x78, 0x1b, 0x13, 0xab, 0xa0, 0x42, 0x52, 0x42, 0xc6, 0x9c, 0xb1, 0x55, 0x2f, 0x3f, 0x71, 0xa9, 0xa3, 0xbb, 0x22, 0xb4, 0xa6, 0xb4, 0x27, 0x7b, 0x46, 0xdd },
+ { 0xe3, 0x3c, 0x4c, 0x9b, 0xd0, 0xcc, 0x7e, 0x45, 0xc8, 0x0e, 0x65, 0xc7, 0x7f, 0xa5, 0x99, 0x7f, 0xec, 0x70, 0x02, 0x73, 0x85, 0x41, 0x50, 0x9e, 0x68, 0xa9, 0x42, 0x38, 0x91, 0xe8, 0x22, 0xa3 },
+ { 0xfb, 0xa1, 0x61, 0x69, 0xb2, 0xc3, 0xee, 0x10, 0x5b, 0xe6, 0xe1, 0xe6, 0x50, 0xe5, 0xcb, 0xf4, 0x07, 0x46, 0xb6, 0x75, 0x3d, 0x03, 0x6a, 0xb5, 0x51, 0x79, 0x01, 0x4a, 0xd7, 0xef, 0x66, 0x51 },
+ { 0xf5, 0xc4, 0xbe, 0xc6, 0xd6, 0x2f, 0xc6, 0x08, 0xbf, 0x41, 0xcc, 0x11, 0x5f, 0x16, 0xd6, 0x1c, 0x7e, 0xfd, 0x3f, 0xf6, 0xc6, 0x56, 0x92, 0xbb, 0xe0, 0xaf, 0xff, 0xb1, 0xfe, 0xde, 0x74, 0x75 },
+ { 0xa4, 0x86, 0x2e, 0x76, 0xdb, 0x84, 0x7f, 0x05, 0xba, 0x17, 0xed, 0xe5, 0xda, 0x4e, 0x7f, 0x91, 0xb5, 0x92, 0x5c, 0xf1, 0xad, 0x4b, 0xa1, 0x27, 0x32, 0xc3, 0x99, 0x57, 0x42, 0xa5, 0xcd, 0x6e },
+ { 0x65, 0xf4, 0xb8, 0x60, 0xcd, 0x15, 0xb3, 0x8e, 0xf8, 0x14, 0xa1, 0xa8, 0x04, 0x31, 0x4a, 0x55, 0xbe, 0x95, 0x3c, 0xaa, 0x65, 0xfd, 0x75, 0x8a, 0xd9, 0x89, 0xff, 0x34, 0xa4, 0x1c, 0x1e, 0xea },
+ { 0x19, 0xba, 0x23, 0x4f, 0x0a, 0x4f, 0x38, 0x63, 0x7d, 0x18, 0x39, 0xf9, 0xd9, 0xf7, 0x6a, 0xd9, 0x1c, 0x85, 0x22, 0x30, 0x71, 0x43, 0xc9, 0x7d, 0x5f, 0x93, 0xf6, 0x92, 0x74, 0xce, 0xc9, 0xa7 },
+ { 0x1a, 0x67, 0x18, 0x6c, 0xa4, 0xa5, 0xcb, 0x8e, 0x65, 0xfc, 0xa0, 0xe2, 0xec, 0xbc, 0x5d, 0xdc, 0x14, 0xae, 0x38, 0x1b, 0xb8, 0xbf, 0xfe, 0xb9, 0xe0, 0xa1, 0x03, 0x44, 0x9e, 0x3e, 0xf0, 0x3c },
+ { 0xaf, 0xbe, 0xa3, 0x17, 0xb5, 0xa2, 0xe8, 0x9c, 0x0b, 0xd9, 0x0c, 0xcf, 0x5d, 0x7f, 0xd0, 0xed, 0x57, 0xfe, 0x58, 0x5e, 0x4b, 0xe3, 0x27, 0x1b, 0x0a, 0x6b, 0xf0, 0xf5, 0x78, 0x6b, 0x0f, 0x26 },
+ { 0xf1, 0xb0, 0x15, 0x58, 0xce, 0x54, 0x12, 0x62, 0xf5, 0xec, 0x34, 0x29, 0x9d, 0x6f, 0xb4, 0x09, 0x00, 0x09, 0xe3, 0x43, 0x4b, 0xe2, 0xf4, 0x91, 0x05, 0xcf, 0x46, 0xaf, 0x4d, 0x2d, 0x41, 0x24 },
+ { 0x13, 0xa0, 0xa0, 0xc8, 0x63, 0x35, 0x63, 0x5e, 0xaa, 0x74, 0xca, 0x2d, 0x5d, 0x48, 0x8c, 0x79, 0x7b, 0xbb, 0x4f, 0x47, 0xdc, 0x07, 0x10, 0x50, 0x15, 0xed, 0x6a, 0x1f, 0x33, 0x09, 0xef, 0xce },
+ { 0x15, 0x80, 0xaf, 0xee, 0xbe, 0xbb, 0x34, 0x6f, 0x94, 0xd5, 0x9f, 0xe6, 0x2d, 0xa0, 0xb7, 0x92, 0x37, 0xea, 0xd7, 0xb1, 0x49, 0x1f, 0x56, 0x67, 0xa9, 0x0e, 0x45, 0xed, 0xf6, 0xca, 0x8b, 0x03 },
+ { 0x20, 0xbe, 0x1a, 0x87, 0x5b, 0x38, 0xc5, 0x73, 0xdd, 0x7f, 0xaa, 0xa0, 0xde, 0x48, 0x9d, 0x65, 0x5c, 0x11, 0xef, 0xb6, 0xa5, 0x52, 0x69, 0x8e, 0x07, 0xa2, 0xd3, 0x31, 0xb5, 0xf6, 0x55, 0xc3 },
+ { 0xbe, 0x1f, 0xe3, 0xc4, 0xc0, 0x40, 0x18, 0xc5, 0x4c, 0x4a, 0x0f, 0x6b, 0x9a, 0x2e, 0xd3, 0xc5, 0x3a, 0xbe, 0x3a, 0x9f, 0x76, 0xb4, 0xd2, 0x6d, 0xe5, 0x6f, 0xc9, 0xae, 0x95, 0x05, 0x9a, 0x99 },
+ { 0xe3, 0xe3, 0xac, 0xe5, 0x37, 0xeb, 0x3e, 0xdd, 0x84, 0x63, 0xd9, 0xad, 0x35, 0x82, 0xe1, 0x3c, 0xf8, 0x65, 0x33, 0xff, 0xde, 0x43, 0xd6, 0x68, 0xdd, 0x2e, 0x93, 0xbb, 0xdb, 0xd7, 0x19, 0x5a },
+ { 0x11, 0x0c, 0x50, 0xc0, 0xbf, 0x2c, 0x6e, 0x7a, 0xeb, 0x7e, 0x43, 0x5d, 0x92, 0xd1, 0x32, 0xab, 0x66, 0x55, 0x16, 0x8e, 0x78, 0xa2, 0xde, 0xcd, 0xec, 0x33, 0x30, 0x77, 0x76, 0x84, 0xd9, 0xc1 },
+ { 0xe9, 0xba, 0x8f, 0x50, 0x5c, 0x9c, 0x80, 0xc0, 0x86, 0x66, 0xa7, 0x01, 0xf3, 0x36, 0x7e, 0x6c, 0xc6, 0x65, 0xf3, 0x4b, 0x22, 0xe7, 0x3c, 0x3c, 0x04, 0x17, 0xeb, 0x1c, 0x22, 0x06, 0x08, 0x2f },
+ { 0x26, 0xcd, 0x66, 0xfc, 0xa0, 0x23, 0x79, 0xc7, 0x6d, 0xf1, 0x23, 0x17, 0x05, 0x2b, 0xca, 0xfd, 0x6c, 0xd8, 0xc3, 0xa7, 0xb8, 0x90, 0xd8, 0x05, 0xf3, 0x6c, 0x49, 0x98, 0x97, 0x82, 0x43, 0x3a },
+ { 0x21, 0x3f, 0x35, 0x96, 0xd6, 0xe3, 0xa5, 0xd0, 0xe9, 0x93, 0x2c, 0xd2, 0x15, 0x91, 0x46, 0x01, 0x5e, 0x2a, 0xbc, 0x94, 0x9f, 0x47, 0x29, 0xee, 0x26, 0x32, 0xfe, 0x1e, 0xdb, 0x78, 0xd3, 0x37 },
+ { 0x10, 0x15, 0xd7, 0x01, 0x08, 0xe0, 0x3b, 0xe1, 0xc7, 0x02, 0xfe, 0x97, 0x25, 0x36, 0x07, 0xd1, 0x4a, 0xee, 0x59, 0x1f, 0x24, 0x13, 0xea, 0x67, 0x87, 0x42, 0x7b, 0x64, 0x59, 0xff, 0x21, 0x9a },
+ { 0x3c, 0xa9, 0x89, 0xde, 0x10, 0xcf, 0xe6, 0x09, 0x90, 0x94, 0x72, 0xc8, 0xd3, 0x56, 0x10, 0x80, 0x5b, 0x2f, 0x97, 0x77, 0x34, 0xcf, 0x65, 0x2c, 0xc6, 0x4b, 0x3b, 0xfc, 0x88, 0x2d, 0x5d, 0x89 },
+ { 0xb6, 0x15, 0x6f, 0x72, 0xd3, 0x80, 0xee, 0x9e, 0xa6, 0xac, 0xd1, 0x90, 0x46, 0x4f, 0x23, 0x07, 0xa5, 0xc1, 0x79, 0xef, 0x01, 0xfd, 0x71, 0xf9, 0x9f, 0x2d, 0x0f, 0x7a, 0x57, 0x36, 0x0a, 0xea },
+ { 0xc0, 0x3b, 0xc6, 0x42, 0xb2, 0x09, 0x59, 0xcb, 0xe1, 0x33, 0xa0, 0x30, 0x3e, 0x0c, 0x1a, 0xbf, 0xf3, 0xe3, 0x1e, 0xc8, 0xe1, 0xa3, 0x28, 0xec, 0x85, 0x65, 0xc3, 0x6d, 0xec, 0xff, 0x52, 0x65 },
+ { 0x2c, 0x3e, 0x08, 0x17, 0x6f, 0x76, 0x0c, 0x62, 0x64, 0xc3, 0xa2, 0xcd, 0x66, 0xfe, 0xc6, 0xc3, 0xd7, 0x8d, 0xe4, 0x3f, 0xc1, 0x92, 0x45, 0x7b, 0x2a, 0x4a, 0x66, 0x0a, 0x1e, 0x0e, 0xb2, 0x2b },
+ { 0xf7, 0x38, 0xc0, 0x2f, 0x3c, 0x1b, 0x19, 0x0c, 0x51, 0x2b, 0x1a, 0x32, 0xde, 0xab, 0xf3, 0x53, 0x72, 0x8e, 0x0e, 0x9a, 0xb0, 0x34, 0x49, 0x0e, 0x3c, 0x34, 0x09, 0x94, 0x6a, 0x97, 0xae, 0xec },
+ { 0x8b, 0x18, 0x80, 0xdf, 0x30, 0x1c, 0xc9, 0x63, 0x41, 0x88, 0x11, 0x08, 0x89, 0x64, 0x83, 0x92, 0x87, 0xff, 0x7f, 0xe3, 0x1c, 0x49, 0xea, 0x6e, 0xbd, 0x9e, 0x48, 0xbd, 0xee, 0xe4, 0x97, 0xc5 },
+ { 0x1e, 0x75, 0xcb, 0x21, 0xc6, 0x09, 0x89, 0x02, 0x03, 0x75, 0xf1, 0xa7, 0xa2, 0x42, 0x83, 0x9f, 0x0b, 0x0b, 0x68, 0x97, 0x3a, 0x4c, 0x2a, 0x05, 0xcf, 0x75, 0x55, 0xed, 0x5a, 0xae, 0xc4, 0xc1 },
+ { 0x62, 0xbf, 0x8a, 0x9c, 0x32, 0xa5, 0xbc, 0xcf, 0x29, 0x0b, 0x6c, 0x47, 0x4d, 0x75, 0xb2, 0xa2, 0xa4, 0x09, 0x3f, 0x1a, 0x9e, 0x27, 0x13, 0x94, 0x33, 0xa8, 0xf2, 0xb3, 0xbc, 0xe7, 0xb8, 0xd7 },
+ { 0x16, 0x6c, 0x83, 0x50, 0xd3, 0x17, 0x3b, 0x5e, 0x70, 0x2b, 0x78, 0x3d, 0xfd, 0x33, 0xc6, 0x6e, 0xe0, 0x43, 0x27, 0x42, 0xe9, 0xb9, 0x2b, 0x99, 0x7f, 0xd2, 0x3c, 0x60, 0xdc, 0x67, 0x56, 0xca },
+ { 0x04, 0x4a, 0x14, 0xd8, 0x22, 0xa9, 0x0c, 0xac, 0xf2, 0xf5, 0xa1, 0x01, 0x42, 0x8a, 0xdc, 0x8f, 0x41, 0x09, 0x38, 0x6c, 0xcb, 0x15, 0x8b, 0xf9, 0x05, 0xc8, 0x61, 0x8b, 0x8e, 0xe2, 0x4e, 0xc3 },
+ { 0x38, 0x7d, 0x39, 0x7e, 0xa4, 0x3a, 0x99, 0x4b, 0xe8, 0x4d, 0x2d, 0x54, 0x4a, 0xfb, 0xe4, 0x81, 0xa2, 0x00, 0x0f, 0x55, 0x25, 0x26, 0x96, 0xbb, 0xa2, 0xc5, 0x0c, 0x8e, 0xbd, 0x10, 0x13, 0x47 },
+ { 0x56, 0xf8, 0xcc, 0xf1, 0xf8, 0x64, 0x09, 0xb4, 0x6c, 0xe3, 0x61, 0x66, 0xae, 0x91, 0x65, 0x13, 0x84, 0x41, 0x57, 0x75, 0x89, 0xdb, 0x08, 0xcb, 0xc5, 0xf6, 0x6c, 0xa2, 0x97, 0x43, 0xb9, 0xfd },
+ { 0x97, 0x06, 0xc0, 0x92, 0xb0, 0x4d, 0x91, 0xf5, 0x3d, 0xff, 0x91, 0xfa, 0x37, 0xb7, 0x49, 0x3d, 0x28, 0xb5, 0x76, 0xb5, 0xd7, 0x10, 0x46, 0x9d, 0xf7, 0x94, 0x01, 0x66, 0x22, 0x36, 0xfc, 0x03 },
+ { 0x87, 0x79, 0x68, 0x68, 0x6c, 0x06, 0x8c, 0xe2, 0xf7, 0xe2, 0xad, 0xcf, 0xf6, 0x8b, 0xf8, 0x74, 0x8e, 0xdf, 0x3c, 0xf8, 0x62, 0xcf, 0xb4, 0xd3, 0x94, 0x7a, 0x31, 0x06, 0x95, 0x80, 0x54, 0xe3 },
+ { 0x88, 0x17, 0xe5, 0x71, 0x98, 0x79, 0xac, 0xf7, 0x02, 0x47, 0x87, 0xec, 0xcd, 0xb2, 0x71, 0x03, 0x55, 0x66, 0xcf, 0xa3, 0x33, 0xe0, 0x49, 0x40, 0x7c, 0x01, 0x78, 0xcc, 0xc5, 0x7a, 0x5b, 0x9f },
+ { 0x89, 0x38, 0x24, 0x9e, 0x4b, 0x50, 0xca, 0xda, 0xcc, 0xdf, 0x5b, 0x18, 0x62, 0x13, 0x26, 0xcb, 0xb1, 0x52, 0x53, 0xe3, 0x3a, 0x20, 0xf5, 0x63, 0x6e, 0x99, 0x5d, 0x72, 0x47, 0x8d, 0xe4, 0x72 },
+ { 0xf1, 0x64, 0xab, 0xba, 0x49, 0x63, 0xa4, 0x4d, 0x10, 0x72, 0x57, 0xe3, 0x23, 0x2d, 0x90, 0xac, 0xa5, 0xe6, 0x6a, 0x14, 0x08, 0x24, 0x8c, 0x51, 0x74, 0x1e, 0x99, 0x1d, 0xb5, 0x22, 0x77, 0x56 },
+ { 0xd0, 0x55, 0x63, 0xe2, 0xb1, 0xcb, 0xa0, 0xc4, 0xa2, 0xa1, 0xe8, 0xbd, 0xe3, 0xa1, 0xa0, 0xd9, 0xf5, 0xb4, 0x0c, 0x85, 0xa0, 0x70, 0xd6, 0xf5, 0xfb, 0x21, 0x06, 0x6e, 0xad, 0x5d, 0x06, 0x01 },
+ { 0x03, 0xfb, 0xb1, 0x63, 0x84, 0xf0, 0xa3, 0x86, 0x6f, 0x4c, 0x31, 0x17, 0x87, 0x76, 0x66, 0xef, 0xbf, 0x12, 0x45, 0x97, 0x56, 0x4b, 0x29, 0x3d, 0x4a, 0xab, 0x0d, 0x26, 0x9f, 0xab, 0xdd, 0xfa },
+ { 0x5f, 0xa8, 0x48, 0x6a, 0xc0, 0xe5, 0x29, 0x64, 0xd1, 0x88, 0x1b, 0xbe, 0x33, 0x8e, 0xb5, 0x4b, 0xe2, 0xf7, 0x19, 0x54, 0x92, 0x24, 0x89, 0x20, 0x57, 0xb4, 0xda, 0x04, 0xba, 0x8b, 0x34, 0x75 },
+ { 0xcd, 0xfa, 0xbc, 0xee, 0x46, 0x91, 0x11, 0x11, 0x23, 0x6a, 0x31, 0x70, 0x8b, 0x25, 0x39, 0xd7, 0x1f, 0xc2, 0x11, 0xd9, 0xb0, 0x9c, 0x0d, 0x85, 0x30, 0xa1, 0x1e, 0x1d, 0xbf, 0x6e, 0xed, 0x01 },
+ { 0x4f, 0x82, 0xde, 0x03, 0xb9, 0x50, 0x47, 0x93, 0xb8, 0x2a, 0x07, 0xa0, 0xbd, 0xcd, 0xff, 0x31, 0x4d, 0x75, 0x9e, 0x7b, 0x62, 0xd2, 0x6b, 0x78, 0x49, 0x46, 0xb0, 0xd3, 0x6f, 0x91, 0x6f, 0x52 },
+ { 0x25, 0x9e, 0xc7, 0xf1, 0x73, 0xbc, 0xc7, 0x6a, 0x09, 0x94, 0xc9, 0x67, 0xb4, 0xf5, 0xf0, 0x24, 0xc5, 0x60, 0x57, 0xfb, 0x79, 0xc9, 0x65, 0xc4, 0xfa, 0xe4, 0x18, 0x75, 0xf0, 0x6a, 0x0e, 0x4c },
+ { 0x19, 0x3c, 0xc8, 0xe7, 0xc3, 0xe0, 0x8b, 0xb3, 0x0f, 0x54, 0x37, 0xaa, 0x27, 0xad, 0xe1, 0xf1, 0x42, 0x36, 0x9b, 0x24, 0x6a, 0x67, 0x5b, 0x23, 0x83, 0xe6, 0xda, 0x9b, 0x49, 0xa9, 0x80, 0x9e },
+ { 0x5c, 0x10, 0x89, 0x6f, 0x0e, 0x28, 0x56, 0xb2, 0xa2, 0xee, 0xe0, 0xfe, 0x4a, 0x2c, 0x16, 0x33, 0x56, 0x5d, 0x18, 0xf0, 0xe9, 0x3e, 0x1f, 0xab, 0x26, 0xc3, 0x73, 0xe8, 0xf8, 0x29, 0x65, 0x4d },
+ { 0xf1, 0x60, 0x12, 0xd9, 0x3f, 0x28, 0x85, 0x1a, 0x1e, 0xb9, 0x89, 0xf5, 0xd0, 0xb4, 0x3f, 0x3f, 0x39, 0xca, 0x73, 0xc9, 0xa6, 0x2d, 0x51, 0x81, 0xbf, 0xf2, 0x37, 0x53, 0x6b, 0xd3, 0x48, 0xc3 },
+ { 0x29, 0x66, 0xb3, 0xcf, 0xae, 0x1e, 0x44, 0xea, 0x99, 0x6d, 0xc5, 0xd6, 0x86, 0xcf, 0x25, 0xfa, 0x05, 0x3f, 0xb6, 0xf6, 0x72, 0x01, 0xb9, 0xe4, 0x6e, 0xad, 0xe8, 0x5d, 0x0a, 0xd6, 0xb8, 0x06 },
+ { 0xdd, 0xb8, 0x78, 0x24, 0x85, 0xe9, 0x00, 0xbc, 0x60, 0xbc, 0xf4, 0xc3, 0x3a, 0x6f, 0xd5, 0x85, 0x68, 0x0c, 0xc6, 0x83, 0xd5, 0x16, 0xef, 0xa0, 0x3e, 0xb9, 0x98, 0x5f, 0xad, 0x87, 0x15, 0xfb },
+ { 0x4c, 0x4d, 0x6e, 0x71, 0xae, 0xa0, 0x57, 0x86, 0x41, 0x31, 0x48, 0xfc, 0x7a, 0x78, 0x6b, 0x0e, 0xca, 0xf5, 0x82, 0xcf, 0xf1, 0x20, 0x9f, 0x5a, 0x80, 0x9f, 0xba, 0x85, 0x04, 0xce, 0x66, 0x2c },
+ { 0xfb, 0x4c, 0x5e, 0x86, 0xd7, 0xb2, 0x22, 0x9b, 0x99, 0xb8, 0xba, 0x6d, 0x94, 0xc2, 0x47, 0xef, 0x96, 0x4a, 0xa3, 0xa2, 0xba, 0xe8, 0xed, 0xc7, 0x75, 0x69, 0xf2, 0x8d, 0xbb, 0xff, 0x2d, 0x4e },
+ { 0xe9, 0x4f, 0x52, 0x6d, 0xe9, 0x01, 0x96, 0x33, 0xec, 0xd5, 0x4a, 0xc6, 0x12, 0x0f, 0x23, 0x95, 0x8d, 0x77, 0x18, 0xf1, 0xe7, 0x71, 0x7b, 0xf3, 0x29, 0x21, 0x1a, 0x4f, 0xae, 0xed, 0x4e, 0x6d },
+ { 0xcb, 0xd6, 0x66, 0x0a, 0x10, 0xdb, 0x3f, 0x23, 0xf7, 0xa0, 0x3d, 0x4b, 0x9d, 0x40, 0x44, 0xc7, 0x93, 0x2b, 0x28, 0x01, 0xac, 0x89, 0xd6, 0x0b, 0xc9, 0xeb, 0x92, 0xd6, 0x5a, 0x46, 0xc2, 0xa0 },
+ { 0x88, 0x18, 0xbb, 0xd3, 0xdb, 0x4d, 0xc1, 0x23, 0xb2, 0x5c, 0xbb, 0xa5, 0xf5, 0x4c, 0x2b, 0xc4, 0xb3, 0xfc, 0xf9, 0xbf, 0x7d, 0x7a, 0x77, 0x09, 0xf4, 0xae, 0x58, 0x8b, 0x26, 0x7c, 0x4e, 0xce },
+ { 0xc6, 0x53, 0x82, 0x51, 0x3f, 0x07, 0x46, 0x0d, 0xa3, 0x98, 0x33, 0xcb, 0x66, 0x6c, 0x5e, 0xd8, 0x2e, 0x61, 0xb9, 0xe9, 0x98, 0xf4, 0xb0, 0xc4, 0x28, 0x7c, 0xee, 0x56, 0xc3, 0xcc, 0x9b, 0xcd },
+ { 0x89, 0x75, 0xb0, 0x57, 0x7f, 0xd3, 0x55, 0x66, 0xd7, 0x50, 0xb3, 0x62, 0xb0, 0x89, 0x7a, 0x26, 0xc3, 0x99, 0x13, 0x6d, 0xf0, 0x7b, 0xab, 0xab, 0xbd, 0xe6, 0x20, 0x3f, 0xf2, 0x95, 0x4e, 0xd4 },
+ { 0x21, 0xfe, 0x0c, 0xeb, 0x00, 0x52, 0xbe, 0x7f, 0xb0, 0xf0, 0x04, 0x18, 0x7c, 0xac, 0xd7, 0xde, 0x67, 0xfa, 0x6e, 0xb0, 0x93, 0x8d, 0x92, 0x76, 0x77, 0xf2, 0x39, 0x8c, 0x13, 0x23, 0x17, 0xa8 },
+ { 0x2e, 0xf7, 0x3f, 0x3c, 0x26, 0xf1, 0x2d, 0x93, 0x88, 0x9f, 0x3c, 0x78, 0xb6, 0xa6, 0x6c, 0x1d, 0x52, 0xb6, 0x49, 0xdc, 0x9e, 0x85, 0x6e, 0x2c, 0x17, 0x2e, 0xa7, 0xc5, 0x8a, 0xc2, 0xb5, 0xe3 },
+ { 0x38, 0x8a, 0x3c, 0xd5, 0x6d, 0x73, 0x86, 0x7a, 0xbb, 0x5f, 0x84, 0x01, 0x49, 0x2b, 0x6e, 0x26, 0x81, 0xeb, 0x69, 0x85, 0x1e, 0x76, 0x7f, 0xd8, 0x42, 0x10, 0xa5, 0x60, 0x76, 0xfb, 0x3d, 0xd3 },
+ { 0xaf, 0x53, 0x3e, 0x02, 0x2f, 0xc9, 0x43, 0x9e, 0x4e, 0x3c, 0xb8, 0x38, 0xec, 0xd1, 0x86, 0x92, 0x23, 0x2a, 0xdf, 0x6f, 0xe9, 0x83, 0x95, 0x26, 0xd3, 0xc3, 0xdd, 0x1b, 0x71, 0x91, 0x0b, 0x1a },
+ { 0x75, 0x1c, 0x09, 0xd4, 0x1a, 0x93, 0x43, 0x88, 0x2a, 0x81, 0xcd, 0x13, 0xee, 0x40, 0x81, 0x8d, 0x12, 0xeb, 0x44, 0xc6, 0xc7, 0xf4, 0x0d, 0xf1, 0x6e, 0x4a, 0xea, 0x8f, 0xab, 0x91, 0x97, 0x2a },
+ { 0x5b, 0x73, 0xdd, 0xb6, 0x8d, 0x9d, 0x2b, 0x0a, 0xa2, 0x65, 0xa0, 0x79, 0x88, 0xd6, 0xb8, 0x8a, 0xe9, 0xaa, 0xc5, 0x82, 0xaf, 0x83, 0x03, 0x2f, 0x8a, 0x9b, 0x21, 0xa2, 0xe1, 0xb7, 0xbf, 0x18 },
+ { 0x3d, 0xa2, 0x91, 0x26, 0xc7, 0xc5, 0xd7, 0xf4, 0x3e, 0x64, 0x24, 0x2a, 0x79, 0xfe, 0xaa, 0x4e, 0xf3, 0x45, 0x9c, 0xde, 0xcc, 0xc8, 0x98, 0xed, 0x59, 0xa9, 0x7f, 0x6e, 0xc9, 0x3b, 0x9d, 0xab },
+ { 0x56, 0x6d, 0xc9, 0x20, 0x29, 0x3d, 0xa5, 0xcb, 0x4f, 0xe0, 0xaa, 0x8a, 0xbd, 0xa8, 0xbb, 0xf5, 0x6f, 0x55, 0x23, 0x13, 0xbf, 0xf1, 0x90, 0x46, 0x64, 0x1e, 0x36, 0x15, 0xc1, 0xe3, 0xed, 0x3f },
+ { 0x41, 0x15, 0xbe, 0xa0, 0x2f, 0x73, 0xf9, 0x7f, 0x62, 0x9e, 0x5c, 0x55, 0x90, 0x72, 0x0c, 0x01, 0xe7, 0xe4, 0x49, 0xae, 0x2a, 0x66, 0x97, 0xd4, 0xd2, 0x78, 0x33, 0x21, 0x30, 0x36, 0x92, 0xf9 },
+ { 0x4c, 0xe0, 0x8f, 0x47, 0x62, 0x46, 0x8a, 0x76, 0x70, 0x01, 0x21, 0x64, 0x87, 0x8d, 0x68, 0x34, 0x0c, 0x52, 0xa3, 0x5e, 0x66, 0xc1, 0x88, 0x4d, 0x5c, 0x86, 0x48, 0x89, 0xab, 0xc9, 0x66, 0x77 },
+ { 0x81, 0xea, 0x0b, 0x78, 0x04, 0x12, 0x4e, 0x0c, 0x22, 0xea, 0x5f, 0xc7, 0x11, 0x04, 0xa2, 0xaf, 0xcb, 0x52, 0xa1, 0xfa, 0x81, 0x6f, 0x3e, 0xcb, 0x7d, 0xcb, 0x5d, 0x9d, 0xea, 0x17, 0x86, 0xd0 },
+ { 0xfe, 0x36, 0x27, 0x33, 0xb0, 0x5f, 0x6b, 0xed, 0xaf, 0x93, 0x79, 0xd7, 0xf7, 0x93, 0x6e, 0xde, 0x20, 0x9b, 0x1f, 0x83, 0x23, 0xc3, 0x92, 0x25, 0x49, 0xd9, 0xe7, 0x36, 0x81, 0xb5, 0xdb, 0x7b },
+ { 0xef, 0xf3, 0x7d, 0x30, 0xdf, 0xd2, 0x03, 0x59, 0xbe, 0x4e, 0x73, 0xfd, 0xf4, 0x0d, 0x27, 0x73, 0x4b, 0x3d, 0xf9, 0x0a, 0x97, 0xa5, 0x5e, 0xd7, 0x45, 0x29, 0x72, 0x94, 0xca, 0x85, 0xd0, 0x9f },
+ { 0x17, 0x2f, 0xfc, 0x67, 0x15, 0x3d, 0x12, 0xe0, 0xca, 0x76, 0xa8, 0xb6, 0xcd, 0x5d, 0x47, 0x31, 0x88, 0x5b, 0x39, 0xce, 0x0c, 0xac, 0x93, 0xa8, 0x97, 0x2a, 0x18, 0x00, 0x6c, 0x8b, 0x8b, 0xaf },
+ { 0xc4, 0x79, 0x57, 0xf1, 0xcc, 0x88, 0xe8, 0x3e, 0xf9, 0x44, 0x58, 0x39, 0x70, 0x9a, 0x48, 0x0a, 0x03, 0x6b, 0xed, 0x5f, 0x88, 0xac, 0x0f, 0xcc, 0x8e, 0x1e, 0x70, 0x3f, 0xfa, 0xac, 0x13, 0x2c },
+ { 0x30, 0xf3, 0x54, 0x83, 0x70, 0xcf, 0xdc, 0xed, 0xa5, 0xc3, 0x7b, 0x56, 0x9b, 0x61, 0x75, 0xe7, 0x99, 0xee, 0xf1, 0xa6, 0x2a, 0xaa, 0x94, 0x32, 0x45, 0xae, 0x76, 0x69, 0xc2, 0x27, 0xa7, 0xb5 },
+ { 0xc9, 0x5d, 0xcb, 0x3c, 0xf1, 0xf2, 0x7d, 0x0e, 0xef, 0x2f, 0x25, 0xd2, 0x41, 0x38, 0x70, 0x90, 0x4a, 0x87, 0x7c, 0x4a, 0x56, 0xc2, 0xde, 0x1e, 0x83, 0xe2, 0xbc, 0x2a, 0xe2, 0xe4, 0x68, 0x21 },
+ { 0xd5, 0xd0, 0xb5, 0xd7, 0x05, 0x43, 0x4c, 0xd4, 0x6b, 0x18, 0x57, 0x49, 0xf6, 0x6b, 0xfb, 0x58, 0x36, 0xdc, 0xdf, 0x6e, 0xe5, 0x49, 0xa2, 0xb7, 0xa4, 0xae, 0xe7, 0xf5, 0x80, 0x07, 0xca, 0xaf },
+ { 0xbb, 0xc1, 0x24, 0xa7, 0x12, 0xf1, 0x5d, 0x07, 0xc3, 0x00, 0xe0, 0x5b, 0x66, 0x83, 0x89, 0xa4, 0x39, 0xc9, 0x17, 0x77, 0xf7, 0x21, 0xf8, 0x32, 0x0c, 0x1c, 0x90, 0x78, 0x06, 0x6d, 0x2c, 0x7e },
+ { 0xa4, 0x51, 0xb4, 0x8c, 0x35, 0xa6, 0xc7, 0x85, 0x4c, 0xfa, 0xae, 0x60, 0x26, 0x2e, 0x76, 0x99, 0x08, 0x16, 0x38, 0x2a, 0xc0, 0x66, 0x7e, 0x5a, 0x5c, 0x9e, 0x1b, 0x46, 0xc4, 0x34, 0x2d, 0xdf },
+ { 0xb0, 0xd1, 0x50, 0xfb, 0x55, 0xe7, 0x78, 0xd0, 0x11, 0x47, 0xf0, 0xb5, 0xd8, 0x9d, 0x99, 0xec, 0xb2, 0x0f, 0xf0, 0x7e, 0x5e, 0x67, 0x60, 0xd6, 0xb6, 0x45, 0xeb, 0x5b, 0x65, 0x4c, 0x62, 0x2b },
+ { 0x34, 0xf7, 0x37, 0xc0, 0xab, 0x21, 0x99, 0x51, 0xee, 0xe8, 0x9a, 0x9f, 0x8d, 0xac, 0x29, 0x9c, 0x9d, 0x4c, 0x38, 0xf3, 0x3f, 0xa4, 0x94, 0xc5, 0xc6, 0xee, 0xfc, 0x92, 0xb6, 0xdb, 0x08, 0xbc },
+ { 0x1a, 0x62, 0xcc, 0x3a, 0x00, 0x80, 0x0d, 0xcb, 0xd9, 0x98, 0x91, 0x08, 0x0c, 0x1e, 0x09, 0x84, 0x58, 0x19, 0x3a, 0x8c, 0xc9, 0xf9, 0x70, 0xea, 0x99, 0xfb, 0xef, 0xf0, 0x03, 0x18, 0xc2, 0x89 },
+ { 0xcf, 0xce, 0x55, 0xeb, 0xaf, 0xc8, 0x40, 0xd7, 0xae, 0x48, 0x28, 0x1c, 0x7f, 0xd5, 0x7e, 0xc8, 0xb4, 0x82, 0xd4, 0xb7, 0x04, 0x43, 0x74, 0x95, 0x49, 0x5a, 0xc4, 0x14, 0xcf, 0x4a, 0x37, 0x4b },
+ { 0x67, 0x46, 0xfa, 0xcf, 0x71, 0x14, 0x6d, 0x99, 0x9d, 0xab, 0xd0, 0x5d, 0x09, 0x3a, 0xe5, 0x86, 0x64, 0x8d, 0x1e, 0xe2, 0x8e, 0x72, 0x61, 0x7b, 0x99, 0xd0, 0xf0, 0x08, 0x6e, 0x1e, 0x45, 0xbf },
+ { 0x57, 0x1c, 0xed, 0x28, 0x3b, 0x3f, 0x23, 0xb4, 0xe7, 0x50, 0xbf, 0x12, 0xa2, 0xca, 0xf1, 0x78, 0x18, 0x47, 0xbd, 0x89, 0x0e, 0x43, 0x60, 0x3c, 0xdc, 0x59, 0x76, 0x10, 0x2b, 0x7b, 0xb1, 0x1b },
+ { 0xcf, 0xcb, 0x76, 0x5b, 0x04, 0x8e, 0x35, 0x02, 0x2c, 0x5d, 0x08, 0x9d, 0x26, 0xe8, 0x5a, 0x36, 0xb0, 0x05, 0xa2, 0xb8, 0x04, 0x93, 0xd0, 0x3a, 0x14, 0x4e, 0x09, 0xf4, 0x09, 0xb6, 0xaf, 0xd1 },
+ { 0x40, 0x50, 0xc7, 0xa2, 0x77, 0x05, 0xbb, 0x27, 0xf4, 0x20, 0x89, 0xb2, 0x99, 0xf3, 0xcb, 0xe5, 0x05, 0x4e, 0xad, 0x68, 0x72, 0x7e, 0x8e, 0xf9, 0x31, 0x8c, 0xe6, 0xf2, 0x5c, 0xd6, 0xf3, 0x1d },
+ { 0x18, 0x40, 0x70, 0xbd, 0x5d, 0x26, 0x5f, 0xbd, 0xc1, 0x42, 0xcd, 0x1c, 0x5c, 0xd0, 0xd7, 0xe4, 0x14, 0xe7, 0x03, 0x69, 0xa2, 0x66, 0xd6, 0x27, 0xc8, 0xfb, 0xa8, 0x4f, 0xa5, 0xe8, 0x4c, 0x34 },
+ { 0x9e, 0xdd, 0xa9, 0xa4, 0x44, 0x39, 0x02, 0xa9, 0x58, 0x8c, 0x0d, 0x0c, 0xcc, 0x62, 0xb9, 0x30, 0x21, 0x84, 0x79, 0xa6, 0x84, 0x1e, 0x6f, 0xe7, 0xd4, 0x30, 0x03, 0xf0, 0x4b, 0x1f, 0xd6, 0x43 },
+ { 0xe4, 0x12, 0xfe, 0xef, 0x79, 0x08, 0x32, 0x4a, 0x6d, 0xa1, 0x84, 0x16, 0x29, 0xf3, 0x5d, 0x3d, 0x35, 0x86, 0x42, 0x01, 0x93, 0x10, 0xec, 0x57, 0xc6, 0x14, 0x83, 0x6b, 0x63, 0xd3, 0x07, 0x63 },
+ { 0x1a, 0x2b, 0x8e, 0xdf, 0xf3, 0xf9, 0xac, 0xc1, 0x55, 0x4f, 0xcb, 0xae, 0x3c, 0xf1, 0xd6, 0x29, 0x8c, 0x64, 0x62, 0xe2, 0x2e, 0x5e, 0xb0, 0x25, 0x96, 0x84, 0xf8, 0x35, 0x01, 0x2b, 0xd1, 0x3f },
+ { 0x28, 0x8c, 0x4a, 0xd9, 0xb9, 0x40, 0x97, 0x62, 0xea, 0x07, 0xc2, 0x4a, 0x41, 0xf0, 0x4f, 0x69, 0xa7, 0xd7, 0x4b, 0xee, 0x2d, 0x95, 0x43, 0x53, 0x74, 0xbd, 0xe9, 0x46, 0xd7, 0x24, 0x1c, 0x7b },
+ { 0x80, 0x56, 0x91, 0xbb, 0x28, 0x67, 0x48, 0xcf, 0xb5, 0x91, 0xd3, 0xae, 0xbe, 0x7e, 0x6f, 0x4e, 0x4d, 0xc6, 0xe2, 0x80, 0x8c, 0x65, 0x14, 0x3c, 0xc0, 0x04, 0xe4, 0xeb, 0x6f, 0xd0, 0x9d, 0x43 },
+ { 0xd4, 0xac, 0x8d, 0x3a, 0x0a, 0xfc, 0x6c, 0xfa, 0x7b, 0x46, 0x0a, 0xe3, 0x00, 0x1b, 0xae, 0xb3, 0x6d, 0xad, 0xb3, 0x7d, 0xa0, 0x7d, 0x2e, 0x8a, 0xc9, 0x18, 0x22, 0xdf, 0x34, 0x8a, 0xed, 0x3d },
+ { 0xc3, 0x76, 0x61, 0x70, 0x14, 0xd2, 0x01, 0x58, 0xbc, 0xed, 0x3d, 0x3b, 0xa5, 0x52, 0xb6, 0xec, 0xcf, 0x84, 0xe6, 0x2a, 0xa3, 0xeb, 0x65, 0x0e, 0x90, 0x02, 0x9c, 0x84, 0xd1, 0x3e, 0xea, 0x69 },
+ { 0xc4, 0x1f, 0x09, 0xf4, 0x3c, 0xec, 0xae, 0x72, 0x93, 0xd6, 0x00, 0x7c, 0xa0, 0xa3, 0x57, 0x08, 0x7d, 0x5a, 0xe5, 0x9b, 0xe5, 0x00, 0xc1, 0xcd, 0x5b, 0x28, 0x9e, 0xe8, 0x10, 0xc7, 0xb0, 0x82 },
+ { 0x03, 0xd1, 0xce, 0xd1, 0xfb, 0xa5, 0xc3, 0x91, 0x55, 0xc4, 0x4b, 0x77, 0x65, 0xcb, 0x76, 0x0c, 0x78, 0x70, 0x8d, 0xcf, 0xc8, 0x0b, 0x0b, 0xd8, 0xad, 0xe3, 0xa5, 0x6d, 0xa8, 0x83, 0x0b, 0x29 },
+ { 0x09, 0xbd, 0xe6, 0xf1, 0x52, 0x21, 0x8d, 0xc9, 0x2c, 0x41, 0xd7, 0xf4, 0x53, 0x87, 0xe6, 0x3e, 0x58, 0x69, 0xd8, 0x07, 0xec, 0x70, 0xb8, 0x21, 0x40, 0x5d, 0xbd, 0x88, 0x4b, 0x7f, 0xcf, 0x4b },
+ { 0x71, 0xc9, 0x03, 0x6e, 0x18, 0x17, 0x9b, 0x90, 0xb3, 0x7d, 0x39, 0xe9, 0xf0, 0x5e, 0xb8, 0x9c, 0xc5, 0xfc, 0x34, 0x1f, 0xd7, 0xc4, 0x77, 0xd0, 0xd7, 0x49, 0x32, 0x85, 0xfa, 0xca, 0x08, 0xa4 },
+ { 0x59, 0x16, 0x83, 0x3e, 0xbb, 0x05, 0xcd, 0x91, 0x9c, 0xa7, 0xfe, 0x83, 0xb6, 0x92, 0xd3, 0x20, 0x5b, 0xef, 0x72, 0x39, 0x2b, 0x2c, 0xf6, 0xbb, 0x0a, 0x6d, 0x43, 0xf9, 0x94, 0xf9, 0x5f, 0x11 },
+ { 0xf6, 0x3a, 0xab, 0x3e, 0xc6, 0x41, 0xb3, 0xb0, 0x24, 0x96, 0x4c, 0x2b, 0x43, 0x7c, 0x04, 0xf6, 0x04, 0x3c, 0x4c, 0x7e, 0x02, 0x79, 0x23, 0x99, 0x95, 0x40, 0x19, 0x58, 0xf8, 0x6b, 0xbe, 0x54 },
+ { 0xf1, 0x72, 0xb1, 0x80, 0xbf, 0xb0, 0x97, 0x40, 0x49, 0x31, 0x20, 0xb6, 0x32, 0x6c, 0xbd, 0xc5, 0x61, 0xe4, 0x77, 0xde, 0xf9, 0xbb, 0xcf, 0xd2, 0x8c, 0xc8, 0xc1, 0xc5, 0xe3, 0x37, 0x9a, 0x31 },
+ { 0xcb, 0x9b, 0x89, 0xcc, 0x18, 0x38, 0x1d, 0xd9, 0x14, 0x1a, 0xde, 0x58, 0x86, 0x54, 0xd4, 0xe6, 0xa2, 0x31, 0xd5, 0xbf, 0x49, 0xd4, 0xd5, 0x9a, 0xc2, 0x7d, 0x86, 0x9c, 0xbe, 0x10, 0x0c, 0xf3 },
+ { 0x7b, 0xd8, 0x81, 0x50, 0x46, 0xfd, 0xd8, 0x10, 0xa9, 0x23, 0xe1, 0x98, 0x4a, 0xae, 0xbd, 0xcd, 0xf8, 0x4d, 0x87, 0xc8, 0x99, 0x2d, 0x68, 0xb5, 0xee, 0xb4, 0x60, 0xf9, 0x3e, 0xb3, 0xc8, 0xd7 },
+ { 0x60, 0x7b, 0xe6, 0x68, 0x62, 0xfd, 0x08, 0xee, 0x5b, 0x19, 0xfa, 0xca, 0xc0, 0x9d, 0xfd, 0xbc, 0xd4, 0x0c, 0x31, 0x21, 0x01, 0xd6, 0x6e, 0x6e, 0xbd, 0x2b, 0x84, 0x1f, 0x1b, 0x9a, 0x93, 0x25 },
+ { 0x9f, 0xe0, 0x3b, 0xbe, 0x69, 0xab, 0x18, 0x34, 0xf5, 0x21, 0x9b, 0x0d, 0xa8, 0x8a, 0x08, 0xb3, 0x0a, 0x66, 0xc5, 0x91, 0x3f, 0x01, 0x51, 0x96, 0x3c, 0x36, 0x05, 0x60, 0xdb, 0x03, 0x87, 0xb3 },
+ { 0x90, 0xa8, 0x35, 0x85, 0x71, 0x7b, 0x75, 0xf0, 0xe9, 0xb7, 0x25, 0xe0, 0x55, 0xee, 0xee, 0xb9, 0xe7, 0xa0, 0x28, 0xea, 0x7e, 0x6c, 0xbc, 0x07, 0xb2, 0x09, 0x17, 0xec, 0x03, 0x63, 0xe3, 0x8c },
+ { 0x33, 0x6e, 0xa0, 0x53, 0x0f, 0x4a, 0x74, 0x69, 0x12, 0x6e, 0x02, 0x18, 0x58, 0x7e, 0xbb, 0xde, 0x33, 0x58, 0xa0, 0xb3, 0x1c, 0x29, 0xd2, 0x00, 0xf7, 0xdc, 0x7e, 0xb1, 0x5c, 0x6a, 0xad, 0xd8 },
+ { 0xa7, 0x9e, 0x76, 0xdc, 0x0a, 0xbc, 0xa4, 0x39, 0x6f, 0x07, 0x47, 0xcd, 0x7b, 0x74, 0x8d, 0xf9, 0x13, 0x00, 0x76, 0x26, 0xb1, 0xd6, 0x59, 0xda, 0x0c, 0x1f, 0x78, 0xb9, 0x30, 0x3d, 0x01, 0xa3 },
+ { 0x44, 0xe7, 0x8a, 0x77, 0x37, 0x56, 0xe0, 0x95, 0x15, 0x19, 0x50, 0x4d, 0x70, 0x38, 0xd2, 0x8d, 0x02, 0x13, 0xa3, 0x7e, 0x0c, 0xe3, 0x75, 0x37, 0x17, 0x57, 0xbc, 0x99, 0x63, 0x11, 0xe3, 0xb8 },
+ { 0x77, 0xac, 0x01, 0x2a, 0x3f, 0x75, 0x4d, 0xcf, 0xea, 0xb5, 0xeb, 0x99, 0x6b, 0xe9, 0xcd, 0x2d, 0x1f, 0x96, 0x11, 0x1b, 0x6e, 0x49, 0xf3, 0x99, 0x4d, 0xf1, 0x81, 0xf2, 0x85, 0x69, 0xd8, 0x25 },
+ { 0xce, 0x5a, 0x10, 0xdb, 0x6f, 0xcc, 0xda, 0xf1, 0x40, 0xaa, 0xa4, 0xde, 0xd6, 0x25, 0x0a, 0x9c, 0x06, 0xe9, 0x22, 0x2b, 0xc9, 0xf9, 0xf3, 0x65, 0x8a, 0x4a, 0xff, 0x93, 0x5f, 0x2b, 0x9f, 0x3a },
+ { 0xec, 0xc2, 0x03, 0xa7, 0xfe, 0x2b, 0xe4, 0xab, 0xd5, 0x5b, 0xb5, 0x3e, 0x6e, 0x67, 0x35, 0x72, 0xe0, 0x07, 0x8d, 0xa8, 0xcd, 0x37, 0x5e, 0xf4, 0x30, 0xcc, 0x97, 0xf9, 0xf8, 0x00, 0x83, 0xaf },
+ { 0x14, 0xa5, 0x18, 0x6d, 0xe9, 0xd7, 0xa1, 0x8b, 0x04, 0x12, 0xb8, 0x56, 0x3e, 0x51, 0xcc, 0x54, 0x33, 0x84, 0x0b, 0x4a, 0x12, 0x9a, 0x8f, 0xf9, 0x63, 0xb3, 0x3a, 0x3c, 0x4a, 0xfe, 0x8e, 0xbb },
+ { 0x13, 0xf8, 0xef, 0x95, 0xcb, 0x86, 0xe6, 0xa6, 0x38, 0x93, 0x1c, 0x8e, 0x10, 0x76, 0x73, 0xeb, 0x76, 0xba, 0x10, 0xd7, 0xc2, 0xcd, 0x70, 0xb9, 0xd9, 0x92, 0x0b, 0xbe, 0xed, 0x92, 0x94, 0x09 },
+ { 0x0b, 0x33, 0x8f, 0x4e, 0xe1, 0x2f, 0x2d, 0xfc, 0xb7, 0x87, 0x13, 0x37, 0x79, 0x41, 0xe0, 0xb0, 0x63, 0x21, 0x52, 0x58, 0x1d, 0x13, 0x32, 0x51, 0x6e, 0x4a, 0x2c, 0xab, 0x19, 0x42, 0xcc, 0xa4 },
+ { 0xea, 0xab, 0x0e, 0xc3, 0x7b, 0x3b, 0x8a, 0xb7, 0x96, 0xe9, 0xf5, 0x72, 0x38, 0xde, 0x14, 0xa2, 0x64, 0xa0, 0x76, 0xf3, 0x88, 0x7d, 0x86, 0xe2, 0x9b, 0xb5, 0x90, 0x6d, 0xb5, 0xa0, 0x0e, 0x02 },
+ { 0x23, 0xcb, 0x68, 0xb8, 0xc0, 0xe6, 0xdc, 0x26, 0xdc, 0x27, 0x76, 0x6d, 0xdc, 0x0a, 0x13, 0xa9, 0x94, 0x38, 0xfd, 0x55, 0x61, 0x7a, 0xa4, 0x09, 0x5d, 0x8f, 0x96, 0x97, 0x20, 0xc8, 0x72, 0xdf },
+ { 0x09, 0x1d, 0x8e, 0xe3, 0x0d, 0x6f, 0x29, 0x68, 0xd4, 0x6b, 0x68, 0x7d, 0xd6, 0x52, 0x92, 0x66, 0x57, 0x42, 0xde, 0x0b, 0xb8, 0x3d, 0xcc, 0x00, 0x04, 0xc7, 0x2c, 0xe1, 0x00, 0x07, 0xa5, 0x49 },
+ { 0x7f, 0x50, 0x7a, 0xbc, 0x6d, 0x19, 0xba, 0x00, 0xc0, 0x65, 0xa8, 0x76, 0xec, 0x56, 0x57, 0x86, 0x88, 0x82, 0xd1, 0x8a, 0x22, 0x1b, 0xc4, 0x6c, 0x7a, 0x69, 0x12, 0x54, 0x1f, 0x5b, 0xc7, 0xba },
+ { 0xa0, 0x60, 0x7c, 0x24, 0xe1, 0x4e, 0x8c, 0x22, 0x3d, 0xb0, 0xd7, 0x0b, 0x4d, 0x30, 0xee, 0x88, 0x01, 0x4d, 0x60, 0x3f, 0x43, 0x7e, 0x9e, 0x02, 0xaa, 0x7d, 0xaf, 0xa3, 0xcd, 0xfb, 0xad, 0x94 },
+ { 0xdd, 0xbf, 0xea, 0x75, 0xcc, 0x46, 0x78, 0x82, 0xeb, 0x34, 0x83, 0xce, 0x5e, 0x2e, 0x75, 0x6a, 0x4f, 0x47, 0x01, 0xb7, 0x6b, 0x44, 0x55, 0x19, 0xe8, 0x9f, 0x22, 0xd6, 0x0f, 0xa8, 0x6e, 0x06 },
+ { 0x0c, 0x31, 0x1f, 0x38, 0xc3, 0x5a, 0x4f, 0xb9, 0x0d, 0x65, 0x1c, 0x28, 0x9d, 0x48, 0x68, 0x56, 0xcd, 0x14, 0x13, 0xdf, 0x9b, 0x06, 0x77, 0xf5, 0x3e, 0xce, 0x2c, 0xd9, 0xe4, 0x77, 0xc6, 0x0a },
+ { 0x46, 0xa7, 0x3a, 0x8d, 0xd3, 0xe7, 0x0f, 0x59, 0xd3, 0x94, 0x2c, 0x01, 0xdf, 0x59, 0x9d, 0xef, 0x78, 0x3c, 0x9d, 0xa8, 0x2f, 0xd8, 0x32, 0x22, 0xcd, 0x66, 0x2b, 0x53, 0xdc, 0xe7, 0xdb, 0xdf },
+ { 0xad, 0x03, 0x8f, 0xf9, 0xb1, 0x4d, 0xe8, 0x4a, 0x80, 0x1e, 0x4e, 0x62, 0x1c, 0xe5, 0xdf, 0x02, 0x9d, 0xd9, 0x35, 0x20, 0xd0, 0xc2, 0xfa, 0x38, 0xbf, 0xf1, 0x76, 0xa8, 0xb1, 0xd1, 0x69, 0x8c },
+ { 0xab, 0x70, 0xc5, 0xdf, 0xbd, 0x1e, 0xa8, 0x17, 0xfe, 0xd0, 0xcd, 0x06, 0x72, 0x93, 0xab, 0xf3, 0x19, 0xe5, 0xd7, 0x90, 0x1c, 0x21, 0x41, 0xd5, 0xd9, 0x9b, 0x23, 0xf0, 0x3a, 0x38, 0xe7, 0x48 },
+ { 0x1f, 0xff, 0xda, 0x67, 0x93, 0x2b, 0x73, 0xc8, 0xec, 0xaf, 0x00, 0x9a, 0x34, 0x91, 0xa0, 0x26, 0x95, 0x3b, 0xab, 0xfe, 0x1f, 0x66, 0x3b, 0x06, 0x97, 0xc3, 0xc4, 0xae, 0x8b, 0x2e, 0x7d, 0xcb },
+ { 0xb0, 0xd2, 0xcc, 0x19, 0x47, 0x2d, 0xd5, 0x7f, 0x2b, 0x17, 0xef, 0xc0, 0x3c, 0x8d, 0x58, 0xc2, 0x28, 0x3d, 0xbb, 0x19, 0xda, 0x57, 0x2f, 0x77, 0x55, 0x85, 0x5a, 0xa9, 0x79, 0x43, 0x17, 0xa0 },
+ { 0xa0, 0xd1, 0x9a, 0x6e, 0xe3, 0x39, 0x79, 0xc3, 0x25, 0x51, 0x0e, 0x27, 0x66, 0x22, 0xdf, 0x41, 0xf7, 0x15, 0x83, 0xd0, 0x75, 0x01, 0xb8, 0x70, 0x71, 0x12, 0x9a, 0x0a, 0xd9, 0x47, 0x32, 0xa5 },
+ { 0x72, 0x46, 0x42, 0xa7, 0x03, 0x2d, 0x10, 0x62, 0xb8, 0x9e, 0x52, 0xbe, 0xa3, 0x4b, 0x75, 0xdf, 0x7d, 0x8f, 0xe7, 0x72, 0xd9, 0xfe, 0x3c, 0x93, 0xdd, 0xf3, 0xc4, 0x54, 0x5a, 0xb5, 0xa9, 0x9b },
+ { 0xad, 0xe5, 0xea, 0xa7, 0xe6, 0x1f, 0x67, 0x2d, 0x58, 0x7e, 0xa0, 0x3d, 0xae, 0x7d, 0x7b, 0x55, 0x22, 0x9c, 0x01, 0xd0, 0x6b, 0xc0, 0xa5, 0x70, 0x14, 0x36, 0xcb, 0xd1, 0x83, 0x66, 0xa6, 0x26 },
+ { 0x01, 0x3b, 0x31, 0xeb, 0xd2, 0x28, 0xfc, 0xdd, 0xa5, 0x1f, 0xab, 0xb0, 0x3b, 0xb0, 0x2d, 0x60, 0xac, 0x20, 0xca, 0x21, 0x5a, 0xaf, 0xa8, 0x3b, 0xdd, 0x85, 0x5e, 0x37, 0x55, 0xa3, 0x5f, 0x0b },
+ { 0x33, 0x2e, 0xd4, 0x0b, 0xb1, 0x0d, 0xde, 0x3c, 0x95, 0x4a, 0x75, 0xd7, 0xb8, 0x99, 0x9d, 0x4b, 0x26, 0xa1, 0xc0, 0x63, 0xc1, 0xdc, 0x6e, 0x32, 0xc1, 0xd9, 0x1b, 0xab, 0x7b, 0xbb, 0x7d, 0x16 },
+ { 0xc7, 0xa1, 0x97, 0xb3, 0xa0, 0x5b, 0x56, 0x6b, 0xcc, 0x9f, 0xac, 0xd2, 0x0e, 0x44, 0x1d, 0x6f, 0x6c, 0x28, 0x60, 0xac, 0x96, 0x51, 0xcd, 0x51, 0xd6, 0xb9, 0xd2, 0xcd, 0xee, 0xea, 0x03, 0x90 },
+ { 0xbd, 0x9c, 0xf6, 0x4e, 0xa8, 0x95, 0x3c, 0x03, 0x71, 0x08, 0xe6, 0xf6, 0x54, 0x91, 0x4f, 0x39, 0x58, 0xb6, 0x8e, 0x29, 0xc1, 0x67, 0x00, 0xdc, 0x18, 0x4d, 0x94, 0xa2, 0x17, 0x08, 0xff, 0x60 },
+ { 0x88, 0x35, 0xb0, 0xac, 0x02, 0x11, 0x51, 0xdf, 0x71, 0x64, 0x74, 0xce, 0x27, 0xce, 0x4d, 0x3c, 0x15, 0xf0, 0xb2, 0xda, 0xb4, 0x80, 0x03, 0xcf, 0x3f, 0x3e, 0xfd, 0x09, 0x45, 0x10, 0x6b, 0x9a },
+ { 0x3b, 0xfe, 0xfa, 0x33, 0x01, 0xaa, 0x55, 0xc0, 0x80, 0x19, 0x0c, 0xff, 0xda, 0x8e, 0xae, 0x51, 0xd9, 0xaf, 0x48, 0x8b, 0x4c, 0x1f, 0x24, 0xc3, 0xd9, 0xa7, 0x52, 0x42, 0xfd, 0x8e, 0xa0, 0x1d },
+ { 0x08, 0x28, 0x4d, 0x14, 0x99, 0x3c, 0xd4, 0x7d, 0x53, 0xeb, 0xae, 0xcf, 0x0d, 0xf0, 0x47, 0x8c, 0xc1, 0x82, 0xc8, 0x9c, 0x00, 0xe1, 0x85, 0x9c, 0x84, 0x85, 0x16, 0x86, 0xdd, 0xf2, 0xc1, 0xb7 },
+ { 0x1e, 0xd7, 0xef, 0x9f, 0x04, 0xc2, 0xac, 0x8d, 0xb6, 0xa8, 0x64, 0xdb, 0x13, 0x10, 0x87, 0xf2, 0x70, 0x65, 0x09, 0x8e, 0x69, 0xc3, 0xfe, 0x78, 0x71, 0x8d, 0x9b, 0x94, 0x7f, 0x4a, 0x39, 0xd0 },
+ { 0xc1, 0x61, 0xf2, 0xdc, 0xd5, 0x7e, 0x9c, 0x14, 0x39, 0xb3, 0x1a, 0x9d, 0xd4, 0x3d, 0x8f, 0x3d, 0x7d, 0xd8, 0xf0, 0xeb, 0x7c, 0xfa, 0xc6, 0xfb, 0x25, 0xa0, 0xf2, 0x8e, 0x30, 0x6f, 0x06, 0x61 },
+ { 0xc0, 0x19, 0x69, 0xad, 0x34, 0xc5, 0x2c, 0xaf, 0x3d, 0xc4, 0xd8, 0x0d, 0x19, 0x73, 0x5c, 0x29, 0x73, 0x1a, 0xc6, 0xe7, 0xa9, 0x20, 0x85, 0xab, 0x92, 0x50, 0xc4, 0x8d, 0xea, 0x48, 0xa3, 0xfc },
+ { 0x17, 0x20, 0xb3, 0x65, 0x56, 0x19, 0xd2, 0xa5, 0x2b, 0x35, 0x21, 0xae, 0x0e, 0x49, 0xe3, 0x45, 0xcb, 0x33, 0x89, 0xeb, 0xd6, 0x20, 0x8a, 0xca, 0xf9, 0xf1, 0x3f, 0xda, 0xcc, 0xa8, 0xbe, 0x49 },
+ { 0x75, 0x62, 0x88, 0x36, 0x1c, 0x83, 0xe2, 0x4c, 0x61, 0x7c, 0xf9, 0x5c, 0x90, 0x5b, 0x22, 0xd0, 0x17, 0xcd, 0xc8, 0x6f, 0x0b, 0xf1, 0xd6, 0x58, 0xf4, 0x75, 0x6c, 0x73, 0x79, 0x87, 0x3b, 0x7f },
+ { 0xe7, 0xd0, 0xed, 0xa3, 0x45, 0x26, 0x93, 0xb7, 0x52, 0xab, 0xcd, 0xa1, 0xb5, 0x5e, 0x27, 0x6f, 0x82, 0x69, 0x8f, 0x5f, 0x16, 0x05, 0x40, 0x3e, 0xff, 0x83, 0x0b, 0xea, 0x00, 0x71, 0xa3, 0x94 },
+ { 0x2c, 0x82, 0xec, 0xaa, 0x6b, 0x84, 0x80, 0x3e, 0x04, 0x4a, 0xf6, 0x31, 0x18, 0xaf, 0xe5, 0x44, 0x68, 0x7c, 0xb6, 0xe6, 0xc7, 0xdf, 0x49, 0xed, 0x76, 0x2d, 0xfd, 0x7c, 0x86, 0x93, 0xa1, 0xbc },
+ { 0x61, 0x36, 0xcb, 0xf4, 0xb4, 0x41, 0x05, 0x6f, 0xa1, 0xe2, 0x72, 0x24, 0x98, 0x12, 0x5d, 0x6d, 0xed, 0x45, 0xe1, 0x7b, 0x52, 0x14, 0x39, 0x59, 0xc7, 0xf4, 0xd4, 0xe3, 0x95, 0x21, 0x8a, 0xc2 },
+ { 0x72, 0x1d, 0x32, 0x45, 0xaa, 0xfe, 0xf2, 0x7f, 0x6a, 0x62, 0x4f, 0x47, 0x95, 0x4b, 0x6c, 0x25, 0x50, 0x79, 0x52, 0x6f, 0xfa, 0x25, 0xe9, 0xff, 0x77, 0xe5, 0xdc, 0xff, 0x47, 0x3b, 0x15, 0x97 },
+ { 0x9d, 0xd2, 0xfb, 0xd8, 0xce, 0xf1, 0x6c, 0x35, 0x3c, 0x0a, 0xc2, 0x11, 0x91, 0xd5, 0x09, 0xeb, 0x28, 0xdd, 0x9e, 0x3e, 0x0d, 0x8c, 0xea, 0x5d, 0x26, 0xca, 0x83, 0x93, 0x93, 0x85, 0x1c, 0x3a },
+ { 0xb2, 0x39, 0x4c, 0xea, 0xcd, 0xeb, 0xf2, 0x1b, 0xf9, 0xdf, 0x2c, 0xed, 0x98, 0xe5, 0x8f, 0x1c, 0x3a, 0x4b, 0xbb, 0xff, 0x66, 0x0d, 0xd9, 0x00, 0xf6, 0x22, 0x02, 0xd6, 0x78, 0x5c, 0xc4, 0x6e },
+ { 0x57, 0x08, 0x9f, 0x22, 0x27, 0x49, 0xad, 0x78, 0x71, 0x76, 0x5f, 0x06, 0x2b, 0x11, 0x4f, 0x43, 0xba, 0x20, 0xec, 0x56, 0x42, 0x2a, 0x8b, 0x1e, 0x3f, 0x87, 0x19, 0x2c, 0x0e, 0xa7, 0x18, 0xc6 },
+ { 0xe4, 0x9a, 0x94, 0x59, 0x96, 0x1c, 0xd3, 0x3c, 0xdf, 0x4a, 0xae, 0x1b, 0x10, 0x78, 0xa5, 0xde, 0xa7, 0xc0, 0x40, 0xe0, 0xfe, 0xa3, 0x40, 0xc9, 0x3a, 0x72, 0x48, 0x72, 0xfc, 0x4a, 0xf8, 0x06 },
+ { 0xed, 0xe6, 0x7f, 0x72, 0x0e, 0xff, 0xd2, 0xca, 0x9c, 0x88, 0x99, 0x41, 0x52, 0xd0, 0x20, 0x1d, 0xee, 0x6b, 0x0a, 0x2d, 0x2c, 0x07, 0x7a, 0xca, 0x6d, 0xae, 0x29, 0xf7, 0x3f, 0x8b, 0x63, 0x09 },
+ { 0xe0, 0xf4, 0x34, 0xbf, 0x22, 0xe3, 0x08, 0x80, 0x39, 0xc2, 0x1f, 0x71, 0x9f, 0xfc, 0x67, 0xf0, 0xf2, 0xcb, 0x5e, 0x98, 0xa7, 0xa0, 0x19, 0x4c, 0x76, 0xe9, 0x6b, 0xf4, 0xe8, 0xe1, 0x7e, 0x61 },
+ { 0x27, 0x7c, 0x04, 0xe2, 0x85, 0x34, 0x84, 0xa4, 0xeb, 0xa9, 0x10, 0xad, 0x33, 0x6d, 0x01, 0xb4, 0x77, 0xb6, 0x7c, 0xc2, 0x00, 0xc5, 0x9f, 0x3c, 0x8d, 0x77, 0xee, 0xf8, 0x49, 0x4f, 0x29, 0xcd },
+ { 0x15, 0x6d, 0x57, 0x47, 0xd0, 0xc9, 0x9c, 0x7f, 0x27, 0x09, 0x7d, 0x7b, 0x7e, 0x00, 0x2b, 0x2e, 0x18, 0x5c, 0xb7, 0x2d, 0x8d, 0xd7, 0xeb, 0x42, 0x4a, 0x03, 0x21, 0x52, 0x81, 0x61, 0x21, 0x9f },
+ { 0x20, 0xdd, 0xd1, 0xed, 0x9b, 0x1c, 0xa8, 0x03, 0x94, 0x6d, 0x64, 0xa8, 0x3a, 0xe4, 0x65, 0x9d, 0xa6, 0x7f, 0xba, 0x7a, 0x1a, 0x3e, 0xdd, 0xb1, 0xe1, 0x03, 0xc0, 0xf5, 0xe0, 0x3e, 0x3a, 0x2c },
+ { 0xf0, 0xaf, 0x60, 0x4d, 0x3d, 0xab, 0xbf, 0x9a, 0x0f, 0x2a, 0x7d, 0x3d, 0xda, 0x6b, 0xd3, 0x8b, 0xba, 0x72, 0xc6, 0xd0, 0x9b, 0xe4, 0x94, 0xfc, 0xef, 0x71, 0x3f, 0xf1, 0x01, 0x89, 0xb6, 0xe6 },
+ { 0x98, 0x02, 0xbb, 0x87, 0xde, 0xf4, 0xcc, 0x10, 0xc4, 0xa5, 0xfd, 0x49, 0xaa, 0x58, 0xdf, 0xe2, 0xf3, 0xfd, 0xdb, 0x46, 0xb4, 0x70, 0x88, 0x14, 0xea, 0xd8, 0x1d, 0x23, 0xba, 0x95, 0x13, 0x9b },
+ { 0x4f, 0x8c, 0xe1, 0xe5, 0x1d, 0x2f, 0xe7, 0xf2, 0x40, 0x43, 0xa9, 0x04, 0xd8, 0x98, 0xeb, 0xfc, 0x91, 0x97, 0x54, 0x18, 0x75, 0x34, 0x13, 0xaa, 0x09, 0x9b, 0x79, 0x5e, 0xcb, 0x35, 0xce, 0xdb },
+ { 0xbd, 0xdc, 0x65, 0x14, 0xd7, 0xee, 0x6a, 0xce, 0x0a, 0x4a, 0xc1, 0xd0, 0xe0, 0x68, 0x11, 0x22, 0x88, 0xcb, 0xcf, 0x56, 0x04, 0x54, 0x64, 0x27, 0x05, 0x63, 0x01, 0x77, 0xcb, 0xa6, 0x08, 0xbd },
+ { 0xd6, 0x35, 0x99, 0x4f, 0x62, 0x91, 0x51, 0x7b, 0x02, 0x81, 0xff, 0xdd, 0x49, 0x6a, 0xfa, 0x86, 0x27, 0x12, 0xe5, 0xb3, 0xc4, 0xe5, 0x2e, 0x4c, 0xd5, 0xfd, 0xae, 0x8c, 0x0e, 0x72, 0xfb, 0x08 },
+ { 0x87, 0x8d, 0x9c, 0xa6, 0x00, 0xcf, 0x87, 0xe7, 0x69, 0xcc, 0x30, 0x5c, 0x1b, 0x35, 0x25, 0x51, 0x86, 0x61, 0x5a, 0x73, 0xa0, 0xda, 0x61, 0x3b, 0x5f, 0x1c, 0x98, 0xdb, 0xf8, 0x12, 0x83, 0xea },
+ { 0xa6, 0x4e, 0xbe, 0x5d, 0xc1, 0x85, 0xde, 0x9f, 0xdd, 0xe7, 0x60, 0x7b, 0x69, 0x98, 0x70, 0x2e, 0xb2, 0x34, 0x56, 0x18, 0x49, 0x57, 0x30, 0x7d, 0x2f, 0xa7, 0x2e, 0x87, 0xa4, 0x77, 0x02, 0xd6 },
+ { 0xce, 0x50, 0xea, 0xb7, 0xb5, 0xeb, 0x52, 0xbd, 0xc9, 0xad, 0x8e, 0x5a, 0x48, 0x0a, 0xb7, 0x80, 0xca, 0x93, 0x20, 0xe4, 0x43, 0x60, 0xb1, 0xfe, 0x37, 0xe0, 0x3f, 0x2f, 0x7a, 0xd7, 0xde, 0x01 },
+ { 0xee, 0xdd, 0xb7, 0xc0, 0xdb, 0x6e, 0x30, 0xab, 0xe6, 0x6d, 0x79, 0xe3, 0x27, 0x51, 0x1e, 0x61, 0xfc, 0xeb, 0xbc, 0x29, 0xf1, 0x59, 0xb4, 0x0a, 0x86, 0xb0, 0x46, 0xec, 0xf0, 0x51, 0x38, 0x23 },
+ { 0x78, 0x7f, 0xc9, 0x34, 0x40, 0xc1, 0xec, 0x96, 0xb5, 0xad, 0x01, 0xc1, 0x6c, 0xf7, 0x79, 0x16, 0xa1, 0x40, 0x5f, 0x94, 0x26, 0x35, 0x6e, 0xc9, 0x21, 0xd8, 0xdf, 0xf3, 0xea, 0x63, 0xb7, 0xe0 },
+ { 0x7f, 0x0d, 0x5e, 0xab, 0x47, 0xee, 0xfd, 0xa6, 0x96, 0xc0, 0xbf, 0x0f, 0xbf, 0x86, 0xab, 0x21, 0x6f, 0xce, 0x46, 0x1e, 0x93, 0x03, 0xab, 0xa6, 0xac, 0x37, 0x41, 0x20, 0xe8, 0x90, 0xe8, 0xdf },
+ { 0xb6, 0x80, 0x04, 0xb4, 0x2f, 0x14, 0xad, 0x02, 0x9f, 0x4c, 0x2e, 0x03, 0xb1, 0xd5, 0xeb, 0x76, 0xd5, 0x71, 0x60, 0xe2, 0x64, 0x76, 0xd2, 0x11, 0x31, 0xbe, 0xf2, 0x0a, 0xda, 0x7d, 0x27, 0xf4 },
+ { 0xb0, 0xc4, 0xeb, 0x18, 0xae, 0x25, 0x0b, 0x51, 0xa4, 0x13, 0x82, 0xea, 0xd9, 0x2d, 0x0d, 0xc7, 0x45, 0x5f, 0x93, 0x79, 0xfc, 0x98, 0x84, 0x42, 0x8e, 0x47, 0x70, 0x60, 0x8d, 0xb0, 0xfa, 0xec },
+ { 0xf9, 0x2b, 0x7a, 0x87, 0x0c, 0x05, 0x9f, 0x4d, 0x46, 0x46, 0x4c, 0x82, 0x4e, 0xc9, 0x63, 0x55, 0x14, 0x0b, 0xdc, 0xe6, 0x81, 0x32, 0x2c, 0xc3, 0xa9, 0x92, 0xff, 0x10, 0x3e, 0x3f, 0xea, 0x52 },
+ { 0x53, 0x64, 0x31, 0x26, 0x14, 0x81, 0x33, 0x98, 0xcc, 0x52, 0x5d, 0x4c, 0x4e, 0x14, 0x6e, 0xde, 0xb3, 0x71, 0x26, 0x5f, 0xba, 0x19, 0x13, 0x3a, 0x2c, 0x3d, 0x21, 0x59, 0x29, 0x8a, 0x17, 0x42 },
+ { 0xf6, 0x62, 0x0e, 0x68, 0xd3, 0x7f, 0xb2, 0xaf, 0x50, 0x00, 0xfc, 0x28, 0xe2, 0x3b, 0x83, 0x22, 0x97, 0xec, 0xd8, 0xbc, 0xe9, 0x9e, 0x8b, 0xe4, 0xd0, 0x4e, 0x85, 0x30, 0x9e, 0x3d, 0x33, 0x74 },
+ { 0x53, 0x16, 0xa2, 0x79, 0x69, 0xd7, 0xfe, 0x04, 0xff, 0x27, 0xb2, 0x83, 0x96, 0x1b, 0xff, 0xc3, 0xbf, 0x5d, 0xfb, 0x32, 0xfb, 0x6a, 0x89, 0xd1, 0x01, 0xc6, 0xc3, 0xb1, 0x93, 0x7c, 0x28, 0x71 },
+ { 0x81, 0xd1, 0x66, 0x4f, 0xdf, 0x3c, 0xb3, 0x3c, 0x24, 0xee, 0xba, 0xc0, 0xbd, 0x64, 0x24, 0x4b, 0x77, 0xc4, 0xab, 0xea, 0x90, 0xbb, 0xe8, 0xb5, 0xee, 0x0b, 0x2a, 0xaf, 0xcf, 0x2d, 0x6a, 0x53 },
+ { 0x34, 0x57, 0x82, 0xf2, 0x95, 0xb0, 0x88, 0x03, 0x52, 0xe9, 0x24, 0xa0, 0x46, 0x7b, 0x5f, 0xbc, 0x3e, 0x8f, 0x3b, 0xfb, 0xc3, 0xc7, 0xe4, 0x8b, 0x67, 0x09, 0x1f, 0xb5, 0xe8, 0x0a, 0x94, 0x42 },
+ { 0x79, 0x41, 0x11, 0xea, 0x6c, 0xd6, 0x5e, 0x31, 0x1f, 0x74, 0xee, 0x41, 0xd4, 0x76, 0xcb, 0x63, 0x2c, 0xe1, 0xe4, 0xb0, 0x51, 0xdc, 0x1d, 0x9e, 0x9d, 0x06, 0x1a, 0x19, 0xe1, 0xd0, 0xbb, 0x49 },
+ { 0x2a, 0x85, 0xda, 0xf6, 0x13, 0x88, 0x16, 0xb9, 0x9b, 0xf8, 0xd0, 0x8b, 0xa2, 0x11, 0x4b, 0x7a, 0xb0, 0x79, 0x75, 0xa7, 0x84, 0x20, 0xc1, 0xa3, 0xb0, 0x6a, 0x77, 0x7c, 0x22, 0xdd, 0x8b, 0xcb },
+ { 0x89, 0xb0, 0xd5, 0xf2, 0x89, 0xec, 0x16, 0x40, 0x1a, 0x06, 0x9a, 0x96, 0x0d, 0x0b, 0x09, 0x3e, 0x62, 0x5d, 0xa3, 0xcf, 0x41, 0xee, 0x29, 0xb5, 0x9b, 0x93, 0x0c, 0x58, 0x20, 0x14, 0x54, 0x55 },
+ { 0xd0, 0xfd, 0xcb, 0x54, 0x39, 0x43, 0xfc, 0x27, 0xd2, 0x08, 0x64, 0xf5, 0x21, 0x81, 0x47, 0x1b, 0x94, 0x2c, 0xc7, 0x7c, 0xa6, 0x75, 0xbc, 0xb3, 0x0d, 0xf3, 0x1d, 0x35, 0x8e, 0xf7, 0xb1, 0xeb },
+ { 0xb1, 0x7e, 0xa8, 0xd7, 0x70, 0x63, 0xc7, 0x09, 0xd4, 0xdc, 0x6b, 0x87, 0x94, 0x13, 0xc3, 0x43, 0xe3, 0x79, 0x0e, 0x9e, 0x62, 0xca, 0x85, 0xb7, 0x90, 0x0b, 0x08, 0x6f, 0x6b, 0x75, 0xc6, 0x72 },
+ { 0xe7, 0x1a, 0x3e, 0x2c, 0x27, 0x4d, 0xb8, 0x42, 0xd9, 0x21, 0x14, 0xf2, 0x17, 0xe2, 0xc0, 0xea, 0xc8, 0xb4, 0x50, 0x93, 0xfd, 0xfd, 0x9d, 0xf4, 0xca, 0x71, 0x62, 0x39, 0x48, 0x62, 0xd5, 0x01 },
+ { 0xc0, 0x47, 0x67, 0x59, 0xab, 0x7a, 0xa3, 0x33, 0x23, 0x4f, 0x6b, 0x44, 0xf5, 0xfd, 0x85, 0x83, 0x90, 0xec, 0x23, 0x69, 0x4c, 0x62, 0x2c, 0xb9, 0x86, 0xe7, 0x69, 0xc7, 0x8e, 0xdd, 0x73, 0x3e },
+ { 0x9a, 0xb8, 0xea, 0xbb, 0x14, 0x16, 0x43, 0x4d, 0x85, 0x39, 0x13, 0x41, 0xd5, 0x69, 0x93, 0xc5, 0x54, 0x58, 0x16, 0x7d, 0x44, 0x18, 0xb1, 0x9a, 0x0f, 0x2a, 0xd8, 0xb7, 0x9a, 0x83, 0xa7, 0x5b },
+ { 0x79, 0x92, 0xd0, 0xbb, 0xb1, 0x5e, 0x23, 0x82, 0x6f, 0x44, 0x3e, 0x00, 0x50, 0x5d, 0x68, 0xd3, 0xed, 0x73, 0x72, 0x99, 0x5a, 0x5c, 0x3e, 0x49, 0x86, 0x54, 0x10, 0x2f, 0xbc, 0xd0, 0x96, 0x4e },
+ { 0xc0, 0x21, 0xb3, 0x00, 0x85, 0x15, 0x14, 0x35, 0xdf, 0x33, 0xb0, 0x07, 0xcc, 0xec, 0xc6, 0x9d, 0xf1, 0x26, 0x9f, 0x39, 0xba, 0x25, 0x09, 0x2b, 0xed, 0x59, 0xd9, 0x32, 0xac, 0x0f, 0xdc, 0x28 },
+ { 0x91, 0xa2, 0x5e, 0xc0, 0xec, 0x0d, 0x9a, 0x56, 0x7f, 0x89, 0xc4, 0xbf, 0xe1, 0xa6, 0x5a, 0x0e, 0x43, 0x2d, 0x07, 0x06, 0x4b, 0x41, 0x90, 0xe2, 0x7d, 0xfb, 0x81, 0x90, 0x1f, 0xd3, 0x13, 0x9b },
+ { 0x59, 0x50, 0xd3, 0x9a, 0x23, 0xe1, 0x54, 0x5f, 0x30, 0x12, 0x70, 0xaa, 0x1a, 0x12, 0xf2, 0xe6, 0xc4, 0x53, 0x77, 0x6e, 0x4d, 0x63, 0x55, 0xde, 0x42, 0x5c, 0xc1, 0x53, 0xf9, 0x81, 0x88, 0x67 },
+ { 0xd7, 0x9f, 0x14, 0x72, 0x0c, 0x61, 0x0a, 0xf1, 0x79, 0xa3, 0x76, 0x5d, 0x4b, 0x7c, 0x09, 0x68, 0xf9, 0x77, 0x96, 0x2d, 0xbf, 0x65, 0x5b, 0x52, 0x12, 0x72, 0xb6, 0xf1, 0xe1, 0x94, 0x48, 0x8e },
+ { 0xe9, 0x53, 0x1b, 0xfc, 0x8b, 0x02, 0x99, 0x5a, 0xea, 0xa7, 0x5b, 0xa2, 0x70, 0x31, 0xfa, 0xdb, 0xcb, 0xf4, 0xa0, 0xda, 0xb8, 0x96, 0x1d, 0x92, 0x96, 0xcd, 0x7e, 0x84, 0xd2, 0x5d, 0x60, 0x06 },
+ { 0x34, 0xe9, 0xc2, 0x6a, 0x01, 0xd7, 0xf1, 0x61, 0x81, 0xb4, 0x54, 0xa9, 0xd1, 0x62, 0x3c, 0x23, 0x3c, 0xb9, 0x9d, 0x31, 0xc6, 0x94, 0x65, 0x6e, 0x94, 0x13, 0xac, 0xa3, 0xe9, 0x18, 0x69, 0x2f },
+ { 0xd9, 0xd7, 0x42, 0x2f, 0x43, 0x7b, 0xd4, 0x39, 0xdd, 0xd4, 0xd8, 0x83, 0xda, 0xe2, 0xa0, 0x83, 0x50, 0x17, 0x34, 0x14, 0xbe, 0x78, 0x15, 0x51, 0x33, 0xff, 0xf1, 0x96, 0x4c, 0x3d, 0x79, 0x72 },
+ { 0x4a, 0xee, 0x0c, 0x7a, 0xaf, 0x07, 0x54, 0x14, 0xff, 0x17, 0x93, 0xea, 0xd7, 0xea, 0xca, 0x60, 0x17, 0x75, 0xc6, 0x15, 0xdb, 0xd6, 0x0b, 0x64, 0x0b, 0x0a, 0x9f, 0x0c, 0xe5, 0x05, 0xd4, 0x35 },
+ { 0x6b, 0xfd, 0xd1, 0x54, 0x59, 0xc8, 0x3b, 0x99, 0xf0, 0x96, 0xbf, 0xb4, 0x9e, 0xe8, 0x7b, 0x06, 0x3d, 0x69, 0xc1, 0x97, 0x4c, 0x69, 0x28, 0xac, 0xfc, 0xfb, 0x40, 0x99, 0xf8, 0xc4, 0xef, 0x67 },
+ { 0x9f, 0xd1, 0xc4, 0x08, 0xfd, 0x75, 0xc3, 0x36, 0x19, 0x3a, 0x2a, 0x14, 0xd9, 0x4f, 0x6a, 0xf5, 0xad, 0xf0, 0x50, 0xb8, 0x03, 0x87, 0xb4, 0xb0, 0x10, 0xfb, 0x29, 0xf4, 0xcc, 0x72, 0x70, 0x7c },
+ { 0x13, 0xc8, 0x84, 0x80, 0xa5, 0xd0, 0x0d, 0x6c, 0x8c, 0x7a, 0xd2, 0x11, 0x0d, 0x76, 0xa8, 0x2d, 0x9b, 0x70, 0xf4, 0xfa, 0x66, 0x96, 0xd4, 0xe5, 0xdd, 0x42, 0xa0, 0x66, 0xdc, 0xaf, 0x99, 0x20 },
+ { 0x82, 0x0e, 0x72, 0x5e, 0xe2, 0x5f, 0xe8, 0xfd, 0x3a, 0x8d, 0x5a, 0xbe, 0x4c, 0x46, 0xc3, 0xba, 0x88, 0x9d, 0xe6, 0xfa, 0x91, 0x91, 0xaa, 0x22, 0xba, 0x67, 0xd5, 0x70, 0x54, 0x21, 0x54, 0x2b },
+ { 0x32, 0xd9, 0x3a, 0x0e, 0xb0, 0x2f, 0x42, 0xfb, 0xbc, 0xaf, 0x2b, 0xad, 0x00, 0x85, 0xb2, 0x82, 0xe4, 0x60, 0x46, 0xa4, 0xdf, 0x7a, 0xd1, 0x06, 0x57, 0xc9, 0xd6, 0x47, 0x63, 0x75, 0xb9, 0x3e },
+ { 0xad, 0xc5, 0x18, 0x79, 0x05, 0xb1, 0x66, 0x9c, 0xd8, 0xec, 0x9c, 0x72, 0x1e, 0x19, 0x53, 0x78, 0x6b, 0x9d, 0x89, 0xa9, 0xba, 0xe3, 0x07, 0x80, 0xf1, 0xe1, 0xea, 0xb2, 0x4a, 0x00, 0x52, 0x3c },
+ { 0xe9, 0x07, 0x56, 0xff, 0x7f, 0x9a, 0xd8, 0x10, 0xb2, 0x39, 0xa1, 0x0c, 0xed, 0x2c, 0xf9, 0xb2, 0x28, 0x43, 0x54, 0xc1, 0xf8, 0xc7, 0xe0, 0xac, 0xcc, 0x24, 0x61, 0xdc, 0x79, 0x6d, 0x6e, 0x89 },
+ { 0x12, 0x51, 0xf7, 0x6e, 0x56, 0x97, 0x84, 0x81, 0x87, 0x53, 0x59, 0x80, 0x1d, 0xb5, 0x89, 0xa0, 0xb2, 0x2f, 0x86, 0xd8, 0xd6, 0x34, 0xdc, 0x04, 0x50, 0x6f, 0x32, 0x2e, 0xd7, 0x8f, 0x17, 0xe8 },
+ { 0x3a, 0xfa, 0x89, 0x9f, 0xd9, 0x80, 0xe7, 0x3e, 0xcb, 0x7f, 0x4d, 0x8b, 0x8f, 0x29, 0x1d, 0xc9, 0xaf, 0x79, 0x6b, 0xc6, 0x5d, 0x27, 0xf9, 0x74, 0xc6, 0xf1, 0x93, 0xc9, 0x19, 0x1a, 0x09, 0xfd },
+ { 0xaa, 0x30, 0x5b, 0xe2, 0x6e, 0x5d, 0xed, 0xdc, 0x3c, 0x10, 0x10, 0xcb, 0xc2, 0x13, 0xf9, 0x5f, 0x05, 0x1c, 0x78, 0x5c, 0x5b, 0x43, 0x1e, 0x6a, 0x7c, 0xd0, 0x48, 0xf1, 0x61, 0x78, 0x75, 0x28 },
+ { 0x8e, 0xa1, 0x88, 0x4f, 0xf3, 0x2e, 0x9d, 0x10, 0xf0, 0x39, 0xb4, 0x07, 0xd0, 0xd4, 0x4e, 0x7e, 0x67, 0x0a, 0xbd, 0x88, 0x4a, 0xee, 0xe0, 0xfb, 0x75, 0x7a, 0xe9, 0x4e, 0xaa, 0x97, 0x37, 0x3d },
+ { 0xd4, 0x82, 0xb2, 0x15, 0x5d, 0x4d, 0xec, 0x6b, 0x47, 0x36, 0xa1, 0xf1, 0x61, 0x7b, 0x53, 0xaa, 0xa3, 0x73, 0x10, 0x27, 0x7d, 0x3f, 0xef, 0x0c, 0x37, 0xad, 0x41, 0x76, 0x8f, 0xc2, 0x35, 0xb4 },
+ { 0x4d, 0x41, 0x39, 0x71, 0x38, 0x7e, 0x7a, 0x88, 0x98, 0xa8, 0xdc, 0x2a, 0x27, 0x50, 0x07, 0x78, 0x53, 0x9e, 0xa2, 0x14, 0xa2, 0xdf, 0xe9, 0xb3, 0xd7, 0xe8, 0xeb, 0xdc, 0xe5, 0xcf, 0x3d, 0xb3 },
+ { 0x69, 0x6e, 0x5d, 0x46, 0xe6, 0xc5, 0x7e, 0x87, 0x96, 0xe4, 0x73, 0x5d, 0x08, 0x91, 0x6e, 0x0b, 0x79, 0x29, 0xb3, 0xcf, 0x29, 0x8c, 0x29, 0x6d, 0x22, 0xe9, 0xd3, 0x01, 0x96, 0x53, 0x37, 0x1c },
+ { 0x1f, 0x56, 0x47, 0xc1, 0xd3, 0xb0, 0x88, 0x22, 0x88, 0x85, 0x86, 0x5c, 0x89, 0x40, 0x90, 0x8b, 0xf4, 0x0d, 0x1a, 0x82, 0x72, 0x82, 0x19, 0x73, 0xb1, 0x60, 0x00, 0x8e, 0x7a, 0x3c, 0xe2, 0xeb },
+ { 0xb6, 0xe7, 0x6c, 0x33, 0x0f, 0x02, 0x1a, 0x5b, 0xda, 0x65, 0x87, 0x50, 0x10, 0xb0, 0xed, 0xf0, 0x91, 0x26, 0xc0, 0xf5, 0x10, 0xea, 0x84, 0x90, 0x48, 0x19, 0x20, 0x03, 0xae, 0xf4, 0xc6, 0x1c },
+ { 0x3c, 0xd9, 0x52, 0xa0, 0xbe, 0xad, 0xa4, 0x1a, 0xbb, 0x42, 0x4c, 0xe4, 0x7f, 0x94, 0xb4, 0x2b, 0xe6, 0x4e, 0x1f, 0xfb, 0x0f, 0xd0, 0x78, 0x22, 0x76, 0x80, 0x79, 0x46, 0xd0, 0xd0, 0xbc, 0x55 },
+ { 0x98, 0xd9, 0x26, 0x77, 0x43, 0x9b, 0x41, 0xb7, 0xbb, 0x51, 0x33, 0x12, 0xaf, 0xb9, 0x2b, 0xcc, 0x8e, 0xe9, 0x68, 0xb2, 0xe3, 0xb2, 0x38, 0xce, 0xcb, 0x9b, 0x0f, 0x34, 0xc9, 0xbb, 0x63, 0xd0 },
+ { 0xec, 0xbc, 0xa2, 0xcf, 0x08, 0xae, 0x57, 0xd5, 0x17, 0xad, 0x16, 0x15, 0x8a, 0x32, 0xbf, 0xa7, 0xdc, 0x03, 0x82, 0xea, 0xed, 0xa1, 0x28, 0xe9, 0x18, 0x86, 0x73, 0x4c, 0x24, 0xa0, 0xb2, 0x9d },
+ { 0x94, 0x2c, 0xc7, 0xc0, 0xb5, 0x2e, 0x2b, 0x16, 0xa4, 0xb8, 0x9f, 0xa4, 0xfc, 0x7e, 0x0b, 0xf6, 0x09, 0xe2, 0x9a, 0x08, 0xc1, 0xa8, 0x54, 0x34, 0x52, 0xb7, 0x7c, 0x7b, 0xfd, 0x11, 0xbb, 0x28 },
+ { 0x8a, 0x06, 0x5d, 0x8b, 0x61, 0xa0, 0xdf, 0xfb, 0x17, 0x0d, 0x56, 0x27, 0x73, 0x5a, 0x76, 0xb0, 0xe9, 0x50, 0x60, 0x37, 0x80, 0x8c, 0xba, 0x16, 0xc3, 0x45, 0x00, 0x7c, 0x9f, 0x79, 0xcf, 0x8f },
+ { 0x1b, 0x9f, 0xa1, 0x97, 0x14, 0x65, 0x9c, 0x78, 0xff, 0x41, 0x38, 0x71, 0x84, 0x92, 0x15, 0x36, 0x10, 0x29, 0xac, 0x80, 0x2b, 0x1c, 0xbc, 0xd5, 0x4e, 0x40, 0x8b, 0xd8, 0x72, 0x87, 0xf8, 0x1f },
+ { 0x8d, 0xab, 0x07, 0x1b, 0xcd, 0x6c, 0x72, 0x92, 0xa9, 0xef, 0x72, 0x7b, 0x4a, 0xe0, 0xd8, 0x67, 0x13, 0x30, 0x1d, 0xa8, 0x61, 0x8d, 0x9a, 0x48, 0xad, 0xce, 0x55, 0xf3, 0x03, 0xa8, 0x69, 0xa1 },
+ { 0x82, 0x53, 0xe3, 0xe7, 0xc7, 0xb6, 0x84, 0xb9, 0xcb, 0x2b, 0xeb, 0x01, 0x4c, 0xe3, 0x30, 0xff, 0x3d, 0x99, 0xd1, 0x7a, 0xbb, 0xdb, 0xab, 0xe4, 0xf4, 0xd6, 0x74, 0xde, 0xd5, 0x3f, 0xfc, 0x6b },
+ { 0xf1, 0x95, 0xf3, 0x21, 0xe9, 0xe3, 0xd6, 0xbd, 0x7d, 0x07, 0x45, 0x04, 0xdd, 0x2a, 0xb0, 0xe6, 0x24, 0x1f, 0x92, 0xe7, 0x84, 0xb1, 0xaa, 0x27, 0x1f, 0xf6, 0x48, 0xb1, 0xca, 0xb6, 0xd7, 0xf6 },
+ { 0x27, 0xe4, 0xcc, 0x72, 0x09, 0x0f, 0x24, 0x12, 0x66, 0x47, 0x6a, 0x7c, 0x09, 0x49, 0x5f, 0x2d, 0xb1, 0x53, 0xd5, 0xbc, 0xbd, 0x76, 0x19, 0x03, 0xef, 0x79, 0x27, 0x5e, 0xc5, 0x6b, 0x2e, 0xd8 },
+ { 0x89, 0x9c, 0x24, 0x05, 0x78, 0x8e, 0x25, 0xb9, 0x9a, 0x18, 0x46, 0x35, 0x5e, 0x64, 0x6d, 0x77, 0xcf, 0x40, 0x00, 0x83, 0x41, 0x5f, 0x7d, 0xc5, 0xaf, 0xe6, 0x9d, 0x6e, 0x17, 0xc0, 0x00, 0x23 },
+ { 0xa5, 0x9b, 0x78, 0xc4, 0x90, 0x57, 0x44, 0x07, 0x6b, 0xfe, 0xe8, 0x94, 0xde, 0x70, 0x7d, 0x4f, 0x12, 0x0b, 0x5c, 0x68, 0x93, 0xea, 0x04, 0x00, 0x29, 0x7d, 0x0b, 0xb8, 0x34, 0x72, 0x76, 0x32 },
+ { 0x59, 0xdc, 0x78, 0xb1, 0x05, 0x64, 0x97, 0x07, 0xa2, 0xbb, 0x44, 0x19, 0xc4, 0x8f, 0x00, 0x54, 0x00, 0xd3, 0x97, 0x3d, 0xe3, 0x73, 0x66, 0x10, 0x23, 0x04, 0x35, 0xb1, 0x04, 0x24, 0xb2, 0x4f },
+ { 0xc0, 0x14, 0x9d, 0x1d, 0x7e, 0x7a, 0x63, 0x53, 0xa6, 0xd9, 0x06, 0xef, 0xe7, 0x28, 0xf2, 0xf3, 0x29, 0xfe, 0x14, 0xa4, 0x14, 0x9a, 0x3e, 0xa7, 0x76, 0x09, 0xbc, 0x42, 0xb9, 0x75, 0xdd, 0xfa },
+ { 0xa3, 0x2f, 0x24, 0x14, 0x74, 0xa6, 0xc1, 0x69, 0x32, 0xe9, 0x24, 0x3b, 0xe0, 0xcf, 0x09, 0xbc, 0xdc, 0x7e, 0x0c, 0xa0, 0xe7, 0xa6, 0xa1, 0xb9, 0xb1, 0xa0, 0xf0, 0x1e, 0x41, 0x50, 0x23, 0x77 },
+ { 0xb2, 0x39, 0xb2, 0xe4, 0xf8, 0x18, 0x41, 0x36, 0x1c, 0x13, 0x39, 0xf6, 0x8e, 0x2c, 0x35, 0x9f, 0x92, 0x9a, 0xf9, 0xad, 0x9f, 0x34, 0xe0, 0x1a, 0xab, 0x46, 0x31, 0xad, 0x6d, 0x55, 0x00, 0xb0 },
+ { 0x85, 0xfb, 0x41, 0x9c, 0x70, 0x02, 0xa3, 0xe0, 0xb4, 0xb6, 0xea, 0x09, 0x3b, 0x4c, 0x1a, 0xc6, 0x93, 0x66, 0x45, 0xb6, 0x5d, 0xac, 0x5a, 0xc1, 0x5a, 0x85, 0x28, 0xb7, 0xb9, 0x4c, 0x17, 0x54 },
+ { 0x96, 0x19, 0x72, 0x06, 0x25, 0xf1, 0x90, 0xb9, 0x3a, 0x3f, 0xad, 0x18, 0x6a, 0xb3, 0x14, 0x18, 0x96, 0x33, 0xc0, 0xd3, 0xa0, 0x1e, 0x6f, 0x9b, 0xc8, 0xc4, 0xa8, 0xf8, 0x2f, 0x38, 0x3d, 0xbf },
+ { 0x7d, 0x62, 0x0d, 0x90, 0xfe, 0x69, 0xfa, 0x46, 0x9a, 0x65, 0x38, 0x38, 0x89, 0x70, 0xa1, 0xaa, 0x09, 0xbb, 0x48, 0xa2, 0xd5, 0x9b, 0x34, 0x7b, 0x97, 0xe8, 0xce, 0x71, 0xf4, 0x8c, 0x7f, 0x46 },
+ { 0x29, 0x43, 0x83, 0x56, 0x85, 0x96, 0xfb, 0x37, 0xc7, 0x5b, 0xba, 0xcd, 0x97, 0x9c, 0x5f, 0xf6, 0xf2, 0x0a, 0x55, 0x6b, 0xf8, 0x87, 0x9c, 0xc7, 0x29, 0x24, 0x85, 0x5d, 0xf9, 0xb8, 0x24, 0x0e },
+ { 0x16, 0xb1, 0x8a, 0xb3, 0x14, 0x35, 0x9c, 0x2b, 0x83, 0x3c, 0x1c, 0x69, 0x86, 0xd4, 0x8c, 0x55, 0xa9, 0xfc, 0x97, 0xcd, 0xe9, 0xa3, 0xc1, 0xf1, 0x0a, 0x31, 0x77, 0x14, 0x0f, 0x73, 0xf7, 0x38 },
+ { 0x8c, 0xbb, 0xdd, 0x14, 0xbc, 0x33, 0xf0, 0x4c, 0xf4, 0x58, 0x13, 0xe4, 0xa1, 0x53, 0xa2, 0x73, 0xd3, 0x6a, 0xda, 0xd5, 0xce, 0x71, 0xf4, 0x99, 0xee, 0xb8, 0x7f, 0xb8, 0xac, 0x63, 0xb7, 0x29 },
+ { 0x69, 0xc9, 0xa4, 0x98, 0xdb, 0x17, 0x4e, 0xca, 0xef, 0xcc, 0x5a, 0x3a, 0xc9, 0xfd, 0xed, 0xf0, 0xf8, 0x13, 0xa5, 0xbe, 0xc7, 0x27, 0xf1, 0xe7, 0x75, 0xba, 0xbd, 0xec, 0x77, 0x18, 0x81, 0x6e },
+ { 0xb4, 0x62, 0xc3, 0xbe, 0x40, 0x44, 0x8f, 0x1d, 0x4f, 0x80, 0x62, 0x62, 0x54, 0xe5, 0x35, 0xb0, 0x8b, 0xc9, 0xcd, 0xcf, 0xf5, 0x99, 0xa7, 0x68, 0x57, 0x8d, 0x4b, 0x28, 0x81, 0xa8, 0xe3, 0xf0 },
+ { 0x55, 0x3e, 0x9d, 0x9c, 0x5f, 0x36, 0x0a, 0xc0, 0xb7, 0x4a, 0x7d, 0x44, 0xe5, 0xa3, 0x91, 0xda, 0xd4, 0xce, 0xd0, 0x3e, 0x0c, 0x24, 0x18, 0x3b, 0x7e, 0x8e, 0xca, 0xbd, 0xf1, 0x71, 0x5a, 0x64 },
+ { 0x7a, 0x7c, 0x55, 0xa5, 0x6f, 0xa9, 0xae, 0x51, 0xe6, 0x55, 0xe0, 0x19, 0x75, 0xd8, 0xa6, 0xff, 0x4a, 0xe9, 0xe4, 0xb4, 0x86, 0xfc, 0xbe, 0x4e, 0xac, 0x04, 0x45, 0x88, 0xf2, 0x45, 0xeb, 0xea },
+ { 0x2a, 0xfd, 0xf3, 0xc8, 0x2a, 0xbc, 0x48, 0x67, 0xf5, 0xde, 0x11, 0x12, 0x86, 0xc2, 0xb3, 0xbe, 0x7d, 0x6e, 0x48, 0x65, 0x7b, 0xa9, 0x23, 0xcf, 0xbf, 0x10, 0x1a, 0x6d, 0xfc, 0xf9, 0xdb, 0x9a },
+ { 0x41, 0x03, 0x7d, 0x2e, 0xdc, 0xdc, 0xe0, 0xc4, 0x9b, 0x7f, 0xb4, 0xa6, 0xaa, 0x09, 0x99, 0xca, 0x66, 0x97, 0x6c, 0x74, 0x83, 0xaf, 0xe6, 0x31, 0xd4, 0xed, 0xa2, 0x83, 0x14, 0x4f, 0x6d, 0xfc },
+ { 0xc4, 0x46, 0x6f, 0x84, 0x97, 0xca, 0x2e, 0xeb, 0x45, 0x83, 0xa0, 0xb0, 0x8e, 0x9d, 0x9a, 0xc7, 0x43, 0x95, 0x70, 0x9f, 0xda, 0x10, 0x9d, 0x24, 0xf2, 0xe4, 0x46, 0x21, 0x96, 0x77, 0x9c, 0x5d },
+ { 0x75, 0xf6, 0x09, 0x33, 0x8a, 0xa6, 0x7d, 0x96, 0x9a, 0x2a, 0xe2, 0xa2, 0x36, 0x2b, 0x2d, 0xa9, 0xd7, 0x7c, 0x69, 0x5d, 0xfd, 0x1d, 0xf7, 0x22, 0x4a, 0x69, 0x01, 0xdb, 0x93, 0x2c, 0x33, 0x64 },
+ { 0x68, 0x60, 0x6c, 0xeb, 0x98, 0x9d, 0x54, 0x88, 0xfc, 0x7c, 0xf6, 0x49, 0xf3, 0xd7, 0xc2, 0x72, 0xef, 0x05, 0x5d, 0xa1, 0xa9, 0x3f, 0xae, 0xcd, 0x55, 0xfe, 0x06, 0xf6, 0x96, 0x70, 0x98, 0xca },
+ { 0x44, 0x34, 0x6b, 0xde, 0xb7, 0xe0, 0x52, 0xf6, 0x25, 0x50, 0x48, 0xf0, 0xd9, 0xb4, 0x2c, 0x42, 0x5b, 0xab, 0x9c, 0x3d, 0xd2, 0x41, 0x68, 0x21, 0x2c, 0x3e, 0xcf, 0x1e, 0xbf, 0x34, 0xe6, 0xae },
+ { 0x8e, 0x9c, 0xf6, 0xe1, 0xf3, 0x66, 0x47, 0x1f, 0x2a, 0xc7, 0xd2, 0xee, 0x9b, 0x5e, 0x62, 0x66, 0xfd, 0xa7, 0x1f, 0x8f, 0x2e, 0x41, 0x09, 0xf2, 0x23, 0x7e, 0xd5, 0xf8, 0x81, 0x3f, 0xc7, 0x18 },
+ { 0x84, 0xbb, 0xeb, 0x84, 0x06, 0xd2, 0x50, 0x95, 0x1f, 0x8c, 0x1b, 0x3e, 0x86, 0xa7, 0xc0, 0x10, 0x08, 0x29, 0x21, 0x83, 0x3d, 0xfd, 0x95, 0x55, 0xa2, 0xf9, 0x09, 0xb1, 0x08, 0x6e, 0xb4, 0xb8 },
+ { 0xee, 0x66, 0x6f, 0x3e, 0xef, 0x0f, 0x7e, 0x2a, 0x9c, 0x22, 0x29, 0x58, 0xc9, 0x7e, 0xaf, 0x35, 0xf5, 0x1c, 0xed, 0x39, 0x3d, 0x71, 0x44, 0x85, 0xab, 0x09, 0xa0, 0x69, 0x34, 0x0f, 0xdf, 0x88 },
+ { 0xc1, 0x53, 0xd3, 0x4a, 0x65, 0xc4, 0x7b, 0x4a, 0x62, 0xc5, 0xca, 0xcf, 0x24, 0x01, 0x09, 0x75, 0xd0, 0x35, 0x6b, 0x2f, 0x32, 0xc8, 0xf5, 0xda, 0x53, 0x0d, 0x33, 0x88, 0x16, 0xad, 0x5d, 0xe6 },
+ { 0x9f, 0xc5, 0x45, 0x01, 0x09, 0xe1, 0xb7, 0x79, 0xf6, 0xc7, 0xae, 0x79, 0xd5, 0x6c, 0x27, 0x63, 0x5c, 0x8d, 0xd4, 0x26, 0xc5, 0xa9, 0xd5, 0x4e, 0x25, 0x78, 0xdb, 0x98, 0x9b, 0x8c, 0x3b, 0x4e },
+ { 0xd1, 0x2b, 0xf3, 0x73, 0x2e, 0xf4, 0xaf, 0x5c, 0x22, 0xfa, 0x90, 0x35, 0x6a, 0xf8, 0xfc, 0x50, 0xfc, 0xb4, 0x0f, 0x8f, 0x2e, 0xa5, 0xc8, 0x59, 0x47, 0x37, 0xa3, 0xb3, 0xd5, 0xab, 0xdb, 0xd7 },
+ { 0x11, 0x03, 0x0b, 0x92, 0x89, 0xbb, 0xa5, 0xaf, 0x65, 0x26, 0x06, 0x72, 0xab, 0x6f, 0xee, 0x88, 0xb8, 0x74, 0x20, 0xac, 0xef, 0x4a, 0x17, 0x89, 0xa2, 0x07, 0x3b, 0x7e, 0xc2, 0xf2, 0xa0, 0x9e },
+ { 0x69, 0xcb, 0x19, 0x2b, 0x84, 0x44, 0x00, 0x5c, 0x8c, 0x0c, 0xeb, 0x12, 0xc8, 0x46, 0x86, 0x07, 0x68, 0x18, 0x8c, 0xda, 0x0a, 0xec, 0x27, 0xa9, 0xc8, 0xa5, 0x5c, 0xde, 0xe2, 0x12, 0x36, 0x32 },
+ { 0xdb, 0x44, 0x4c, 0x15, 0x59, 0x7b, 0x5f, 0x1a, 0x03, 0xd1, 0xf9, 0xed, 0xd1, 0x6e, 0x4a, 0x9f, 0x43, 0xa6, 0x67, 0xcc, 0x27, 0x51, 0x75, 0xdf, 0xa2, 0xb7, 0x04, 0xe3, 0xbb, 0x1a, 0x9b, 0x83 },
+ { 0x3f, 0xb7, 0x35, 0x06, 0x1a, 0xbc, 0x51, 0x9d, 0xfe, 0x97, 0x9e, 0x54, 0xc1, 0xee, 0x5b, 0xfa, 0xd0, 0xa9, 0xd8, 0x58, 0xb3, 0x31, 0x5b, 0xad, 0x34, 0xbd, 0xe9, 0x99, 0xef, 0xd7, 0x24, 0xdd },
+ };
+ unsigned char inp[1000], out[1000];
+ unsigned char key[] = { 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 };
+ unsigned long ilen, klen = sizeof(key), mlen = 32;
+ blake2smac_state st;
+
+ for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen;
+
+ for (ilen = 0; ilen < 256; ilen++) {
+ const unsigned char *mac = tests[ilen];
+ unsigned long olen = mlen;
+ /* process piece by piece */
+ if (ilen > 15) {
+ blake2smac_init(&st, olen, key, klen);
+ blake2smac_process(&st, (unsigned char*)inp, 5);
+ blake2smac_process(&st, (unsigned char*)inp + 5, 4);
+ blake2smac_process(&st, (unsigned char*)inp + 9, 3);
+ blake2smac_process(&st, (unsigned char*)inp + 12, 2);
+ blake2smac_process(&st, (unsigned char*)inp + 14, 1);
+ blake2smac_process(&st, (unsigned char*)inp + 15, ilen - 15);
+ blake2smac_done(&st, out, &olen);
+ if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ /* process in one go */
+ blake2smac_init(&st, olen, key, klen);
+ blake2smac_process(&st, (unsigned char*)inp, ilen);
+ blake2smac_done(&st, out, &olen);
+ if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/f9/f9_done.c b/Sources/libtomcrypt/mac/f9/f9_done.c
new file mode 100644
index 00000000..38d1371a
--- /dev/null
+++ b/Sources/libtomcrypt/mac/f9/f9_done.c
@@ -0,0 +1,65 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f9_done.c
+ f9 Support, terminate the state
+*/
+
+#ifdef LTC_F9_MODE
+
+/** Terminate the f9-MAC state
+ @param f9 f9 state to terminate
+ @param out [out] Destination for the MAC tag
+ @param outlen [in/out] Destination size and final tag size
+ Return CRYPT_OK on success
+*/
+int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen)
+{
+ int err, x;
+ LTC_ARGCHK(f9 != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* check structure */
+ if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((f9->blocksize > cipher_descriptor[f9->cipher].block_length) || (f9->blocksize < 0) ||
+ (f9->buflen > f9->blocksize) || (f9->buflen < 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (f9->buflen != 0) {
+ /* encrypt */
+ cipher_descriptor[f9->cipher].ecb_encrypt(f9->IV, f9->IV, &f9->key);
+ f9->buflen = 0;
+ for (x = 0; x < f9->blocksize; x++) {
+ f9->ACC[x] ^= f9->IV[x];
+ }
+ }
+
+ /* schedule modified key */
+ if ((err = cipher_descriptor[f9->cipher].setup(f9->akey, f9->keylen, 0, &f9->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* encrypt the ACC */
+ cipher_descriptor[f9->cipher].ecb_encrypt(f9->ACC, f9->ACC, &f9->key);
+ cipher_descriptor[f9->cipher].done(&f9->key);
+
+ /* extract tag */
+ for (x = 0; x < f9->blocksize && (unsigned long)x < *outlen; x++) {
+ out[x] = f9->ACC[x];
+ }
+ *outlen = x;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(f9, sizeof(*f9));
+#endif
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/f9/f9_file.c b/Sources/libtomcrypt/mac/f9/f9_file.c
new file mode 100644
index 00000000..c06f5480
--- /dev/null
+++ b/Sources/libtomcrypt/mac/f9/f9_file.c
@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f9_file.c
+ f9 support, process a file, Tom St Denis
+*/
+
+#ifdef LTC_F9_MODE
+
+/**
+ f9 a file
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param fname The name of the file you wish to f9
+ @param out [out] Where the authentication tag is to be stored
+ @param outlen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int f9_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *fname,
+ unsigned char *out, unsigned long *outlen)
+{
+#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(cipher);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
+ return CRYPT_NOP;
+#else
+ size_t x;
+ int err;
+ f9_state f9;
+ FILE *in;
+ unsigned char *buf;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(fname != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = f9_init(&f9, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ in = fopen(fname, "rb");
+ if (in == NULL) {
+ err = CRYPT_FILE_NOTFOUND;
+ goto LBL_ERR;
+ }
+
+ do {
+ x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+ if ((err = f9_process(&f9, buf, (unsigned long)x)) != CRYPT_OK) {
+ fclose(in);
+ goto LBL_CLEANBUF;
+ }
+ } while (x == LTC_FILE_READ_BUFSIZE);
+
+ if (fclose(in) != 0) {
+ err = CRYPT_ERROR;
+ goto LBL_CLEANBUF;
+ }
+
+ err = f9_done(&f9, out, outlen);
+
+LBL_CLEANBUF:
+ zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&f9, sizeof(f9_state));
+#endif
+ XFREE(buf);
+ return err;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/f9/f9_init.c b/Sources/libtomcrypt/mac/f9/f9_init.c
new file mode 100644
index 00000000..0bd599e2
--- /dev/null
+++ b/Sources/libtomcrypt/mac/f9/f9_init.c
@@ -0,0 +1,58 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f9_init.c
+ F9 Support, start an F9 state
+*/
+
+#ifdef LTC_F9_MODE
+
+/** Initialize F9-MAC state
+ @param f9 [out] f9 state to initialize
+ @param cipher Index of cipher to use
+ @param key [in] Secret key
+ @param keylen Length of secret key in octets
+ Return CRYPT_OK on success
+*/
+int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen)
+{
+ int x, err;
+
+ LTC_ARGCHK(f9 != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* schedule the key */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+#ifdef LTC_FAST
+ if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &f9->key)) != CRYPT_OK) {
+ goto done;
+ }
+
+ /* make the second key */
+ for (x = 0; (unsigned)x < keylen; x++) {
+ f9->akey[x] = key[x] ^ 0xAA;
+ }
+
+ /* setup struct */
+ zeromem(f9->IV, cipher_descriptor[cipher].block_length);
+ zeromem(f9->ACC, cipher_descriptor[cipher].block_length);
+ f9->blocksize = cipher_descriptor[cipher].block_length;
+ f9->cipher = cipher;
+ f9->buflen = 0;
+ f9->keylen = keylen;
+done:
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/f9/f9_memory.c b/Sources/libtomcrypt/mac/f9/f9_memory.c
new file mode 100644
index 00000000..5f05209a
--- /dev/null
+++ b/Sources/libtomcrypt/mac/f9/f9_memory.c
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f9_process.c
+ f9 Support, Process a block through F9-MAC
+*/
+
+#ifdef LTC_F9_MODE
+
+/** f9-MAC a block of memory
+ @param cipher Index of cipher to use
+ @param key [in] Secret key
+ @param keylen Length of key in octets
+ @param in [in] Message to MAC
+ @param inlen Length of input in octets
+ @param out [out] Destination for the MAC tag
+ @param outlen [in/out] Output size and final tag size
+ Return CRYPT_OK on success.
+*/
+int f9_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ f9_state *f9;
+ int err;
+
+ /* is the cipher valid? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* Use accelerator if found */
+ if (cipher_descriptor[cipher].f9_memory != NULL) {
+ return cipher_descriptor[cipher].f9_memory(key, keylen, in, inlen, out, outlen);
+ }
+
+ f9 = XCALLOC(1, sizeof(*f9));
+ if (f9 == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) {
+ goto done;
+ }
+
+ if ((err = f9_process(f9, in, inlen)) != CRYPT_OK) {
+ goto done;
+ }
+
+ err = f9_done(f9, out, outlen);
+done:
+ XFREE(f9);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/f9/f9_memory_multi.c b/Sources/libtomcrypt/mac/f9/f9_memory_multi.c
new file mode 100644
index 00000000..c97ffd3f
--- /dev/null
+++ b/Sources/libtomcrypt/mac/f9/f9_memory_multi.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+/**
+ @file f9_memory_multi.c
+ f9 support, process multiple blocks of memory, Tom St Denis
+*/
+
+#ifdef LTC_F9_MODE
+
+/**
+ f9 multiple blocks of memory
+ @param cipher The index of the desired cipher
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param out [out] The destination of the authentication tag
+ @param outlen [in/out] The max size and resulting size of the authentication tag (octets)
+ @param in The data to send through f9
+ @param inlen The length of the data to send through f9 (octets)
+ @param ... tuples of (data,len) pairs to f9, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int f9_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+{
+ int err;
+ f9_state *f9;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* allocate ram for f9 state */
+ f9 = XMALLOC(sizeof(f9_state));
+ if (f9 == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* f9 process the message */
+ if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ for (;;) {
+ /* process buf */
+ if ((err = f9_process(f9, curptr, curlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* step to next */
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) {
+ break;
+ }
+ curlen = va_arg(args, unsigned long);
+ }
+ if ((err = f9_done(f9, out, outlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(f9, sizeof(f9_state));
+#endif
+ XFREE(f9);
+ va_end(args);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/f9/f9_process.c b/Sources/libtomcrypt/mac/f9/f9_process.c
new file mode 100644
index 00000000..e416b540
--- /dev/null
+++ b/Sources/libtomcrypt/mac/f9/f9_process.c
@@ -0,0 +1,66 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f9_process.c
+ f9 Support, process blocks with f9
+*/
+
+#ifdef LTC_F9_MODE
+
+/** Process data through f9-MAC
+ @param f9 The f9-MAC state
+ @param in Input data to process
+ @param inlen Length of input in octets
+ Return CRYPT_OK on success
+*/
+int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen)
+{
+ int err, x;
+
+ LTC_ARGCHK(f9 != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* check structure */
+ if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((f9->blocksize > cipher_descriptor[f9->cipher].block_length) || (f9->blocksize < 0) ||
+ (f9->buflen > f9->blocksize) || (f9->buflen < 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+#ifdef LTC_FAST
+ if (f9->buflen == 0) {
+ while (inlen >= (unsigned long)f9->blocksize) {
+ for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x])));
+ }
+ cipher_descriptor[f9->cipher].ecb_encrypt(f9->IV, f9->IV, &f9->key);
+ for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&(f9->ACC[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x])));
+ }
+ in += f9->blocksize;
+ inlen -= f9->blocksize;
+ }
+ }
+#endif
+
+ while (inlen) {
+ if (f9->buflen == f9->blocksize) {
+ cipher_descriptor[f9->cipher].ecb_encrypt(f9->IV, f9->IV, &f9->key);
+ for (x = 0; x < f9->blocksize; x++) {
+ f9->ACC[x] ^= f9->IV[x];
+ }
+ f9->buflen = 0;
+ }
+ f9->IV[f9->buflen++] ^= *in++;
+ --inlen;
+ }
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/f9/f9_test.c b/Sources/libtomcrypt/mac/f9/f9_test.c
new file mode 100644
index 00000000..779fdf13
--- /dev/null
+++ b/Sources/libtomcrypt/mac/f9/f9_test.c
@@ -0,0 +1,66 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f9_test.c
+ f9 Support, Test F9 mode
+*/
+
+#ifdef LTC_F9_MODE
+
+/** Test f9-MAC mode
+ Return CRYPT_OK on success
+*/
+int f9_test(void)
+{
+#ifdef LTC_NO_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ int msglen;
+ unsigned char K[16], M[128], T[4];
+ } tests[] = {
+{
+ 20,
+ { 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 },
+ { 0x38, 0xA6, 0xF0, 0x56, 0xB8, 0xAE, 0xFD, 0xA9, 0x33, 0x32, 0x34, 0x62, 0x63, 0x39, 0x38, 0x61, 0x37, 0x34, 0x79, 0x40 },
+ { 0x46, 0xE0, 0x0D, 0x4B }
+},
+
+{
+ 105,
+ { 0x83, 0xFD, 0x23, 0xA2, 0x44, 0xA7, 0x4C, 0xF3, 0x58, 0xDA, 0x30, 0x19, 0xF1, 0x72, 0x26, 0x35 },
+ { 0x36, 0xAF, 0x61, 0x44, 0x4F, 0x30, 0x2A, 0xD2,
+ 0x35, 0xC6, 0x87, 0x16, 0x63, 0x3C, 0x66, 0xFB, 0x75, 0x0C, 0x26, 0x68, 0x65, 0xD5, 0x3C, 0x11, 0xEA, 0x05, 0xB1, 0xE9, 0xFA, 0x49, 0xC8, 0x39, 0x8D, 0x48, 0xE1, 0xEF, 0xA5, 0x90, 0x9D, 0x39,
+ 0x47, 0x90, 0x28, 0x37, 0xF5, 0xAE, 0x96, 0xD5, 0xA0, 0x5B, 0xC8, 0xD6, 0x1C, 0xA8, 0xDB, 0xEF, 0x1B, 0x13, 0xA4, 0xB4, 0xAB, 0xFE, 0x4F, 0xB1, 0x00, 0x60, 0x45, 0xB6, 0x74, 0xBB, 0x54, 0x72,
+ 0x93, 0x04, 0xC3, 0x82, 0xBE, 0x53, 0xA5, 0xAF, 0x05, 0x55, 0x61, 0x76, 0xF6, 0xEA, 0xA2, 0xEF, 0x1D, 0x05, 0xE4, 0xB0, 0x83, 0x18, 0x1E, 0xE6, 0x74, 0xCD, 0xA5, 0xA4, 0x85, 0xF7, 0x4D, 0x7A,
+ 0x40|0x80 },
+ { 0x95, 0xAE, 0x41, 0xBA },
+}
+};
+ unsigned char T[16];
+ unsigned long taglen;
+ int err, x, idx;
+
+ /* find kasumi */
+ if ((idx = find_cipher("kasumi")) == -1) {
+ return CRYPT_NOP;
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ taglen = 4;
+ if ((err = f9_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(T, taglen, tests[x].T, 4, "F9", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/hmac/hmac_done.c b/Sources/libtomcrypt/mac/hmac/hmac_done.c
new file mode 100644
index 00000000..a3d3c382
--- /dev/null
+++ b/Sources/libtomcrypt/mac/hmac/hmac_done.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file hmac_done.c
+ HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer
+*/
+
+#ifdef LTC_HMAC
+
+#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
+
+/**
+ Terminate an HMAC session
+ @param hmac The HMAC state
+ @param out [out] The destination of the HMAC authentication tag
+ @param outlen [in/out] The max size and resulting size of the HMAC authentication tag
+ @return CRYPT_OK if successful
+*/
+int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen)
+{
+ unsigned char *buf, *isha;
+ unsigned long hashsize, i;
+ int hash, err;
+
+ LTC_ARGCHK(hmac != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* test hash */
+ hash = hmac->hash;
+ if((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get the hash message digest size */
+ hashsize = hash_descriptor[hash].hashsize;
+
+ /* allocate buffers */
+ buf = XMALLOC(LTC_HMAC_BLOCKSIZE);
+ isha = XMALLOC(hashsize);
+ if (buf == NULL || isha == NULL) {
+ if (buf != NULL) {
+ XFREE(buf);
+ }
+ if (isha != NULL) {
+ XFREE(isha);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* Get the hash of the first HMAC vector plus the data */
+ if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* Create the second HMAC vector vector for step (3) */
+ for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) {
+ buf[i] = hmac->key[i] ^ 0x5C;
+ }
+
+ /* Now calculate the "outer" hash for step (5), (6), and (7) */
+ if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* copy to output */
+ for (i = 0; i < hashsize && i < *outlen; i++) {
+ out[i] = buf[i];
+ }
+ *outlen = i;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(isha, hashsize);
+ zeromem(buf, hashsize);
+ zeromem(hmac, sizeof(*hmac));
+#endif
+
+ XFREE(isha);
+ XFREE(buf);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/hmac/hmac_file.c b/Sources/libtomcrypt/mac/hmac/hmac_file.c
new file mode 100644
index 00000000..c944a285
--- /dev/null
+++ b/Sources/libtomcrypt/mac/hmac/hmac_file.c
@@ -0,0 +1,90 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file hmac_file.c
+ HMAC support, process a file, Tom St Denis/Dobes Vandermeer
+*/
+
+#ifdef LTC_HMAC
+
+/**
+ HMAC a file
+ @param hash The index of the hash you wish to use
+ @param fname The name of the file you wish to HMAC
+ @param key The secret key
+ @param keylen The length of the secret key
+ @param out [out] The HMAC authentication tag
+ @param outlen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int hmac_file(int hash, const char *fname,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen)
+{
+#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(hash);
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
+ return CRYPT_NOP;
+#else
+ hmac_state hmac;
+ FILE *in;
+ unsigned char *buf;
+ size_t x;
+ int err;
+
+ LTC_ARGCHK(fname != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ in = fopen(fname, "rb");
+ if (in == NULL) {
+ err = CRYPT_FILE_NOTFOUND;
+ goto LBL_ERR;
+ }
+
+ do {
+ x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+ if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) {
+ fclose(in); /* we don't trap this error since we're already returning an error! */
+ goto LBL_CLEANBUF;
+ }
+ } while (x == LTC_FILE_READ_BUFSIZE);
+
+ if (fclose(in) != 0) {
+ err = CRYPT_ERROR;
+ goto LBL_CLEANBUF;
+ }
+
+ err = hmac_done(&hmac, out, outlen);
+
+LBL_CLEANBUF:
+ zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&hmac, sizeof(hmac_state));
+#endif
+ XFREE(buf);
+ return err;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/hmac/hmac_init.c b/Sources/libtomcrypt/mac/hmac/hmac_init.c
new file mode 100644
index 00000000..50c5bcc9
--- /dev/null
+++ b/Sources/libtomcrypt/mac/hmac/hmac_init.c
@@ -0,0 +1,94 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file hmac_init.c
+ HMAC support, initialize state, Tom St Denis/Dobes Vandermeer
+*/
+
+#ifdef LTC_HMAC
+
+#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
+
+/**
+ Initialize an HMAC context.
+ @param hmac The HMAC state
+ @param hash The index of the hash you want to use
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @return CRYPT_OK if successful
+*/
+int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen)
+{
+ unsigned char *buf;
+ unsigned long hashsize;
+ unsigned long i, z;
+ int err;
+
+ LTC_ARGCHK(hmac != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* valid hash? */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+ hmac->hash = hash;
+ hashsize = hash_descriptor[hash].hashsize;
+
+ /* valid key length? */
+ if (keylen == 0) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ /* allocate ram for buf */
+ buf = XMALLOC(LTC_HMAC_BLOCKSIZE);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* check hash block fits */
+ if (sizeof(hmac->key) < LTC_HMAC_BLOCKSIZE) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* (1) make sure we have a large enough key */
+ if(keylen > LTC_HMAC_BLOCKSIZE) {
+ z = LTC_HMAC_BLOCKSIZE;
+ if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ keylen = hashsize;
+ } else {
+ XMEMCPY(hmac->key, key, (size_t)keylen);
+ }
+
+ if(keylen < LTC_HMAC_BLOCKSIZE) {
+ zeromem((hmac->key) + keylen, (size_t)(LTC_HMAC_BLOCKSIZE - keylen));
+ }
+
+ /* Create the initialization vector for step (3) */
+ for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) {
+ buf[i] = hmac->key[i] ^ 0x36;
+ }
+
+ /* Pre-pend that to the hash data */
+ if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, LTC_HMAC_BLOCKSIZE);
+#endif
+
+ XFREE(buf);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/hmac/hmac_memory.c b/Sources/libtomcrypt/mac/hmac/hmac_memory.c
new file mode 100644
index 00000000..221be580
--- /dev/null
+++ b/Sources/libtomcrypt/mac/hmac/hmac_memory.c
@@ -0,0 +1,76 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file hmac_memory.c
+ HMAC support, process a block of memory, Tom St Denis/Dobes Vandermeer
+*/
+
+#ifdef LTC_HMAC
+
+/**
+ HMAC a block of memory to produce the authentication tag
+ @param hash The index of the hash to use
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param in The data to HMAC
+ @param inlen The length of the data to HMAC (octets)
+ @param out [out] Destination of the authentication tag
+ @param outlen [in/out] Max size and resulting size of authentication tag
+ @return CRYPT_OK if successful
+*/
+int hmac_memory(int hash,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ hmac_state *hmac;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* make sure hash descriptor is valid */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* is there a descriptor? */
+ if (hash_descriptor[hash].hmac_block != NULL) {
+ return hash_descriptor[hash].hmac_block(key, keylen, in, inlen, out, outlen);
+ }
+
+ /* nope, so call the hmac functions */
+ /* allocate ram for hmac state */
+ hmac = XMALLOC(sizeof(hmac_state));
+ if (hmac == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if ((err = hmac_process(hmac, in, inlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(hmac, sizeof(hmac_state));
+#endif
+
+ XFREE(hmac);
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/hmac/hmac_memory_multi.c b/Sources/libtomcrypt/mac/hmac/hmac_memory_multi.c
new file mode 100644
index 00000000..2809d713
--- /dev/null
+++ b/Sources/libtomcrypt/mac/hmac/hmac_memory_multi.c
@@ -0,0 +1,80 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+/**
+ @file hmac_memory_multi.c
+ HMAC support, process multiple blocks of memory, Tom St Denis/Dobes Vandermeer
+*/
+
+#ifdef LTC_HMAC
+
+/**
+ HMAC multiple blocks of memory to produce the authentication tag
+ @param hash The index of the hash to use
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param out [out] Destination of the authentication tag
+ @param outlen [in/out] Max size and resulting size of authentication tag
+ @param in The data to HMAC
+ @param inlen The length of the data to HMAC (octets)
+ @param ... tuples of (data,len) pairs to HMAC, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int hmac_memory_multi(int hash,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+
+{
+ hmac_state *hmac;
+ int err;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* allocate ram for hmac state */
+ hmac = XMALLOC(sizeof(hmac_state));
+ if (hmac == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ for (;;) {
+ /* process buf */
+ if ((err = hmac_process(hmac, curptr, curlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* step to next */
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) {
+ break;
+ }
+ curlen = va_arg(args, unsigned long);
+ }
+ if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(hmac, sizeof(hmac_state));
+#endif
+ XFREE(hmac);
+ va_end(args);
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/hmac/hmac_process.c b/Sources/libtomcrypt/mac/hmac/hmac_process.c
new file mode 100644
index 00000000..14738b65
--- /dev/null
+++ b/Sources/libtomcrypt/mac/hmac/hmac_process.c
@@ -0,0 +1,31 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file hmac_process.c
+ HMAC support, process data, Tom St Denis/Dobes Vandermeer
+*/
+
+#ifdef LTC_HMAC
+
+/**
+ Process data through HMAC
+ @param hmac The hmac state
+ @param in The data to send through HMAC
+ @param inlen The length of the data to HMAC (octets)
+ @return CRYPT_OK if successful
+*/
+int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen)
+{
+ int err;
+ LTC_ARGCHK(hmac != NULL);
+ LTC_ARGCHK(in != NULL);
+ if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) {
+ return err;
+ }
+ return hash_descriptor[hmac->hash].process(&hmac->md, in, inlen);
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/hmac/hmac_test.c b/Sources/libtomcrypt/mac/hmac/hmac_test.c
new file mode 100644
index 00000000..b0970033
--- /dev/null
+++ b/Sources/libtomcrypt/mac/hmac/hmac_test.c
@@ -0,0 +1,618 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file hmac_test.c
+ HMAC support, self-test, Tom St Denis/Dobes Vandermeer/Steffen Jaeckel
+*/
+
+#ifdef LTC_HMAC
+
+/*
+ TEST CASES SOURCE:
+
+Network Working Group P. Cheng
+Request for Comments: 2202 IBM
+Category: Informational R. Glenn
+ NIST
+ September 1997
+
+ Test Cases for HMAC-MD5 and HMAC-SHA-1
+
+*******************************************************************************
+
+Network Working Group J. Kapp
+Request for Comments: 2286 Reaper Technologies
+Category: Informational February 1998
+
+ Test Cases for HMAC-RIPEMD160 and HMAC-RIPEMD128
+
+*******************************************************************************
+
+Network Working Group M. Nystrom
+Request for Comments: 4231 RSA Security
+Category: Standards Track December 2005
+
+ Identifiers and Test Vectors for HMAC-SHA-224, HMAC-SHA-256,
+ HMAC-SHA-384, and HMAC-SHA-512
+*/
+
+/**
+ HMAC self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled.
+*/
+int hmac_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ unsigned char digest[MAXBLOCKSIZE];
+ int i;
+
+ static const unsigned char hmac_test_case_keys[][136] = {
+ { /* 1 */
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b
+ },
+#ifdef LTC_TEST_EXT
+ { /* 2 */
+ 0x4a, 0x65, 0x66, 0x65
+ },
+ { /* 4 */
+ 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
+ },
+ { /* 5 */
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c
+ },
+ { /* 3, 6, 7 */
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+ }
+#endif /* LTC_TEST_EXT */
+ };
+
+
+ static const unsigned char hmac_test_case_data[][153] = {
+ {
+ "Hi There"
+ },
+#ifdef LTC_TEST_EXT
+ {
+ "what do ya want for nothing?"
+ },
+ {
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd
+ },
+ {
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd
+ },
+ {
+ "Test With Truncation"
+ },
+ {
+ "Test Using Larger Than Block-Size Key - Hash Key First"
+ },
+ {
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+ },
+ {
+ "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+ }
+#endif /* LTC_TEST_EXT */
+ };
+
+ static const struct hmac_test_case {
+ const char *num;
+ const char *algo;
+ const unsigned char *key;
+ unsigned long keylen;
+ const unsigned char *data;
+ unsigned long datalen;
+ unsigned char digest[MAXBLOCKSIZE];
+ } cases[] = {
+ /*
+ RFC 2202 3. Test Cases for HMAC-SHA-1
+ */
+ { "rfc2202 3.1", "sha1",
+ hmac_test_case_keys[0], 20,
+ hmac_test_case_data[0], 8,
+ {0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
+ 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e,
+ 0xf1, 0x46, 0xbe, 0x00} },
+
+#ifdef LTC_TEST_EXT
+ { "rfc2202 3.2", "sha1",
+ hmac_test_case_keys[1], 4,
+ hmac_test_case_data[1], 28,
+ {0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2,
+ 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c,
+ 0x25, 0x9a, 0x7c, 0x79} },
+
+ { "rfc2202 3.3", "sha1",
+ hmac_test_case_keys[4], 20,
+ hmac_test_case_data[2], 50,
+ {0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd,
+ 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f,
+ 0x63, 0xf1, 0x75, 0xd3} },
+
+ { "rfc2202 3.4", "sha1",
+ hmac_test_case_keys[2], 25,
+ hmac_test_case_data[3], 50,
+ {0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6,
+ 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c,
+ 0x2d, 0x72, 0x35, 0xda} },
+
+ { "rfc2202 3.5", "sha1",
+ hmac_test_case_keys[3], 20,
+ hmac_test_case_data[4], 20,
+ {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
+ 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} },
+
+ { "rfc2202 3.6", "sha1",
+ hmac_test_case_keys[4], 80,
+ hmac_test_case_data[5], 54,
+ {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e,
+ 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55,
+ 0xed, 0x40, 0x21, 0x12} },
+
+ { "rfc2202 3.7", "sha1",
+ hmac_test_case_keys[4], 80,
+ hmac_test_case_data[6], 73,
+ {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d,
+ 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} },
+#endif /* LTC_TEST_EXT */
+
+ /*
+ RFC 2202 2. Test Cases for HMAC-MD5
+ */
+ { "rfc2202 2.1", "md5",
+ hmac_test_case_keys[0], 16,
+ hmac_test_case_data[0], 8,
+ {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
+ 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d} },
+
+#ifdef LTC_TEST_EXT
+ { "rfc2202 2.2", "md5",
+ hmac_test_case_keys[1], 4,
+ hmac_test_case_data[1], 28,
+ {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
+ 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} },
+
+ { "rfc2202 2.3", "md5",
+ hmac_test_case_keys[4], 16,
+ hmac_test_case_data[2], 50,
+ {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
+ 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} },
+
+ { "rfc2202 2.4", "md5",
+ hmac_test_case_keys[2], 25,
+ hmac_test_case_data[3], 50,
+ {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea,
+ 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} },
+
+ { "rfc2202 2.5", "md5",
+ hmac_test_case_keys[3], 16,
+ hmac_test_case_data[4], 20,
+ {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00,
+ 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} },
+
+ { "rfc2202 2.6", "md5",
+ hmac_test_case_keys[4], 80,
+ hmac_test_case_data[5], 54,
+ {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f,
+ 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} },
+
+ { "rfc2202 2.7", "md5",
+ hmac_test_case_keys[4], 80,
+ hmac_test_case_data[6], 73,
+ {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
+ 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} },
+#endif /* LTC_TEST_EXT */
+
+ /*
+ RFC 2286 2. Test Cases for HMAC-RIPEMD160
+ */
+ { "rfc2286 2.1", "rmd160",
+ hmac_test_case_keys[0], 20,
+ hmac_test_case_data[0], 8,
+ {0x24, 0xcb, 0x4b, 0xd6, 0x7d, 0x20, 0xfc, 0x1a,
+ 0x5d, 0x2e, 0xd7, 0x73, 0x2d, 0xcc, 0x39, 0x37,
+ 0x7f, 0x0a, 0x56, 0x68} },
+
+#ifdef LTC_TEST_EXT
+ { "rfc2286 2.2", "rmd160",
+ hmac_test_case_keys[1], 4,
+ hmac_test_case_data[1], 28,
+ {0xdd, 0xa6, 0xc0, 0x21, 0x3a, 0x48, 0x5a, 0x9e,
+ 0x24, 0xf4, 0x74, 0x20, 0x64, 0xa7, 0xf0, 0x33,
+ 0xb4, 0x3c, 0x40, 0x69} },
+
+ { "rfc2286 2.3", "rmd160",
+ hmac_test_case_keys[4], 20,
+ hmac_test_case_data[2], 50,
+ {0xb0, 0xb1, 0x05, 0x36, 0x0d, 0xe7, 0x59, 0x96,
+ 0x0a, 0xb4, 0xf3, 0x52, 0x98, 0xe1, 0x16, 0xe2,
+ 0x95, 0xd8, 0xe7, 0xc1} },
+
+ { "rfc2286 2.4", "rmd160",
+ hmac_test_case_keys[2], 25,
+ hmac_test_case_data[3], 50,
+ {0xd5, 0xca, 0x86, 0x2f, 0x4d, 0x21, 0xd5, 0xe6,
+ 0x10, 0xe1, 0x8b, 0x4c, 0xf1, 0xbe, 0xb9, 0x7a,
+ 0x43, 0x65, 0xec, 0xf4} },
+
+ { "rfc2286 2.5", "rmd160",
+ hmac_test_case_keys[3], 20,
+ hmac_test_case_data[4], 20,
+ {0x76, 0x19, 0x69, 0x39, 0x78, 0xf9, 0x1d, 0x90,
+ 0x53, 0x9a, 0xe7, 0x86, 0x50, 0x0f, 0xf3, 0xd8,
+ 0xe0, 0x51, 0x8e, 0x39} },
+
+ { "rfc2286 2.6", "rmd160",
+ hmac_test_case_keys[4], 80,
+ hmac_test_case_data[5], 54,
+ {0x64, 0x66, 0xca, 0x07, 0xac, 0x5e, 0xac, 0x29,
+ 0xe1, 0xbd, 0x52, 0x3e, 0x5a, 0xda, 0x76, 0x05,
+ 0xb7, 0x91, 0xfd, 0x8b} },
+
+ { "rfc2286 2.7", "rmd160",
+ hmac_test_case_keys[4], 80,
+ hmac_test_case_data[6], 73,
+ {0x69, 0xea, 0x60, 0x79, 0x8d, 0x71, 0x61, 0x6c,
+ 0xce, 0x5f, 0xd0, 0x87, 0x1e, 0x23, 0x75, 0x4c,
+ 0xd7, 0x5d, 0x5a, 0x0a} },
+#endif /* LTC_TEST_EXT */
+
+ /*
+ RFC 2286 3. Test Cases for HMAC-RIPEMD128
+ */
+ { "rfc2286 3.1", "rmd128",
+ hmac_test_case_keys[0], 16,
+ hmac_test_case_data[0], 8,
+ {0xfb, 0xf6, 0x1f, 0x94, 0x92, 0xaa, 0x4b, 0xbf,
+ 0x81, 0xc1, 0x72, 0xe8, 0x4e, 0x07, 0x34, 0xdb} },
+
+#ifdef LTC_TEST_EXT
+ { "rfc2286 3.2", "rmd128",
+ hmac_test_case_keys[1], 4,
+ hmac_test_case_data[1], 28,
+ {0x87, 0x5f, 0x82, 0x88, 0x62, 0xb6, 0xb3, 0x34,
+ 0xb4, 0x27, 0xc5, 0x5f, 0x9f, 0x7f, 0xf0, 0x9b} },
+
+ { "rfc2286 3.3", "rmd128",
+ hmac_test_case_keys[4], 16,
+ hmac_test_case_data[2], 50,
+ {0x09, 0xf0, 0xb2, 0x84, 0x6d, 0x2f, 0x54, 0x3d,
+ 0xa3, 0x63, 0xcb, 0xec, 0x8d, 0x62, 0xa3, 0x8d} },
+
+ { "rfc2286 3.4", "rmd128",
+ hmac_test_case_keys[2], 25,
+ hmac_test_case_data[3], 50,
+ {0xbd, 0xbb, 0xd7, 0xcf, 0x03, 0xe4, 0x4b, 0x5a,
+ 0xa6, 0x0a, 0xf8, 0x15, 0xbe, 0x4d, 0x22, 0x94} },
+
+ { "rfc2286 3.5", "rmd128",
+ hmac_test_case_keys[3], 16,
+ hmac_test_case_data[4], 20,
+ {0xe7, 0x98, 0x08, 0xf2, 0x4b, 0x25, 0xfd, 0x03,
+ 0x1c, 0x15, 0x5f, 0x0d, 0x55, 0x1d, 0x9a, 0x3a} },
+
+ { "rfc2286 3.6", "rmd128",
+ hmac_test_case_keys[4], 80,
+ hmac_test_case_data[5], 54,
+ {0xdc, 0x73, 0x29, 0x28, 0xde, 0x98, 0x10, 0x4a,
+ 0x1f, 0x59, 0xd3, 0x73, 0xc1, 0x50, 0xac, 0xbb} },
+
+ { "rfc2286 3.7", "rmd128",
+ hmac_test_case_keys[4], 80,
+ hmac_test_case_data[6], 73,
+ {0x5c, 0x6b, 0xec, 0x96, 0x79, 0x3e, 0x16, 0xd4,
+ 0x06, 0x90, 0xc2, 0x37, 0x63, 0x5f, 0x30, 0xc5} },
+#endif /* LTC_TEST_EXT */
+
+ /*
+ RFC 4231 4. Test Vectors
+ Ch. 4.6 with truncated output left out to simplify tests
+ */
+ { "rfc4231 4.2", "sha224",
+ hmac_test_case_keys[0], 20,
+ hmac_test_case_data[0], 8,
+ {0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19,
+ 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f,
+ 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f,
+ 0x53, 0x68, 0x4b, 0x22} },
+
+#ifdef LTC_TEST_EXT
+ { "rfc4231 4.3", "sha224",
+ hmac_test_case_keys[1], 4,
+ hmac_test_case_data[1], 28,
+ {0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf,
+ 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
+ 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00,
+ 0x8f, 0xd0, 0x5e, 0x44} },
+
+ { "rfc4231 4.4", "sha224",
+ hmac_test_case_keys[4], 20,
+ hmac_test_case_data[2], 50,
+ {0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6,
+ 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64,
+ 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1,
+ 0xec, 0x83, 0x33, 0xea} },
+
+ { "rfc4231 4.5", "sha224",
+ hmac_test_case_keys[2], 25,
+ hmac_test_case_data[3], 50,
+ {0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac,
+ 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c,
+ 0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d,
+ 0xe7, 0xaf, 0xec, 0x5a} },
+
+ { "rfc4231 4.7", "sha224",
+ hmac_test_case_keys[4], 131,
+ hmac_test_case_data[5], 54,
+ {0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad,
+ 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
+ 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27,
+ 0x3f, 0xa6, 0x87, 0x0e} },
+
+ { "rfc4231 4.8", "sha224",
+ hmac_test_case_keys[4], 131,
+ hmac_test_case_data[7], 152,
+ {0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02,
+ 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd,
+ 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9,
+ 0xf6, 0xf5, 0x65, 0xd1} },
+#endif /* LTC_TEST_EXT */
+
+ { "rfc4231 4.2", "sha256",
+ hmac_test_case_keys[0], 20,
+ hmac_test_case_data[0], 8,
+ {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
+ 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
+ 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
+ 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7} },
+
+#ifdef LTC_TEST_EXT
+ { "rfc4231 4.3", "sha256",
+ hmac_test_case_keys[1], 4,
+ hmac_test_case_data[1], 28,
+ {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
+ 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
+ 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
+ 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43} },
+
+ { "rfc4231 4.4", "sha256",
+ hmac_test_case_keys[4], 20,
+ hmac_test_case_data[2], 50,
+ {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46,
+ 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
+ 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
+ 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe} },
+
+ { "rfc4231 4.5", "sha256",
+ hmac_test_case_keys[2], 25,
+ hmac_test_case_data[3], 50,
+ {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e,
+ 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
+ 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
+ 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b} },
+
+ { "rfc4231 4.7", "sha256",
+ hmac_test_case_keys[4], 131,
+ hmac_test_case_data[5], 54,
+ {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
+ 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
+ 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
+ 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54} },
+
+ { "rfc4231 4.8", "sha256",
+ hmac_test_case_keys[4], 131,
+ hmac_test_case_data[7], 152,
+ {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb,
+ 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
+ 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
+ 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} },
+#endif /* LTC_TEST_EXT */
+
+ { "rfc4231 4.2", "sha384",
+ hmac_test_case_keys[0], 20,
+ hmac_test_case_data[0], 8,
+ {0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62,
+ 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f,
+ 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
+ 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
+ 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f,
+ 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6} },
+
+#ifdef LTC_TEST_EXT
+ { "rfc4231 4.3", "sha384",
+ hmac_test_case_keys[1], 4,
+ hmac_test_case_data[1], 28,
+ {0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31,
+ 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
+ 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
+ 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
+ 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7,
+ 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49} },
+
+ { "rfc4231 4.4", "sha384",
+ hmac_test_case_keys[4], 20,
+ hmac_test_case_data[2], 50,
+ {0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a,
+ 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f,
+ 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb,
+ 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b,
+ 0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9,
+ 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27} },
+
+ { "rfc4231 4.5", "sha384",
+ hmac_test_case_keys[2], 25,
+ hmac_test_case_data[3], 50,
+ {0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85,
+ 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7,
+ 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c,
+ 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e,
+ 0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79,
+ 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb} },
+
+ { "rfc4231 4.7", "sha384",
+ hmac_test_case_keys[4], 131,
+ hmac_test_case_data[5], 54,
+ {0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90,
+ 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
+ 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
+ 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
+ 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82,
+ 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52} },
+
+ { "rfc4231 4.8", "sha384",
+ hmac_test_case_keys[4], 131,
+ hmac_test_case_data[7], 152,
+ {0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d,
+ 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c,
+ 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
+ 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5,
+ 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d,
+ 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e} },
+#endif /* LTC_TEST_EXT */
+
+ { "rfc4231 4.2", "sha512",
+ hmac_test_case_keys[0], 20,
+ hmac_test_case_data[0], 8,
+ {0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
+ 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
+ 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
+ 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
+ 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02,
+ 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
+ 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70,
+ 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54} },
+
+#ifdef LTC_TEST_EXT
+ { "rfc4231 4.3", "sha512",
+ hmac_test_case_keys[1], 4,
+ hmac_test_case_data[1], 28,
+ {0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
+ 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
+ 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
+ 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
+ 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a,
+ 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
+ 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b,
+ 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37} },
+
+ { "rfc4231 4.4", "sha512",
+ hmac_test_case_keys[4], 20,
+ hmac_test_case_data[2], 50,
+ {0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84,
+ 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
+ 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36,
+ 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39,
+ 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8,
+ 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07,
+ 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26,
+ 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb} },
+
+ { "rfc4231 4.5", "sha512",
+ hmac_test_case_keys[2], 25,
+ hmac_test_case_data[3], 50,
+ {0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69,
+ 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7,
+ 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d,
+ 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb,
+ 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4,
+ 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63,
+ 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d,
+ 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd} },
+
+ { "rfc4231 4.7", "sha512",
+ hmac_test_case_keys[4], 131,
+ hmac_test_case_data[5], 54,
+ {0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb,
+ 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
+ 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1,
+ 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
+ 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98,
+ 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
+ 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec,
+ 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98} },
+
+ { "rfc4231 4.8", "sha512",
+ hmac_test_case_keys[4], 131,
+ hmac_test_case_data[7], 152,
+ {0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba,
+ 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd,
+ 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86,
+ 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44,
+ 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1,
+ 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
+ 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60,
+ 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58} },
+#endif /* LTC_TEST_EXT */
+
+ };
+
+ unsigned long outlen;
+ int err;
+ int tested=0,failed=0;
+ for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
+ int hash = find_hash(cases[i].algo);
+ if (hash == -1) continue;
+ ++tested;
+ outlen = sizeof(digest);
+ if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) {
+#ifdef LTC_TEST_DBG
+ printf("HMAC-%s test %s, %s\n", cases[i].algo, cases[i].num, error_to_string(err));
+#endif
+ return err;
+ }
+
+ if(compare_testvector(digest, outlen, cases[i].digest, (size_t)hash_descriptor[hash].hashsize, cases[i].num, i)) {
+ failed++;
+ }
+ }
+
+ if (failed != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ if (tested == 0) {
+ return CRYPT_NOP;
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/omac/omac_done.c b/Sources/libtomcrypt/mac/omac/omac_done.c
new file mode 100644
index 00000000..c60067f8
--- /dev/null
+++ b/Sources/libtomcrypt/mac/omac/omac_done.c
@@ -0,0 +1,74 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file omac_done.c
+ OMAC1 support, terminate a stream, Tom St Denis
+*/
+
+#ifdef LTC_OMAC
+
+/**
+ Terminate an OMAC stream
+ @param omac The OMAC state
+ @param out [out] Destination for the authentication tag
+ @param outlen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful
+*/
+int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen)
+{
+ int err, mode;
+ unsigned x;
+
+ LTC_ARGCHK(omac != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) ||
+ (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* figure out mode */
+ if (omac->buflen != omac->blklen) {
+ /* add the 0x80 byte */
+ omac->block[omac->buflen++] = 0x80;
+
+ /* pad with 0x00 */
+ while (omac->buflen < omac->blklen) {
+ omac->block[omac->buflen++] = 0x00;
+ }
+ mode = 1;
+ } else {
+ mode = 0;
+ }
+
+ /* now xor prev + Lu[mode] */
+ for (x = 0; x < (unsigned)omac->blklen; x++) {
+ omac->block[x] ^= omac->prev[x] ^ omac->Lu[mode][x];
+ }
+
+ /* encrypt it */
+ if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->block, omac->block, &omac->key)) != CRYPT_OK) {
+ return err;
+ }
+ cipher_descriptor[omac->cipher_idx].done(&omac->key);
+
+ /* output it */
+ for (x = 0; x < (unsigned)omac->blklen && x < *outlen; x++) {
+ out[x] = omac->block[x];
+ }
+ *outlen = x;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(omac, sizeof(*omac));
+#endif
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/omac/omac_file.c b/Sources/libtomcrypt/mac/omac/omac_file.c
new file mode 100644
index 00000000..012958a4
--- /dev/null
+++ b/Sources/libtomcrypt/mac/omac/omac_file.c
@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file omac_file.c
+ OMAC1 support, process a file, Tom St Denis
+*/
+
+#ifdef LTC_OMAC
+
+/**
+ OMAC a file
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param filename The name of the file you wish to OMAC
+ @param out [out] Where the authentication tag is to be stored
+ @param outlen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int omac_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen)
+{
+#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(cipher);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(filename);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
+ return CRYPT_NOP;
+#else
+ size_t x;
+ int err;
+ omac_state omac;
+ FILE *in;
+ unsigned char *buf;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(filename != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ in = fopen(filename, "rb");
+ if (in == NULL) {
+ err = CRYPT_FILE_NOTFOUND;
+ goto LBL_ERR;
+ }
+
+ do {
+ x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+ if ((err = omac_process(&omac, buf, (unsigned long)x)) != CRYPT_OK) {
+ fclose(in);
+ goto LBL_CLEANBUF;
+ }
+ } while (x == LTC_FILE_READ_BUFSIZE);
+
+ if (fclose(in) != 0) {
+ err = CRYPT_ERROR;
+ goto LBL_CLEANBUF;
+ }
+
+ err = omac_done(&omac, out, outlen);
+
+LBL_CLEANBUF:
+ zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&omac, sizeof(omac_state));
+#endif
+ XFREE(buf);
+ return err;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/omac/omac_init.c b/Sources/libtomcrypt/mac/omac/omac_init.c
new file mode 100644
index 00000000..f527701d
--- /dev/null
+++ b/Sources/libtomcrypt/mac/omac/omac_init.c
@@ -0,0 +1,89 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file omac_init.c
+ OMAC1 support, initialize state, by Tom St Denis
+*/
+
+
+#ifdef LTC_OMAC
+
+/**
+ Initialize an OMAC state
+ @param omac The OMAC state to initialize
+ @param cipher The index of the desired cipher
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @return CRYPT_OK if successful
+*/
+int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen)
+{
+ int err, x, y, mask, msb, len;
+
+ LTC_ARGCHK(omac != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* schedule the key */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+#ifdef LTC_FAST
+ if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ /* now setup the system */
+ switch (cipher_descriptor[cipher].block_length) {
+ case 8: mask = 0x1B;
+ len = 8;
+ break;
+ case 16: mask = 0x87;
+ len = 16;
+ break;
+ default: return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &omac->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* ok now we need Lu and Lu^2 [calc one from the other] */
+
+ /* first calc L which is Ek(0) */
+ zeromem(omac->Lu[0], cipher_descriptor[cipher].block_length);
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(omac->Lu[0], omac->Lu[0], &omac->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* now do the mults, whoopy! */
+ for (x = 0; x < 2; x++) {
+ /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */
+ msb = omac->Lu[x][0] >> 7;
+
+ /* shift left */
+ for (y = 0; y < (len - 1); y++) {
+ omac->Lu[x][y] = ((omac->Lu[x][y] << 1) | (omac->Lu[x][y+1] >> 7)) & 255;
+ }
+ omac->Lu[x][len - 1] = ((omac->Lu[x][len - 1] << 1) ^ (msb ? mask : 0)) & 255;
+
+ /* copy up as require */
+ if (x == 0) {
+ XMEMCPY(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0]));
+ }
+ }
+
+ /* setup state */
+ omac->cipher_idx = cipher;
+ omac->buflen = 0;
+ omac->blklen = len;
+ zeromem(omac->prev, sizeof(omac->prev));
+ zeromem(omac->block, sizeof(omac->block));
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/omac/omac_memory.c b/Sources/libtomcrypt/mac/omac/omac_memory.c
new file mode 100644
index 00000000..56ac137a
--- /dev/null
+++ b/Sources/libtomcrypt/mac/omac/omac_memory.c
@@ -0,0 +1,73 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file omac_memory.c
+ OMAC1 support, process a block of memory, Tom St Denis
+*/
+
+#ifdef LTC_OMAC
+
+/**
+ OMAC a block of memory
+ @param cipher The index of the desired cipher
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param in The data to send through OMAC
+ @param inlen The length of the data to send through OMAC (octets)
+ @param out [out] The destination of the authentication tag
+ @param outlen [in/out] The max size and resulting size of the authentication tag (octets)
+ @return CRYPT_OK if successful
+*/
+int omac_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ int err;
+ omac_state *omac;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* is the cipher valid? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* Use accelerator if found */
+ if (cipher_descriptor[cipher].omac_memory != NULL) {
+ return cipher_descriptor[cipher].omac_memory(key, keylen, in, inlen, out, outlen);
+ }
+
+ /* allocate ram for omac state */
+ omac = XMALLOC(sizeof(omac_state));
+ if (omac == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* omac process the message */
+ if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = omac_process(omac, in, inlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(omac, sizeof(omac_state));
+#endif
+
+ XFREE(omac);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/omac/omac_memory_multi.c b/Sources/libtomcrypt/mac/omac/omac_memory_multi.c
new file mode 100644
index 00000000..4f3b708e
--- /dev/null
+++ b/Sources/libtomcrypt/mac/omac/omac_memory_multi.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+/**
+ @file omac_memory_multi.c
+ OMAC1 support, process multiple blocks of memory, Tom St Denis
+*/
+
+#ifdef LTC_OMAC
+
+/**
+ OMAC multiple blocks of memory
+ @param cipher The index of the desired cipher
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param out [out] The destination of the authentication tag
+ @param outlen [in/out] The max size and resulting size of the authentication tag (octets)
+ @param in The data to send through OMAC
+ @param inlen The length of the data to send through OMAC (octets)
+ @param ... tuples of (data,len) pairs to OMAC, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int omac_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+{
+ int err;
+ omac_state *omac;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* allocate ram for omac state */
+ omac = XMALLOC(sizeof(omac_state));
+ if (omac == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* omac process the message */
+ if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ for (;;) {
+ /* process buf */
+ if ((err = omac_process(omac, curptr, curlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* step to next */
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) {
+ break;
+ }
+ curlen = va_arg(args, unsigned long);
+ }
+ if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(omac, sizeof(omac_state));
+#endif
+ XFREE(omac);
+ va_end(args);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/omac/omac_process.c b/Sources/libtomcrypt/mac/omac/omac_process.c
new file mode 100644
index 00000000..b8e3160a
--- /dev/null
+++ b/Sources/libtomcrypt/mac/omac/omac_process.c
@@ -0,0 +1,80 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file omac_process.c
+ OMAC1 support, process data, Tom St Denis
+*/
+
+
+#ifdef LTC_OMAC
+
+/**
+ Process data through OMAC
+ @param omac The OMAC state
+ @param in The input data to send through OMAC
+ @param inlen The length of the input (octets)
+ @return CRYPT_OK if successful
+*/
+int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen)
+{
+ unsigned long n, x;
+ int err;
+
+ LTC_ARGCHK(omac != NULL);
+ LTC_ARGCHK(in != NULL);
+ if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) ||
+ (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+#ifdef LTC_FAST
+ {
+ unsigned long blklen = cipher_descriptor[omac->cipher_idx].block_length;
+
+ if (omac->buflen == 0 && inlen > blklen) {
+ unsigned long y;
+ for (x = 0; x < (inlen - blklen); x += blklen) {
+ for (y = 0; y < blklen; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&omac->prev[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&in[y]));
+ }
+ in += blklen;
+ if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->prev, omac->prev, &omac->key)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ inlen -= x;
+ }
+ }
+#endif
+
+ while (inlen != 0) {
+ /* ok if the block is full we xor in prev, encrypt and replace prev */
+ if (omac->buflen == omac->blklen) {
+ for (x = 0; x < (unsigned long)omac->blklen; x++) {
+ omac->block[x] ^= omac->prev[x];
+ }
+ if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->block, omac->prev, &omac->key)) != CRYPT_OK) {
+ return err;
+ }
+ omac->buflen = 0;
+ }
+
+ /* add bytes */
+ n = MIN(inlen, (unsigned long)(omac->blklen - omac->buflen));
+ XMEMCPY(omac->block + omac->buflen, in, n);
+ omac->buflen += n;
+ inlen -= n;
+ in += n;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/omac/omac_test.c b/Sources/libtomcrypt/mac/omac/omac_test.c
new file mode 100644
index 00000000..bca6d9c6
--- /dev/null
+++ b/Sources/libtomcrypt/mac/omac/omac_test.c
@@ -0,0 +1,93 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file omac_test.c
+ OMAC1 support, self-test, by Tom St Denis
+*/
+
+#ifdef LTC_OMAC
+
+/**
+ Test the OMAC setup
+ @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled
+*/
+int omac_test(void)
+{
+#if !defined(LTC_TEST)
+ return CRYPT_NOP;
+#else
+ static const struct {
+ int keylen, msglen;
+ unsigned char key[16], msg[64], tag[16];
+ } tests[] = {
+ { 16, 0,
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { 0x00 },
+ { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+ 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 }
+ },
+ { 16, 16,
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
+ { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+ 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c }
+ },
+ { 16, 40,
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 },
+ { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
+ 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 }
+ },
+ { 16, 64,
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+ { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+ 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe }
+ }
+
+ };
+ unsigned char out[16];
+ int x, err, idx;
+ unsigned long len;
+
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((idx = find_cipher("aes")) == -1) {
+ if ((idx = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ len = sizeof(out);
+ if ((err = omac_memory(idx, tests[x].key, tests[x].keylen, tests[x].msg, tests[x].msglen, out, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (compare_testvector(out, len, tests[x].tag, sizeof(tests[x].tag), "OMAC", x) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pelican/pelican.c b/Sources/libtomcrypt/mac/pelican/pelican.c
new file mode 100644
index 00000000..25592cc5
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pelican/pelican.c
@@ -0,0 +1,154 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pelican.c
+ Pelican MAC, initialize state, by Tom St Denis
+*/
+
+#ifdef LTC_PELICAN
+
+#define LTC_AES_TAB_C
+#define ENCRYPT_ONLY
+#define PELI_TAB
+#include "../../ciphers/aes/aes_tab.c"
+
+/**
+ Initialize a Pelican state
+ @param pelmac The Pelican state to initialize
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @return CRYPT_OK if successful
+*/
+int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen)
+{
+ int err;
+
+ LTC_ARGCHK(pelmac != NULL);
+ LTC_ARGCHK(key != NULL);
+
+#ifdef LTC_FAST
+ if (16 % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ if ((err = aes_setup(key, keylen, 0, &pelmac->K)) != CRYPT_OK) {
+ return err;
+ }
+
+ zeromem(pelmac->state, 16);
+ aes_ecb_encrypt(pelmac->state, pelmac->state, &pelmac->K);
+ pelmac->buflen = 0;
+
+ return CRYPT_OK;
+}
+
+static void s_four_rounds(pelican_state *pelmac)
+{
+ ulong32 s0, s1, s2, s3, t0, t1, t2, t3;
+ int r;
+
+ LOAD32H(s0, pelmac->state );
+ LOAD32H(s1, pelmac->state + 4);
+ LOAD32H(s2, pelmac->state + 8);
+ LOAD32H(s3, pelmac->state + 12);
+ for (r = 0; r < 4; r++) {
+ t0 =
+ Te0(LTC_BYTE(s0, 3)) ^
+ Te1(LTC_BYTE(s1, 2)) ^
+ Te2(LTC_BYTE(s2, 1)) ^
+ Te3(LTC_BYTE(s3, 0));
+ t1 =
+ Te0(LTC_BYTE(s1, 3)) ^
+ Te1(LTC_BYTE(s2, 2)) ^
+ Te2(LTC_BYTE(s3, 1)) ^
+ Te3(LTC_BYTE(s0, 0));
+ t2 =
+ Te0(LTC_BYTE(s2, 3)) ^
+ Te1(LTC_BYTE(s3, 2)) ^
+ Te2(LTC_BYTE(s0, 1)) ^
+ Te3(LTC_BYTE(s1, 0));
+ t3 =
+ Te0(LTC_BYTE(s3, 3)) ^
+ Te1(LTC_BYTE(s0, 2)) ^
+ Te2(LTC_BYTE(s1, 1)) ^
+ Te3(LTC_BYTE(s2, 0));
+ s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+ }
+ STORE32H(s0, pelmac->state );
+ STORE32H(s1, pelmac->state + 4);
+ STORE32H(s2, pelmac->state + 8);
+ STORE32H(s3, pelmac->state + 12);
+}
+
+/**
+ Process a block of text through Pelican
+ @param pelmac The Pelican MAC state
+ @param in The input
+ @param inlen The length input (octets)
+ @return CRYPT_OK on success
+ */
+int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen)
+{
+
+ LTC_ARGCHK(pelmac != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* check range */
+ if (pelmac->buflen < 0 || pelmac->buflen > 15) {
+ return CRYPT_INVALID_ARG;
+ }
+
+#ifdef LTC_FAST
+ if (pelmac->buflen == 0) {
+ while (inlen & ~15) {
+ int x;
+ for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pelmac->state + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)in + x));
+ }
+ s_four_rounds(pelmac);
+ in += 16;
+ inlen -= 16;
+ }
+ }
+#endif
+
+ while (inlen--) {
+ pelmac->state[pelmac->buflen++] ^= *in++;
+ if (pelmac->buflen == 16) {
+ s_four_rounds(pelmac);
+ pelmac->buflen = 0;
+ }
+ }
+ return CRYPT_OK;
+}
+
+/**
+ Terminate Pelican MAC
+ @param pelmac The Pelican MAC state
+ @param out [out] The TAG
+ @return CRYPT_OK on sucess
+*/
+int pelican_done(pelican_state *pelmac, unsigned char *out)
+{
+ LTC_ARGCHK(pelmac != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* check range */
+ if (pelmac->buflen < 0 || pelmac->buflen > 16) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (pelmac->buflen == 16) {
+ s_four_rounds(pelmac);
+ pelmac->buflen = 0;
+ }
+ pelmac->state[pelmac->buflen++] ^= 0x80;
+ aes_ecb_encrypt(pelmac->state, out, &pelmac->K);
+ aes_done(&pelmac->K);
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pelican/pelican_memory.c b/Sources/libtomcrypt/mac/pelican/pelican_memory.c
new file mode 100644
index 00000000..f67eaee2
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pelican/pelican_memory.c
@@ -0,0 +1,47 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pelican_memory.c
+ Pelican MAC, MAC a block of memory, by Tom St Denis
+*/
+
+#ifdef LTC_PELICAN
+
+/**
+ Pelican block of memory
+ @param key The key for the MAC
+ @param keylen The length of the key (octets)
+ @param in The input to MAC
+ @param inlen The length of the input (octets)
+ @param out [out] The output TAG
+ @return CRYPT_OK on success
+*/
+int pelican_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out)
+{
+ pelican_state *pel;
+ int err;
+
+ pel = XMALLOC(sizeof(*pel));
+ if (pel == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = pelican_init(pel, key, keylen)) != CRYPT_OK) {
+ XFREE(pel);
+ return err;
+ }
+ if ((err = pelican_process(pel, in ,inlen)) != CRYPT_OK) {
+ XFREE(pel);
+ return err;
+ }
+ err = pelican_done(pel, out);
+ XFREE(pel);
+ return err;
+}
+
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pelican/pelican_test.c b/Sources/libtomcrypt/mac/pelican/pelican_test.c
new file mode 100644
index 00000000..2ec696aa
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pelican/pelican_test.c
@@ -0,0 +1,103 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pelican_test.c
+ Pelican MAC, test, by Tom St Denis
+*/
+
+#ifdef LTC_PELICAN
+
+int pelican_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ unsigned char K[32], MSG[64], T[16];
+ int keylen, ptlen;
+ } tests[] = {
+/* K=16, M=0 */
+{
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
+ { 0 },
+ { 0xeb, 0x58, 0x37, 0x15, 0xf8, 0x34, 0xde, 0xe5,
+ 0xa4, 0xd1, 0x6e, 0xe4, 0xb9, 0xd7, 0x76, 0x0e, },
+ 16, 0
+},
+
+/* K=16, M=3 */
+{
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
+ { 0x00, 0x01, 0x02 },
+ { 0x1c, 0x97, 0x40, 0x60, 0x6c, 0x58, 0x17, 0x2d,
+ 0x03, 0x94, 0x19, 0x70, 0x81, 0xc4, 0x38, 0x54, },
+ 16, 3
+},
+
+/* K=16, M=16 */
+{
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
+ { 0x03, 0xcc, 0x46, 0xb8, 0xac, 0xa7, 0x9c, 0x36,
+ 0x1e, 0x8c, 0x6e, 0xa6, 0x7b, 0x89, 0x32, 0x49, },
+ 16, 16
+},
+
+/* K=16, M=32 */
+{
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
+ { 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 },
+ { 0x89, 0xcc, 0x36, 0x58, 0x1b, 0xdd, 0x4d, 0xb5,
+ 0x78, 0xbb, 0xac, 0xf0, 0xff, 0x8b, 0x08, 0x15, },
+ 16, 32
+},
+
+/* K=16, M=35 */
+{
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
+ { 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,
+ 0x20, 0x21, 0x23 },
+ { 0x4a, 0x7d, 0x45, 0x4d, 0xcd, 0xb5, 0xda, 0x8d,
+ 0x48, 0x78, 0x16, 0x48, 0x5d, 0x45, 0x95, 0x99, },
+ 16, 35
+},
+};
+ int x, err;
+ unsigned char out[16];
+ pelican_state pel;
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ if ((err = pelican_init(&pel, tests[x].K, tests[x].keylen)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = pelican_process(&pel, tests[x].MSG, tests[x].ptlen)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = pelican_done(&pel, out)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (compare_testvector(out, 16, tests[x].T, 16, "PELICAN", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pmac/pmac_done.c b/Sources/libtomcrypt/mac/pmac/pmac_done.c
new file mode 100644
index 00000000..222790d1
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pmac/pmac_done.c
@@ -0,0 +1,62 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pmac_done.c
+ PMAC implementation, terminate a session, by Tom St Denis
+*/
+
+#ifdef LTC_PMAC
+
+int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen)
+{
+ int err, x;
+
+ LTC_ARGCHK(pmac != NULL);
+ LTC_ARGCHK(out != NULL);
+ if ((err = cipher_is_valid(pmac->cipher_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) ||
+ (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* handle padding. If multiple xor in L/x */
+
+ if (pmac->buflen == pmac->block_len) {
+ /* xor Lr against the checksum */
+ for (x = 0; x < pmac->block_len; x++) {
+ pmac->checksum[x] ^= pmac->block[x] ^ pmac->Lr[x];
+ }
+ } else {
+ /* otherwise xor message bytes then the 0x80 byte */
+ for (x = 0; x < pmac->buflen; x++) {
+ pmac->checksum[x] ^= pmac->block[x];
+ }
+ pmac->checksum[x] ^= 0x80;
+ }
+
+ /* encrypt it */
+ if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(pmac->checksum, pmac->checksum, &pmac->key)) != CRYPT_OK) {
+ return err;
+ }
+ cipher_descriptor[pmac->cipher_idx].done(&pmac->key);
+
+ /* store it */
+ for (x = 0; x < pmac->block_len && x < (int)*outlen; x++) {
+ out[x] = pmac->checksum[x];
+ }
+ *outlen = x;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(pmac, sizeof(*pmac));
+#endif
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/pmac/pmac_file.c b/Sources/libtomcrypt/mac/pmac/pmac_file.c
new file mode 100644
index 00000000..fca9b001
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pmac/pmac_file.c
@@ -0,0 +1,88 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pmac_file.c
+ PMAC implementation, process a file, by Tom St Denis
+*/
+
+#ifdef LTC_PMAC
+
+/**
+ PMAC a file
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param filename The name of the file to send through PMAC
+ @param out [out] Destination for the authentication tag
+ @param outlen [in/out] Max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int pmac_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen)
+{
+#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(cipher);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(filename);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
+ return CRYPT_NOP;
+#else
+ size_t x;
+ int err;
+ pmac_state pmac;
+ FILE *in;
+ unsigned char *buf;
+
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(filename != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ in = fopen(filename, "rb");
+ if (in == NULL) {
+ err = CRYPT_FILE_NOTFOUND;
+ goto LBL_ERR;
+ }
+
+ do {
+ x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+ if ((err = pmac_process(&pmac, buf, (unsigned long)x)) != CRYPT_OK) {
+ fclose(in);
+ goto LBL_CLEANBUF;
+ }
+ } while (x == LTC_FILE_READ_BUFSIZE);
+
+ if (fclose(in) != 0) {
+ err = CRYPT_ERROR;
+ goto LBL_CLEANBUF;
+ }
+
+ err = pmac_done(&pmac, out, outlen);
+
+LBL_CLEANBUF:
+ zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&pmac, sizeof(pmac_state));
+#endif
+ XFREE(buf);
+ return err;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pmac/pmac_init.c b/Sources/libtomcrypt/mac/pmac/pmac_init.c
new file mode 100644
index 00000000..1af9c295
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pmac/pmac_init.c
@@ -0,0 +1,138 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pmac_init.c
+ PMAC implementation, initialize state, by Tom St Denis
+*/
+
+#ifdef LTC_PMAC
+
+static const struct {
+ int len;
+ unsigned char poly_div[MAXBLOCKSIZE],
+ poly_mul[MAXBLOCKSIZE];
+} polys[] = {
+{
+ 8,
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }
+}, {
+ 16,
+ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }
+}
+};
+
+/**
+ Initialize a PMAC state
+ @param pmac The PMAC state to initialize
+ @param cipher The index of the desired cipher
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @return CRYPT_OK if successful
+*/
+int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen)
+{
+ int poly, x, y, m, err;
+ unsigned char *L;
+
+ LTC_ARGCHK(pmac != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* valid cipher? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* determine which polys to use */
+ pmac->block_len = cipher_descriptor[cipher].block_length;
+ for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) {
+ if (polys[poly].len == pmac->block_len) {
+ break;
+ }
+ }
+ if (poly >= (int)(sizeof(polys)/sizeof(polys[0]))) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (polys[poly].len != pmac->block_len) {
+ return CRYPT_INVALID_ARG;
+ }
+
+#ifdef LTC_FAST
+ if (pmac->block_len % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+
+ /* schedule the key */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* allocate L */
+ L = XMALLOC(pmac->block_len);
+ if (L == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* find L = E[0] */
+ zeromem(L, pmac->block_len);
+ if ((err = cipher_descriptor[cipher].ecb_encrypt(L, L, &pmac->key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* find Ls[i] = L << i for i == 0..31 */
+ XMEMCPY(pmac->Ls[0], L, pmac->block_len);
+ for (x = 1; x < 32; x++) {
+ m = pmac->Ls[x-1][0] >> 7;
+ for (y = 0; y < pmac->block_len-1; y++) {
+ pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255;
+ }
+ pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255;
+
+ if (m == 1) {
+ for (y = 0; y < pmac->block_len; y++) {
+ pmac->Ls[x][y] ^= polys[poly].poly_mul[y];
+ }
+ }
+ }
+
+ /* find Lr = L / x */
+ m = L[pmac->block_len-1] & 1;
+
+ /* shift right */
+ for (x = pmac->block_len - 1; x > 0; x--) {
+ pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255;
+ }
+ pmac->Lr[0] = L[0] >> 1;
+
+ if (m == 1) {
+ for (x = 0; x < pmac->block_len; x++) {
+ pmac->Lr[x] ^= polys[poly].poly_div[x];
+ }
+ }
+
+ /* zero buffer, counters, etc... */
+ pmac->block_index = 1;
+ pmac->cipher_idx = cipher;
+ pmac->buflen = 0;
+ zeromem(pmac->block, sizeof(pmac->block));
+ zeromem(pmac->Li, sizeof(pmac->Li));
+ zeromem(pmac->checksum, sizeof(pmac->checksum));
+ err = CRYPT_OK;
+error:
+#ifdef LTC_CLEAN_STACK
+ zeromem(L, pmac->block_len);
+#endif
+
+ XFREE(L);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pmac/pmac_memory.c b/Sources/libtomcrypt/mac/pmac/pmac_memory.c
new file mode 100644
index 00000000..46715471
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pmac/pmac_memory.c
@@ -0,0 +1,62 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pmac_memory.c
+ PMAC implementation, process a block of memory, by Tom St Denis
+*/
+
+#ifdef LTC_PMAC
+
+/**
+ PMAC a block of memory
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param in The data you wish to send through PMAC
+ @param inlen The length of data you wish to send through PMAC (octets)
+ @param out [out] Destination for the authentication tag
+ @param outlen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful
+*/
+int pmac_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ int err;
+ pmac_state *pmac;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* allocate ram for pmac state */
+ pmac = XMALLOC(sizeof(pmac_state));
+ if (pmac == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = pmac_process(pmac, in, inlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(pmac, sizeof(pmac_state));
+#endif
+
+ XFREE(pmac);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pmac/pmac_memory_multi.c b/Sources/libtomcrypt/mac/pmac/pmac_memory_multi.c
new file mode 100644
index 00000000..94d450cc
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pmac/pmac_memory_multi.c
@@ -0,0 +1,77 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+/**
+ @file pmac_memory_multi.c
+ PMAC implementation, process multiple blocks of memory, by Tom St Denis
+*/
+
+#ifdef LTC_PMAC
+
+/**
+ PMAC multiple blocks of memory
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param out [out] Destination for the authentication tag
+ @param outlen [in/out] The max size and resulting size of the authentication tag
+ @param in The data you wish to send through PMAC
+ @param inlen The length of data you wish to send through PMAC (octets)
+ @param ... tuples of (data,len) pairs to PMAC, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int pmac_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+{
+ int err;
+ pmac_state *pmac;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* allocate ram for pmac state */
+ pmac = XMALLOC(sizeof(pmac_state));
+ if (pmac == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ for (;;) {
+ /* process buf */
+ if ((err = pmac_process(pmac, curptr, curlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* step to next */
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) {
+ break;
+ }
+ curlen = va_arg(args, unsigned long);
+ }
+ if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(pmac, sizeof(pmac_state));
+#endif
+ XFREE(pmac);
+ va_end(args);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pmac/pmac_ntz.c b/Sources/libtomcrypt/mac/pmac/pmac_ntz.c
new file mode 100644
index 00000000..ed71f331
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pmac/pmac_ntz.c
@@ -0,0 +1,27 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pmac_ntz.c
+ PMAC implementation, internal function, by Tom St Denis
+*/
+
+#ifdef LTC_PMAC
+
+/**
+ Internal PMAC function
+*/
+int pmac_ntz(unsigned long x)
+{
+ int c;
+ x &= 0xFFFFFFFFUL;
+ c = 0;
+ while ((x & 1) == 0) {
+ ++c;
+ x >>= 1;
+ }
+ return c;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pmac/pmac_process.c b/Sources/libtomcrypt/mac/pmac/pmac_process.c
new file mode 100644
index 00000000..3f38e8a7
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pmac/pmac_process.c
@@ -0,0 +1,88 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pmac_process.c
+ PMAC implementation, process data, by Tom St Denis
+*/
+
+
+#ifdef LTC_PMAC
+
+/**
+ Process data in a PMAC stream
+ @param pmac The PMAC state
+ @param in The data to send through PMAC
+ @param inlen The length of the data to send through PMAC
+ @return CRYPT_OK if successful
+*/
+int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen)
+{
+ int err, n;
+ unsigned long x;
+ unsigned char Z[MAXBLOCKSIZE];
+
+ LTC_ARGCHK(pmac != NULL);
+ LTC_ARGCHK(in != NULL);
+ if ((err = cipher_is_valid(pmac->cipher_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) ||
+ (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+#ifdef LTC_FAST
+ if (pmac->buflen == 0 && inlen > 16) {
+ unsigned long y;
+ for (x = 0; x < (inlen - 16); x += 16) {
+ pmac_shift_xor(pmac);
+ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&Z[y])) = *(LTC_FAST_TYPE_PTR_CAST(&in[y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&pmac->Li[y]));
+ }
+ if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) {
+ return err;
+ }
+ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&pmac->checksum[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&Z[y]));
+ }
+ in += 16;
+ }
+ inlen -= x;
+ }
+#endif
+
+ while (inlen != 0) {
+ /* ok if the block is full we xor in prev, encrypt and replace prev */
+ if (pmac->buflen == pmac->block_len) {
+ pmac_shift_xor(pmac);
+ for (x = 0; x < (unsigned long)pmac->block_len; x++) {
+ Z[x] = pmac->Li[x] ^ pmac->block[x];
+ }
+ if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) {
+ return err;
+ }
+ for (x = 0; x < (unsigned long)pmac->block_len; x++) {
+ pmac->checksum[x] ^= Z[x];
+ }
+ pmac->buflen = 0;
+ }
+
+ /* add bytes */
+ n = MIN(inlen, (unsigned long)(pmac->block_len - pmac->buflen));
+ XMEMCPY(pmac->block + pmac->buflen, in, n);
+ pmac->buflen += n;
+ inlen -= n;
+ in += n;
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(Z, sizeof(Z));
+#endif
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pmac/pmac_shift_xor.c b/Sources/libtomcrypt/mac/pmac/pmac_shift_xor.c
new file mode 100644
index 00000000..ad97fa8b
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pmac/pmac_shift_xor.c
@@ -0,0 +1,32 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pmac_shift_xor.c
+ PMAC implementation, internal function, by Tom St Denis
+*/
+
+#ifdef LTC_PMAC
+
+/**
+ Internal function. Performs the state update (adding correct multiple)
+ @param pmac The PMAC state.
+*/
+void pmac_shift_xor(pmac_state *pmac)
+{
+ int x, y;
+ y = pmac_ntz(pmac->block_index++);
+#ifdef LTC_FAST
+ for (x = 0; x < pmac->block_len; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pmac->Li + x)) ^=
+ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pmac->Ls[y] + x));
+ }
+#else
+ for (x = 0; x < pmac->block_len; x++) {
+ pmac->Li[x] ^= pmac->Ls[y][x];
+ }
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/pmac/pmac_test.c b/Sources/libtomcrypt/mac/pmac/pmac_test.c
new file mode 100644
index 00000000..3ccf06e2
--- /dev/null
+++ b/Sources/libtomcrypt/mac/pmac/pmac_test.c
@@ -0,0 +1,144 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pmac_test.c
+ PMAC implementation, self-test, by Tom St Denis
+*/
+
+
+#ifdef LTC_PMAC
+
+/**
+ Test the LTC_OMAC implementation
+ @return CRYPT_OK if successful, CRYPT_NOP if testing has been disabled
+*/
+int pmac_test(void)
+{
+#if !defined(LTC_TEST)
+ return CRYPT_NOP;
+#else
+ static const struct {
+ int msglen;
+ unsigned char key[16], msg[34], tag[16];
+ } tests[] = {
+
+ /* PMAC-AES-128-0B */
+{
+ 0,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* msg */
+ { 0x00 },
+ /* tag */
+ { 0x43, 0x99, 0x57, 0x2c, 0xd6, 0xea, 0x53, 0x41,
+ 0xb8, 0xd3, 0x58, 0x76, 0xa7, 0x09, 0x8a, 0xf7 }
+},
+
+ /* PMAC-AES-128-3B */
+{
+ 3,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* msg */
+ { 0x00, 0x01, 0x02 },
+ /* tag */
+ { 0x25, 0x6b, 0xa5, 0x19, 0x3c, 0x1b, 0x99, 0x1b,
+ 0x4d, 0xf0, 0xc5, 0x1f, 0x38, 0x8a, 0x9e, 0x27 }
+},
+
+ /* PMAC-AES-128-16B */
+{
+ 16,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* msg */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* tag */
+ { 0xeb, 0xbd, 0x82, 0x2f, 0xa4, 0x58, 0xda, 0xf6,
+ 0xdf, 0xda, 0xd7, 0xc2, 0x7d, 0xa7, 0x63, 0x38 }
+},
+
+ /* PMAC-AES-128-20B */
+{
+ 20,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* msg */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13 },
+ /* tag */
+ { 0x04, 0x12, 0xca, 0x15, 0x0b, 0xbf, 0x79, 0x05,
+ 0x8d, 0x8c, 0x75, 0xa5, 0x8c, 0x99, 0x3f, 0x55 }
+},
+
+ /* PMAC-AES-128-32B */
+{
+ 32,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* msg */
+ { 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 },
+ /* tag */
+ { 0xe9, 0x7a, 0xc0, 0x4e, 0x9e, 0x5e, 0x33, 0x99,
+ 0xce, 0x53, 0x55, 0xcd, 0x74, 0x07, 0xbc, 0x75 }
+},
+
+ /* PMAC-AES-128-34B */
+{
+ 34,
+ /* key */
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ /* msg */
+ { 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,
+ 0x20, 0x21 },
+ /* tag */
+ { 0x5c, 0xba, 0x7d, 0x5e, 0xb2, 0x4f, 0x7c, 0x86,
+ 0xcc, 0xc5, 0x46, 0x04, 0xe5, 0x3d, 0x55, 0x12 }
+}
+
+};
+ int err, x, idx;
+ unsigned long len;
+ unsigned char outtag[MAXBLOCKSIZE];
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((idx = find_cipher("aes")) == -1) {
+ if ((idx = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ len = sizeof(outtag);
+ if ((err = pmac_memory(idx, tests[x].key, 16, tests[x].msg, tests[x].msglen, outtag, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "PMAC", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif /* LTC_TEST */
+}
+
+#endif /* PMAC_MODE */
+
+
+
diff --git a/Sources/libtomcrypt/mac/poly1305/poly1305.c b/Sources/libtomcrypt/mac/poly1305/poly1305.c
new file mode 100644
index 00000000..32cdb550
--- /dev/null
+++ b/Sources/libtomcrypt/mac/poly1305/poly1305.c
@@ -0,0 +1,258 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * Public Domain poly1305 from Andrew Moon
+ * https://github.com/floodyberry/poly1305-donna
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_POLY1305
+
+/* internal only */
+static void s_poly1305_block(poly1305_state *st, const unsigned char *in, unsigned long inlen)
+{
+ const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */
+ ulong32 r0,r1,r2,r3,r4;
+ ulong32 s1,s2,s3,s4;
+ ulong32 h0,h1,h2,h3,h4;
+ ulong32 tmp;
+ ulong64 d0,d1,d2,d3,d4;
+ ulong32 c;
+
+ r0 = st->r[0];
+ r1 = st->r[1];
+ r2 = st->r[2];
+ r3 = st->r[3];
+ r4 = st->r[4];
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ h0 = st->h[0];
+ h1 = st->h[1];
+ h2 = st->h[2];
+ h3 = st->h[3];
+ h4 = st->h[4];
+
+ while (inlen >= 16) {
+ /* h += in[i] */
+ LOAD32L(tmp, in+ 0); h0 += (tmp ) & 0x3ffffff;
+ LOAD32L(tmp, in+ 3); h1 += (tmp >> 2) & 0x3ffffff;
+ LOAD32L(tmp, in+ 6); h2 += (tmp >> 4) & 0x3ffffff;
+ LOAD32L(tmp, in+ 9); h3 += (tmp >> 6) & 0x3ffffff;
+ LOAD32L(tmp, in+12); h4 += (tmp >> 8) | hibit;
+
+ /* h *= r */
+ d0 = ((ulong64)h0 * r0) + ((ulong64)h1 * s4) + ((ulong64)h2 * s3) + ((ulong64)h3 * s2) + ((ulong64)h4 * s1);
+ d1 = ((ulong64)h0 * r1) + ((ulong64)h1 * r0) + ((ulong64)h2 * s4) + ((ulong64)h3 * s3) + ((ulong64)h4 * s2);
+ d2 = ((ulong64)h0 * r2) + ((ulong64)h1 * r1) + ((ulong64)h2 * r0) + ((ulong64)h3 * s4) + ((ulong64)h4 * s3);
+ d3 = ((ulong64)h0 * r3) + ((ulong64)h1 * r2) + ((ulong64)h2 * r1) + ((ulong64)h3 * r0) + ((ulong64)h4 * s4);
+ d4 = ((ulong64)h0 * r4) + ((ulong64)h1 * r3) + ((ulong64)h2 * r2) + ((ulong64)h3 * r1) + ((ulong64)h4 * r0);
+
+ /* (partial) h %= p */
+ c = (ulong32)(d0 >> 26); h0 = (ulong32)d0 & 0x3ffffff;
+ d1 += c; c = (ulong32)(d1 >> 26); h1 = (ulong32)d1 & 0x3ffffff;
+ d2 += c; c = (ulong32)(d2 >> 26); h2 = (ulong32)d2 & 0x3ffffff;
+ d3 += c; c = (ulong32)(d3 >> 26); h3 = (ulong32)d3 & 0x3ffffff;
+ d4 += c; c = (ulong32)(d4 >> 26); h4 = (ulong32)d4 & 0x3ffffff;
+ h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff;
+ h1 += c;
+
+ in += 16;
+ inlen -= 16;
+ }
+
+ st->h[0] = h0;
+ st->h[1] = h1;
+ st->h[2] = h2;
+ st->h[3] = h3;
+ st->h[4] = h4;
+}
+
+/**
+ Initialize an POLY1305 context.
+ @param st The POLY1305 state
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @return CRYPT_OK if successful
+*/
+int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen)
+{
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(keylen == 32);
+
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+ LOAD32L(st->r[0], key + 0); st->r[0] = (st->r[0] ) & 0x3ffffff;
+ LOAD32L(st->r[1], key + 3); st->r[1] = (st->r[1] >> 2) & 0x3ffff03;
+ LOAD32L(st->r[2], key + 6); st->r[2] = (st->r[2] >> 4) & 0x3ffc0ff;
+ LOAD32L(st->r[3], key + 9); st->r[3] = (st->r[3] >> 6) & 0x3f03fff;
+ LOAD32L(st->r[4], key + 12); st->r[4] = (st->r[4] >> 8) & 0x00fffff;
+
+ /* h = 0 */
+ st->h[0] = 0;
+ st->h[1] = 0;
+ st->h[2] = 0;
+ st->h[3] = 0;
+ st->h[4] = 0;
+
+ /* save pad for later */
+ LOAD32L(st->pad[0], key + 16);
+ LOAD32L(st->pad[1], key + 20);
+ LOAD32L(st->pad[2], key + 24);
+ LOAD32L(st->pad[3], key + 28);
+
+ st->leftover = 0;
+ st->final = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process data through POLY1305
+ @param st The POLY1305 state
+ @param in The data to send through HMAC
+ @param inlen The length of the data to HMAC (octets)
+ @return CRYPT_OK if successful
+*/
+int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen)
+{
+ unsigned long i;
+
+ if (inlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* handle leftover */
+ if (st->leftover) {
+ unsigned long want = (16 - st->leftover);
+ if (want > inlen) want = inlen;
+ for (i = 0; i < want; i++) st->buffer[st->leftover + i] = in[i];
+ inlen -= want;
+ in += want;
+ st->leftover += want;
+ if (st->leftover < 16) return CRYPT_OK;
+ s_poly1305_block(st, st->buffer, 16);
+ st->leftover = 0;
+ }
+
+ /* process full blocks */
+ if (inlen >= 16) {
+ unsigned long want = (inlen & ~(16 - 1));
+ s_poly1305_block(st, in, want);
+ in += want;
+ inlen -= want;
+ }
+
+ /* store leftover */
+ if (inlen) {
+ for (i = 0; i < inlen; i++) st->buffer[st->leftover + i] = in[i];
+ st->leftover += inlen;
+ }
+ return CRYPT_OK;
+}
+
+/**
+ Terminate a POLY1305 session
+ @param st The POLY1305 state
+ @param mac [out] The destination of the POLY1305 authentication tag
+ @param maclen [in/out] The max size and resulting size of the POLY1305 authentication tag
+ @return CRYPT_OK if successful
+*/
+int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen)
+{
+ ulong32 h0,h1,h2,h3,h4,c;
+ ulong32 g0,g1,g2,g3,g4;
+ ulong64 f;
+ ulong32 mask;
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+ LTC_ARGCHK(*maclen >= 16);
+
+ /* process the remaining block */
+ if (st->leftover) {
+ unsigned long i = st->leftover;
+ st->buffer[i++] = 1;
+ for (; i < 16; i++) st->buffer[i] = 0;
+ st->final = 1;
+ s_poly1305_block(st, st->buffer, 16);
+ }
+
+ /* fully carry h */
+ h0 = st->h[0];
+ h1 = st->h[1];
+ h2 = st->h[2];
+ h3 = st->h[3];
+ h4 = st->h[4];
+
+ c = h1 >> 26; h1 = h1 & 0x3ffffff;
+ h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
+ h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
+ h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
+ h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
+ h1 += c;
+
+ /* compute h + -p */
+ g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
+ g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
+ g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
+ g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
+ g4 = h4 + c - (1UL << 26);
+
+ /* select h if h < p, or h + -p if h >= p */
+ mask = (g4 >> 31) - 1;
+ g0 &= mask;
+ g1 &= mask;
+ g2 &= mask;
+ g3 &= mask;
+ g4 &= mask;
+ mask = ~mask;
+ h0 = (h0 & mask) | g0;
+ h1 = (h1 & mask) | g1;
+ h2 = (h2 & mask) | g2;
+ h3 = (h3 & mask) | g3;
+ h4 = (h4 & mask) | g4;
+
+ /* h = h % (2^128) */
+ h0 = ((h0 ) | (h1 << 26)) & 0xffffffff;
+ h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
+ h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
+ h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
+
+ /* mac = (h + pad) % (2^128) */
+ f = (ulong64)h0 + st->pad[0] ; h0 = (ulong32)f;
+ f = (ulong64)h1 + st->pad[1] + (f >> 32); h1 = (ulong32)f;
+ f = (ulong64)h2 + st->pad[2] + (f >> 32); h2 = (ulong32)f;
+ f = (ulong64)h3 + st->pad[3] + (f >> 32); h3 = (ulong32)f;
+
+ STORE32L(h0, mac + 0);
+ STORE32L(h1, mac + 4);
+ STORE32L(h2, mac + 8);
+ STORE32L(h3, mac + 12);
+
+ /* zero out the state */
+ st->h[0] = 0;
+ st->h[1] = 0;
+ st->h[2] = 0;
+ st->h[3] = 0;
+ st->h[4] = 0;
+ st->r[0] = 0;
+ st->r[1] = 0;
+ st->r[2] = 0;
+ st->r[3] = 0;
+ st->r[4] = 0;
+ st->pad[0] = 0;
+ st->pad[1] = 0;
+ st->pad[2] = 0;
+ st->pad[3] = 0;
+
+ *maclen = 16;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/poly1305/poly1305_file.c b/Sources/libtomcrypt/mac/poly1305/poly1305_file.c
new file mode 100644
index 00000000..e09c9942
--- /dev/null
+++ b/Sources/libtomcrypt/mac/poly1305/poly1305_file.c
@@ -0,0 +1,83 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * Public Domain poly1305 from Andrew Moon
+ * https://github.com/floodyberry/poly1305-donna
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_POLY1305
+
+/**
+ POLY1305 a file
+ @param fname The name of the file you wish to POLY1305
+ @param key The secret key
+ @param keylen The length of the secret key
+ @param mac [out] The POLY1305 authentication tag
+ @param maclen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen)
+{
+#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(mac);
+ LTC_UNUSED_PARAM(maclen);
+ return CRYPT_NOP;
+#else
+ poly1305_state st;
+ FILE *in;
+ unsigned char *buf;
+ size_t x;
+ int err;
+
+ LTC_ARGCHK(fname != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+
+ if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ in = fopen(fname, "rb");
+ if (in == NULL) {
+ err = CRYPT_FILE_NOTFOUND;
+ goto LBL_ERR;
+ }
+
+ do {
+ x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+ if ((err = poly1305_process(&st, buf, (unsigned long)x)) != CRYPT_OK) {
+ fclose(in);
+ goto LBL_CLEANBUF;
+ }
+ } while (x == LTC_FILE_READ_BUFSIZE);
+
+ if (fclose(in) != 0) {
+ err = CRYPT_ERROR;
+ goto LBL_CLEANBUF;
+ }
+
+ err = poly1305_done(&st, mac, maclen);
+
+LBL_CLEANBUF:
+ zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(poly1305_state));
+#endif
+ XFREE(buf);
+ return err;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/poly1305/poly1305_memory.c b/Sources/libtomcrypt/mac/poly1305/poly1305_memory.c
new file mode 100644
index 00000000..8a9fea69
--- /dev/null
+++ b/Sources/libtomcrypt/mac/poly1305/poly1305_memory.c
@@ -0,0 +1,43 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * Public Domain poly1305 from Andrew Moon
+ * https://github.com/floodyberry/poly1305-donna
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_POLY1305
+
+/**
+ POLY1305 a block of memory to produce the authentication tag
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param in The data to POLY1305
+ @param inlen The length of the data to POLY1305 (octets)
+ @param mac [out] Destination of the authentication tag
+ @param maclen [in/out] Max size and resulting size of authentication tag
+ @return CRYPT_OK if successful
+*/
+int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen)
+{
+ poly1305_state st;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+
+ if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = poly1305_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
+ err = poly1305_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(poly1305_state));
+#endif
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/poly1305/poly1305_memory_multi.c b/Sources/libtomcrypt/mac/poly1305/poly1305_memory_multi.c
new file mode 100644
index 00000000..6bd61df0
--- /dev/null
+++ b/Sources/libtomcrypt/mac/poly1305/poly1305_memory_multi.c
@@ -0,0 +1,57 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * Public Domain poly1305 from Andrew Moon
+ * https://github.com/floodyberry/poly1305-donna
+ */
+
+#include "tomcrypt_private.h"
+#include
+
+#ifdef LTC_POLY1305
+
+/**
+ POLY1305 multiple blocks of memory to produce the authentication tag
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param mac [out] Destination of the authentication tag
+ @param maclen [in/out] Max size and resulting size of authentication tag
+ @param in The data to POLY1305
+ @param inlen The length of the data to POLY1305 (octets)
+ @param ... tuples of (data,len) pairs to POLY1305, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...)
+{
+ poly1305_state st;
+ int err;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(mac != NULL);
+ LTC_ARGCHK(maclen != NULL);
+
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; }
+ for (;;) {
+ if ((err = poly1305_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; }
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) break;
+ curlen = va_arg(args, unsigned long);
+ }
+ err = poly1305_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&st, sizeof(poly1305_state));
+#endif
+ va_end(args);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/poly1305/poly1305_test.c b/Sources/libtomcrypt/mac/poly1305/poly1305_test.c
new file mode 100644
index 00000000..f9b3f75e
--- /dev/null
+++ b/Sources/libtomcrypt/mac/poly1305/poly1305_test.c
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * Public Domain poly1305 from Andrew Moon
+ * https://github.com/floodyberry/poly1305-donna
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_POLY1305
+
+int poly1305_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ /* https://tools.ietf.org/html/rfc7539#section-2.5.2 */
+ unsigned char k[] = { 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 tag[] = { 0xA8, 0x06, 0x1D, 0xC1, 0x30, 0x51, 0x36, 0xC6, 0xC2, 0x2B, 0x8B, 0xAF, 0x0C, 0x01, 0x27, 0xA9 };
+ char m[] = "Cryptographic Forum Research Group";
+ unsigned long len = 16, mlen = XSTRLEN(m);
+ unsigned char out[1000];
+ poly1305_state st;
+ int err;
+
+ /* process piece by piece */
+ if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err;
+ if ((err = poly1305_process(&st, (unsigned char*)m, 5)) != CRYPT_OK) return err;
+ if ((err = poly1305_process(&st, (unsigned char*)m + 5, 4)) != CRYPT_OK) return err;
+ if ((err = poly1305_process(&st, (unsigned char*)m + 9, 3)) != CRYPT_OK) return err;
+ if ((err = poly1305_process(&st, (unsigned char*)m + 12, 2)) != CRYPT_OK) return err;
+ if ((err = poly1305_process(&st, (unsigned char*)m + 14, 1)) != CRYPT_OK) return err;
+ if ((err = poly1305_process(&st, (unsigned char*)m + 15, mlen - 15)) != CRYPT_OK) return err;
+ if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV1", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+ /* process in one go */
+ if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err;
+ if ((err = poly1305_process(&st, (unsigned char*)m, mlen)) != CRYPT_OK) return err;
+ if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV2", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/xcbc/xcbc_done.c b/Sources/libtomcrypt/mac/xcbc/xcbc_done.c
new file mode 100644
index 00000000..7da72f38
--- /dev/null
+++ b/Sources/libtomcrypt/mac/xcbc/xcbc_done.c
@@ -0,0 +1,65 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file xcbc_done.c
+ XCBC Support, terminate the state
+*/
+
+#ifdef LTC_XCBC
+
+/** Terminate the XCBC-MAC state
+ @param xcbc XCBC state to terminate
+ @param out [out] Destination for the MAC tag
+ @param outlen [in/out] Destination size and final tag size
+ Return CRYPT_OK on success
+*/
+int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen)
+{
+ int err, x;
+ LTC_ARGCHK(xcbc != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* check structure */
+ if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher].block_length) || (xcbc->blocksize < 0) ||
+ (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* which key do we use? */
+ if (xcbc->buflen == xcbc->blocksize) {
+ /* k2 */
+ for (x = 0; x < xcbc->blocksize; x++) {
+ xcbc->IV[x] ^= xcbc->K[1][x];
+ }
+ } else {
+ xcbc->IV[xcbc->buflen] ^= 0x80;
+ /* k3 */
+ for (x = 0; x < xcbc->blocksize; x++) {
+ xcbc->IV[x] ^= xcbc->K[2][x];
+ }
+ }
+
+ /* encrypt */
+ cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key);
+ cipher_descriptor[xcbc->cipher].done(&xcbc->key);
+
+ /* extract tag */
+ for (x = 0; x < xcbc->blocksize && (unsigned long)x < *outlen; x++) {
+ out[x] = xcbc->IV[x];
+ }
+ *outlen = x;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(xcbc, sizeof(*xcbc));
+#endif
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/xcbc/xcbc_file.c b/Sources/libtomcrypt/mac/xcbc/xcbc_file.c
new file mode 100644
index 00000000..d8612df4
--- /dev/null
+++ b/Sources/libtomcrypt/mac/xcbc/xcbc_file.c
@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file xcbc_file.c
+ XCBC support, process a file, Tom St Denis
+*/
+
+#ifdef LTC_XCBC
+
+/**
+ XCBC a file
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param filename The name of the file you wish to XCBC
+ @param out [out] Where the authentication tag is to be stored
+ @param outlen [in/out] The max size and resulting size of the authentication tag
+ @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int xcbc_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen)
+{
+#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(cipher);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(filename);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
+ return CRYPT_NOP;
+#else
+ size_t x;
+ int err;
+ xcbc_state xcbc;
+ FILE *in;
+ unsigned char *buf;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(filename != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = xcbc_init(&xcbc, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ in = fopen(filename, "rb");
+ if (in == NULL) {
+ err = CRYPT_FILE_NOTFOUND;
+ goto LBL_ERR;
+ }
+
+ do {
+ x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+ if ((err = xcbc_process(&xcbc, buf, (unsigned long)x)) != CRYPT_OK) {
+ fclose(in);
+ goto LBL_CLEANBUF;
+ }
+ } while (x == LTC_FILE_READ_BUFSIZE);
+
+ if (fclose(in) != 0) {
+ err = CRYPT_ERROR;
+ goto LBL_CLEANBUF;
+ }
+
+ err = xcbc_done(&xcbc, out, outlen);
+
+LBL_CLEANBUF:
+ zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(&xcbc, sizeof(xcbc_state));
+#endif
+ XFREE(buf);
+ return err;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/xcbc/xcbc_init.c b/Sources/libtomcrypt/mac/xcbc/xcbc_init.c
new file mode 100644
index 00000000..3e4044a4
--- /dev/null
+++ b/Sources/libtomcrypt/mac/xcbc/xcbc_init.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file xcbc_init.c
+ XCBC Support, start an XCBC state
+*/
+
+#ifdef LTC_XCBC
+
+/** Initialize XCBC-MAC state
+ @param xcbc [out] XCBC state to initialize
+ @param cipher Index of cipher to use
+ @param key [in] Secret key
+ @param keylen Length of secret key in octets
+ Return CRYPT_OK on success
+*/
+int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen)
+{
+ int x, y, err;
+ symmetric_key *skey;
+ unsigned long k1;
+
+ LTC_ARGCHK(xcbc != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* schedule the key */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+#ifdef LTC_FAST
+ if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ skey = NULL;
+
+ /* are we in pure XCBC mode with three keys? */
+ if (keylen & LTC_XCBC_PURE) {
+ keylen &= ~LTC_XCBC_PURE;
+
+ if (keylen < 2UL*cipher_descriptor[cipher].block_length) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ k1 = keylen - 2*cipher_descriptor[cipher].block_length;
+ XMEMCPY(xcbc->K[0], key, k1);
+ XMEMCPY(xcbc->K[1], key+k1, cipher_descriptor[cipher].block_length);
+ XMEMCPY(xcbc->K[2], key+k1 + cipher_descriptor[cipher].block_length, cipher_descriptor[cipher].block_length);
+ } else {
+ /* use the key expansion */
+ k1 = cipher_descriptor[cipher].block_length;
+
+ /* schedule the user key */
+ skey = XCALLOC(1, sizeof(*skey));
+ if (skey == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) {
+ goto done;
+ }
+
+ /* make the three keys */
+ for (y = 0; y < 3; y++) {
+ for (x = 0; x < cipher_descriptor[cipher].block_length; x++) {
+ xcbc->K[y][x] = y + 1;
+ }
+ cipher_descriptor[cipher].ecb_encrypt(xcbc->K[y], xcbc->K[y], skey);
+ }
+ }
+
+ /* setup K1 */
+ err = cipher_descriptor[cipher].setup(xcbc->K[0], k1, 0, &xcbc->key);
+
+ /* setup struct */
+ zeromem(xcbc->IV, cipher_descriptor[cipher].block_length);
+ xcbc->blocksize = cipher_descriptor[cipher].block_length;
+ xcbc->cipher = cipher;
+ xcbc->buflen = 0;
+done:
+ cipher_descriptor[cipher].done(skey);
+ if (skey != NULL) {
+#ifdef LTC_CLEAN_STACK
+ zeromem(skey, sizeof(*skey));
+#endif
+ XFREE(skey);
+ }
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/xcbc/xcbc_memory.c b/Sources/libtomcrypt/mac/xcbc/xcbc_memory.c
new file mode 100644
index 00000000..bd7f3887
--- /dev/null
+++ b/Sources/libtomcrypt/mac/xcbc/xcbc_memory.c
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file xcbc_process.c
+ XCBC Support, XCBC-MAC a block of memory
+*/
+
+#ifdef LTC_XCBC
+
+/** XCBC-MAC a block of memory
+ @param cipher Index of cipher to use
+ @param key [in] Secret key
+ @param keylen Length of key in octets
+ @param in [in] Message to MAC
+ @param inlen Length of input in octets
+ @param out [out] Destination for the MAC tag
+ @param outlen [in/out] Output size and final tag size
+ Return CRYPT_OK on success.
+*/
+int xcbc_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ xcbc_state *xcbc;
+ int err;
+
+ /* is the cipher valid? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* Use accelerator if found */
+ if (cipher_descriptor[cipher].xcbc_memory != NULL) {
+ return cipher_descriptor[cipher].xcbc_memory(key, keylen, in, inlen, out, outlen);
+ }
+
+ xcbc = XCALLOC(1, sizeof(*xcbc));
+ if (xcbc == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) {
+ goto done;
+ }
+
+ if ((err = xcbc_process(xcbc, in, inlen)) != CRYPT_OK) {
+ goto done;
+ }
+
+ err = xcbc_done(xcbc, out, outlen);
+done:
+ XFREE(xcbc);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/xcbc/xcbc_memory_multi.c b/Sources/libtomcrypt/mac/xcbc/xcbc_memory_multi.c
new file mode 100644
index 00000000..d9e48d97
--- /dev/null
+++ b/Sources/libtomcrypt/mac/xcbc/xcbc_memory_multi.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+/**
+ @file xcbc_memory_multi.c
+ XCBC support, process multiple blocks of memory, Tom St Denis
+*/
+
+#ifdef LTC_XCBC
+
+/**
+ XCBC multiple blocks of memory
+ @param cipher The index of the desired cipher
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param out [out] The destination of the authentication tag
+ @param outlen [in/out] The max size and resulting size of the authentication tag (octets)
+ @param in The data to send through XCBC
+ @param inlen The length of the data to send through XCBC (octets)
+ @param ... tuples of (data,len) pairs to XCBC, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int xcbc_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+{
+ int err;
+ xcbc_state *xcbc;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* allocate ram for xcbc state */
+ xcbc = XMALLOC(sizeof(xcbc_state));
+ if (xcbc == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* xcbc process the message */
+ if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ for (;;) {
+ /* process buf */
+ if ((err = xcbc_process(xcbc, curptr, curlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* step to next */
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) {
+ break;
+ }
+ curlen = va_arg(args, unsigned long);
+ }
+ if ((err = xcbc_done(xcbc, out, outlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(xcbc, sizeof(xcbc_state));
+#endif
+ XFREE(xcbc);
+ va_end(args);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/mac/xcbc/xcbc_process.c b/Sources/libtomcrypt/mac/xcbc/xcbc_process.c
new file mode 100644
index 00000000..3cb0c46a
--- /dev/null
+++ b/Sources/libtomcrypt/mac/xcbc/xcbc_process.c
@@ -0,0 +1,63 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file xcbc_process.c
+ XCBC Support, process blocks with XCBC
+*/
+
+#ifdef LTC_XCBC
+
+/** Process data through XCBC-MAC
+ @param xcbc The XCBC-MAC state
+ @param in Input data to process
+ @param inlen Length of input in octets
+ Return CRYPT_OK on success
+*/
+int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen)
+{
+ int err;
+#ifdef LTC_FAST
+ int x;
+#endif
+
+ LTC_ARGCHK(xcbc != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* check structure */
+ if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher].block_length) || (xcbc->blocksize < 0) ||
+ (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+#ifdef LTC_FAST
+ if (xcbc->buflen == 0) {
+ while (inlen > (unsigned long)xcbc->blocksize) {
+ for (x = 0; x < xcbc->blocksize; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&(xcbc->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x])));
+ }
+ cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key);
+ in += xcbc->blocksize;
+ inlen -= xcbc->blocksize;
+ }
+ }
+#endif
+
+ while (inlen) {
+ if (xcbc->buflen == xcbc->blocksize) {
+ cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key);
+ xcbc->buflen = 0;
+ }
+ xcbc->IV[xcbc->buflen++] ^= *in++;
+ --inlen;
+ }
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/mac/xcbc/xcbc_test.c b/Sources/libtomcrypt/mac/xcbc/xcbc_test.c
new file mode 100644
index 00000000..23555de0
--- /dev/null
+++ b/Sources/libtomcrypt/mac/xcbc/xcbc_test.c
@@ -0,0 +1,116 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file xcbc_test.c
+ XCBC Support, Test XCBC-MAC mode
+*/
+
+#ifdef LTC_XCBC
+
+/** Test XCBC-MAC mode
+ Return CRYPT_OK on success
+*/
+int xcbc_test(void)
+{
+#ifdef LTC_NO_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ int msglen;
+ unsigned char K[16], M[34], T[16];
+ } tests[] = {
+{
+ 0,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+
+ { 0 },
+
+ { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c,
+ 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 }
+},
+
+{
+ 3,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+
+ { 0x00, 0x01, 0x02 },
+
+ { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf,
+ 0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f }
+},
+
+{
+ 16,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+
+ { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7,
+ 0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 }
+},
+
+{
+ 32,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+
+ { 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 },
+
+ { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3,
+ 0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 }
+},
+
+{
+ 34,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+
+ { 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,
+ 0x20, 0x21 },
+
+ { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3,
+ 0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 },
+},
+
+
+
+};
+ unsigned char T[16];
+ unsigned long taglen;
+ int err, x, idx;
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((idx = find_cipher("aes")) == -1) {
+ if ((idx = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ taglen = 16;
+ if ((err = xcbc_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) {
+ return err;
+ }
+ if (compare_testvector(T, taglen, tests[x].T, 16, "XCBC", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/math/fp/ltc_ecc_fp_mulmod.c b/Sources/libtomcrypt/math/fp/ltc_ecc_fp_mulmod.c
new file mode 100644
index 00000000..9be2ebf1
--- /dev/null
+++ b/Sources/libtomcrypt/math/fp/ltc_ecc_fp_mulmod.c
@@ -0,0 +1,1580 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ltc_ecc_fp_mulmod.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(LTC_MECC) && defined(LTC_MECC_FP)
+#include
+
+/* number of entries in the cache */
+#ifndef FP_ENTRIES
+#define FP_ENTRIES 16
+#endif
+
+/* number of bits in LUT */
+#ifndef FP_LUT
+#define FP_LUT 8U
+#endif
+
+#if (FP_LUT > 12) || (FP_LUT < 2)
+ #error FP_LUT must be between 2 and 12 inclusively
+#endif
+
+/** Our FP cache */
+static struct {
+ ecc_point *g, /* cached COPY of base point */
+ *LUT[1U< 6
+ { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 },
+ { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 },
+ { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 },
+ { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 },
+ { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 },
+ { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 },
+ { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 },
+ { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 },
+#if FP_LUT > 7
+ { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 },
+ { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 },
+ { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 },
+ { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 },
+ { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 },
+ { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 },
+ { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 },
+ { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 },
+ { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 },
+ { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 },
+ { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 },
+ { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 },
+ { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 },
+ { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 },
+ { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 },
+ { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 },
+#if FP_LUT > 8
+ { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 },
+ { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 },
+ { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 },
+ { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 },
+ { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 },
+ { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 },
+ { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 },
+ { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 },
+ { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 },
+ { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 },
+ { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 },
+ { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 },
+ { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 },
+ { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 },
+ { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 },
+ { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 },
+ { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 },
+ { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 },
+ { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 },
+ { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 },
+ { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 },
+ { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 },
+ { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 },
+ { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 },
+ { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 },
+ { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 },
+ { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 },
+ { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 },
+ { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 },
+ { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 },
+ { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 },
+ { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 },
+#if FP_LUT > 9
+ { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 },
+ { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 },
+ { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 },
+ { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 },
+ { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 },
+ { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 },
+ { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 },
+ { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 },
+ { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 },
+ { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 },
+ { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 },
+ { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 },
+ { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 },
+ { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 },
+ { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 },
+ { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 },
+ { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 },
+ { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 },
+ { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 },
+ { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 },
+ { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 },
+ { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 },
+ { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 },
+ { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 },
+ { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 },
+ { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 },
+ { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 },
+ { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 },
+ { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 },
+ { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 },
+ { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 },
+ { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 },
+ { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 },
+ { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 },
+ { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 },
+ { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 },
+ { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 },
+ { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 },
+ { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 },
+ { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 },
+ { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 },
+ { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 },
+ { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 },
+ { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 },
+ { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 },
+ { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 },
+ { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 },
+ { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 },
+ { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 },
+ { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 },
+ { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 },
+ { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 },
+ { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 },
+ { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 },
+ { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 },
+ { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 },
+ { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 },
+ { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 },
+ { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 },
+ { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 },
+ { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 },
+ { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 },
+ { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 },
+ { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 },
+#if FP_LUT > 10
+ { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 },
+ { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 },
+ { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 },
+ { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 },
+ { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 },
+ { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 },
+ { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 },
+ { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 },
+ { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 },
+ { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 },
+ { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 },
+ { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 },
+ { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 },
+ { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 },
+ { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 },
+ { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 },
+ { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 },
+ { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 },
+ { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 },
+ { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 },
+ { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 },
+ { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 },
+ { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 },
+ { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 },
+ { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 },
+ { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 },
+ { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 },
+ { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 },
+ { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 },
+ { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 },
+ { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 },
+ { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 },
+ { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 },
+ { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 },
+ { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 },
+ { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 },
+ { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 },
+ { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 },
+ { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 },
+ { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 },
+ { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 },
+ { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 },
+ { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 },
+ { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 },
+ { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 },
+ { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 },
+ { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 },
+ { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 },
+ { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 },
+ { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 },
+ { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 },
+ { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 },
+ { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 },
+ { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 },
+ { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 },
+ { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 },
+ { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 },
+ { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 },
+ { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 },
+ { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 },
+ { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 },
+ { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 },
+ { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 },
+ { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 },
+ { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 },
+ { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 },
+ { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 },
+ { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 },
+ { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 },
+ { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 },
+ { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 },
+ { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 },
+ { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 },
+ { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 },
+ { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 },
+ { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 },
+ { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 },
+ { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 },
+ { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 },
+ { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 },
+ { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 },
+ { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 },
+ { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 },
+ { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 },
+ { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 },
+ { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 },
+ { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 },
+ { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 },
+ { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 },
+ { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 },
+ { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 },
+ { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 },
+ { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 },
+ { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 },
+ { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 },
+ { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 },
+ { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 },
+ { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 },
+ { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 },
+ { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 },
+ { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 },
+ { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 },
+ { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 },
+ { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 },
+ { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 },
+ { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 },
+ { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 },
+ { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 },
+ { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 },
+ { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 },
+ { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 },
+ { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 },
+ { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 },
+ { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 },
+ { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 },
+ { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 },
+ { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 },
+ { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 },
+ { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 },
+ { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 },
+ { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 },
+ { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 },
+ { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 },
+ { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 },
+ { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 },
+ { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 },
+ { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 },
+ { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 },
+#if FP_LUT > 11
+ { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 },
+ { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 },
+ { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 },
+ { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 },
+ { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 },
+ { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 },
+ { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 },
+ { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 },
+ { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 },
+ { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 },
+ { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 },
+ { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 },
+ { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 },
+ { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 },
+ { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 },
+ { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 },
+ { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 },
+ { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 },
+ { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 },
+ { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 },
+ { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 },
+ { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 },
+ { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 },
+ { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 },
+ { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 },
+ { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 },
+ { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 },
+ { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 },
+ { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 },
+ { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 },
+ { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 },
+ { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 },
+ { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 },
+ { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 },
+ { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 },
+ { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 },
+ { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 },
+ { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 },
+ { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 },
+ { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 },
+ { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 },
+ { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 },
+ { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 },
+ { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 },
+ { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 },
+ { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 },
+ { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 },
+ { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 },
+ { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 },
+ { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 },
+ { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 },
+ { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 },
+ { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 },
+ { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 },
+ { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 },
+ { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 },
+ { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 },
+ { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 },
+ { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 },
+ { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 },
+ { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 },
+ { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 },
+ { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 },
+ { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 },
+ { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 },
+ { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 },
+ { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 },
+ { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 },
+ { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 },
+ { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 },
+ { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 },
+ { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 },
+ { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 },
+ { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 },
+ { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 },
+ { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 },
+ { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 },
+ { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 },
+ { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 },
+ { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 },
+ { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 },
+ { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 },
+ { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 },
+ { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 },
+ { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 },
+ { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 },
+ { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 },
+ { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 },
+ { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 },
+ { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 },
+ { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 },
+ { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 },
+ { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 },
+ { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 },
+ { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 },
+ { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 },
+ { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 },
+ { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 },
+ { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 },
+ { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 },
+ { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 },
+ { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 },
+ { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 },
+ { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 },
+ { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 },
+ { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 },
+ { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 },
+ { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 },
+ { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 },
+ { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 },
+ { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 },
+ { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 },
+ { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 },
+ { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 },
+ { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 },
+ { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 },
+ { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 },
+ { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 },
+ { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 },
+ { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 },
+ { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 },
+ { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 },
+ { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 },
+ { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 },
+ { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 },
+ { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 },
+ { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 },
+ { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 },
+ { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 },
+ { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 },
+ { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 },
+ { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 },
+ { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 },
+ { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 },
+ { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 },
+ { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 },
+ { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 },
+ { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 },
+ { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 },
+ { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 },
+ { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 },
+ { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 },
+ { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 },
+ { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 },
+ { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 },
+ { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 },
+ { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 },
+ { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 },
+ { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 },
+ { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 },
+ { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 },
+ { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 },
+ { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 },
+ { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 },
+ { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 },
+ { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 },
+ { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 },
+ { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 },
+ { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 },
+ { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 },
+ { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 },
+ { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 },
+ { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 },
+ { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 },
+ { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 },
+ { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 },
+ { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 },
+ { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 },
+ { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 },
+ { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 },
+ { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 },
+ { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 },
+ { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 },
+ { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 },
+ { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 },
+ { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 },
+ { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 },
+ { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 },
+ { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 },
+ { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 },
+ { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 },
+ { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 },
+ { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 },
+ { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 },
+ { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 },
+ { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 },
+ { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 },
+ { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 },
+ { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 },
+ { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 },
+ { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 },
+ { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 },
+ { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 },
+ { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 },
+ { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 },
+ { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 },
+ { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 },
+ { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 },
+ { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 },
+ { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 },
+ { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 },
+ { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 },
+ { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 },
+ { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 },
+ { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 },
+ { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 },
+ { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 },
+ { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 },
+ { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 },
+ { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 },
+ { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 },
+ { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 },
+ { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 },
+ { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 },
+ { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 },
+ { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 },
+ { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 },
+ { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 },
+ { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 },
+ { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 },
+ { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 },
+ { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 },
+ { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 },
+ { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 },
+ { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 },
+ { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 },
+ { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 },
+ { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 },
+ { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 },
+ { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 },
+ { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 },
+ { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 },
+ { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 },
+ { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 },
+ { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 },
+ { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 },
+ { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 },
+ { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 },
+ { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 },
+ { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 },
+ { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 },
+ { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 },
+ { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 },
+ { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 },
+ { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 },
+ { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 },
+ { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 },
+ { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 },
+ { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 },
+ { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 },
+ { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 },
+ { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 },
+ { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 },
+ { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 },
+ { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 },
+ { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 },
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+};
+
+/* find a hole and free as required, return -1 if no hole found */
+static int s_find_hole(void)
+{
+ unsigned x;
+ int y, z;
+ for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) {
+ if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) {
+ z = x;
+ y = fp_cache[x].lru_count;
+ }
+ }
+
+ /* decrease all */
+ for (x = 0; x < FP_ENTRIES; x++) {
+ if (fp_cache[x].lru_count > 3) {
+ --(fp_cache[x].lru_count);
+ }
+ }
+
+ /* free entry z */
+ if (z >= 0 && fp_cache[z].g) {
+ if (fp_cache[z].mu != NULL) {
+ mp_clear(fp_cache[z].mu);
+ fp_cache[z].mu = NULL;
+ }
+ ltc_ecc_del_point(fp_cache[z].g);
+ fp_cache[z].g = NULL;
+ for (x = 0; x < (1U<x, g->x) == LTC_MP_EQ &&
+ mp_cmp(fp_cache[x].g->y, g->y) == LTC_MP_EQ &&
+ mp_cmp(fp_cache[x].g->z, g->z) == LTC_MP_EQ) {
+ break;
+ }
+ }
+ if (x == FP_ENTRIES) {
+ x = -1;
+ }
+ return x;
+}
+
+/* add a new base to the cache */
+static int s_add_entry(int idx, ecc_point *g)
+{
+ unsigned x, y;
+
+ /* allocate base and LUT */
+ fp_cache[idx].g = ltc_ecc_new_point();
+ if (fp_cache[idx].g == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* copy x and y */
+ if ((mp_copy(g->x, fp_cache[idx].g->x) != CRYPT_OK) ||
+ (mp_copy(g->y, fp_cache[idx].g->y) != CRYPT_OK) ||
+ (mp_copy(g->z, fp_cache[idx].g->z) != CRYPT_OK)) {
+ ltc_ecc_del_point(fp_cache[idx].g);
+ fp_cache[idx].g = NULL;
+ return CRYPT_MEM;
+ }
+
+ for (x = 0; x < (1U<x, mu, modulus, fp_cache[idx].LUT[1]->x) != CRYPT_OK) ||
+ (mp_mulmod(fp_cache[idx].g->y, mu, modulus, fp_cache[idx].LUT[1]->y) != CRYPT_OK) ||
+ (mp_mulmod(fp_cache[idx].g->z, mu, modulus, fp_cache[idx].LUT[1]->z) != CRYPT_OK)) { goto ERR; }
+
+ /* make all single bit entries */
+ for (x = 1; x < FP_LUT; x++) {
+ if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x, fp_cache[idx].LUT[1<x) != CRYPT_OK) ||
+ (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y, fp_cache[idx].LUT[1<y) != CRYPT_OK) ||
+ (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z, fp_cache[idx].LUT[1<z) != CRYPT_OK)) { goto ERR; }
+
+ /* now double it bitlen/FP_LUT times */
+ for (y = 0; y < lut_gap; y++) {
+ if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<z, modulus, mp)) != CRYPT_OK) { goto ERR; }
+
+ /* invert it */
+ if ((err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus, fp_cache[idx].LUT[x]->z)) != CRYPT_OK) { goto ERR; }
+
+ /* now square it */
+ if ((err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; }
+
+ /* fix x */
+ if ((err = mp_mulmod(fp_cache[idx].LUT[x]->x, tmp, modulus, fp_cache[idx].LUT[x]->x)) != CRYPT_OK) { goto ERR; }
+
+ /* get 1/z^3 */
+ if ((err = mp_mulmod(tmp, fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; }
+
+ /* fix y */
+ if ((err = mp_mulmod(fp_cache[idx].LUT[x]->y, tmp, modulus, fp_cache[idx].LUT[x]->y)) != CRYPT_OK) { goto ERR; }
+
+ /* free z */
+ mp_clear(fp_cache[idx].LUT[x]->z);
+ fp_cache[idx].LUT[x]->z = NULL;
+ }
+ mp_clear(tmp);
+
+ return CRYPT_OK;
+ERR:
+ err = CRYPT_MEM;
+DONE:
+ for (y = 0; y < (1U< mp_unsigned_bin_size(modulus)) {
+ /* find order */
+ y = mp_unsigned_bin_size(modulus);
+ for (x = 0; ltc_ecc_sets[x].size; x++) {
+ if (y <= (unsigned)ltc_ecc_sets[x].size) break;
+ }
+
+ /* back off if we are on the 521 bit curve */
+ if (y == 66) --x;
+
+ if ((err = mp_init(&order)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) {
+ mp_clear(&order);
+ return err;
+ }
+
+ /* k must be less than modulus */
+ if (mp_cmp(k, order) != LTC_MP_LT) {
+ if ((err = mp_init(&tk)) != CRYPT_OK) {
+ mp_clear(order);
+ return err;
+ }
+ if ((err = mp_mod(k, order, tk)) != CRYPT_OK) {
+ mp_clear(tk);
+ mp_clear(order);
+ return err;
+ }
+ } else {
+ tk = k;
+ }
+ mp_clear(order);
+ } else {
+ tk = k;
+ }
+
+ /* get bitlen and round up to next multiple of FP_LUT */
+ bitlen = mp_unsigned_bin_size(modulus) << 3;
+ x = bitlen % FP_LUT;
+ if (x) {
+ bitlen += FP_LUT - x;
+ }
+ lut_gap = bitlen / FP_LUT;
+
+ /* get the k value */
+ if (mp_unsigned_bin_size(tk) > (sizeof(kb) - 2)) {
+ if (tk != k) {
+ mp_clear(tk);
+ }
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store k */
+ zeromem(kb, sizeof(kb));
+ if ((err = mp_to_unsigned_bin(tk, kb)) != CRYPT_OK) {
+ if (tk != k) {
+ mp_clear(tk);
+ }
+ return err;
+ }
+
+ /* let's reverse kb so it's little endian */
+ x = 0;
+ y = mp_unsigned_bin_size(tk) - 1;
+ if (tk != k) {
+ mp_clear(tk);
+ }
+ while ((unsigned)x < y) {
+ z = kb[x]; kb[x] = kb[y]; kb[y] = z;
+ ++x; --y;
+ }
+
+ /* at this point we can start, yipee */
+ first = 1;
+ for (x = lut_gap-1; x >= 0; x--) {
+ /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */
+ bitpos = x;
+ for (y = z = 0; y < FP_LUT; y++) {
+ z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y;
+ bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */
+ }
+
+ /* double if not first */
+ if (!first) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* add if not first, otherwise copy */
+ if (!first && z) {
+ if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, a, modulus, mp)) != CRYPT_OK) {
+ return err;
+ }
+ } else if (z) {
+ if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != CRYPT_OK) ||
+ (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != CRYPT_OK) ||
+ (mp_copy(fp_cache[idx].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; }
+ first = 0;
+ }
+ }
+ z = 0;
+ zeromem(kb, sizeof(kb));
+ /* map R back from projective space */
+ if (map) {
+ err = ltc_ecc_map(R, modulus, mp);
+ } else {
+ err = CRYPT_OK;
+ }
+ return err;
+}
+
+#ifdef LTC_ECC_SHAMIR
+/* perform a fixed point ECC mulmod */
+static int ss_accel_fp_mul2add(int idx1, int idx2,
+ void *kA, void *kB,
+ ecc_point *R, void *a, void *modulus, void *mp)
+{
+ unsigned char kb[2][128];
+ int x;
+ unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB;
+ void *tka, *tkb, *order;
+
+ /* if it's smaller than modulus we fine */
+ if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) {
+ /* find order */
+ y = mp_unsigned_bin_size(modulus);
+ for (x = 0; ltc_ecc_sets[x].size; x++) {
+ if (y <= (unsigned)ltc_ecc_sets[x].size) break;
+ }
+
+ /* back off if we are on the 521 bit curve */
+ if (y == 66) --x;
+
+ if ((err = mp_init(&order)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) {
+ mp_clear(&order);
+ return err;
+ }
+
+ /* kA must be less than modulus */
+ if (mp_cmp(kA, order) != LTC_MP_LT) {
+ if ((err = mp_init(&tka)) != CRYPT_OK) {
+ mp_clear(order);
+ return err;
+ }
+ if ((err = mp_mod(kA, order, tka)) != CRYPT_OK) {
+ mp_clear(tka);
+ mp_clear(order);
+ return err;
+ }
+ } else {
+ tka = kA;
+ }
+ mp_clear(order);
+ } else {
+ tka = kA;
+ }
+
+ /* if it's smaller than modulus we fine */
+ if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) {
+ /* find order */
+ y = mp_unsigned_bin_size(modulus);
+ for (x = 0; ltc_ecc_sets[x].size; x++) {
+ if (y <= (unsigned)ltc_ecc_sets[x].size) break;
+ }
+
+ /* back off if we are on the 521 bit curve */
+ if (y == 66) --x;
+
+ if ((err = mp_init(&order)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) {
+ mp_clear(&order);
+ return err;
+ }
+
+ /* kB must be less than modulus */
+ if (mp_cmp(kB, order) != LTC_MP_LT) {
+ if ((err = mp_init(&tkb)) != CRYPT_OK) {
+ mp_clear(order);
+ return err;
+ }
+ if ((err = mp_mod(kB, order, tkb)) != CRYPT_OK) {
+ mp_clear(tkb);
+ mp_clear(order);
+ return err;
+ }
+ } else {
+ tkb = kB;
+ }
+ mp_clear(order);
+ } else {
+ tkb = kB;
+ }
+
+ /* get bitlen and round up to next multiple of FP_LUT */
+ bitlen = mp_unsigned_bin_size(modulus) << 3;
+ x = bitlen % FP_LUT;
+ if (x) {
+ bitlen += FP_LUT - x;
+ }
+ lut_gap = bitlen / FP_LUT;
+
+ /* get the k value */
+ if ((mp_unsigned_bin_size(tka) > (sizeof(kb[0]) - 2)) || (mp_unsigned_bin_size(tkb) > (sizeof(kb[0]) - 2)) ) {
+ if (tka != kA) {
+ mp_clear(tka);
+ }
+ if (tkb != kB) {
+ mp_clear(tkb);
+ }
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store k */
+ zeromem(kb, sizeof(kb));
+ if ((err = mp_to_unsigned_bin(tka, kb[0])) != CRYPT_OK) {
+ if (tka != kA) {
+ mp_clear(tka);
+ }
+ if (tkb != kB) {
+ mp_clear(tkb);
+ }
+ return err;
+ }
+
+ /* let's reverse kb so it's little endian */
+ x = 0;
+ y = mp_unsigned_bin_size(tka) - 1;
+ if (tka != kA) {
+ mp_clear(tka);
+ }
+ while ((unsigned)x < y) {
+ z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z;
+ ++x; --y;
+ }
+
+ /* store b */
+ if ((err = mp_to_unsigned_bin(tkb, kb[1])) != CRYPT_OK) {
+ if (tkb != kB) {
+ mp_clear(tkb);
+ }
+ return err;
+ }
+
+ x = 0;
+ y = mp_unsigned_bin_size(tkb) - 1;
+ if (tkb != kB) {
+ mp_clear(tkb);
+ }
+ while ((unsigned)x < y) {
+ z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z;
+ ++x; --y;
+ }
+
+ /* at this point we can start, yipee */
+ first = 1;
+ for (x = lut_gap-1; x >= 0; x--) {
+ /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */
+ bitpos = x;
+ for (y = zA = zB = 0; y < FP_LUT; y++) {
+ zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y;
+ zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y;
+ bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */
+ }
+
+ /* double if not first */
+ if (!first) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* add if not first, otherwise copy */
+ if (!first) {
+ if (zA) {
+ if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, a, modulus, mp)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ if (zB) {
+ if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ } else {
+ if (zA) {
+ if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != CRYPT_OK) ||
+ (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != CRYPT_OK) ||
+ (mp_copy(fp_cache[idx1].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; }
+ first = 0;
+ }
+ if (zB && first == 0) {
+ if (zB) {
+ if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ } else if (zB && first == 1) {
+ if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != CRYPT_OK) ||
+ (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != CRYPT_OK) ||
+ (mp_copy(fp_cache[idx2].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; }
+ first = 0;
+ }
+ }
+ }
+ zeromem(kb, sizeof(kb));
+ return ltc_ecc_map(R, modulus, mp);
+}
+
+/** ECC Fixed Point mulmod global
+ Computes kA*A + kB*B = C using Shamir's Trick
+ @param A First point to multiply
+ @param kA What to multiple A by
+ @param B Second point to multiply
+ @param kB What to multiple B by
+ @param C [out] Destination point (can overlap with A or B)
+ @param modulus Modulus for curve
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
+ ecc_point *B, void *kB,
+ ecc_point *C,
+ void *a,
+ void *modulus)
+{
+ int idx1, idx2, err;
+ void *mp, *mu;
+
+ mp = NULL;
+ mu = NULL;
+ LTC_MUTEX_LOCK(<c_ecc_fp_lock);
+ /* find point */
+ idx1 = s_find_base(A);
+
+ /* no entry? */
+ if (idx1 == -1) {
+ /* find hole and add it */
+ if ((idx1 = s_find_hole()) >= 0) {
+ if ((err = s_add_entry(idx1, A)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+ }
+ if (idx1 != -1) {
+ /* increment LRU */
+ ++(fp_cache[idx1].lru_count);
+ }
+
+ /* find point */
+ idx2 = s_find_base(B);
+
+ /* no entry? */
+ if (idx2 == -1) {
+ /* find hole and add it */
+ if ((idx2 = s_find_hole()) >= 0) {
+ if ((err = s_add_entry(idx2, B)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+ }
+ if (idx2 != -1) {
+ /* increment LRU */
+ ++(fp_cache[idx2].lru_count);
+ }
+
+ /* if it's 2 build the LUT, if it's higher just use the LUT */
+ if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) {
+ /* compute mp */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; }
+
+ /* compute mu */
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* build the LUT */
+ if ((err = s_build_lut(idx1, a, modulus, mp, mu)) != CRYPT_OK) {
+ goto LBL_ERR;;
+ }
+ }
+
+ /* if it's 2 build the LUT, if it's higher just use the LUT */
+ if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) {
+ if (mp == NULL) {
+ /* compute mp */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; }
+
+ /* compute mu */
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* build the LUT */
+ if ((err = s_build_lut(idx2, a, modulus, mp, mu)) != CRYPT_OK) {
+ goto LBL_ERR;;
+ }
+ }
+
+
+ if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 && fp_cache[idx2].lru_count >= 2) {
+ if (mp == NULL) {
+ /* compute mp */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; }
+ }
+ err = ss_accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp);
+ } else {
+ err = ltc_ecc_mul2add(A, kA, B, kB, C, a, modulus);
+ }
+LBL_ERR:
+ LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
+ if (mp != NULL) {
+ mp_montgomery_free(mp);
+ }
+ if (mu != NULL) {
+ mp_clear(mu);
+ }
+ return err;
+}
+#endif
+
+/** ECC Fixed Point mulmod global
+ @param k The multiplicand
+ @param G Base point to multiply
+ @param R [out] Destination of product
+ @param a ECC curve parameter a
+ @param modulus The modulus for the curve
+ @param map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form
+ @return CRYPT_OK if successful
+*/
+int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
+{
+ int idx, err;
+ void *mp, *mu;
+
+ mp = NULL;
+ mu = NULL;
+ LTC_MUTEX_LOCK(<c_ecc_fp_lock);
+ /* find point */
+ idx = s_find_base(G);
+
+ /* no entry? */
+ if (idx == -1) {
+ /* find hole and add it */
+ idx = s_find_hole();
+
+ if (idx >= 0) {
+ if ((err = s_add_entry(idx, G)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+ }
+ if (idx != -1) {
+ /* increment LRU */
+ ++(fp_cache[idx].lru_count);
+ }
+
+
+ /* if it's 2 build the LUT, if it's higher just use the LUT */
+ if (idx >= 0 && fp_cache[idx].lru_count == 2) {
+ /* compute mp */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; }
+
+ /* compute mu */
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* build the LUT */
+ if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) {
+ goto LBL_ERR;;
+ }
+ }
+
+ if (idx >= 0 && fp_cache[idx].lru_count >= 2) {
+ if (mp == NULL) {
+ /* compute mp */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; }
+ }
+ err = s_accel_fp_mul(idx, k, R, a, modulus, mp, map);
+ } else {
+ err = ltc_ecc_mulmod(k, G, R, a, modulus, map);
+ }
+LBL_ERR:
+ LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
+ if (mp != NULL) {
+ mp_montgomery_free(mp);
+ }
+ if (mu != NULL) {
+ mp_clear(mu);
+ }
+ return err;
+}
+
+/* helper function for freeing the cache ... must be called with the cache mutex locked */
+static void s_ltc_ecc_fp_free_cache(void)
+{
+ unsigned x, y;
+ for (x = 0; x < FP_ENTRIES; x++) {
+ if (fp_cache[x].g != NULL) {
+ for (y = 0; y < (1U<= 0) {
+ /* it is already in the cache ... just check that the LUT is initialized */
+ if(fp_cache[idx].lru_count >= 2) {
+ LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
+ return CRYPT_OK;
+ }
+ }
+
+ if(idx == -1 && (idx = s_find_hole()) == -1) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+ if ((err = s_add_entry(idx, g)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* compute mp */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* compute mu */
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* build the LUT */
+ if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ fp_cache[idx].lru_count = 2;
+ fp_cache[idx].lock = lock;
+LBL_ERR:
+ LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
+ if (mp != NULL) {
+ mp_montgomery_free(mp);
+ }
+ if (mu != NULL) {
+ mp_clear(mu);
+ }
+ return err;
+}
+
+/** Prevent/permit the FP cache from being updated
+ @param flag If flag is 0, remove cache lock (unlock), otherwise lock it
+*/
+void ltc_ecc_fp_tablelock(int lock)
+{
+ int i;
+
+ LTC_MUTEX_LOCK(<c_ecc_fp_lock);
+ for (i = 0; i < FP_ENTRIES; i++) {
+ fp_cache[i].lock = lock;
+ }
+ LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
+}
+
+/** Export the current cache as a binary packet
+ @param out [out] pointer to malloc'ed space containing the packet
+ @param outlen [out] size of exported packet
+ @return CRYPT_OK if successful
+*/
+int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen)
+{
+ ltc_asn1_list *cache_entry;
+ unsigned int i, j, k;
+ unsigned long fp_entries, fp_lut, num_entries;
+ int err;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ fp_entries = FP_ENTRIES;
+ fp_lut = FP_LUT;
+ num_entries = 0;
+
+ LTC_MUTEX_LOCK(<c_ecc_fp_lock);
+ /*
+ * build the list;
+ Cache DEFINITIONS ::=
+ BEGIN
+ CacheDump ::= SEQUENCE {
+ numEntries SHORTINTEGER,
+ maxEntries SHORTINTEGER,
+ numLUT SHORTINTEGER,
+ cache SEQUENCE OF INTEGER
+ }
+ END
+ *
+ */
+ /*
+ * The cache itself is a point (3 INTEGERS),
+ * the LUT as pairs of INTEGERS (2 * 1<x, 1);
+ LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1);
+ LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1);
+ for (k = 0; k < (1U<x, 1);
+ LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].LUT[k]->y, 1);
+ }
+ LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1);
+ }
+ LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_EOL, 0, 0);
+
+ LTC_SET_ASN1(cache_entry, 0, LTC_ASN1_SHORT_INTEGER, &num_entries, 1);
+
+ if ((err = der_length_sequence(cache_entry, j, outlen)) != CRYPT_OK) {
+ goto save_err;
+ }
+ if ((*out = XMALLOC(*outlen)) == NULL) {
+ err = CRYPT_MEM;
+ goto save_err;
+ }
+ err = der_encode_sequence(cache_entry, j, *out, outlen);
+save_err:
+ XFREE(cache_entry);
+ LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
+ return err;
+}
+
+/** Import a binary packet into the current cache
+ @param in [in] pointer to packet
+ @param inlen [in] size of packet (bytes)
+ @return CRYPT_OK if successful
+*/
+int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen)
+{
+ int err;
+ ltc_asn1_list *asn1_list;
+ unsigned long num_entries, fp_entries, fp_lut;
+ unsigned long i, j;
+ unsigned int x;
+
+ LTC_ARGCHK(in != NULL);
+ if (inlen == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* zero indecies */
+ i = 0;
+ j = 0;
+ asn1_list = NULL;
+
+ LTC_MUTEX_LOCK(<c_ecc_fp_lock);
+ /*
+ * start with an empty cache
+ */
+ s_ltc_ecc_fp_free_cache();
+
+ /*
+ * decode the input packet: It consists of a sequence with a few
+ * integers (including the FP_ENTRIES and FP_LUT sizes), followed by a
+ * SEQUENCE which is the cache itself.
+ *
+ * use standard decoding for the first part, then flexible for the second
+ */
+ if((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_SHORT_INTEGER, 1, &num_entries,
+ LTC_ASN1_SHORT_INTEGER, 1, &fp_entries,
+ LTC_ASN1_SHORT_INTEGER, 1, &fp_lut,
+ LTC_ASN1_EOL, 0, 0)) != CRYPT_OK) {
+ goto ERR_OUT;
+ }
+ if (fp_entries != FP_ENTRIES || fp_lut != FP_LUT || num_entries > fp_entries) {
+ err = CRYPT_INVALID_PACKET;
+ goto ERR_OUT;
+ }
+ if ((asn1_list = XCALLOC(3+num_entries*(4+2*(1<x, 1);
+ LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1);
+ LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1);
+ for (x = 0; x < (1U<x, &p->y, LTC_NULL)) != CRYPT_OK) {
+ goto ERR_OUT;
+ }
+ p->z = NULL;
+ LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->x, 1);
+ LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->y, 1);
+ }
+ if((err = mp_init(&fp_cache[i].mu)) != CRYPT_OK) {
+ goto ERR_OUT;
+ }
+ LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1);
+ fp_cache[i].lru_count = 3;
+ fp_cache[i].lock = 1;
+ }
+
+ if ((err = der_decode_sequence(in, inlen, asn1_list, j)) != CRYPT_OK) {
+ goto ERR_OUT;
+ }
+ XFREE(asn1_list);
+ LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
+ return CRYPT_OK;
+ERR_OUT:
+ if(asn1_list)
+ XFREE(asn1_list);
+ s_ltc_ecc_fp_free_cache();
+ LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
+ return err;
+}
+
+#endif
+
+
diff --git a/Sources/libtomcrypt/math/gmp_desc.c b/Sources/libtomcrypt/math/gmp_desc.c
new file mode 100644
index 00000000..2db699d4
--- /dev/null
+++ b/Sources/libtomcrypt/math/gmp_desc.c
@@ -0,0 +1,658 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#define DESC_DEF_ONLY
+#include "tomcrypt_private.h"
+
+#ifdef GMP_DESC
+
+#include
+#include
+
+static int init(void **a)
+{
+ LTC_ARGCHK(a != NULL);
+
+ *a = XCALLOC(1, sizeof(__mpz_struct));
+ if (*a == NULL) {
+ return CRYPT_MEM;
+ }
+ mpz_init(((__mpz_struct *)*a));
+ return CRYPT_OK;
+}
+
+static void deinit(void *a)
+{
+ LTC_ARGCHKVD(a != NULL);
+ mpz_clear(a);
+ XFREE(a);
+}
+
+static int neg(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ mpz_neg(b, a);
+ return CRYPT_OK;
+}
+
+static int copy(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ mpz_set(b, a);
+ return CRYPT_OK;
+}
+
+static int init_copy(void **a, void *b)
+{
+ if (init(a) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+ return copy(b, *a);
+}
+
+/* ---- trivial ---- */
+static int set_int(void *a, ltc_mp_digit b)
+{
+ LTC_ARGCHK(a != NULL);
+ mpz_set_ui(((__mpz_struct *)a), b);
+ return CRYPT_OK;
+}
+
+static unsigned long get_int(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mpz_get_ui(a);
+}
+
+static ltc_mp_digit get_digit(void *a, int n)
+{
+ LTC_ARGCHK(a != NULL);
+ return mpz_getlimbn(a, n);
+}
+
+static int get_digit_count(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mpz_size(a);
+}
+
+static int compare(void *a, void *b)
+{
+ int ret;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ ret = mpz_cmp(a, b);
+ if (ret < 0) {
+ return LTC_MP_LT;
+ } else if (ret > 0) {
+ return LTC_MP_GT;
+ } else {
+ return LTC_MP_EQ;
+ }
+}
+
+static int compare_d(void *a, ltc_mp_digit b)
+{
+ int ret;
+ LTC_ARGCHK(a != NULL);
+ ret = mpz_cmp_ui(((__mpz_struct *)a), b);
+ if (ret < 0) {
+ return LTC_MP_LT;
+ } else if (ret > 0) {
+ return LTC_MP_GT;
+ } else {
+ return LTC_MP_EQ;
+ }
+}
+
+static int count_bits(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mpz_sizeinbase(a, 2);
+}
+
+static int count_lsb_bits(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mpz_scan1(a, 0);
+}
+
+
+static int twoexpt(void *a, int n)
+{
+ LTC_ARGCHK(a != NULL);
+ mpz_set_ui(a, 0);
+ mpz_setbit(a, n);
+ return CRYPT_OK;
+}
+
+/* ---- conversions ---- */
+
+static const char rmap[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+/* read ascii string */
+static int read_radix(void *a, const char *b, int radix)
+{
+ int ret;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ if (radix == 64) {
+ /* Sadly, GMP only supports radixes up to 62, but we need 64.
+ * So, although this is not the most elegant or efficient way,
+ * let's just convert the base 64 string (6 bits per digit) to
+ * an octal string (3 bits per digit) that's twice as long. */
+ char c, *tmp, *q;
+ const char *p;
+ int i;
+ tmp = XMALLOC (1 + 2 * XSTRLEN (b));
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+ p = b;
+ q = tmp;
+ while ((c = *p++) != 0) {
+ for (i = 0; i < 64; i++) {
+ if (c == rmap[i])
+ break;
+ }
+ if (i == 64) {
+ XFREE (tmp);
+ /* printf ("c = '%c'\n", c); */
+ return CRYPT_ERROR;
+ }
+ *q++ = '0' + (i / 8);
+ *q++ = '0' + (i % 8);
+ }
+ *q = 0;
+ ret = mpz_set_str(a, tmp, 8);
+ /* printf ("ret = %d for '%s'\n", ret, tmp); */
+ XFREE (tmp);
+ } else {
+ ret = mpz_set_str(a, b, radix);
+ }
+ return (ret == 0 ? CRYPT_OK : CRYPT_ERROR);
+}
+
+/* write one */
+static int write_radix(void *a, char *b, int radix)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ if (radix >= 11 && radix <= 36)
+ /* If radix is positive, GMP uses lowercase, and if negative, uppercase.
+ * We want it to use uppercase, to match the test vectors (presumably
+ * generated with LibTomMath). */
+ radix = -radix;
+ mpz_get_str(b, radix, a);
+ return CRYPT_OK;
+}
+
+/* get size as unsigned char string */
+static unsigned long unsigned_size(void *a)
+{
+ unsigned long t;
+ LTC_ARGCHK(a != NULL);
+ t = mpz_sizeinbase(a, 2);
+ if (mpz_cmp_ui(((__mpz_struct *)a), 0) == 0) return 0;
+ return (t>>3) + ((t&7)?1:0);
+}
+
+/* store */
+static int unsigned_write(void *a, unsigned char *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ mpz_export(b, NULL, 1, 1, 1, 0, ((__mpz_struct*)a));
+ return CRYPT_OK;
+}
+
+/* read */
+static int unsigned_read(void *a, unsigned char *b, unsigned long len)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ mpz_import(a, len, 1, 1, 1, 0, b);
+ return CRYPT_OK;
+}
+
+/* add */
+static int add(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_add(c, a, b);
+ return CRYPT_OK;
+}
+
+static int addi(void *a, ltc_mp_digit b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_add_ui(c, a, b);
+ return CRYPT_OK;
+}
+
+/* sub */
+static int sub(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_sub(c, a, b);
+ return CRYPT_OK;
+}
+
+static int subi(void *a, ltc_mp_digit b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_sub_ui(c, a, b);
+ return CRYPT_OK;
+}
+
+/* mul */
+static int mul(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_mul(c, a, b);
+ return CRYPT_OK;
+}
+
+static int muli(void *a, ltc_mp_digit b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_mul_ui(c, a, b);
+ return CRYPT_OK;
+}
+
+/* sqr */
+static int sqr(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ mpz_mul(b, a, a);
+ return CRYPT_OK;
+}
+
+/* sqrtmod_prime */
+static int sqrtmod_prime(void *n, void *prime, void *ret)
+{
+ int res, legendre, i;
+ mpz_t t1, C, Q, S, Z, M, T, R, two;
+
+ LTC_ARGCHK(n != NULL);
+ LTC_ARGCHK(prime != NULL);
+ LTC_ARGCHK(ret != NULL);
+
+ /* first handle the simple cases */
+ if (mpz_cmp_ui(((__mpz_struct *)n), 0) == 0) {
+ mpz_set_ui(ret, 0);
+ return CRYPT_OK;
+ }
+ if (mpz_cmp_ui(((__mpz_struct *)prime), 2) == 0) return CRYPT_ERROR; /* prime must be odd */
+ legendre = mpz_legendre(n, prime);
+ if (legendre == -1) return CRYPT_ERROR; /* quadratic non-residue mod prime */
+
+ mpz_init(t1); mpz_init(C); mpz_init(Q);
+ mpz_init(S); mpz_init(Z); mpz_init(M);
+ mpz_init(T); mpz_init(R); mpz_init(two);
+
+ /* SPECIAL CASE: if prime mod 4 == 3
+ * compute directly: res = n^(prime+1)/4 mod prime
+ * Handbook of Applied Cryptography algorithm 3.36
+ */
+ i = mpz_mod_ui(t1, prime, 4); /* t1 is ignored here */
+ if (i == 3) {
+ mpz_add_ui(t1, prime, 1);
+ mpz_fdiv_q_2exp(t1, t1, 2);
+ mpz_powm(ret, n, t1, prime);
+ res = CRYPT_OK;
+ goto cleanup;
+ }
+
+ /* NOW: Tonelli-Shanks algorithm */
+
+ /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */
+ mpz_set(Q, prime);
+ mpz_sub_ui(Q, Q, 1);
+ /* Q = prime - 1 */
+ mpz_set_ui(S, 0);
+ /* S = 0 */
+ while (mpz_even_p(Q)) {
+ mpz_fdiv_q_2exp(Q, Q, 1);
+ /* Q = Q / 2 */
+ mpz_add_ui(S, S, 1);
+ /* S = S + 1 */
+ }
+
+ /* find a Z such that the Legendre symbol (Z|prime) == -1 */
+ mpz_set_ui(Z, 2);
+ /* Z = 2 */
+ while(1) {
+ legendre = mpz_legendre(Z, prime);
+ if (legendre == -1) break;
+ mpz_add_ui(Z, Z, 1);
+ /* Z = Z + 1 */
+ }
+
+ mpz_powm(C, Z, Q, prime);
+ /* C = Z ^ Q mod prime */
+ mpz_add_ui(t1, Q, 1);
+ mpz_fdiv_q_2exp(t1, t1, 1);
+ /* t1 = (Q + 1) / 2 */
+ mpz_powm(R, n, t1, prime);
+ /* R = n ^ ((Q + 1) / 2) mod prime */
+ mpz_powm(T, n, Q, prime);
+ /* T = n ^ Q mod prime */
+ mpz_set(M, S);
+ /* M = S */
+ mpz_set_ui(two, 2);
+
+ while (1) {
+ mpz_set(t1, T);
+ i = 0;
+ while (1) {
+ if (mpz_cmp_ui(((__mpz_struct *)t1), 1) == 0) break;
+ mpz_powm(t1, t1, two, prime);
+ i++;
+ }
+ if (i == 0) {
+ mpz_set(ret, R);
+ res = CRYPT_OK;
+ goto cleanup;
+ }
+ mpz_sub_ui(t1, M, i);
+ mpz_sub_ui(t1, t1, 1);
+ mpz_powm(t1, two, t1, prime);
+ /* t1 = 2 ^ (M - i - 1) */
+ mpz_powm(t1, C, t1, prime);
+ /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
+ mpz_mul(C, t1, t1);
+ mpz_mod(C, C, prime);
+ /* C = (t1 * t1) mod prime */
+ mpz_mul(R, R, t1);
+ mpz_mod(R, R, prime);
+ /* R = (R * t1) mod prime */
+ mpz_mul(T, T, C);
+ mpz_mod(T, T, prime);
+ /* T = (T * C) mod prime */
+ mpz_set_ui(M, i);
+ /* M = i */
+ }
+
+cleanup:
+ mpz_clear(t1); mpz_clear(C); mpz_clear(Q);
+ mpz_clear(S); mpz_clear(Z); mpz_clear(M);
+ mpz_clear(T); mpz_clear(R); mpz_clear(two);
+ return res;
+}
+
+/* div */
+static int divide(void *a, void *b, void *c, void *d)
+{
+ mpz_t tmp;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ if (c != NULL) {
+ mpz_init(tmp);
+ mpz_divexact(tmp, a, b);
+ }
+ if (d != NULL) {
+ mpz_mod(d, a, b);
+ }
+ if (c != NULL) {
+ mpz_set(c, tmp);
+ mpz_clear(tmp);
+ }
+ return CRYPT_OK;
+}
+
+static int div_2(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ mpz_divexact_ui(b, a, 2);
+ return CRYPT_OK;
+}
+
+/* modi */
+static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+
+ *c = mpz_fdiv_ui(a, b);
+ return CRYPT_OK;
+}
+
+/* gcd */
+static int gcd(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_gcd(c, a, b);
+ return CRYPT_OK;
+}
+
+/* lcm */
+static int lcm(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_lcm(c, a, b);
+ return CRYPT_OK;
+}
+
+static int addmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ mpz_add(d, a, b);
+ mpz_mod(d, d, c);
+ return CRYPT_OK;
+}
+
+static int submod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ mpz_sub(d, a, b);
+ mpz_mod(d, d, c);
+ return CRYPT_OK;
+}
+
+static int mulmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ mpz_mul(d, a, b);
+ mpz_mod(d, d, c);
+ return CRYPT_OK;
+}
+
+static int sqrmod(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_mul(c, a, a);
+ mpz_mod(c, c, b);
+ return CRYPT_OK;
+}
+
+/* invmod */
+static int invmod(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_invert(c, a, b);
+ return CRYPT_OK;
+}
+
+/* setup */
+static int montgomery_setup(void *a, void **b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ *b = (void *)1;
+ return CRYPT_OK;
+}
+
+/* get normalization value */
+static int montgomery_normalization(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ mpz_set_ui(a, 1);
+ return CRYPT_OK;
+}
+
+/* reduce */
+static int montgomery_reduce(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ mpz_mod(a, a, b);
+ return CRYPT_OK;
+}
+
+/* clean up */
+static void montgomery_deinit(void *a)
+{
+ LTC_UNUSED_PARAM(a);
+}
+
+static int exptmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ mpz_powm(d, a, b, c);
+ return CRYPT_OK;
+}
+
+static int isprime(void *a, int b, int *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ if (b == 0) {
+ b = LTC_MILLER_RABIN_REPS;
+ } /* if */
+ *c = mpz_probab_prime_p(a, b) > 0 ? LTC_MP_YES : LTC_MP_NO;
+ return CRYPT_OK;
+}
+
+static int set_rand(void *a, int size)
+{
+ LTC_ARGCHK(a != NULL);
+ mpz_random(a, size);
+ return CRYPT_OK;
+}
+
+const ltc_math_descriptor gmp_desc = {
+ "GNU MP",
+ sizeof(mp_limb_t) * CHAR_BIT - GMP_NAIL_BITS,
+
+ &init,
+ &init_copy,
+ &deinit,
+
+ &neg,
+ ©,
+
+ &set_int,
+ &get_int,
+ &get_digit,
+ &get_digit_count,
+ &compare,
+ &compare_d,
+ &count_bits,
+ &count_lsb_bits,
+ &twoexpt,
+
+ &read_radix,
+ &write_radix,
+ &unsigned_size,
+ &unsigned_write,
+ &unsigned_read,
+
+ &add,
+ &addi,
+ &sub,
+ &subi,
+ &mul,
+ &muli,
+ &sqr,
+ &sqrtmod_prime,
+ ÷,
+ &div_2,
+ &modi,
+ &gcd,
+ &lcm,
+
+ &mulmod,
+ &sqrmod,
+ &invmod,
+
+ &montgomery_setup,
+ &montgomery_normalization,
+ &montgomery_reduce,
+ &montgomery_deinit,
+
+ &exptmod,
+ &isprime,
+
+#ifdef LTC_MECC
+#ifdef LTC_MECC_FP
+ <c_ecc_fp_mulmod,
+#else
+ <c_ecc_mulmod,
+#endif /* LTC_MECC_FP */
+ <c_ecc_projective_add_point,
+ <c_ecc_projective_dbl_point,
+ <c_ecc_map,
+#ifdef LTC_ECC_SHAMIR
+#ifdef LTC_MECC_FP
+ <c_ecc_fp_mul2add,
+#else
+ <c_ecc_mul2add,
+#endif /* LTC_MECC_FP */
+#else
+ NULL,
+#endif /* LTC_ECC_SHAMIR */
+#else
+ NULL, NULL, NULL, NULL, NULL,
+#endif /* LTC_MECC */
+
+#ifdef LTC_MRSA
+ &rsa_make_key,
+ &rsa_exptmod,
+#else
+ NULL, NULL,
+#endif
+ &addmod,
+ &submod,
+
+ &set_rand,
+
+};
+
+
+#endif
diff --git a/Sources/libtomcrypt/math/ltm_desc.c b/Sources/libtomcrypt/math/ltm_desc.c
new file mode 100644
index 00000000..b49b30eb
--- /dev/null
+++ b/Sources/libtomcrypt/math/ltm_desc.c
@@ -0,0 +1,560 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#define DESC_DEF_ONLY
+#include "tomcrypt_private.h"
+
+#ifdef LTM_DESC
+
+#include
+#if !defined(PRIVATE_MP_WARRAY) && !defined(BN_MP_PRIME_IS_PRIME_C)
+#include
+#endif
+
+static const struct {
+ mp_err mpi_code;
+ int ltc_code;
+} mpi_to_ltc_codes[] = {
+ { MP_OKAY , CRYPT_OK},
+ { MP_MEM , CRYPT_MEM},
+ { MP_VAL , CRYPT_INVALID_ARG},
+#if defined(MP_BUF) || defined(MP_USE_ENUMS)
+ { MP_ITER , CRYPT_INVALID_PACKET},
+ { MP_BUF , CRYPT_BUFFER_OVERFLOW},
+#endif
+};
+
+/**
+ Convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no)
+ @param err The error to convert
+ @return The equivalent LTC error code or CRYPT_ERROR if none found
+*/
+static int mpi_to_ltc_error(mp_err err)
+{
+ size_t x;
+
+ for (x = 0; x < sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0]); x++) {
+ if (err == mpi_to_ltc_codes[x].mpi_code) {
+ return mpi_to_ltc_codes[x].ltc_code;
+ }
+ }
+ return CRYPT_ERROR;
+}
+
+static int init_mpi(void **a)
+{
+ LTC_ARGCHK(a != NULL);
+
+ *a = XCALLOC(1, sizeof(mp_int));
+ if (*a == NULL) {
+ return CRYPT_MEM;
+ } else {
+ return CRYPT_OK;
+ }
+}
+
+static int init(void **a)
+{
+ int err;
+
+ LTC_ARGCHK(a != NULL);
+
+ if ((err = init_mpi(a)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) {
+ XFREE(*a);
+ }
+ return err;
+}
+
+static void deinit(void *a)
+{
+ LTC_ARGCHKVD(a != NULL);
+ mp_clear(a);
+ XFREE(a);
+}
+
+static int neg(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_neg(a, b));
+}
+
+static int copy(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_copy(a, b));
+}
+
+static int init_copy(void **a, void *b)
+{
+ int err;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ if ((err = init_mpi(a)) != CRYPT_OK) return err;
+ return mpi_to_ltc_error(mp_init_copy(*a, b));
+}
+
+/* ---- trivial ---- */
+static int set_int(void *a, ltc_mp_digit b)
+{
+ LTC_ARGCHK(a != NULL);
+#ifdef BN_MP_SET_INT_C
+ return mpi_to_ltc_error(mp_set_int(a, b));
+#else
+ mp_set_u32(a, b);
+ return CRYPT_OK;
+#endif
+}
+
+static unsigned long get_int(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+#ifdef BN_MP_GET_INT_C
+ return mp_get_int(a);
+#else
+ return mp_get_ul(a);
+#endif
+}
+
+static ltc_mp_digit get_digit(void *a, int n)
+{
+ mp_int *A;
+ LTC_ARGCHK(a != NULL);
+ A = a;
+ return (n >= A->used || n < 0) ? 0 : A->dp[n];
+}
+
+static int get_digit_count(void *a)
+{
+ mp_int *A;
+ LTC_ARGCHK(a != NULL);
+ A = a;
+ return A->used;
+}
+
+static int compare(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ switch (mp_cmp(a, b)) {
+ case MP_LT: return LTC_MP_LT;
+ case MP_EQ: return LTC_MP_EQ;
+ case MP_GT: return LTC_MP_GT;
+ default: return 0;
+ }
+}
+
+static int compare_d(void *a, ltc_mp_digit b)
+{
+ LTC_ARGCHK(a != NULL);
+ switch (mp_cmp_d(a, b)) {
+ case MP_LT: return LTC_MP_LT;
+ case MP_EQ: return LTC_MP_EQ;
+ case MP_GT: return LTC_MP_GT;
+ default: return 0;
+ }
+}
+
+static int count_bits(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mp_count_bits(a);
+}
+
+static int count_lsb_bits(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mp_cnt_lsb(a);
+}
+
+
+static int twoexpt(void *a, int n)
+{
+ LTC_ARGCHK(a != NULL);
+ return mpi_to_ltc_error(mp_2expt(a, n));
+}
+
+/* ---- conversions ---- */
+
+/* read ascii string */
+static int read_radix(void *a, const char *b, int radix)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_read_radix(a, b, radix));
+}
+
+/* write one */
+static int write_radix(void *a, char *b, int radix)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+#ifdef BN_MP_TORADIX_C
+ return mpi_to_ltc_error(mp_toradix(a, b, radix));
+#else
+ return mpi_to_ltc_error(mp_to_radix(a, b, SIZE_MAX, NULL, radix));
+#endif
+}
+
+/* get size as unsigned char string */
+static unsigned long unsigned_size(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
+ return mp_unsigned_bin_size(a);
+#else
+ return (unsigned long)mp_ubin_size(a);
+#endif
+}
+
+/* store */
+static int unsigned_write(void *a, unsigned char *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+#ifdef BN_MP_TO_UNSIGNED_BIN_C
+ return mpi_to_ltc_error(mp_to_unsigned_bin(a, b));
+#else
+ return mpi_to_ltc_error(mp_to_ubin(a, b, SIZE_MAX, NULL));
+#endif
+}
+
+/* read */
+static int unsigned_read(void *a, unsigned char *b, unsigned long len)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+#ifdef BN_MP_READ_UNSIGNED_BIN_C
+ return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len));
+#else
+ return mpi_to_ltc_error(mp_from_ubin(a, b, (size_t)len));
+#endif
+}
+
+/* add */
+static int add(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_add(a, b, c));
+}
+
+static int addi(void *a, ltc_mp_digit b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_add_d(a, b, c));
+}
+
+/* sub */
+static int sub(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_sub(a, b, c));
+}
+
+static int subi(void *a, ltc_mp_digit b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_sub_d(a, b, c));
+}
+
+/* mul */
+static int mul(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_mul(a, b, c));
+}
+
+static int muli(void *a, ltc_mp_digit b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_mul_d(a, b, c));
+}
+
+/* sqr */
+static int sqr(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_sqr(a, b));
+}
+
+/* sqrtmod_prime */
+static int sqrtmod_prime(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_sqrtmod_prime(a, b, c));
+}
+
+/* div */
+static int divide(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_div(a, b, c, d));
+}
+
+static int div_2(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_div_2(a, b));
+}
+
+/* modi */
+static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c)
+{
+ mp_digit tmp;
+ int err;
+
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+
+ if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) {
+ return err;
+ }
+ *c = tmp;
+ return CRYPT_OK;
+}
+
+/* gcd */
+static int gcd(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_gcd(a, b, c));
+}
+
+/* lcm */
+static int lcm(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_lcm(a, b, c));
+}
+
+static int addmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return mpi_to_ltc_error(mp_addmod(a,b,c,d));
+}
+
+static int submod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return mpi_to_ltc_error(mp_submod(a,b,c,d));
+}
+
+static int mulmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return mpi_to_ltc_error(mp_mulmod(a,b,c,d));
+}
+
+static int sqrmod(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_sqrmod(a,b,c));
+}
+
+/* invmod */
+static int invmod(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_invmod(a, b, c));
+}
+
+/* setup */
+static int montgomery_setup(void *a, void **b)
+{
+ int err;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ *b = XCALLOC(1, sizeof(mp_digit));
+ if (*b == NULL) {
+ return CRYPT_MEM;
+ }
+ if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, (mp_digit *)*b))) != CRYPT_OK) {
+ XFREE(*b);
+ }
+ return err;
+}
+
+/* get normalization value */
+static int montgomery_normalization(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b));
+}
+
+/* reduce */
+static int montgomery_reduce(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c)));
+}
+
+/* clean up */
+static void montgomery_deinit(void *a)
+{
+ XFREE(a);
+}
+
+static int exptmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return mpi_to_ltc_error(mp_exptmod(a,b,c,d));
+}
+
+static int isprime(void *a, int b, int *c)
+{
+ int err;
+#if defined(PRIVATE_MP_WARRAY) || defined(BN_MP_PRIME_IS_PRIME_C)
+ int res;
+#else
+ bool res;
+#endif
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ b = mp_prime_rabin_miller_trials(mp_count_bits(a));
+ err = mpi_to_ltc_error(mp_prime_is_prime(a, b, &res));
+ *c = res ? LTC_MP_YES : LTC_MP_NO;
+ return err;
+}
+
+static int set_rand(void *a, int size)
+{
+ LTC_ARGCHK(a != NULL);
+ return mpi_to_ltc_error(mp_rand(a, size));
+}
+
+#ifndef MP_DIGIT_BIT
+#define MP_DIGIT_BIT DIGIT_BIT
+#endif
+
+const ltc_math_descriptor ltm_desc = {
+
+ "LibTomMath",
+ (int)MP_DIGIT_BIT,
+
+ &init,
+ &init_copy,
+ &deinit,
+
+ &neg,
+ ©,
+
+ &set_int,
+ &get_int,
+ &get_digit,
+ &get_digit_count,
+ &compare,
+ &compare_d,
+ &count_bits,
+ &count_lsb_bits,
+ &twoexpt,
+
+ &read_radix,
+ &write_radix,
+ &unsigned_size,
+ &unsigned_write,
+ &unsigned_read,
+
+ &add,
+ &addi,
+ &sub,
+ &subi,
+ &mul,
+ &muli,
+ &sqr,
+ &sqrtmod_prime,
+ ÷,
+ &div_2,
+ &modi,
+ &gcd,
+ &lcm,
+
+ &mulmod,
+ &sqrmod,
+ &invmod,
+
+ &montgomery_setup,
+ &montgomery_normalization,
+ &montgomery_reduce,
+ &montgomery_deinit,
+
+ &exptmod,
+ &isprime,
+
+#ifdef LTC_MECC
+#ifdef LTC_MECC_FP
+ <c_ecc_fp_mulmod,
+#else
+ <c_ecc_mulmod,
+#endif
+ <c_ecc_projective_add_point,
+ <c_ecc_projective_dbl_point,
+ <c_ecc_map,
+#ifdef LTC_ECC_SHAMIR
+#ifdef LTC_MECC_FP
+ <c_ecc_fp_mul2add,
+#else
+ <c_ecc_mul2add,
+#endif /* LTC_MECC_FP */
+#else
+ NULL,
+#endif /* LTC_ECC_SHAMIR */
+#else
+ NULL, NULL, NULL, NULL, NULL,
+#endif /* LTC_MECC */
+
+#ifdef LTC_MRSA
+ &rsa_make_key,
+ &rsa_exptmod,
+#else
+ NULL, NULL,
+#endif
+ &addmod,
+ &submod,
+
+ &set_rand,
+
+};
+
+
+#endif
diff --git a/Sources/libtomcrypt/math/multi.c b/Sources/libtomcrypt/math/multi.c
new file mode 100644
index 00000000..a88497bb
--- /dev/null
+++ b/Sources/libtomcrypt/math/multi.c
@@ -0,0 +1,66 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MPI
+#include
+
+int ltc_init_multi(void **a, ...)
+{
+ void **cur = a;
+ int np = 0;
+ va_list args;
+
+ va_start(args, a);
+ while (cur != NULL) {
+ if (mp_init(cur) != CRYPT_OK) {
+ /* failed */
+ va_list clean_list;
+
+ va_start(clean_list, a);
+ cur = a;
+ while (np--) {
+ mp_clear(*cur);
+ cur = va_arg(clean_list, void**);
+ }
+ va_end(clean_list);
+ va_end(args);
+ return CRYPT_MEM;
+ }
+ ++np;
+ cur = va_arg(args, void**);
+ }
+ va_end(args);
+ return CRYPT_OK;
+}
+
+void ltc_deinit_multi(void *a, ...)
+{
+ void *cur = a;
+ va_list args;
+
+ va_start(args, a);
+ while (cur != NULL) {
+ mp_clear(cur);
+ cur = va_arg(args, void *);
+ }
+ va_end(args);
+}
+
+void ltc_cleanup_multi(void **a, ...)
+{
+ void **cur = a;
+ va_list args;
+
+ va_start(args, a);
+ while (cur != NULL) {
+ if (*cur != NULL) {
+ mp_clear(*cur);
+ *cur = NULL;
+ }
+ cur = va_arg(args, void**);
+ }
+ va_end(args);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/math/radix_to_bin.c b/Sources/libtomcrypt/math/radix_to_bin.c
new file mode 100644
index 00000000..5c17f0d2
--- /dev/null
+++ b/Sources/libtomcrypt/math/radix_to_bin.c
@@ -0,0 +1,52 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file radix_to_bin.c
+ Convert data from a specific radix to binary.
+ Steffen Jaeckel
+*/
+
+/**
+ Convert data from a specific radix to binary
+
+ The default MPI descriptors #ltm_desc, #tfm_desc and #gmp_desc
+ have the following restrictions on parameters:
+
+ \p in - NUL-terminated char buffer
+
+ \p radix - 2..64
+
+ @param in The input
+ @param radix The radix of the input
+ @param out The output buffer
+ @param len [in/out] The length of the output buffer
+
+ @return CRYPT_OK on success.
+*/
+int radix_to_bin(const void *in, int radix, void *out, unsigned long *len)
+{
+ unsigned long l;
+ void* mpi;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(len != NULL);
+
+ if ((err = mp_init(&mpi)) != CRYPT_OK) return err;
+ if ((err = mp_read_radix(mpi, in, radix)) != CRYPT_OK) goto LBL_ERR;
+
+ if ((l = mp_unsigned_bin_size(mpi)) > *len) {
+ *len = l;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+ *len = l;
+
+ if ((err = mp_to_unsigned_bin(mpi, out)) != CRYPT_OK) goto LBL_ERR;
+
+LBL_ERR:
+ mp_clear(mpi);
+ return err;
+}
diff --git a/Sources/libtomcrypt/math/rand_bn.c b/Sources/libtomcrypt/math/rand_bn.c
new file mode 100644
index 00000000..03a81b7e
--- /dev/null
+++ b/Sources/libtomcrypt/math/rand_bn.c
@@ -0,0 +1,65 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#if defined(LTC_MDSA) || defined(LTC_MECC)
+/**
+ Generate a random number N with given bitlength (note: MSB can be 0)
+*/
+
+int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng)
+{
+ int res, bytes;
+ unsigned char *buf, mask;
+
+ LTC_ARGCHK(N != NULL);
+ LTC_ARGCHK(bits > 1);
+
+ /* check PRNG */
+ if ((res = prng_is_valid(wprng)) != CRYPT_OK) return res;
+
+ bytes = (bits+7) >> 3;
+ mask = 0xff >> (bits % 8 == 0 ? 0 : 8 - bits % 8);
+
+ /* allocate buffer */
+ if ((buf = XCALLOC(1, bytes)) == NULL) return CRYPT_MEM;
+
+ /* generate random bytes */
+ if (prng_descriptor[wprng].read(buf, bytes, prng) != (unsigned long)bytes) {
+ res = CRYPT_ERROR_READPRNG;
+ goto cleanup;
+ }
+ /* mask bits */
+ buf[0] &= mask;
+ /* load value */
+ if ((res = mp_read_unsigned_bin(N, buf, bytes)) != CRYPT_OK) goto cleanup;
+
+ res = CRYPT_OK;
+
+cleanup:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, bytes);
+#endif
+ XFREE(buf);
+ return res;
+}
+
+/**
+ Generate a random number N in a range: 1 <= N < limit
+*/
+int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng)
+{
+ int res, bits;
+
+ LTC_ARGCHK(N != NULL);
+ LTC_ARGCHK(limit != NULL);
+
+ bits = mp_count_bits(limit);
+ do {
+ res = rand_bn_bits(N, bits, prng, wprng);
+ if (res != CRYPT_OK) return res;
+ } while (mp_cmp_d(N, 0) != LTC_MP_GT || mp_cmp(N, limit) != LTC_MP_LT);
+
+ return CRYPT_OK;
+}
+#endif
diff --git a/Sources/libtomcrypt/math/rand_prime.c b/Sources/libtomcrypt/math/rand_prime.c
new file mode 100644
index 00000000..498912cb
--- /dev/null
+++ b/Sources/libtomcrypt/math/rand_prime.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#if defined(LTC_MRSA) || (!defined(LTC_NO_MATH) && !defined(LTC_NO_PRNGS))
+
+/**
+ @file rand_prime.c
+ Generate a random prime, Tom St Denis
+*/
+
+#define USE_BBS 1
+
+int rand_prime(void *N, long len, prng_state *prng, int wprng)
+{
+ int err, res, type;
+ unsigned char *buf;
+
+ LTC_ARGCHK(N != NULL);
+
+ /* get type */
+ if (len < 0) {
+ type = USE_BBS;
+ len = -len;
+ } else {
+ type = 0;
+ }
+
+ /* allow sizes between 2 and 512 bytes for a prime size */
+ if (len < 2 || len > 512) {
+ return CRYPT_INVALID_PRIME_SIZE;
+ }
+
+ /* valid PRNG? Better be! */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* allocate buffer to work with */
+ buf = XCALLOC(1, len);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ do {
+ /* generate value */
+ if (prng_descriptor[wprng].read(buf, len, prng) != (unsigned long)len) {
+ XFREE(buf);
+ return CRYPT_ERROR_READPRNG;
+ }
+
+ /* munge bits */
+ buf[0] |= 0x80 | 0x40;
+ buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
+
+ /* load value */
+ if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+
+ /* test */
+ if ((err = mp_prime_is_prime(N, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+ } while (res == LTC_MP_NO);
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, len);
+#endif
+
+ XFREE(buf);
+ return CRYPT_OK;
+}
+
+#endif /* LTC_NO_MATH */
+
diff --git a/Sources/libtomcrypt/math/tfm_desc.c b/Sources/libtomcrypt/math/tfm_desc.c
new file mode 100644
index 00000000..cee753a1
--- /dev/null
+++ b/Sources/libtomcrypt/math/tfm_desc.c
@@ -0,0 +1,857 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#define DESC_DEF_ONLY
+#include "tomcrypt_private.h"
+
+#ifdef TFM_DESC
+
+#include
+
+static const struct {
+ int tfm_code, ltc_code;
+} tfm_to_ltc_codes[] = {
+ { FP_OKAY , CRYPT_OK},
+ { FP_MEM , CRYPT_MEM},
+ { FP_VAL , CRYPT_INVALID_ARG},
+};
+
+/**
+ Convert a tfm error to a LTC error (Possibly the most powerful function ever! Oh wait... no)
+ @param err The error to convert
+ @return The equivalent LTC error code or CRYPT_ERROR if none found
+*/
+static int tfm_to_ltc_error(int err)
+{
+ int x;
+
+ for (x = 0; x < (int)(sizeof(tfm_to_ltc_codes)/sizeof(tfm_to_ltc_codes[0])); x++) {
+ if (err == tfm_to_ltc_codes[x].tfm_code) {
+ return tfm_to_ltc_codes[x].ltc_code;
+ }
+ }
+ return CRYPT_ERROR;
+}
+
+static int init(void **a)
+{
+ LTC_ARGCHK(a != NULL);
+
+ *a = XCALLOC(1, sizeof(fp_int));
+ if (*a == NULL) {
+ return CRYPT_MEM;
+ }
+ fp_init(*a);
+ return CRYPT_OK;
+}
+
+static void deinit(void *a)
+{
+ LTC_ARGCHKVD(a != NULL);
+ XFREE(a);
+}
+
+static int neg(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ fp_neg(((fp_int*)a), ((fp_int*)b));
+ return CRYPT_OK;
+}
+
+static int copy(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ fp_copy(a, b);
+ return CRYPT_OK;
+}
+
+static int init_copy(void **a, void *b)
+{
+ if (init(a) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+ return copy(b, *a);
+}
+
+/* ---- trivial ---- */
+static int set_int(void *a, ltc_mp_digit b)
+{
+ LTC_ARGCHK(a != NULL);
+ fp_set(a, b);
+ return CRYPT_OK;
+}
+
+static unsigned long get_int(void *a)
+{
+ fp_int *A;
+ LTC_ARGCHK(a != NULL);
+ A = a;
+ return A->used > 0 ? A->dp[0] : 0;
+}
+
+static ltc_mp_digit get_digit(void *a, int n)
+{
+ fp_int *A;
+ LTC_ARGCHK(a != NULL);
+ A = a;
+ return (n >= A->used || n < 0) ? 0 : A->dp[n];
+}
+
+static int get_digit_count(void *a)
+{
+ fp_int *A;
+ LTC_ARGCHK(a != NULL);
+ A = a;
+ return A->used;
+}
+
+static int compare(void *a, void *b)
+{
+ int ret;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ ret = fp_cmp(a, b);
+ switch (ret) {
+ case FP_LT: return LTC_MP_LT;
+ case FP_EQ: return LTC_MP_EQ;
+ case FP_GT: return LTC_MP_GT;
+ }
+ return 0;
+}
+
+static int compare_d(void *a, ltc_mp_digit b)
+{
+ int ret;
+ LTC_ARGCHK(a != NULL);
+ ret = fp_cmp_d(a, b);
+ switch (ret) {
+ case FP_LT: return LTC_MP_LT;
+ case FP_EQ: return LTC_MP_EQ;
+ case FP_GT: return LTC_MP_GT;
+ }
+ return 0;
+}
+
+static int count_bits(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return fp_count_bits(a);
+}
+
+static int count_lsb_bits(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return fp_cnt_lsb(a);
+}
+
+static int twoexpt(void *a, int n)
+{
+ LTC_ARGCHK(a != NULL);
+ fp_2expt(a, n);
+ return CRYPT_OK;
+}
+
+/* ---- conversions ---- */
+
+/* read ascii string */
+static int read_radix(void *a, const char *b, int radix)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return tfm_to_ltc_error(fp_read_radix(a, (char *)b, radix));
+}
+
+/* write one */
+static int write_radix(void *a, char *b, int radix)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return tfm_to_ltc_error(fp_toradix(a, b, radix));
+}
+
+/* get size as unsigned char string */
+static unsigned long unsigned_size(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return fp_unsigned_bin_size(a);
+}
+
+/* store */
+static int unsigned_write(void *a, unsigned char *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ fp_to_unsigned_bin(a, b);
+ return CRYPT_OK;
+}
+
+/* read */
+static int unsigned_read(void *a, unsigned char *b, unsigned long len)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ fp_read_unsigned_bin(a, b, len);
+ return CRYPT_OK;
+}
+
+/* add */
+static int add(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ fp_add(a, b, c);
+ return CRYPT_OK;
+}
+
+static int addi(void *a, ltc_mp_digit b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ fp_add_d(a, b, c);
+ return CRYPT_OK;
+}
+
+/* sub */
+static int sub(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ fp_sub(a, b, c);
+ return CRYPT_OK;
+}
+
+static int subi(void *a, ltc_mp_digit b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ fp_sub_d(a, b, c);
+ return CRYPT_OK;
+}
+
+/* mul */
+static int mul(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ fp_mul(a, b, c);
+ return CRYPT_OK;
+}
+
+static int muli(void *a, ltc_mp_digit b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ fp_mul_d(a, b, c);
+ return CRYPT_OK;
+}
+
+/* sqr */
+static int sqr(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ fp_sqr(a, b);
+ return CRYPT_OK;
+}
+
+/* sqrtmod_prime - NOT SUPPORTED */
+
+/* div */
+static int divide(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return tfm_to_ltc_error(fp_div(a, b, c, d));
+}
+
+static int div_2(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ fp_div_2(a, b);
+ return CRYPT_OK;
+}
+
+/* modi */
+static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c)
+{
+ fp_digit tmp;
+ int err;
+
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+
+ if ((err = tfm_to_ltc_error(fp_mod_d(a, b, &tmp))) != CRYPT_OK) {
+ return err;
+ }
+ *c = tmp;
+ return CRYPT_OK;
+}
+
+/* gcd */
+static int gcd(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ fp_gcd(a, b, c);
+ return CRYPT_OK;
+}
+
+/* lcm */
+static int lcm(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ fp_lcm(a, b, c);
+ return CRYPT_OK;
+}
+
+static int addmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return tfm_to_ltc_error(fp_addmod(a,b,c,d));
+}
+
+static int submod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return tfm_to_ltc_error(fp_submod(a,b,c,d));
+}
+
+static int mulmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return tfm_to_ltc_error(fp_mulmod(a,b,c,d));
+}
+
+static int sqrmod(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return tfm_to_ltc_error(fp_sqrmod(a,b,c));
+}
+
+/* invmod */
+static int invmod(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return tfm_to_ltc_error(fp_invmod(a, b, c));
+}
+
+/* setup */
+static int montgomery_setup(void *a, void **b)
+{
+ int err;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ *b = XCALLOC(1, sizeof(fp_digit));
+ if (*b == NULL) {
+ return CRYPT_MEM;
+ }
+ if ((err = tfm_to_ltc_error(fp_montgomery_setup(a, (fp_digit *)*b))) != CRYPT_OK) {
+ XFREE(*b);
+ }
+ return err;
+}
+
+/* get normalization value */
+static int montgomery_normalization(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ fp_montgomery_calc_normalization(a, b);
+ return CRYPT_OK;
+}
+
+/* reduce */
+static int montgomery_reduce(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ fp_montgomery_reduce(a, b, *((fp_digit *)c));
+ return CRYPT_OK;
+}
+
+/* clean up */
+static void montgomery_deinit(void *a)
+{
+ XFREE(a);
+}
+
+static int exptmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return tfm_to_ltc_error(fp_exptmod(a,b,c,d));
+}
+
+static int isprime(void *a, int b, int *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ if (b == 0) {
+ b = LTC_MILLER_RABIN_REPS;
+ } /* if */
+ *c = (fp_isprime_ex(a, b) == FP_YES) ? LTC_MP_YES : LTC_MP_NO;
+ return CRYPT_OK;
+}
+
+#if defined(LTC_MECC) && defined(LTC_MECC_ACCEL)
+
+static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *Mp)
+{
+ fp_int t1, t2;
+ fp_digit mp;
+ int err, inf;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(Mp != NULL);
+
+ mp = *((fp_digit*)Mp);
+
+ fp_init(&t1);
+ fp_init(&t2);
+
+ if (P != R) {
+ fp_copy(P->x, R->x);
+ fp_copy(P->y, R->y);
+ fp_copy(P->z, R->z);
+ }
+
+ if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
+ if (inf) {
+ /* if P is point at infinity >> Result = point at infinity */
+ ltc_mp.set_int(R->x, 1);
+ ltc_mp.set_int(R->y, 1);
+ ltc_mp.set_int(R->z, 0);
+ return CRYPT_OK;
+ }
+
+ /* t1 = Z * Z */
+ fp_sqr(R->z, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+ /* Z = Y * Z */
+ fp_mul(R->z, R->y, R->z);
+ fp_montgomery_reduce(R->z, modulus, mp);
+ /* Z = 2Z */
+ fp_add(R->z, R->z, R->z);
+ if (fp_cmp(R->z, modulus) != FP_LT) {
+ fp_sub(R->z, modulus, R->z);
+ }
+
+ if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */
+ /* T2 = X - T1 */
+ fp_sub(R->x, &t1, &t2);
+ if (fp_cmp_d(&t2, 0) == LTC_MP_LT) {
+ fp_add(&t2, modulus, &t2);
+ }
+ /* T1 = X + T1 */
+ fp_add(&t1, R->x, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* T2 = T1 * T2 */
+ fp_mul(&t1, &t2, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* T1 = 2T2 */
+ fp_add(&t2, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* T1 = T1 + T2 */
+ fp_add(&t1, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ }
+ else {
+ /* T2 = T1 * T1 */
+ fp_sqr(&t1, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* T1 = T2 * a */
+ fp_mul(&t2, ma, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+ /* T2 = X * X */
+ fp_sqr(R->x, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* T1 = T1 + T2 */
+ fp_add(&t1, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* T1 = T1 + T2 */
+ fp_add(&t1, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* T1 = T1 + T2 */
+ fp_add(&t1, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ }
+
+ /* Y = 2Y */
+ fp_add(R->y, R->y, R->y);
+ if (fp_cmp(R->y, modulus) != FP_LT) {
+ fp_sub(R->y, modulus, R->y);
+ }
+ /* Y = Y * Y */
+ fp_sqr(R->y, R->y);
+ fp_montgomery_reduce(R->y, modulus, mp);
+ /* T2 = Y * Y */
+ fp_sqr(R->y, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* T2 = T2/2 */
+ if (fp_isodd(&t2)) {
+ fp_add(&t2, modulus, &t2);
+ }
+ fp_div_2(&t2, &t2);
+ /* Y = Y * X */
+ fp_mul(R->y, R->x, R->y);
+ fp_montgomery_reduce(R->y, modulus, mp);
+
+ /* X = T1 * T1 */
+ fp_sqr(&t1, R->x);
+ fp_montgomery_reduce(R->x, modulus, mp);
+ /* X = X - Y */
+ fp_sub(R->x, R->y, R->x);
+ if (fp_cmp_d(R->x, 0) == FP_LT) {
+ fp_add(R->x, modulus, R->x);
+ }
+ /* X = X - Y */
+ fp_sub(R->x, R->y, R->x);
+ if (fp_cmp_d(R->x, 0) == FP_LT) {
+ fp_add(R->x, modulus, R->x);
+ }
+
+ /* Y = Y - X */
+ fp_sub(R->y, R->x, R->y);
+ if (fp_cmp_d(R->y, 0) == FP_LT) {
+ fp_add(R->y, modulus, R->y);
+ }
+ /* Y = Y * T1 */
+ fp_mul(R->y, &t1, R->y);
+ fp_montgomery_reduce(R->y, modulus, mp);
+ /* Y = Y - T2 */
+ fp_sub(R->y, &t2, R->y);
+ if (fp_cmp_d(R->y, 0) == FP_LT) {
+ fp_add(R->y, modulus, R->y);
+ }
+
+ return CRYPT_OK;
+}
+
+/**
+ Add two ECC points
+ @param P The point to add
+ @param Q The point to add
+ @param R [out] The destination of the double
+ @param modulus The modulus of the field the ECC curve is in
+ @param Mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *Mp)
+{
+ fp_int t1, t2, x, y, z;
+ fp_digit mp;
+ int err, inf;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(Q != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(Mp != NULL);
+
+ mp = *((fp_digit*)Mp);
+
+ fp_init(&t1);
+ fp_init(&t2);
+ fp_init(&x);
+ fp_init(&y);
+ fp_init(&z);
+
+ if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
+ if (inf) {
+ /* P is point at infinity >> Result = Q */
+ ltc_mp.copy(Q->x, R->x);
+ ltc_mp.copy(Q->y, R->y);
+ ltc_mp.copy(Q->z, R->z);
+ return CRYPT_OK;
+ }
+
+ if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err;
+ if (inf) {
+ /* Q is point at infinity >> Result = P */
+ ltc_mp.copy(P->x, R->x);
+ ltc_mp.copy(P->y, R->y);
+ ltc_mp.copy(P->z, R->z);
+ return CRYPT_OK;
+ }
+
+ /* should we dbl instead? */
+ fp_sub(modulus, Q->y, &t1);
+ if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
+ (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) &&
+ (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
+ return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp);
+ }
+
+ fp_copy(P->x, &x);
+ fp_copy(P->y, &y);
+ fp_copy(P->z, &z);
+
+ /* if Z is one then these are no-operations */
+ if (Q->z != NULL) {
+ /* T1 = Z' * Z' */
+ fp_sqr(Q->z, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+ /* X = X * T1 */
+ fp_mul(&t1, &x, &x);
+ fp_montgomery_reduce(&x, modulus, mp);
+ /* T1 = Z' * T1 */
+ fp_mul(Q->z, &t1, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+ /* Y = Y * T1 */
+ fp_mul(&t1, &y, &y);
+ fp_montgomery_reduce(&y, modulus, mp);
+ }
+
+ /* T1 = Z*Z */
+ fp_sqr(&z, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+ /* T2 = X' * T1 */
+ fp_mul(Q->x, &t1, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* T1 = Z * T1 */
+ fp_mul(&z, &t1, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+ /* T1 = Y' * T1 */
+ fp_mul(Q->y, &t1, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+
+ /* Y = Y - T1 */
+ fp_sub(&y, &t1, &y);
+ if (fp_cmp_d(&y, 0) == FP_LT) {
+ fp_add(&y, modulus, &y);
+ }
+ /* T1 = 2T1 */
+ fp_add(&t1, &t1, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* T1 = Y + T1 */
+ fp_add(&t1, &y, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* X = X - T2 */
+ fp_sub(&x, &t2, &x);
+ if (fp_cmp_d(&x, 0) == FP_LT) {
+ fp_add(&x, modulus, &x);
+ }
+ /* T2 = 2T2 */
+ fp_add(&t2, &t2, &t2);
+ if (fp_cmp(&t2, modulus) != FP_LT) {
+ fp_sub(&t2, modulus, &t2);
+ }
+ /* T2 = X + T2 */
+ fp_add(&t2, &x, &t2);
+ if (fp_cmp(&t2, modulus) != FP_LT) {
+ fp_sub(&t2, modulus, &t2);
+ }
+
+ /* if Z' != 1 */
+ if (Q->z != NULL) {
+ /* Z = Z * Z' */
+ fp_mul(&z, Q->z, &z);
+ fp_montgomery_reduce(&z, modulus, mp);
+ }
+
+ /* Z = Z * X */
+ fp_mul(&z, &x, &z);
+ fp_montgomery_reduce(&z, modulus, mp);
+
+ /* T1 = T1 * X */
+ fp_mul(&t1, &x, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+ /* X = X * X */
+ fp_sqr(&x, &x);
+ fp_montgomery_reduce(&x, modulus, mp);
+ /* T2 = T2 * x */
+ fp_mul(&t2, &x, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* T1 = T1 * X */
+ fp_mul(&t1, &x, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+
+ /* X = Y*Y */
+ fp_sqr(&y, &x);
+ fp_montgomery_reduce(&x, modulus, mp);
+ /* X = X - T2 */
+ fp_sub(&x, &t2, &x);
+ if (fp_cmp_d(&x, 0) == FP_LT) {
+ fp_add(&x, modulus, &x);
+ }
+
+ /* T2 = T2 - X */
+ fp_sub(&t2, &x, &t2);
+ if (fp_cmp_d(&t2, 0) == FP_LT) {
+ fp_add(&t2, modulus, &t2);
+ }
+ /* T2 = T2 - X */
+ fp_sub(&t2, &x, &t2);
+ if (fp_cmp_d(&t2, 0) == FP_LT) {
+ fp_add(&t2, modulus, &t2);
+ }
+ /* T2 = T2 * Y */
+ fp_mul(&t2, &y, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* Y = T2 - T1 */
+ fp_sub(&t2, &t1, &y);
+ if (fp_cmp_d(&y, 0) == FP_LT) {
+ fp_add(&y, modulus, &y);
+ }
+ /* Y = Y/2 */
+ if (fp_isodd(&y)) {
+ fp_add(&y, modulus, &y);
+ }
+ fp_div_2(&y, &y);
+
+ fp_copy(&x, R->x);
+ fp_copy(&y, R->y);
+ fp_copy(&z, R->z);
+
+ return CRYPT_OK;
+}
+
+
+#endif
+
+static int set_rand(void *a, int size)
+{
+ LTC_ARGCHK(a != NULL);
+ fp_rand(a, size);
+ return CRYPT_OK;
+}
+
+const ltc_math_descriptor tfm_desc = {
+
+ "TomsFastMath",
+ (int)DIGIT_BIT,
+
+ &init,
+ &init_copy,
+ &deinit,
+
+ &neg,
+ ©,
+
+ &set_int,
+ &get_int,
+ &get_digit,
+ &get_digit_count,
+ &compare,
+ &compare_d,
+ &count_bits,
+ &count_lsb_bits,
+ &twoexpt,
+
+ &read_radix,
+ &write_radix,
+ &unsigned_size,
+ &unsigned_write,
+ &unsigned_read,
+
+ &add,
+ &addi,
+ &sub,
+ &subi,
+ &mul,
+ &muli,
+ &sqr,
+ NULL, /* TODO: &sqrtmod_prime */
+ ÷,
+ &div_2,
+ &modi,
+ &gcd,
+ &lcm,
+
+ &mulmod,
+ &sqrmod,
+ &invmod,
+
+ &montgomery_setup,
+ &montgomery_normalization,
+ &montgomery_reduce,
+ &montgomery_deinit,
+
+ &exptmod,
+ &isprime,
+
+#ifdef LTC_MECC
+#ifdef LTC_MECC_FP
+ <c_ecc_fp_mulmod,
+#else
+ <c_ecc_mulmod,
+#endif /* LTC_MECC_FP */
+#ifdef LTC_MECC_ACCEL
+ &tfm_ecc_projective_add_point,
+ &tfm_ecc_projective_dbl_point,
+#else
+ <c_ecc_projective_add_point,
+ <c_ecc_projective_dbl_point,
+#endif /* LTC_MECC_ACCEL */
+ <c_ecc_map,
+#ifdef LTC_ECC_SHAMIR
+#ifdef LTC_MECC_FP
+ <c_ecc_fp_mul2add,
+#else
+ <c_ecc_mul2add,
+#endif /* LTC_MECC_FP */
+#else
+ NULL,
+#endif /* LTC_ECC_SHAMIR */
+#else
+ NULL, NULL, NULL, NULL, NULL,
+#endif /* LTC_MECC */
+
+#ifdef LTC_MRSA
+ &rsa_make_key,
+ &rsa_exptmod,
+#else
+ NULL, NULL,
+#endif
+ &addmod,
+ &submod,
+
+ set_rand,
+
+};
+
+
+#endif
diff --git a/Sources/libtomcrypt/misc/adler32.c b/Sources/libtomcrypt/misc/adler32.c
new file mode 100644
index 00000000..8c2953d3
--- /dev/null
+++ b/Sources/libtomcrypt/misc/adler32.c
@@ -0,0 +1,123 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file adler32.c
+ Adler-32 checksum algorithm
+ Written and placed in the public domain by Wei Dai
+ Adapted for libtomcrypt by Steffen Jaeckel
+*/
+#ifdef LTC_ADLER32
+
+static const unsigned long s_adler32_base = 65521;
+
+void adler32_init(adler32_state *ctx)
+{
+ LTC_ARGCHKVD(ctx != NULL);
+ ctx->s[0] = 1;
+ ctx->s[1] = 0;
+}
+
+void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length)
+{
+ unsigned long s1, s2;
+
+ LTC_ARGCHKVD(ctx != NULL);
+ LTC_ARGCHKVD(input != NULL);
+ s1 = ctx->s[0];
+ s2 = ctx->s[1];
+
+ if (length % 8 != 0) {
+ do {
+ s1 += *input++;
+ s2 += s1;
+ length--;
+ } while (length % 8 != 0);
+
+ if (s1 >= s_adler32_base) {
+ s1 -= s_adler32_base;
+ }
+ s2 %= s_adler32_base;
+ }
+
+ while (length > 0) {
+ s1 += input[0];
+ s2 += s1;
+ s1 += input[1];
+ s2 += s1;
+ s1 += input[2];
+ s2 += s1;
+ s1 += input[3];
+ s2 += s1;
+ s1 += input[4];
+ s2 += s1;
+ s1 += input[5];
+ s2 += s1;
+ s1 += input[6];
+ s2 += s1;
+ s1 += input[7];
+ s2 += s1;
+
+ length -= 8;
+ input += 8;
+
+ if (s1 >= s_adler32_base) {
+ s1 -= s_adler32_base;
+ }
+ s2 %= s_adler32_base;
+ }
+
+ LTC_ARGCHKVD(s1 < s_adler32_base);
+ LTC_ARGCHKVD(s2 < s_adler32_base);
+
+ ctx->s[0] = (unsigned short)s1;
+ ctx->s[1] = (unsigned short)s2;
+}
+
+void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size)
+{
+ unsigned char* h;
+
+ LTC_ARGCHKVD(ctx != NULL);
+ LTC_ARGCHKVD(hash != NULL);
+
+ h = hash;
+
+ switch (size) {
+ default:
+ h[3] = ctx->s[0] & 0x0ff;
+ /* FALLTHROUGH */
+ case 3:
+ h[2] = (ctx->s[0] >> 8) & 0x0ff;
+ /* FALLTHROUGH */
+ case 2:
+ h[1] = ctx->s[1] & 0x0ff;
+ /* FALLTHROUGH */
+ case 1:
+ h[0] = (ctx->s[1] >> 8) & 0x0ff;
+ /* FALLTHROUGH */
+ case 0:
+ ;
+ }
+}
+
+int adler32_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ const void* in = "libtomcrypt";
+ const unsigned char adler32[] = { 0x1b, 0xe8, 0x04, 0xba };
+ unsigned char out[4];
+ adler32_state ctx;
+ adler32_init(&ctx);
+ adler32_update(&ctx, in, XSTRLEN(in));
+ adler32_finish(&ctx, out, 4);
+ if (compare_testvector(adler32, 4, out, 4, "adler32", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+#endif
+}
+#endif
diff --git a/Sources/libtomcrypt/misc/base16/base16_decode.c b/Sources/libtomcrypt/misc/base16/base16_decode.c
new file mode 100644
index 00000000..8ebc9eac
--- /dev/null
+++ b/Sources/libtomcrypt/misc/base16/base16_decode.c
@@ -0,0 +1,65 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file base16_decode.c
+ Base16/Hex decode a string.
+ Based on https://stackoverflow.com/a/23898449
+ Adapted for libtomcrypt by Steffen Jaeckel
+*/
+
+#ifdef LTC_BASE16
+
+/**
+ Base16 decode a string
+ @param in The Base16 string to decode
+ @param inlen The length of the Base16 data
+ @param out [out] The destination of the binary decoded data
+ @param outlen [in/out] The max size and resulting size of the decoded data
+ @return CRYPT_OK if successful
+*/
+int base16_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long pos, out_len;
+ unsigned char idx0, idx1;
+ char in0, in1;
+
+ const unsigned char hashmap[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
+ 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */
+ 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* @ABCDEFG */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */
+ 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* `abcdefg */
+ };
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((inlen % 2) == 1) return CRYPT_INVALID_PACKET;
+ out_len = *outlen * 2;
+ for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < inlen)); pos += 2) {
+ in0 = in[pos + 0];
+ in1 = in[pos + 1];
+
+ if ((in0 < '0') || (in0 > 'g')) return CRYPT_INVALID_PACKET;
+ if ((in1 < '0') || (in1 > 'g')) return CRYPT_INVALID_PACKET;
+
+ idx0 = (unsigned char) (in0 & 0x1F) ^ 0x10;
+ idx1 = (unsigned char) (in1 & 0x1F) ^ 0x10;
+
+ if (hashmap[idx0] == 0xff) return CRYPT_INVALID_PACKET;
+ if (hashmap[idx1] == 0xff) return CRYPT_INVALID_PACKET;
+
+ out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1];
+ }
+ *outlen = pos / 2;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/base16/base16_encode.c b/Sources/libtomcrypt/misc/base16/base16_encode.c
new file mode 100644
index 00000000..649a4d86
--- /dev/null
+++ b/Sources/libtomcrypt/misc/base16/base16_encode.c
@@ -0,0 +1,64 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file base16_encode.c
+ Base16/Hex encode a string, Steffen Jaeckel
+*/
+
+#ifdef LTC_BASE16
+
+/**
+ Base16 encode a buffer
+ @param in The input buffer to encode
+ @param inlen The length of the input buffer
+ @param out [out] The destination of the Base16 encoded data
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @param options Output 'a-f' on 0 and 'A-F' otherwise.
+ @return CRYPT_OK if successful
+*/
+int base16_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen,
+ unsigned int options)
+{
+ unsigned long i, x;
+ const char *alphabet;
+ const char *alphabets[2] = {
+ "0123456789abcdef",
+ "0123456789ABCDEF",
+ };
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* check the sizes */
+ x = inlen * 2 + 1;
+
+ if (x < inlen) return CRYPT_OVERFLOW;
+
+ if (*outlen < x) {
+ *outlen = x;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ x--;
+ *outlen = x; /* returning the length without terminating NUL */
+
+ if (options == 0) {
+ alphabet = alphabets[0];
+ } else {
+ alphabet = alphabets[1];
+ }
+
+ for (i = 0; i < x; i += 2) {
+ out[i] = alphabet[(in[i/2] >> 4) & 0x0f];
+ out[i+1] = alphabet[in[i/2] & 0x0f];
+ }
+ out[x] = '\0';
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/base32/base32_decode.c b/Sources/libtomcrypt/misc/base32/base32_decode.c
new file mode 100644
index 00000000..fc98ccea
--- /dev/null
+++ b/Sources/libtomcrypt/misc/base32/base32_decode.c
@@ -0,0 +1,111 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BASE32
+
+/**
+ Base32 decode a buffer
+ @param in The Base32 data to decode
+ @param inlen The length of the Base32 data
+ @param out [out] The destination of the binary decoded data
+ @param outlen [in/out] The max size and resulting size of the decoded data
+ @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD
+ @return CRYPT_OK if successful
+*/
+int base32_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ base32_alphabet id)
+{
+ unsigned long x;
+ int y = 0;
+ ulong64 t = 0;
+ char c;
+ const unsigned char *map;
+ const unsigned char tables[4][43] = {
+ { /* id = BASE32_RFC4648 : ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 */
+ 99/*0*/,99/*1*/,26/*2*/,27/*3*/,28/*4*/,29/*5*/,30/*6*/,31/*7*/,99/*8*/,99/*9*/,
+ 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
+ 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, 7/*H*/, 8/*I*/, 9/*J*/,10/*K*/,11/*L*/,12/*M*/,
+ 13/*N*/,14/*O*/,15/*P*/,16/*Q*/,17/*R*/,18/*S*/,19/*T*/,20/*U*/,21/*V*/,22/*W*/,23/*X*/,24/*Y*/,25/*Z*/
+ },
+ { /* id = BASE32_BASE32HEX : 0123456789ABCDEFGHIJKLMNOPQRSTUV */
+ 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/,
+ 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
+ 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/,18/*I*/,19/*J*/,20/*K*/,21/*L*/,22/*M*/,
+ 23/*N*/,24/*O*/,25/*P*/,26/*Q*/,27/*R*/,28/*S*/,29/*T*/,30/*U*/,31/*V*/,99/*W*/,99/*X*/,99/*Y*/,99/*Z*/
+ },
+ { /* id = BASE32_ZBASE32 : YBNDRFG8EJKMCPQXOT1UWISZA345H769 */
+ 99/*0*/,18/*1*/,99/*2*/,25/*3*/,26/*4*/,27/*5*/,30/*6*/,29/*7*/, 7/*8*/,31/*9*/,
+ 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
+ 24/*A*/, 1/*B*/,12/*C*/, 3/*D*/, 8/*E*/, 5/*F*/, 6/*G*/,28/*H*/,21/*I*/, 9/*J*/,10/*K*/,99/*L*/,11/*M*/,
+ 2/*N*/,16/*O*/,13/*P*/,14/*Q*/, 4/*R*/,22/*S*/,17/*T*/,19/*U*/,99/*V*/,20/*W*/,15/*X*/, 0/*Y*/,23/*Z*/
+ },
+ { /* id = BASE32_CROCKFORD : 0123456789ABCDEFGHJKMNPQRSTVWXYZ + O=>0 + IL=>1 */
+ 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/,
+ 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
+ 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/, 1/*I*/,18/*J*/,19/*K*/, 1/*L*/,20/*M*/,
+ 21/*N*/, 0/*O*/,22/*P*/,23/*Q*/,24/*R*/,25/*S*/,26/*T*/,99/*U*/,27/*V*/,28/*W*/,29/*X*/,30/*Y*/,31/*Z*/
+ }
+ };
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(id >= BASE32_RFC4648);
+ LTC_ARGCHK(id <= BASE32_CROCKFORD);
+
+ /* ignore all trailing = */
+ while (inlen > 0 && in[inlen-1] == '=') inlen--;
+
+ /* no input, nothing to do */
+ if (inlen == 0) {
+ *outlen = 0;
+ return CRYPT_OK;
+ }
+
+ /* check the size of output buffer */
+ x = (inlen * 5) / 8;
+ if (*outlen < x) {
+ *outlen = x;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ *outlen = x;
+
+ /* check input data length */
+ x = inlen % 8;
+ if (x == 1 || x == 3 || x == 6) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ map = tables[id];
+ for (x = 0; x < inlen; x++) {
+ c = in[x];
+ /* convert to upper case */
+ if ((c >= 'a') && (c <= 'z')) c -= 32;
+ if (c < '0' || c > 'Z' || map[c-'0'] > 31) {
+ return CRYPT_INVALID_PACKET;
+ }
+ t = (t<<5) | map[c-'0'];
+ if (++y == 8) {
+ *out++ = (unsigned char)((t>>32) & 255);
+ *out++ = (unsigned char)((t>>24) & 255);
+ *out++ = (unsigned char)((t>>16) & 255);
+ *out++ = (unsigned char)((t>> 8) & 255);
+ *out++ = (unsigned char)( t & 255);
+ y = 0;
+ t = 0;
+ }
+ }
+ if (y > 0) {
+ t = t << (5 * (8 - y));
+ if (y >= 2) *out++ = (unsigned char)((t>>32) & 255);
+ if (y >= 4) *out++ = (unsigned char)((t>>24) & 255);
+ if (y >= 5) *out++ = (unsigned char)((t>>16) & 255);
+ if (y >= 7) *out++ = (unsigned char)((t>> 8) & 255);
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/base32/base32_encode.c b/Sources/libtomcrypt/misc/base32/base32_encode.c
new file mode 100644
index 00000000..29519bf7
--- /dev/null
+++ b/Sources/libtomcrypt/misc/base32/base32_encode.c
@@ -0,0 +1,86 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_BASE32
+
+/**
+ Base32 encode a buffer
+ @param in The input buffer to encode
+ @param inlen The length of the input buffer
+ @param out [out] The destination of the Base32 encoded data
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD
+ @return CRYPT_OK if successful
+*/
+int base32_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen,
+ base32_alphabet id)
+{
+ unsigned long i, x;
+ const char *codes;
+ const char *alphabet[4] = {
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", /* id = BASE32_RFC4648 */
+ "0123456789ABCDEFGHIJKLMNOPQRSTUV", /* id = BASE32_BASE32HEX */
+ "ybndrfg8ejkmcpqxot1uwisza345h769", /* id = BASE32_ZBASE32 */
+ "0123456789ABCDEFGHJKMNPQRSTVWXYZ" /* id = BASE32_CROCKFORD */
+ };
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(id >= BASE32_RFC4648);
+ LTC_ARGCHK(id <= BASE32_CROCKFORD);
+
+ /* check the size of output buffer +1 byte for terminating NUL */
+ x = (8 * inlen + 4) / 5 + 1;
+ if (*outlen < x) {
+ *outlen = x;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ *outlen = x - 1; /* returning the length without terminating NUL */
+
+ /* no input, nothing to do */
+ if (inlen == 0) {
+ *out = '\0';
+ return CRYPT_OK;
+ }
+
+ codes = alphabet[id];
+ x = 5 * (inlen / 5);
+ for (i = 0; i < x; i += 5) {
+ *out++ = codes[(in[0] >> 3) & 0x1F];
+ *out++ = codes[(((in[0] & 0x7) << 2) + (in[1] >> 6)) & 0x1F];
+ *out++ = codes[(in[1] >> 1) & 0x1F];
+ *out++ = codes[(((in[1] & 0x1) << 4) + (in[2] >> 4)) & 0x1F];
+ *out++ = codes[(((in[2] & 0xF) << 1) + (in[3] >> 7)) & 0x1F];
+ *out++ = codes[(in[3] >> 2) & 0x1F];
+ *out++ = codes[(((in[3] & 0x3) << 3) + (in[4] >> 5)) & 0x1F];
+ *out++ = codes[in[4] & 0x1F];
+ in += 5;
+ }
+ if (i < inlen) {
+ unsigned a = in[0];
+ unsigned b = (i+1 < inlen) ? in[1] : 0;
+ unsigned c = (i+2 < inlen) ? in[2] : 0;
+ unsigned d = (i+3 < inlen) ? in[3] : 0;
+ *out++ = codes[(a >> 3) & 0x1F];
+ *out++ = codes[(((a & 0x7) << 2) + (b >> 6)) & 0x1F];
+ if (i+1 < inlen) {
+ *out++ = codes[(b >> 1) & 0x1F];
+ *out++ = codes[(((b & 0x1) << 4) + (c >> 4)) & 0x1F];
+ }
+ if (i+2 < inlen) {
+ *out++ = codes[(((c & 0xF) << 1) + (d >> 7)) & 0x1F];
+ }
+ if (i+3 < inlen) {
+ *out++ = codes[(d >> 2) & 0x1F];
+ *out++ = codes[((d & 0x3) << 3) & 0x1F];
+ }
+ }
+ *out = '\0';
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/base64/base64_decode.c b/Sources/libtomcrypt/misc/base64/base64_decode.c
new file mode 100644
index 00000000..20a9ef3e
--- /dev/null
+++ b/Sources/libtomcrypt/misc/base64/base64_decode.c
@@ -0,0 +1,231 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file base64_decode.c
+ Compliant base64 code donated by Wayne Scott (wscott@bitmover.com)
+ base64 URL Safe variant (RFC 4648 section 5) by Karel Miko
+*/
+
+
+#if defined(LTC_BASE64) || defined (LTC_BASE64_URL)
+
+/* 253 - ignored in "relaxed" + "insane" mode: TAB(9), CR(13), LF(10), space(32)
+ * 254 - padding character '=' (allowed only at the end)
+ * 255 - ignored in "insane" mode, but not allowed in "relaxed" + "strict" mode
+ */
+
+#if defined(LTC_BASE64)
+static const unsigned char map_base64[256] = {
+255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255,
+255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
+255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
+255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255 };
+#endif /* LTC_BASE64 */
+
+#if defined(LTC_BASE64_URL)
+static const unsigned char map_base64url[] = {
+255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255,
+255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
+255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 63,
+255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255
+};
+#endif /* LTC_BASE64_URL */
+
+enum {
+ insane = 0,
+ strict = 1,
+ relaxed = 2
+};
+
+static int s_base64_decode_internal(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *map, int mode)
+{
+ unsigned long t, x, y, z;
+ unsigned char c;
+ int g;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ g = 0; /* '=' counter */
+ for (x = y = z = t = 0; x < inlen; x++) {
+ if ((in[x] == 0) && (x == (inlen - 1)) && (mode != strict)) {
+ continue; /* allow the last byte to be NUL (relaxed+insane) */
+ }
+ c = map[(unsigned char)in[x]&0xFF];
+ if (c == 254) {
+ g++;
+ continue;
+ }
+ if (c == 253) {
+ if (mode == strict) {
+ return CRYPT_INVALID_PACKET;
+ }
+ continue; /* allow to ignore white-spaces (relaxed+insane) */
+ }
+ if (c == 255) {
+ if (mode == insane) {
+ continue; /* allow to ignore invalid garbage (insane) */
+ }
+ return CRYPT_INVALID_PACKET;
+ }
+ if ((g > 0) && (mode != insane)) {
+ /* we only allow '=' to be at the end (strict+relaxed) */
+ return CRYPT_INVALID_PACKET;
+ }
+
+ t = (t<<6)|c;
+
+ if (++y == 4) {
+ if (z + 3 > *outlen) return CRYPT_BUFFER_OVERFLOW;
+ out[z++] = (unsigned char)((t>>16)&255);
+ out[z++] = (unsigned char)((t>>8)&255);
+ out[z++] = (unsigned char)(t&255);
+ y = t = 0;
+ }
+ }
+
+ if (y != 0) {
+ if (y == 1) return CRYPT_INVALID_PACKET;
+#if defined(LTC_BASE64)
+ if (((y + g) != 4) && (mode == strict) && (map == map_base64)) return CRYPT_INVALID_PACKET;
+#endif /* LTC_BASE64 */
+ t = t << (6 * (4 - y));
+ if (z + y - 1 > *outlen) return CRYPT_BUFFER_OVERFLOW;
+ if (y >= 2) out[z++] = (unsigned char) ((t >> 16) & 255);
+ if (y == 3) out[z++] = (unsigned char) ((t >> 8) & 255);
+ }
+ *outlen = z;
+ return CRYPT_OK;
+}
+
+#if defined(LTC_BASE64)
+/**
+ Dangerously relaxed base64 decode a block of memory
+ @param in The base64 data to decode
+ @param inlen The length of the base64 data
+ @param out [out] The destination of the binary decoded data
+ @param outlen [in/out] The max size and resulting size of the decoded data
+ @return CRYPT_OK if successful
+*/
+int base64_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ return s_base64_decode_internal(in, inlen, out, outlen, map_base64, insane);
+}
+
+/**
+ Strict base64 decode a block of memory
+ @param in The base64 data to decode
+ @param inlen The length of the base64 data
+ @param out [out] The destination of the binary decoded data
+ @param outlen [in/out] The max size and resulting size of the decoded data
+ @return CRYPT_OK if successful
+*/
+int base64_strict_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ return s_base64_decode_internal(in, inlen, out, outlen, map_base64, strict);
+}
+
+/**
+ Sane base64 decode a block of memory
+ @param in The base64 data to decode
+ @param inlen The length of the base64 data
+ @param out [out] The destination of the binary decoded data
+ @param outlen [in/out] The max size and resulting size of the decoded data
+ @return CRYPT_OK if successful
+*/
+int base64_sane_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ return s_base64_decode_internal(in, inlen, out, outlen, map_base64, relaxed);
+}
+#endif /* LTC_BASE64 */
+
+#if defined(LTC_BASE64_URL)
+/**
+ Dangerously relaxed base64 (URL Safe, RFC 4648 section 5) decode a block of memory
+ @param in The base64 data to decode
+ @param inlen The length of the base64 data
+ @param out [out] The destination of the binary decoded data
+ @param outlen [in/out] The max size and resulting size of the decoded data
+ @return CRYPT_OK if successful
+*/
+int base64url_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, insane);
+}
+
+/**
+ Strict base64 (URL Safe, RFC 4648 section 5) decode a block of memory
+ @param in The base64 data to decode
+ @param inlen The length of the base64 data
+ @param out [out] The destination of the binary decoded data
+ @param outlen [in/out] The max size and resulting size of the decoded data
+ @return CRYPT_OK if successful
+*/
+int base64url_strict_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, strict);
+}
+
+/**
+ Sane base64 (URL Safe, RFC 4648 section 5) decode a block of memory
+ @param in The base64 data to decode
+ @param inlen The length of the base64 data
+ @param out [out] The destination of the binary decoded data
+ @param outlen [in/out] The max size and resulting size of the decoded data
+ @return CRYPT_OK if successful
+*/
+int base64url_sane_decode(const char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, relaxed);
+}
+#endif /* LTC_BASE64_URL */
+
+#endif
+
diff --git a/Sources/libtomcrypt/misc/base64/base64_encode.c b/Sources/libtomcrypt/misc/base64/base64_encode.c
new file mode 100644
index 00000000..ef8aee90
--- /dev/null
+++ b/Sources/libtomcrypt/misc/base64/base64_encode.c
@@ -0,0 +1,159 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file base64_encode.c
+ Compliant base64 encoder donated by Wayne Scott (wscott@bitmover.com)
+ base64 URL Safe variant (RFC 4648 section 5) by Karel Miko
+*/
+
+
+#if defined(LTC_BASE64) || defined (LTC_BASE64_URL)
+
+#if defined(LTC_BASE64)
+static const char * const codes_base64 =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#endif /* LTC_BASE64 */
+
+#if defined(LTC_BASE64_URL)
+static const char * const codes_base64url =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+#endif /* LTC_BASE64_URL */
+
+enum mode {
+ nopad = 0,
+ pad = 1,
+ lf = 2,
+ cr = 4,
+ ssh = 8,
+ crlf = lf | cr,
+};
+
+static int s_base64_encode_internal(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen,
+ const char *codes, unsigned int mode)
+{
+ unsigned long i, len2, leven, linelen;
+ char *p;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ linelen = (mode & ssh) ? 72 : 64;
+
+ /* valid output size ? */
+ len2 = 4 * ((inlen + 2) / 3);
+ if ((mode & crlf) == lf) {
+ len2 += len2 / linelen;
+ } else if ((mode & crlf) == crlf) {
+ len2 += (len2 / linelen) * 2;
+ }
+ if (*outlen < len2 + 1) {
+ *outlen = len2 + 1;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if ((void*)in == out) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ p = out;
+ leven = 3*(inlen / 3);
+ for (i = 0; i < leven; i += 3) {
+ *p++ = codes[(in[0] >> 2) & 0x3F];
+ *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F];
+ *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
+ *p++ = codes[in[2] & 0x3F];
+ in += 3;
+ if ((p - out) % linelen == 0) {
+ if (mode & cr) *p++ = '\r';
+ if (mode & lf) *p++ = '\n';
+ }
+ }
+ /* Pad it if necessary... */
+ if (i < inlen) {
+ unsigned a = in[0];
+ unsigned b = (i+1 < inlen) ? in[1] : 0;
+
+ *p++ = codes[(a >> 2) & 0x3F];
+ *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F];
+ if (mode & pad) {
+ *p++ = (i+1 < inlen) ? codes[(((b & 0xf) << 2)) & 0x3F] : '=';
+ *p++ = '=';
+ }
+ else {
+ if (i+1 < inlen) *p++ = codes[(((b & 0xf) << 2)) & 0x3F];
+ }
+ }
+
+ /* append a NULL byte */
+ *p = '\0';
+
+ /* return ok */
+ *outlen = (unsigned long)(p - out); /* the length without terminating NUL */
+ return CRYPT_OK;
+}
+
+#if defined(LTC_BASE64)
+/**
+ base64 Encode a buffer (NUL terminated)
+ @param in The input buffer to encode
+ @param inlen The length of the input buffer
+ @param out [out] The destination of the base64 encoded data
+ @param outlen [in/out] The max size and resulting size
+ @return CRYPT_OK if successful
+*/
+int base64_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen)
+{
+ return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, pad);
+}
+
+/**
+ base64 Encode a buffer for PEM output
+ (NUL terminated with line-break at 64 chars)
+ @param in The input buffer to encode
+ @param inlen The length of the input buffer
+ @param out [out] The destination of the base64 encoded data
+ @param outlen [in/out] The max size and resulting size
+ @param flags \ref base64_pem_flags
+ @return CRYPT_OK if successful
+*/
+int base64_encode_pem(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen,
+ unsigned int flags)
+{
+ int use_crlf = flags & BASE64_PEM_CRLF ? pad | crlf : pad | lf;
+ int ssh_style = flags & BASE64_PEM_SSH ? ssh : 0;
+ return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, ssh_style | use_crlf);
+}
+#endif /* LTC_BASE64 */
+
+
+#if defined(LTC_BASE64_URL)
+/**
+ base64 (URL Safe, RFC 4648 section 5) Encode a buffer (NUL terminated)
+ @param in The input buffer to encode
+ @param inlen The length of the input buffer
+ @param out [out] The destination of the base64 encoded data
+ @param outlen [in/out] The max size and resulting size
+ @return CRYPT_OK if successful
+*/
+int base64url_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen)
+{
+ return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, nopad);
+}
+
+int base64url_strict_encode(const unsigned char *in, unsigned long inlen,
+ char *out, unsigned long *outlen)
+{
+ return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, pad);
+}
+#endif /* LTC_BASE64_URL */
+
+#endif
+
diff --git a/Sources/libtomcrypt/misc/bcrypt/bcrypt.c b/Sources/libtomcrypt/misc/bcrypt/bcrypt.c
new file mode 100644
index 00000000..1bebdffa
--- /dev/null
+++ b/Sources/libtomcrypt/misc/bcrypt/bcrypt.c
@@ -0,0 +1,191 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file bcrypt.c
+ bcrypt pbkdf, Steffen Jaeckel
+*/
+#ifdef LTC_BCRYPT
+
+#define BCRYPT_WORDS 8
+#define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4)
+
+static int s_bcrypt_hash(const unsigned char *pt,
+ const unsigned char *pass, unsigned long passlen,
+ const unsigned char *salt, unsigned long saltlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ symmetric_key key;
+ int err, n;
+ ulong32 ct[BCRYPT_WORDS];
+
+ if ((err = blowfish_setup_with_data(pass, passlen, salt, saltlen, &key)) != CRYPT_OK) {
+ return err;
+ }
+ for (n = 0; n < 64; ++n) {
+ if ((err = blowfish_expand(salt, saltlen, NULL, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = blowfish_expand(pass, passlen, NULL, 0, &key)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ for (n = 0; n < BCRYPT_WORDS; ++n) {
+ LOAD32H(ct[n], &pt[n*4]);
+ }
+
+ for (n = 0; n < 64; ++n) {
+ blowfish_enc(ct, BCRYPT_WORDS/2, &key);
+ }
+
+ for (n = 0; n < BCRYPT_WORDS; ++n) {
+ STORE32L(ct[n], &out[4 * n]);
+ }
+ *outlen = sizeof(ct);
+#ifdef LTC_CLEAN_STACK
+ zeromem(&key, sizeof(key));
+ zeromem(ct, sizeof(ct));
+#endif
+
+ return CRYPT_OK;
+}
+
+static int s_bcrypt_pbkdf_hash(const unsigned char *pass, unsigned long passlen,
+ const unsigned char *salt, unsigned long saltlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ const unsigned char pt[] = "OxychromaticBlowfishSwatDynamite";
+ return s_bcrypt_hash(pt, pass, passlen, salt, saltlen, out, outlen);
+}
+
+/**
+ Compatible to bcrypt_pbkdf() as provided in OpenBSD
+ @param password The input password (or key)
+ @param password_len The length of the password (octets)
+ @param salt The salt (or nonce)
+ @param salt_len The length of the salt (octets)
+ @param rounds # of iterations desired [read specs for more]
+ @param hash_idx The index of the hash desired
+ @param out [out] The destination for this algorithm
+ @param outlen [in/out] The desired size of the algorithm output
+ @return CRYPT_OK if successful
+*/
+int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len,
+ const unsigned char *salt, unsigned long salt_len,
+ unsigned int rounds, int hash_idx,
+ unsigned char *out, unsigned long *outlen)
+{
+ int err;
+ ulong32 blkno;
+ unsigned long left, itts, x, y, hashed_pass_len, step_size, steps, dest, used_rounds;
+ unsigned char *buf[3], blkbuf[4];
+ unsigned char *hashed_pass;
+
+ LTC_ARGCHK(secret != NULL);
+ LTC_ARGCHK(salt != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((secret_len == 0) || (salt_len == 0) || (*outlen == 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+ /* test hash IDX */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+ /* set default value for rounds if not given */
+ if (rounds == 0) {
+ used_rounds = LTC_BCRYPT_DEFAULT_ROUNDS;
+ } else {
+ used_rounds = rounds;
+ }
+
+ buf[0] = XMALLOC(MAXBLOCKSIZE * 3);
+ hashed_pass = XMALLOC(MAXBLOCKSIZE);
+ if (buf[0] == NULL || hashed_pass == NULL) {
+ if (hashed_pass != NULL) {
+ XFREE(hashed_pass);
+ }
+ if (buf[0] != NULL) {
+ XFREE(buf[0]);
+ }
+ return CRYPT_MEM;
+ }
+ /* buf[1] points to the second block of MAXBLOCKSIZE bytes */
+ buf[1] = buf[0] + MAXBLOCKSIZE;
+ buf[2] = buf[1] + MAXBLOCKSIZE;
+
+ step_size = (*outlen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE;
+ steps = (*outlen + step_size - 1) / step_size;
+
+ hashed_pass_len = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash_idx, (unsigned char*)secret, secret_len, hashed_pass, &hashed_pass_len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ left = *outlen;
+ blkno = 0;
+ while (left != 0) {
+ /* increment and store current block number */
+ ++blkno;
+ STORE32H(blkno, blkbuf);
+
+ /* process block number blkno */
+ zeromem(buf[0], MAXBLOCKSIZE*2);
+
+ x = MAXBLOCKSIZE;
+ if ((err = hash_memory_multi(hash_idx, buf[0], &x,
+ salt, salt_len,
+ blkbuf, 4uL,
+ LTC_NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y = MAXBLOCKSIZE;
+ if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ XMEMCPY(buf[2], buf[1], y);
+
+ /* now compute repeated and XOR it in buf[2] */
+ for (itts = 1; itts < used_rounds; ++itts) {
+ x = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash_idx, buf[1], y, buf[0], &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y = MAXBLOCKSIZE;
+ if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ for (x = 0; x < y; x++) {
+ buf[2][x] ^= buf[1][x];
+ }
+ }
+
+ /* now emit upto `steps` bytes of buf[2] to output */
+ steps = MIN(steps, left);
+ for (y = 0; y < steps; ++y) {
+ dest = y * step_size + (blkno - 1);
+ if (dest >= *outlen)
+ break;
+ out[dest] = buf[2][y];
+ }
+ left -= y;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf[0], MAXBLOCKSIZE*3);
+ zeromem(hashed_pass, MAXBLOCKSIZE);
+#endif
+
+ XFREE(hashed_pass);
+ XFREE(buf[0]);
+
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/misc/burn_stack.c b/Sources/libtomcrypt/misc/burn_stack.c
new file mode 100644
index 00000000..5d276a45
--- /dev/null
+++ b/Sources/libtomcrypt/misc/burn_stack.c
@@ -0,0 +1,23 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file burn_stack.c
+ Burn stack, Tom St Denis
+*/
+
+/**
+ Burn some stack memory
+ @param len amount of stack to burn in bytes
+*/
+void burn_stack(unsigned long len)
+{
+ unsigned char buf[32];
+ zeromem(buf, sizeof(buf));
+ if (len > (unsigned long)sizeof(buf)) {
+ burn_stack(len - sizeof(buf));
+ }
+}
+
+
diff --git a/Sources/libtomcrypt/misc/compare_testvector.c b/Sources/libtomcrypt/misc/compare_testvector.c
new file mode 100644
index 00000000..bb3c8cbf
--- /dev/null
+++ b/Sources/libtomcrypt/misc/compare_testvector.c
@@ -0,0 +1,81 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file compare_testvector.c
+ Function to compare two testvectors and print a (detailed) error-message if required, Steffen Jaeckel
+*/
+
+#if defined(LTC_TEST) && defined(LTC_TEST_DBG)
+static void s_print_hex(const char* what, const void* v, const unsigned long l)
+{
+ const unsigned char* p = v;
+ unsigned long x, y = 0, z;
+ fprintf(stderr, "%s contents: \n", what);
+ for (x = 0; x < l; ) {
+ fprintf(stderr, "%02X ", p[x]);
+ if (!(++x % 16) || x == l) {
+ if((x % 16) != 0) {
+ z = 16 - (x % 16);
+ if(z >= 8)
+ fprintf(stderr, " ");
+ for (; z != 0; --z) {
+ fprintf(stderr, " ");
+ }
+ }
+ fprintf(stderr, " | ");
+ for(; y < x; y++) {
+ if((y % 8) == 0)
+ fprintf(stderr, " ");
+ if(isgraph(p[y]))
+ fprintf(stderr, "%c", p[y]);
+ else
+ fprintf(stderr, ".");
+ }
+ fprintf(stderr, "\n");
+ }
+ else if((x % 8) == 0) {
+ fprintf(stderr, " ");
+ }
+ }
+}
+#endif
+
+/**
+ Compare two test-vectors
+
+ @param is The data as it is
+ @param is_len The length of is
+ @param should The data as it should
+ @param should_len The length of should
+ @param what The type of the data
+ @param which The iteration count
+ @return 0 on equality, -1 or 1 on difference
+*/
+int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which)
+{
+ int res = 0;
+ if(is_len != should_len) {
+ res = is_len > should_len ? -1 : 1;
+ } else {
+ res = XMEMCMP(is, should, is_len);
+ }
+#if defined(LTC_TEST) && defined(LTC_TEST_DBG)
+ if (res != 0) {
+ fprintf(stderr, "Testvector #%i(0x%x) of %s failed:\n", which, which, what);
+ s_print_hex("SHOULD", should, should_len);
+ s_print_hex("IS ", is, is_len);
+#if LTC_TEST_DBG > 1
+ } else {
+ fprintf(stderr, "Testvector #%i(0x%x) of %s passed!\n", which, which, what);
+#endif
+ }
+#else
+ LTC_UNUSED_PARAM(which);
+ LTC_UNUSED_PARAM(what);
+#endif
+
+ return res;
+}
diff --git a/Sources/libtomcrypt/misc/copy_or_zeromem.c b/Sources/libtomcrypt/misc/copy_or_zeromem.c
new file mode 100644
index 00000000..a05eac60
--- /dev/null
+++ b/Sources/libtomcrypt/misc/copy_or_zeromem.c
@@ -0,0 +1,51 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file copy_or_zeromem.c
+ Either copy or zero a block of memory in constant time, Steffen Jaeckel
+*/
+
+/**
+ Either copy or zero a block of memory in constant time
+ @param src The source where to read from
+ @param dest The destination where to write to
+ @param len The length of the area to process (octets)
+ @param coz Copy (on 0) Or Zero (> 0)
+*/
+void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz)
+{
+ unsigned long y;
+#ifdef LTC_FAST
+ unsigned long z;
+ LTC_FAST_TYPE fastMask = ~(LTC_FAST_TYPE)0; /* initialize fastMask at all ones */
+#endif
+ unsigned char mask = 0xff; /* initialize mask at all ones */
+
+ LTC_ARGCHKVD(src != NULL);
+ LTC_ARGCHKVD(dest != NULL);
+
+ if (coz != 0) coz = 1;
+ y = 0;
+ mask *= 1 - coz; /* mask = ( coz ? 0 : 0xff ) */
+#ifdef LTC_FAST
+ fastMask *= 1 - coz;
+ if (len & ~15) {
+ for (; y < (len & ~15); y += 16) {
+ for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&dest[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&src[y+z])) & fastMask;
+ }
+ }
+ }
+#endif
+ for (; y < len; y++) {
+ dest[y] = src[y] & mask;
+ }
+#ifdef LTC_CLEAN_STACK
+#ifdef LTC_FAST
+ fastMask = 0;
+#endif
+ mask = 0;
+#endif
+}
diff --git a/Sources/libtomcrypt/misc/crc32.c b/Sources/libtomcrypt/misc/crc32.c
new file mode 100644
index 00000000..d90e8301
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crc32.c
@@ -0,0 +1,193 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crc32.c
+ CRC-32 checksum algorithm
+ Written and placed in the public domain by Wei Dai
+ Adapted for libtomcrypt by Steffen Jaeckel
+*/
+#ifdef LTC_CRC32
+
+static const ulong32 CRC32_NEGL = 0xffffffffUL;
+
+#if defined(ENDIAN_LITTLE)
+#define CRC32_INDEX(c) (c & 0xff)
+#define CRC32_SHIFTED(c) (c >> 8)
+#elif defined(ENDIAN_BIG)
+#define CRC32_INDEX(c) (c >> 24)
+#define CRC32_SHIFTED(c) (c << 8)
+#else
+#error The existing CRC32 implementation only works properly when the endianness of the target platform is known.
+#endif
+
+/* Table of CRC-32's of all single byte values (made by makecrc.c) */
+static const ulong32 crc32_m_tab[] =
+{
+#if defined(ENDIAN_LITTLE)
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+#else
+ 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L,
+ 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L,
+ 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L,
+ 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L,
+ 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L,
+ 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L,
+ 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L,
+ 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L,
+ 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L,
+ 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L,
+ 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL,
+ 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L,
+ 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L,
+ 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L,
+ 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L,
+ 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L,
+ 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL,
+ 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L,
+ 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL,
+ 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L,
+ 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L,
+ 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L,
+ 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL,
+ 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL,
+ 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L,
+ 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL,
+ 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L,
+ 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL,
+ 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L,
+ 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L,
+ 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L,
+ 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L,
+ 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L,
+ 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL,
+ 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L,
+ 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L,
+ 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L,
+ 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L,
+ 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L,
+ 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L,
+ 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L,
+ 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L,
+ 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL,
+ 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L,
+ 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L,
+ 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L,
+ 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L,
+ 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L,
+ 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL,
+ 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L,
+ 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL,
+ 0x8def022dL
+#endif
+};
+
+void crc32_init(crc32_state *ctx)
+{
+ LTC_ARGCHKVD(ctx != NULL);
+ ctx->crc = CRC32_NEGL;
+}
+
+void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length)
+{
+ ulong32 crc;
+ LTC_ARGCHKVD(ctx != NULL);
+ LTC_ARGCHKVD(input != NULL);
+ crc = ctx->crc;
+
+ while (length--) {
+ crc = crc32_m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc);
+ }
+
+ ctx->crc = crc;
+}
+
+void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size)
+{
+ unsigned long i;
+ unsigned char* h;
+ ulong32 crc;
+ LTC_ARGCHKVD(ctx != NULL);
+ LTC_ARGCHKVD(hash != NULL);
+
+ h = hash;
+ crc = ctx->crc;
+ crc ^= CRC32_NEGL;
+
+ if (size > 4) size = 4;
+ for (i = 0; i < size; i++) {
+ h[i] = ((unsigned char*)&(crc))[size-i-1];
+ }
+}
+
+int crc32_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ const void* in = "libtomcrypt";
+ const unsigned char crc32[] = { 0xb3, 0x73, 0x76, 0xef };
+ unsigned char out[4];
+ crc32_state ctx;
+ crc32_init(&ctx);
+ crc32_update(&ctx, in, XSTRLEN(in));
+ crc32_finish(&ctx, out, 4);
+ if (compare_testvector(crc32, 4, out, 4, "CRC32", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ return CRYPT_OK;
+#endif
+}
+#endif
diff --git a/Sources/libtomcrypt/misc/crypt/crypt.c b/Sources/libtomcrypt/misc/crypt/crypt.c
new file mode 100644
index 00000000..69f21354
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt.c
@@ -0,0 +1,574 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt.c
+ Build strings, Tom St Denis
+*/
+#define NAME_VALUE(s) #s"="NAME(s)
+#define NAME(s) #s
+
+const char *crypt_build_settings =
+ "LibTomCrypt " SCRYPT " (www.libtom.net)\n"
+ "LibTomCrypt is public domain software.\n"
+#if defined(INCLUDE_BUILD_DATE)
+ "Built on " __DATE__ " at " __TIME__ "\n"
+#endif
+ "\n\nEndianness: "
+#if defined(ENDIAN_NEUTRAL)
+ "neutral/"
+#endif
+#if defined(ENDIAN_LITTLE)
+ "little"
+#elif defined(ENDIAN_BIG)
+ "big"
+#endif
+ #if defined(ENDIAN_32BITWORD)
+ " (32-bit words)\n"
+ #elif defined(ENDIAN_64BITWORD)
+ " (64-bit words)\n"
+ #else
+ " (no wordsize defined)\n"
+ #endif
+ "Clean stack: "
+#if defined(LTC_CLEAN_STACK)
+ "enabled\n"
+#else
+ "disabled\n"
+#endif
+ "\nCiphers built-in:\n"
+#if defined(LTC_BLOWFISH)
+ " Blowfish\n"
+#endif
+#if defined(LTC_RC2)
+ " RC2\n"
+#endif
+#if defined(LTC_RC5)
+ " RC5\n"
+#endif
+#if defined(LTC_RC6)
+ " RC6\n"
+#endif
+#if defined(LTC_SAFERP)
+ " Safer+\n"
+#endif
+#if defined(LTC_SAFER)
+ " Safer\n"
+#endif
+#if defined(LTC_RIJNDAEL)
+ " Rijndael\n"
+#endif
+#if defined(LTC_XTEA)
+ " XTEA\n"
+#endif
+#if defined(LTC_TWOFISH)
+ " Twofish "
+ #if defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES)
+ "(small, tables, all_tables)\n"
+ #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES)
+ "(small, tables)\n"
+ #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_ALL_TABLES)
+ "(small, all_tables)\n"
+ #elif defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES)
+ "(tables, all_tables)\n"
+ #elif defined(LTC_TWOFISH_SMALL)
+ "(small)\n"
+ #elif defined(LTC_TWOFISH_TABLES)
+ "(tables)\n"
+ #elif defined(LTC_TWOFISH_ALL_TABLES)
+ "(all_tables)\n"
+ #else
+ "\n"
+ #endif
+#endif
+#if defined(LTC_DES)
+ " DES\n"
+ " DES-X\n"
+ " 3DES\n"
+#endif
+#if defined(LTC_SM4)
+ " SM4\n"
+#endif
+#if defined(LTC_CAST5)
+ " CAST5\n"
+#endif
+#if defined(LTC_NOEKEON)
+ " Noekeon\n"
+#endif
+#if defined(LTC_SKIPJACK)
+ " Skipjack\n"
+#endif
+#if defined(LTC_KHAZAD)
+ " Khazad\n"
+#endif
+#if defined(LTC_ANUBIS)
+ " Anubis "
+#endif
+#if defined(LTC_ANUBIS_TWEAK)
+ " (tweaked)"
+#endif
+ "\n"
+#if defined(LTC_KSEED)
+ " KSEED\n"
+#endif
+#if defined(LTC_KASUMI)
+ " KASUMI\n"
+#endif
+#if defined(LTC_MULTI2)
+ " MULTI2\n"
+#endif
+#if defined(LTC_CAMELLIA)
+ " Camellia\n"
+#endif
+#if defined(LTC_IDEA)
+ " IDEA\n"
+#endif
+#if defined(LTC_SERPENT)
+ " Serpent\n"
+#endif
+#if defined(LTC_TEA)
+ " TEA\n"
+#endif
+ "Stream ciphers built-in:\n"
+#if defined(LTC_CHACHA)
+ " ChaCha\n"
+#endif
+#if defined(LTC_SALSA20)
+ " Salsa20\n"
+#endif
+#if defined(LTC_XSALSA20)
+ " XSalsa20\n"
+#endif
+#if defined(LTC_SOSEMANUK)
+ " Sosemanuk\n"
+#endif
+#if defined(LTC_RABBIT)
+ " Rabbit\n"
+#endif
+#if defined(LTC_RC4_STREAM)
+ " RC4\n"
+#endif
+#if defined(LTC_SOBER128_STREAM)
+ " SOBER128\n"
+#endif
+
+ "\nHashes built-in:\n"
+#if defined(LTC_SHA3)
+ " SHA3\n"
+#endif
+#if defined(LTC_KECCAK)
+ " KECCAK\n"
+#endif
+#if defined(LTC_SHA512)
+ " SHA-512\n"
+#endif
+#if defined(LTC_SHA384)
+ " SHA-384\n"
+#endif
+#if defined(LTC_SHA512_256)
+ " SHA-512/256\n"
+#endif
+#if defined(LTC_SHA256)
+ " SHA-256\n"
+#endif
+#if defined(LTC_SHA512_224)
+ " SHA-512/224\n"
+#endif
+#if defined(LTC_SHA224)
+ " SHA-224\n"
+#endif
+#if defined(LTC_TIGER)
+ " TIGER\n"
+#endif
+#if defined(LTC_SHA1)
+ " SHA1\n"
+#endif
+#if defined(LTC_MD5)
+ " MD5\n"
+#endif
+#if defined(LTC_MD4)
+ " MD4\n"
+#endif
+#if defined(LTC_MD2)
+ " MD2\n"
+#endif
+#if defined(LTC_RIPEMD128)
+ " RIPEMD128\n"
+#endif
+#if defined(LTC_RIPEMD160)
+ " RIPEMD160\n"
+#endif
+#if defined(LTC_RIPEMD256)
+ " RIPEMD256\n"
+#endif
+#if defined(LTC_RIPEMD320)
+ " RIPEMD320\n"
+#endif
+#if defined(LTC_WHIRLPOOL)
+ " WHIRLPOOL\n"
+#endif
+#if defined(LTC_BLAKE2S)
+ " BLAKE2S\n"
+#endif
+#if defined(LTC_BLAKE2B)
+ " BLAKE2B\n"
+#endif
+#if defined(LTC_CHC_HASH)
+ " CHC_HASH\n"
+#endif
+
+ "\nBlock Chaining Modes:\n"
+#if defined(LTC_CFB_MODE)
+ " CFB\n"
+#endif
+#if defined(LTC_OFB_MODE)
+ " OFB\n"
+#endif
+#if defined(LTC_ECB_MODE)
+ " ECB\n"
+#endif
+#if defined(LTC_CBC_MODE)
+ " CBC\n"
+#endif
+#if defined(LTC_CTR_MODE)
+ " CTR\n"
+#endif
+#if defined(LTC_LRW_MODE)
+ " LRW"
+#if defined(LTC_LRW_TABLES)
+ " (tables) "
+#endif
+ "\n"
+#endif
+#if defined(LTC_F8_MODE)
+ " F8\n"
+#endif
+#if defined(LTC_XTS_MODE)
+ " XTS\n"
+#endif
+
+ "\nMACs:\n"
+#if defined(LTC_HMAC)
+ " HMAC\n"
+#endif
+#if defined(LTC_OMAC)
+ " OMAC\n"
+#endif
+#if defined(LTC_PMAC)
+ " PMAC\n"
+#endif
+#if defined(LTC_PELICAN)
+ " PELICAN\n"
+#endif
+#if defined(LTC_XCBC)
+ " XCBC\n"
+#endif
+#if defined(LTC_F9_MODE)
+ " F9\n"
+#endif
+#if defined(LTC_POLY1305)
+ " POLY1305\n"
+#endif
+#if defined(LTC_BLAKE2SMAC)
+ " BLAKE2S MAC\n"
+#endif
+#if defined(LTC_BLAKE2BMAC)
+ " BLAKE2B MAC\n"
+#endif
+
+ "\nENC + AUTH modes:\n"
+#if defined(LTC_EAX_MODE)
+ " EAX\n"
+#endif
+#if defined(LTC_OCB_MODE)
+ " OCB\n"
+#endif
+#if defined(LTC_OCB3_MODE)
+ " OCB3\n"
+#endif
+#if defined(LTC_CCM_MODE)
+ " CCM\n"
+#endif
+#if defined(LTC_GCM_MODE)
+ " GCM"
+#if defined(LTC_GCM_TABLES)
+ " (tables) "
+#endif
+#if defined(LTC_GCM_TABLES_SSE2)
+ " (SSE2) "
+#endif
+ "\n"
+#endif
+#if defined(LTC_CHACHA20POLY1305_MODE)
+ " CHACHA20POLY1305\n"
+#endif
+
+ "\nPRNG:\n"
+#if defined(LTC_YARROW)
+ " Yarrow ("NAME_VALUE(LTC_YARROW_AES)")\n"
+#endif
+#if defined(LTC_SPRNG)
+ " SPRNG\n"
+#endif
+#if defined(LTC_RC4)
+ " RC4\n"
+#endif
+#if defined(LTC_CHACHA20_PRNG)
+ " ChaCha20\n"
+#endif
+#if defined(LTC_FORTUNA)
+ " Fortuna (" NAME_VALUE(LTC_FORTUNA_POOLS) ", "
+#if defined(LTC_FORTUNA_RESEED_RATELIMIT_TIMED)
+ "LTC_FORTUNA_RESEED_RATELIMIT_TIMED"
+#else
+ "LTC_FORTUNA_RESEED_RATELIMIT_STATIC, " NAME_VALUE(LTC_FORTUNA_WD)
+#endif
+#if defined(LTC_FORTUNA_USE_ENCRYPT_ONLY)
+ ", LTC_FORTUNA_USE_ENCRYPT_ONLY"
+#endif
+ ")\n"
+#endif
+#if defined(LTC_SOBER128)
+ " SOBER128\n"
+#endif
+#if defined(LTC_WIN32_BCRYPT)
+ " WIN32_BCRYPT\n"
+#endif
+
+ "\nPK Crypto:\n"
+#if defined(LTC_MRSA)
+ " RSA"
+#if defined(LTC_RSA_BLINDING) && defined(LTC_RSA_CRT_HARDENING)
+ " (with blinding and CRT hardening)"
+#elif defined(LTC_RSA_BLINDING)
+ " (with blinding)"
+#elif defined(LTC_RSA_CRT_HARDENING)
+ " (with CRT hardening)"
+#endif
+ "\n"
+#endif
+#if defined(LTC_MDH)
+ " DH\n"
+#endif
+#if defined(LTC_MECC)
+ " ECC"
+#if defined(LTC_ECC_TIMING_RESISTANT)
+ " (with blinding)"
+#endif
+ "\n"
+#endif
+#if defined(LTC_MDSA)
+ " DSA\n"
+#endif
+#if defined(LTC_CURVE25519)
+#if defined(LTC_CURVE25519)
+ " Ed25519\n"
+#endif
+#if defined(LTC_CURVE25519)
+ " X25519\n"
+#endif
+#endif
+#if defined(LTC_PK_MAX_RETRIES)
+ " "NAME_VALUE(LTC_PK_MAX_RETRIES)"\n"
+#endif
+
+ "\nMPI (Math):\n"
+#if defined(LTC_MPI)
+ " LTC_MPI\n"
+#endif
+#if defined(LTM_DESC)
+ " LTM_DESC\n"
+#endif
+#if defined(TFM_DESC)
+ " TFM_DESC\n"
+#endif
+#if defined(GMP_DESC)
+ " GMP_DESC\n"
+#endif
+#if defined(LTC_MILLER_RABIN_REPS)
+ " "NAME_VALUE(LTC_MILLER_RABIN_REPS)"\n"
+#endif
+
+ "\nCompiler:\n"
+#if defined(_WIN64)
+ " WIN64 platform detected.\n"
+#elif defined(_WIN32)
+ " WIN32 platform detected.\n"
+#endif
+#if defined(__CYGWIN__)
+ " CYGWIN Detected.\n"
+#endif
+#if defined(__DJGPP__)
+ " DJGPP Detected.\n"
+#endif
+#if defined(_MSC_VER)
+ " MSVC compiler detected.\n"
+#endif
+#if defined(__clang_version__)
+ " Clang compiler " __clang_version__ ".\n"
+#elif defined(INTEL_CC)
+ " Intel C Compiler " __VERSION__ ".\n"
+#elif defined(__GNUC__) /* clang and icc also define __GNUC__ */
+ " GCC compiler " __VERSION__ ".\n"
+#endif
+
+#if defined(__x86_64__)
+ " x86-64 detected.\n"
+#endif
+#if defined(LTC_PPC32)
+ " PPC32 detected.\n"
+#endif
+
+ "\nVarious others: "
+#if defined(ARGTYPE)
+ " " NAME_VALUE(ARGTYPE) " "
+#endif
+#if defined(LTC_ADLER32)
+ " ADLER32 "
+#endif
+#if defined(LTC_AES_NI)
+ " AES-NI "
+#endif
+#if defined(LTC_BASE64)
+ " BASE64 "
+#endif
+#if defined(LTC_BASE64_URL)
+ " BASE64-URL-SAFE "
+#endif
+#if defined(LTC_BASE32)
+ " BASE32 "
+#endif
+#if defined(LTC_BASE16)
+ " BASE16 "
+#endif
+#if defined(LTC_BCRYPT)
+ " BCRYPT "
+ " " NAME_VALUE(LTC_BCRYPT_DEFAULT_ROUNDS) " "
+#endif
+#if defined(LTC_CRC32)
+ " CRC32 "
+#endif
+#if defined(LTC_DER)
+ " DER "
+ " " NAME_VALUE(LTC_DER_MAX_RECURSION) " "
+#endif
+#if defined(LTC_PKCS_1)
+ " PKCS#1 "
+#endif
+#if defined(LTC_PKCS_5)
+ " PKCS#5 "
+#endif
+#if defined(LTC_PKCS_8)
+ " PKCS#8 "
+#endif
+#if defined(LTC_PKCS_12)
+ " PKCS#12 "
+#endif
+#if defined(LTC_PADDING)
+ " PADDING "
+#endif
+#if defined(LTC_HKDF)
+ " HKDF "
+#endif
+#if defined(LTC_PBES)
+ " PBES1 "
+ " PBES2 "
+#endif
+#if defined(LTC_PEM)
+ " PEM "
+ " " NAME_VALUE(LTC_PEM_DECODE_BUFSZ) " "
+ " " NAME_VALUE(LTC_PEM_READ_BUFSIZE) " "
+#endif
+#if defined(LTC_SSH)
+ " SSH "
+#endif
+#if defined(LTC_PEM_SSH)
+ " OpenSSH-PEM "
+#endif
+#if defined(LTC_DEVRANDOM)
+ " LTC_DEVRANDOM "
+#endif
+#if defined(LTC_TRY_URANDOM_FIRST)
+ " LTC_TRY_URANDOM_FIRST "
+#endif
+#if defined(LTC_RNG_GET_BYTES)
+ " LTC_RNG_GET_BYTES "
+#endif
+#if defined(LTC_RNG_MAKE_PRNG)
+ " LTC_RNG_MAKE_PRNG "
+#endif
+#if defined(LTC_PRNG_ENABLE_LTC_RNG)
+ " LTC_PRNG_ENABLE_LTC_RNG "
+#endif
+#if defined(LTC_HASH_HELPERS)
+ " LTC_HASH_HELPERS "
+#endif
+#if defined(LTC_VALGRIND)
+ " LTC_VALGRIND "
+#endif
+#if defined(LTC_TEST)
+ " LTC_TEST "
+#endif
+#if defined(LTC_TEST_DBG)
+ " " NAME_VALUE(LTC_TEST_DBG) " "
+#endif
+#if defined(LTC_TEST_EXT)
+ " LTC_TEST_EXT "
+#endif
+#if defined(LTC_SMALL_CODE)
+ " LTC_SMALL_CODE "
+#endif
+#if defined(LTC_NO_FILE)
+ " LTC_NO_FILE "
+#endif
+#if defined(LTC_FILE_READ_BUFSIZE)
+ " " NAME_VALUE(LTC_FILE_READ_BUFSIZE) " "
+#endif
+#if defined(LTC_FAST)
+ " LTC_FAST "
+#endif
+#if defined(LTC_NO_FAST)
+ " LTC_NO_FAST "
+#endif
+#if defined(LTC_NO_BSWAP)
+ " LTC_NO_BSWAP "
+#endif
+#if defined(LTC_NO_ASM)
+ " LTC_NO_ASM "
+#endif
+#if defined(LTC_ROx_BUILTIN)
+ " LTC_ROx_BUILTIN "
+#elif defined(LTC_ROx_ASM)
+ " LTC_ROx_ASM "
+#if defined(LTC_NO_ROLC)
+ " LTC_NO_ROLC "
+#endif
+#endif
+#if defined(LTC_NO_TEST)
+ " LTC_NO_TEST "
+#endif
+#if defined(LTC_NO_TABLES)
+ " LTC_NO_TABLES "
+#endif
+#if defined(LTC_PTHREAD)
+ " LTC_PTHREAD "
+#endif
+#if defined(LTC_EASY)
+ " LTC_EASY "
+#endif
+#if defined(LTC_MECC_ACCEL)
+ " LTC_MECC_ACCEL "
+#endif
+#if defined(LTC_MECC_FP)
+ " LTC_MECC_FP "
+#endif
+#if defined(LTC_ECC_SHAMIR)
+ " LTC_ECC_SHAMIR "
+#endif
+#if defined(LTC_CLOCK_GETTIME)
+ " LTC_CLOCK_GETTIME "
+#endif
+ "\n"
+ ;
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_argchk.c b/Sources/libtomcrypt/misc/crypt/crypt_argchk.c
new file mode 100644
index 00000000..85b562a4
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_argchk.c
@@ -0,0 +1,17 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_argchk.c
+ Perform argument checking, Tom St Denis
+*/
+
+#if (ARGTYPE == 0)
+void crypt_argchk(const char *v, const char *s, int d)
+{
+ fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n",
+ v, d, s);
+ abort();
+}
+#endif
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_cipher_descriptor.c b/Sources/libtomcrypt/misc/crypt/crypt_cipher_descriptor.c
new file mode 100644
index 00000000..b79ff33b
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_cipher_descriptor.c
@@ -0,0 +1,15 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_cipher_descriptor.c
+ Stores the cipher descriptor table, Tom St Denis
+*/
+
+struct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = {
+{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+ };
+
+LTC_MUTEX_GLOBAL(ltc_cipher_mutex)
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_cipher_is_valid.c b/Sources/libtomcrypt/misc/crypt/crypt_cipher_is_valid.c
new file mode 100644
index 00000000..8745acea
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_cipher_is_valid.c
@@ -0,0 +1,24 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_cipher_is_valid.c
+ Determine if cipher is valid, Tom St Denis
+*/
+
+/*
+ Test if a cipher index is valid
+ @param idx The index of the cipher to search for
+ @return CRYPT_OK if valid
+*/
+int cipher_is_valid(int idx)
+{
+ LTC_MUTEX_LOCK(<c_cipher_mutex);
+ if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) {
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return CRYPT_INVALID_CIPHER;
+ }
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return CRYPT_OK;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_constants.c b/Sources/libtomcrypt/misc/crypt/crypt_constants.c
new file mode 100644
index 00000000..eac6daec
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_constants.c
@@ -0,0 +1,290 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_constants.c
+
+ Make various constants available to dynamic languages
+ like Python - Larry Bugbee, February 2013
+
+ LB - Dec 2013 - revised to include compiler define options
+ LB - Mar 2014 - added endianness and word size
+*/
+
+typedef struct {
+ const char *name;
+ const int value;
+} crypt_constant;
+
+#define C_STRINGIFY(s) { #s, s }
+
+static const crypt_constant s_crypt_constants[] = {
+
+ C_STRINGIFY(CRYPT_OK),
+ C_STRINGIFY(CRYPT_ERROR),
+ C_STRINGIFY(CRYPT_NOP),
+ C_STRINGIFY(CRYPT_INVALID_KEYSIZE),
+ C_STRINGIFY(CRYPT_INVALID_ROUNDS),
+ C_STRINGIFY(CRYPT_FAIL_TESTVECTOR),
+ C_STRINGIFY(CRYPT_BUFFER_OVERFLOW),
+ C_STRINGIFY(CRYPT_INVALID_PACKET),
+ C_STRINGIFY(CRYPT_INVALID_PRNGSIZE),
+ C_STRINGIFY(CRYPT_ERROR_READPRNG),
+ C_STRINGIFY(CRYPT_INVALID_CIPHER),
+ C_STRINGIFY(CRYPT_INVALID_HASH),
+ C_STRINGIFY(CRYPT_INVALID_PRNG),
+ C_STRINGIFY(CRYPT_MEM),
+ C_STRINGIFY(CRYPT_PK_TYPE_MISMATCH),
+ C_STRINGIFY(CRYPT_PK_NOT_PRIVATE),
+ C_STRINGIFY(CRYPT_INVALID_ARG),
+ C_STRINGIFY(CRYPT_FILE_NOTFOUND),
+ C_STRINGIFY(CRYPT_PK_INVALID_TYPE),
+ C_STRINGIFY(CRYPT_OVERFLOW),
+ C_STRINGIFY(CRYPT_PK_ASN1_ERROR),
+ C_STRINGIFY(CRYPT_INPUT_TOO_LONG),
+ C_STRINGIFY(CRYPT_PK_INVALID_SIZE),
+ C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE),
+ C_STRINGIFY(CRYPT_PK_INVALID_PADDING),
+ C_STRINGIFY(CRYPT_HASH_OVERFLOW),
+
+ C_STRINGIFY(PK_PUBLIC),
+ C_STRINGIFY(PK_PRIVATE),
+
+ C_STRINGIFY(LTC_ENCRYPT),
+ C_STRINGIFY(LTC_DECRYPT),
+
+#ifdef LTC_PKCS_1
+ {"LTC_PKCS_1", 1},
+ /* Block types */
+ C_STRINGIFY(LTC_PKCS_1_EMSA),
+ C_STRINGIFY(LTC_PKCS_1_EME),
+
+ /* Padding types */
+ C_STRINGIFY(LTC_PKCS_1_V1_5),
+ C_STRINGIFY(LTC_PKCS_1_OAEP),
+ C_STRINGIFY(LTC_PKCS_1_PSS),
+ C_STRINGIFY(LTC_PKCS_1_V1_5_NA1),
+#else
+ {"LTC_PKCS_1", 0},
+#endif
+
+#ifdef LTC_PADDING
+ {"LTC_PADDING", 1},
+
+ C_STRINGIFY(LTC_PAD_PKCS7),
+#ifdef LTC_RNG_GET_BYTES
+ C_STRINGIFY(LTC_PAD_ISO_10126),
+#endif
+ C_STRINGIFY(LTC_PAD_ANSI_X923),
+ C_STRINGIFY(LTC_PAD_ONE_AND_ZERO),
+ C_STRINGIFY(LTC_PAD_ZERO),
+ C_STRINGIFY(LTC_PAD_ZERO_ALWAYS),
+#else
+ {"LTC_PADDING", 0},
+#endif
+
+#ifdef LTC_MRSA
+ {"LTC_MRSA", 1},
+#else
+ {"LTC_MRSA", 0},
+#endif
+
+#ifdef LTC_MECC
+ {"LTC_MECC", 1},
+ C_STRINGIFY(ECC_BUF_SIZE),
+ C_STRINGIFY(ECC_MAXSIZE),
+#else
+ {"LTC_MECC", 0},
+#endif
+
+#ifdef LTC_MDSA
+ {"LTC_MDSA", 1},
+ C_STRINGIFY(LTC_MDSA_DELTA),
+ C_STRINGIFY(LTC_MDSA_MAX_GROUP),
+ C_STRINGIFY(LTC_MDSA_MAX_MODULUS),
+#else
+ {"LTC_MDSA", 0},
+#endif
+
+#ifdef LTC_MILLER_RABIN_REPS
+ C_STRINGIFY(LTC_MILLER_RABIN_REPS),
+#endif
+
+#ifdef LTC_DER
+/* DER handling */
+ {"LTC_DER", 1},
+ C_STRINGIFY(LTC_ASN1_EOL),
+ C_STRINGIFY(LTC_ASN1_BOOLEAN),
+ C_STRINGIFY(LTC_ASN1_INTEGER),
+ C_STRINGIFY(LTC_ASN1_SHORT_INTEGER),
+ C_STRINGIFY(LTC_ASN1_BIT_STRING),
+ C_STRINGIFY(LTC_ASN1_OCTET_STRING),
+ C_STRINGIFY(LTC_ASN1_NULL),
+ C_STRINGIFY(LTC_ASN1_OBJECT_IDENTIFIER),
+ C_STRINGIFY(LTC_ASN1_IA5_STRING),
+ C_STRINGIFY(LTC_ASN1_PRINTABLE_STRING),
+ C_STRINGIFY(LTC_ASN1_UTF8_STRING),
+ C_STRINGIFY(LTC_ASN1_UTCTIME),
+ C_STRINGIFY(LTC_ASN1_CHOICE),
+ C_STRINGIFY(LTC_ASN1_SEQUENCE),
+ C_STRINGIFY(LTC_ASN1_SET),
+ C_STRINGIFY(LTC_ASN1_SETOF),
+ C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING),
+ C_STRINGIFY(LTC_ASN1_TELETEX_STRING),
+ C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME),
+ C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE),
+ C_STRINGIFY(LTC_DER_MAX_RECURSION),
+#else
+ {"LTC_DER", 0},
+#endif
+
+#ifdef LTC_CTR_MODE
+ {"LTC_CTR_MODE", 1},
+ C_STRINGIFY(CTR_COUNTER_LITTLE_ENDIAN),
+ C_STRINGIFY(CTR_COUNTER_BIG_ENDIAN),
+ C_STRINGIFY(LTC_CTR_RFC3686),
+#else
+ {"LTC_CTR_MODE", 0},
+#endif
+#ifdef LTC_GCM_MODE
+ C_STRINGIFY(LTC_GCM_MODE_IV),
+ C_STRINGIFY(LTC_GCM_MODE_AAD),
+ C_STRINGIFY(LTC_GCM_MODE_TEXT),
+#endif
+
+ C_STRINGIFY(LTC_MP_LT),
+ C_STRINGIFY(LTC_MP_EQ),
+ C_STRINGIFY(LTC_MP_GT),
+
+ C_STRINGIFY(LTC_MP_NO),
+ C_STRINGIFY(LTC_MP_YES),
+
+ C_STRINGIFY(MAXBLOCKSIZE),
+ C_STRINGIFY(TAB_SIZE),
+ C_STRINGIFY(ARGTYPE),
+
+#ifdef LTM_DESC
+ {"LTM_DESC", 1},
+#else
+ {"LTM_DESC", 0},
+#endif
+#ifdef TFM_DESC
+ {"TFM_DESC", 1},
+#else
+ {"TFM_DESC", 0},
+#endif
+#ifdef GMP_DESC
+ {"GMP_DESC", 1},
+#else
+ {"GMP_DESC", 0},
+#endif
+
+#ifdef LTC_FAST
+ {"LTC_FAST", 1},
+#else
+ {"LTC_FAST", 0},
+#endif
+
+#ifdef LTC_NO_FILE
+ {"LTC_NO_FILE", 1},
+#else
+ {"LTC_NO_FILE", 0},
+#endif
+
+#ifdef ENDIAN_LITTLE
+ {"ENDIAN_LITTLE", 1},
+#else
+ {"ENDIAN_LITTLE", 0},
+#endif
+
+#ifdef ENDIAN_BIG
+ {"ENDIAN_BIG", 1},
+#else
+ {"ENDIAN_BIG", 0},
+#endif
+
+#ifdef ENDIAN_32BITWORD
+ {"ENDIAN_32BITWORD", 1},
+#else
+ {"ENDIAN_32BITWORD", 0},
+#endif
+
+#ifdef ENDIAN_64BITWORD
+ {"ENDIAN_64BITWORD", 1},
+#else
+ {"ENDIAN_64BITWORD", 0},
+#endif
+
+#ifdef ENDIAN_NEUTRAL
+ {"ENDIAN_NEUTRAL", 1},
+#else
+ {"ENDIAN_NEUTRAL", 0},
+#endif
+};
+
+
+/* crypt_get_constant()
+ * valueout will be the value of the named constant
+ * return -1 if named item not found
+ */
+int crypt_get_constant(const char* namein, int *valueout) {
+ int i;
+ int count = sizeof(s_crypt_constants) / sizeof(s_crypt_constants[0]);
+ for (i=0; i *names_list_size) {
+ return -1;
+ }
+ /* build the names list */
+ ptr = names_list;
+ for (i=0; i total_len) return -1;
+ total_len -= number_len;
+ ptr += number_len;
+ }
+ /* to remove the trailing new-line */
+ ptr -= 1;
+ *ptr = 0;
+ }
+ return 0;
+}
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_find_cipher.c b/Sources/libtomcrypt/misc/crypt/crypt_find_cipher.c
new file mode 100644
index 00000000..e45da9cd
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_find_cipher.c
@@ -0,0 +1,29 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_find_cipher.c
+ Find a cipher in the descriptor tables, Tom St Denis
+*/
+
+/**
+ Find a registered cipher by name
+ @param name The name of the cipher to look for
+ @return >= 0 if found, -1 if not present
+*/
+int find_cipher(const char *name)
+{
+ int x;
+ LTC_ARGCHK(name != NULL);
+ LTC_MUTEX_LOCK(<c_cipher_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (cipher_descriptor[x].name != NULL && !XSTRCMP(cipher_descriptor[x].name, name)) {
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return x;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return -1;
+}
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_find_cipher_any.c b/Sources/libtomcrypt/misc/crypt/crypt_find_cipher_any.c
new file mode 100644
index 00000000..5089733a
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_find_cipher_any.c
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_find_cipher_any.c
+ Find a cipher in the descriptor tables, Tom St Denis
+*/
+
+/**
+ Find a cipher flexibly. First by name then if not present by block and key size
+ @param name The name of the cipher desired
+ @param blocklen The minimum length of the block cipher desired (octets)
+ @param keylen The minimum length of the key size desired (octets)
+ @return >= 0 if found, -1 if not present
+*/
+int find_cipher_any(const char *name, int blocklen, int keylen)
+{
+ int x;
+
+ if(name != NULL) {
+ x = find_cipher(name);
+ if (x != -1) return x;
+ }
+
+ LTC_MUTEX_LOCK(<c_cipher_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (cipher_descriptor[x].name == NULL) {
+ continue;
+ }
+ if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) {
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return x;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return -1;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_find_cipher_id.c b/Sources/libtomcrypt/misc/crypt/crypt_find_cipher_id.c
new file mode 100644
index 00000000..4876e4a1
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_find_cipher_id.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_find_cipher_id.c
+ Find cipher by ID, Tom St Denis
+*/
+
+/**
+ Find a cipher by ID number
+ @param ID The ID (not same as index) of the cipher to find
+ @return >= 0 if found, -1 if not present
+*/
+int find_cipher_id(unsigned char ID)
+{
+ int x;
+ LTC_MUTEX_LOCK(<c_cipher_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (cipher_descriptor[x].ID == ID) {
+ x = (cipher_descriptor[x].name == NULL) ? -1 : x;
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return x;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return -1;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_find_hash.c b/Sources/libtomcrypt/misc/crypt/crypt_find_hash.c
new file mode 100644
index 00000000..4d8ae49e
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_find_hash.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_find_hash.c
+ Find a hash, Tom St Denis
+*/
+
+/**
+ Find a registered hash by name
+ @param name The name of the hash to look for
+ @return >= 0 if found, -1 if not present
+*/
+int find_hash(const char *name)
+{
+ int x;
+ LTC_ARGCHK(name != NULL);
+ LTC_MUTEX_LOCK(<c_hash_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (hash_descriptor[x].name != NULL && XSTRCMP(hash_descriptor[x].name, name) == 0) {
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return x;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return -1;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_find_hash_any.c b/Sources/libtomcrypt/misc/crypt/crypt_find_hash_any.c
new file mode 100644
index 00000000..a2257377
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_find_hash_any.c
@@ -0,0 +1,37 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_find_hash_any.c
+ Find a hash, Tom St Denis
+*/
+
+/**
+ Find a hash flexibly. First by name then if not present by digest size
+ @param name The name of the hash desired
+ @param digestlen The minimum length of the digest size (octets)
+ @return >= 0 if found, -1 if not present
+*/int find_hash_any(const char *name, int digestlen)
+{
+ int x, y, z;
+ LTC_ARGCHK(name != NULL);
+
+ x = find_hash(name);
+ if (x != -1) return x;
+
+ LTC_MUTEX_LOCK(<c_hash_mutex);
+ y = MAXBLOCKSIZE+1;
+ z = -1;
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (hash_descriptor[x].name == NULL) {
+ continue;
+ }
+ if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) {
+ z = x;
+ y = hash_descriptor[x].hashsize;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return z;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_find_hash_id.c b/Sources/libtomcrypt/misc/crypt/crypt_find_hash_id.c
new file mode 100644
index 00000000..5de40951
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_find_hash_id.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_find_hash_id.c
+ Find hash by ID, Tom St Denis
+*/
+
+/**
+ Find a hash by ID number
+ @param ID The ID (not same as index) of the hash to find
+ @return >= 0 if found, -1 if not present
+*/
+int find_hash_id(unsigned char ID)
+{
+ int x;
+ LTC_MUTEX_LOCK(<c_hash_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (hash_descriptor[x].ID == ID) {
+ x = (hash_descriptor[x].name == NULL) ? -1 : x;
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return x;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return -1;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_find_hash_oid.c b/Sources/libtomcrypt/misc/crypt/crypt_find_hash_oid.c
new file mode 100644
index 00000000..0e10235b
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_find_hash_oid.c
@@ -0,0 +1,23 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_find_hash_oid.c
+ Find a hash, Tom St Denis
+*/
+
+int find_hash_oid(const unsigned long *ID, unsigned long IDlen)
+{
+ int x;
+ LTC_ARGCHK(ID != NULL);
+ LTC_MUTEX_LOCK(<c_hash_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (hash_descriptor[x].name != NULL && hash_descriptor[x].OIDlen == IDlen && !XMEMCMP(hash_descriptor[x].OID, ID, sizeof(unsigned long) * IDlen)) {
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return x;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return -1;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_find_prng.c b/Sources/libtomcrypt/misc/crypt/crypt_find_prng.c
new file mode 100644
index 00000000..7297982b
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_find_prng.c
@@ -0,0 +1,29 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_find_prng.c
+ Find a PRNG, Tom St Denis
+*/
+
+/**
+ Find a registered PRNG by name
+ @param name The name of the PRNG to look for
+ @return >= 0 if found, -1 if not present
+*/
+int find_prng(const char *name)
+{
+ int x;
+ LTC_ARGCHK(name != NULL);
+ LTC_MUTEX_LOCK(<c_prng_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if ((prng_descriptor[x].name != NULL) && XSTRCMP(prng_descriptor[x].name, name) == 0) {
+ LTC_MUTEX_UNLOCK(<c_prng_mutex);
+ return x;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_prng_mutex);
+ return -1;
+}
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_fsa.c b/Sources/libtomcrypt/misc/crypt/crypt_fsa.c
new file mode 100644
index 00000000..a23216da
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_fsa.c
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+/**
+ @file crypt_fsa.c
+ LibTomCrypt FULL SPEED AHEAD!, Tom St Denis
+*/
+
+/* format is ltc_mp, cipher_desc, [cipher_desc], NULL, hash_desc, [hash_desc], NULL, prng_desc, [prng_desc], NULL */
+int crypt_fsa(void *mp, ...)
+{
+ va_list args;
+ void *p;
+
+ va_start(args, mp);
+ if (mp != NULL) {
+ XMEMCPY(<c_mp, mp, sizeof(ltc_mp));
+ }
+
+ while ((p = va_arg(args, void*)) != NULL) {
+ if (register_cipher(p) == -1) {
+ va_end(args);
+ return CRYPT_INVALID_CIPHER;
+ }
+ }
+
+ while ((p = va_arg(args, void*)) != NULL) {
+ if (register_hash(p) == -1) {
+ va_end(args);
+ return CRYPT_INVALID_HASH;
+ }
+ }
+
+ while ((p = va_arg(args, void*)) != NULL) {
+ if (register_prng(p) == -1) {
+ va_end(args);
+ return CRYPT_INVALID_PRNG;
+ }
+ }
+
+ va_end(args);
+ return CRYPT_OK;
+}
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_hash_descriptor.c b/Sources/libtomcrypt/misc/crypt/crypt_hash_descriptor.c
new file mode 100644
index 00000000..08e0238c
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_hash_descriptor.c
@@ -0,0 +1,15 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_hash_descriptor.c
+ Stores the hash descriptor table, Tom St Denis
+*/
+
+struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = {
+{ NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL, NULL }
+};
+
+LTC_MUTEX_GLOBAL(ltc_hash_mutex)
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_hash_is_valid.c b/Sources/libtomcrypt/misc/crypt/crypt_hash_is_valid.c
new file mode 100644
index 00000000..c2d9fd93
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_hash_is_valid.c
@@ -0,0 +1,24 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_hash_is_valid.c
+ Determine if hash is valid, Tom St Denis
+*/
+
+/*
+ Test if a hash index is valid
+ @param idx The index of the hash to search for
+ @return CRYPT_OK if valid
+*/
+int hash_is_valid(int idx)
+{
+ LTC_MUTEX_LOCK(<c_hash_mutex);
+ if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) {
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return CRYPT_INVALID_HASH;
+ }
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return CRYPT_OK;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_inits.c b/Sources/libtomcrypt/misc/crypt/crypt_inits.c
new file mode 100644
index 00000000..f7af2b87
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_inits.c
@@ -0,0 +1,81 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_inits.c
+
+ Provide math library functions for dynamic languages
+ like Python - Larry Bugbee, February 2013
+*/
+
+
+#ifdef LTM_DESC
+void init_LTM(void)
+{
+ ltc_mp = ltm_desc;
+}
+#endif
+
+#ifdef TFM_DESC
+void init_TFM(void)
+{
+ ltc_mp = tfm_desc;
+}
+#endif
+
+#ifdef GMP_DESC
+void init_GMP(void)
+{
+ ltc_mp = gmp_desc;
+}
+#endif
+
+int crypt_mp_init(const char* mpi)
+{
+ if (mpi == NULL) return CRYPT_ERROR;
+ switch (mpi[0]) {
+#ifdef LTM_DESC
+ case 'l':
+ case 'L':
+ ltc_mp = ltm_desc;
+ return CRYPT_OK;
+#endif
+#ifdef TFM_DESC
+ case 't':
+ case 'T':
+ ltc_mp = tfm_desc;
+ return CRYPT_OK;
+#endif
+#ifdef GMP_DESC
+ case 'g':
+ case 'G':
+ ltc_mp = gmp_desc;
+ return CRYPT_OK;
+#endif
+#ifdef EXT_MATH_LIB
+ case 'e':
+ case 'E':
+ {
+ extern ltc_math_descriptor EXT_MATH_LIB;
+ ltc_mp = EXT_MATH_LIB;
+ }
+
+#if defined(LTC_TEST_DBG)
+#define NAME_VALUE(s) #s"="NAME(s)
+#define NAME(s) #s
+ printf("EXT_MATH_LIB = %s\n", NAME_VALUE(EXT_MATH_LIB));
+#undef NAME_VALUE
+#undef NAME
+#endif
+
+ return CRYPT_OK;
+#endif
+ default:
+#if defined(LTC_TEST_DBG)
+ printf("Unknown/Invalid MPI provider: %s\n", mpi);
+#endif
+ return CRYPT_ERROR;
+ }
+}
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_ltc_mp_descriptor.c b/Sources/libtomcrypt/misc/crypt/crypt_ltc_mp_descriptor.c
new file mode 100644
index 00000000..760ba634
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_ltc_mp_descriptor.c
@@ -0,0 +1,6 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/* Initialize ltc_mp to nulls, to force allocation on all platforms, including macOS. */
+ltc_math_descriptor ltc_mp = { 0 };
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_prng_descriptor.c b/Sources/libtomcrypt/misc/crypt/crypt_prng_descriptor.c
new file mode 100644
index 00000000..94c26b8d
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_prng_descriptor.c
@@ -0,0 +1,14 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_prng_descriptor.c
+ Stores the PRNG descriptors, Tom St Denis
+*/
+struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = {
+{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+LTC_MUTEX_GLOBAL(ltc_prng_mutex)
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_prng_is_valid.c b/Sources/libtomcrypt/misc/crypt/crypt_prng_is_valid.c
new file mode 100644
index 00000000..f1ba67b1
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_prng_is_valid.c
@@ -0,0 +1,24 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_prng_is_valid.c
+ Determine if PRNG is valid, Tom St Denis
+*/
+
+/*
+ Test if a PRNG index is valid
+ @param idx The index of the PRNG to search for
+ @return CRYPT_OK if valid
+*/
+int prng_is_valid(int idx)
+{
+ LTC_MUTEX_LOCK(<c_prng_mutex);
+ if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) {
+ LTC_MUTEX_UNLOCK(<c_prng_mutex);
+ return CRYPT_INVALID_PRNG;
+ }
+ LTC_MUTEX_UNLOCK(<c_prng_mutex);
+ return CRYPT_OK;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_prng_rng_descriptor.c b/Sources/libtomcrypt/misc/crypt/crypt_prng_rng_descriptor.c
new file mode 100644
index 00000000..49a456fb
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_prng_rng_descriptor.c
@@ -0,0 +1,7 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_PRNG_ENABLE_LTC_RNG
+unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void));
+#endif
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_register_all_ciphers.c b/Sources/libtomcrypt/misc/crypt/crypt_register_all_ciphers.c
new file mode 100644
index 00000000..5193ff90
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_register_all_ciphers.c
@@ -0,0 +1,104 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_register_all_ciphers.c
+
+ Steffen Jaeckel
+*/
+
+#define REGISTER_CIPHER(h) do {\
+ LTC_ARGCHK(register_cipher(h) != -1); \
+} while(0)
+
+int register_all_ciphers(void)
+{
+#ifdef LTC_RIJNDAEL
+ /* `aesni_desc` is explicitely not registered, since it's handled from within the `aes_desc` */
+#ifdef ENCRYPT_ONLY
+ /* alternative would be
+ * register_cipher(&rijndael_enc_desc);
+ */
+ REGISTER_CIPHER(&aes_enc_desc);
+#else
+ /* alternative would be
+ * register_cipher(&rijndael_desc);
+ */
+ REGISTER_CIPHER(&aes_desc);
+#endif
+#endif
+#ifdef LTC_BLOWFISH
+ REGISTER_CIPHER(&blowfish_desc);
+#endif
+#ifdef LTC_XTEA
+ REGISTER_CIPHER(&xtea_desc);
+#endif
+#ifdef LTC_RC5
+ REGISTER_CIPHER(&rc5_desc);
+#endif
+#ifdef LTC_RC6
+ REGISTER_CIPHER(&rc6_desc);
+#endif
+#ifdef LTC_SAFERP
+ REGISTER_CIPHER(&saferp_desc);
+#endif
+#ifdef LTC_TWOFISH
+ REGISTER_CIPHER(&twofish_desc);
+#endif
+#ifdef LTC_SAFER
+ REGISTER_CIPHER(&safer_k64_desc);
+ REGISTER_CIPHER(&safer_sk64_desc);
+ REGISTER_CIPHER(&safer_k128_desc);
+ REGISTER_CIPHER(&safer_sk128_desc);
+#endif
+#ifdef LTC_RC2
+ REGISTER_CIPHER(&rc2_desc);
+#endif
+#ifdef LTC_DES
+ REGISTER_CIPHER(&des_desc);
+ REGISTER_CIPHER(&desx_desc);
+ REGISTER_CIPHER(&des3_desc);
+#endif
+#ifdef LTC_SM4
+ REGISTER_CIPHER(&sm4_desc);
+#endif
+#ifdef LTC_CAST5
+ REGISTER_CIPHER(&cast5_desc);
+#endif
+#ifdef LTC_NOEKEON
+ REGISTER_CIPHER(&noekeon_desc);
+#endif
+#ifdef LTC_SKIPJACK
+ REGISTER_CIPHER(&skipjack_desc);
+#endif
+#ifdef LTC_ANUBIS
+ REGISTER_CIPHER(&anubis_desc);
+#endif
+#ifdef LTC_KHAZAD
+ REGISTER_CIPHER(&khazad_desc);
+#endif
+#ifdef LTC_KSEED
+ REGISTER_CIPHER(&kseed_desc);
+#endif
+#ifdef LTC_KASUMI
+ REGISTER_CIPHER(&kasumi_desc);
+#endif
+#ifdef LTC_MULTI2
+ REGISTER_CIPHER(&multi2_desc);
+#endif
+#ifdef LTC_CAMELLIA
+ REGISTER_CIPHER(&camellia_desc);
+#endif
+#ifdef LTC_IDEA
+ REGISTER_CIPHER(&idea_desc);
+#endif
+#ifdef LTC_SERPENT
+ REGISTER_CIPHER(&serpent_desc);
+#endif
+#ifdef LTC_TEA
+ REGISTER_CIPHER(&tea_desc);
+#endif
+ return CRYPT_OK;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_register_all_hashes.c b/Sources/libtomcrypt/misc/crypt/crypt_register_all_hashes.c
new file mode 100644
index 00000000..328e84a6
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_register_all_hashes.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_register_all_hashes.c
+
+ Steffen Jaeckel
+*/
+
+#define REGISTER_HASH(h) do {\
+ LTC_ARGCHK(register_hash(h) != -1); \
+} while(0)
+
+int register_all_hashes(void)
+{
+#ifdef LTC_TIGER
+ REGISTER_HASH(&tiger_desc);
+ REGISTER_HASH(&tiger2_desc);
+#endif
+#ifdef LTC_MD2
+ REGISTER_HASH(&md2_desc);
+#endif
+#ifdef LTC_MD4
+ REGISTER_HASH(&md4_desc);
+#endif
+#ifdef LTC_MD5
+ REGISTER_HASH(&md5_desc);
+#endif
+#ifdef LTC_SHA1
+ REGISTER_HASH(&sha1_desc);
+#endif
+#ifdef LTC_SHA224
+ REGISTER_HASH(&sha224_desc);
+#endif
+#ifdef LTC_SHA256
+ REGISTER_HASH(&sha256_desc);
+#endif
+#ifdef LTC_SHA384
+ REGISTER_HASH(&sha384_desc);
+#endif
+#ifdef LTC_SHA512
+ REGISTER_HASH(&sha512_desc);
+#endif
+#ifdef LTC_SHA512_224
+ REGISTER_HASH(&sha512_224_desc);
+#endif
+#ifdef LTC_SHA512_256
+ REGISTER_HASH(&sha512_256_desc);
+#endif
+#ifdef LTC_SHA3
+ REGISTER_HASH(&sha3_224_desc);
+ REGISTER_HASH(&sha3_256_desc);
+ REGISTER_HASH(&sha3_384_desc);
+ REGISTER_HASH(&sha3_512_desc);
+#endif
+#ifdef LTC_KECCAK
+ REGISTER_HASH(&keccak_224_desc);
+ REGISTER_HASH(&keccak_256_desc);
+ REGISTER_HASH(&keccak_384_desc);
+ REGISTER_HASH(&keccak_512_desc);
+#endif
+#ifdef LTC_RIPEMD128
+ REGISTER_HASH(&rmd128_desc);
+#endif
+#ifdef LTC_RIPEMD160
+ REGISTER_HASH(&rmd160_desc);
+#endif
+#ifdef LTC_RIPEMD256
+ REGISTER_HASH(&rmd256_desc);
+#endif
+#ifdef LTC_RIPEMD320
+ REGISTER_HASH(&rmd320_desc);
+#endif
+#ifdef LTC_WHIRLPOOL
+ REGISTER_HASH(&whirlpool_desc);
+#endif
+#ifdef LTC_BLAKE2S
+ REGISTER_HASH(&blake2s_128_desc);
+ REGISTER_HASH(&blake2s_160_desc);
+ REGISTER_HASH(&blake2s_224_desc);
+ REGISTER_HASH(&blake2s_256_desc);
+#endif
+#ifdef LTC_BLAKE2S
+ REGISTER_HASH(&blake2b_160_desc);
+ REGISTER_HASH(&blake2b_256_desc);
+ REGISTER_HASH(&blake2b_384_desc);
+ REGISTER_HASH(&blake2b_512_desc);
+#endif
+#ifdef LTC_CHC_HASH
+ REGISTER_HASH(&chc_desc);
+ LTC_ARGCHK(chc_register(find_cipher_any("aes", 8, 16)) == CRYPT_OK);
+#endif
+ return CRYPT_OK;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_register_all_prngs.c b/Sources/libtomcrypt/misc/crypt/crypt_register_all_prngs.c
new file mode 100644
index 00000000..4a2e2ef5
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_register_all_prngs.c
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_register_all_prngs.c
+
+ Steffen Jaeckel
+*/
+
+#define REGISTER_PRNG(h) do {\
+ LTC_ARGCHK(register_prng(h) != -1); \
+} while(0)
+
+int register_all_prngs(void)
+{
+#ifdef LTC_YARROW
+ REGISTER_PRNG(&yarrow_desc);
+#endif
+#ifdef LTC_FORTUNA
+ REGISTER_PRNG(&fortuna_desc);
+#endif
+#ifdef LTC_RC4
+ REGISTER_PRNG(&rc4_desc);
+#endif
+#ifdef LTC_CHACHA20_PRNG
+ REGISTER_PRNG(&chacha20_prng_desc);
+#endif
+#ifdef LTC_SOBER128
+ REGISTER_PRNG(&sober128_desc);
+#endif
+#ifdef LTC_SPRNG
+ REGISTER_PRNG(&sprng_desc);
+#endif
+
+ return CRYPT_OK;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_register_cipher.c b/Sources/libtomcrypt/misc/crypt/crypt_register_cipher.c
new file mode 100644
index 00000000..33c8696c
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_register_cipher.c
@@ -0,0 +1,42 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_register_cipher.c
+ Register a cipher, Tom St Denis
+*/
+
+/**
+ Register a cipher with the descriptor table
+ @param cipher The cipher you wish to register
+ @return value >= 0 if successfully added (or already present), -1 if unsuccessful
+*/
+int register_cipher(const struct ltc_cipher_descriptor *cipher)
+{
+ int x;
+
+ LTC_ARGCHK(cipher != NULL);
+
+ /* is it already registered? */
+ LTC_MUTEX_LOCK(<c_cipher_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) {
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return x;
+ }
+ }
+
+ /* find a blank spot */
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (cipher_descriptor[x].name == NULL) {
+ XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor));
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return x;
+ }
+ }
+
+ /* no spot */
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return -1;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_register_hash.c b/Sources/libtomcrypt/misc/crypt/crypt_register_hash.c
new file mode 100644
index 00000000..1668de39
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_register_hash.c
@@ -0,0 +1,42 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_register_hash.c
+ Register a HASH, Tom St Denis
+*/
+
+/**
+ Register a hash with the descriptor table
+ @param hash The hash you wish to register
+ @return value >= 0 if successfully added (or already present), -1 if unsuccessful
+*/
+int register_hash(const struct ltc_hash_descriptor *hash)
+{
+ int x;
+
+ LTC_ARGCHK(hash != NULL);
+
+ /* is it already registered? */
+ LTC_MUTEX_LOCK(<c_hash_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return x;
+ }
+ }
+
+ /* find a blank spot */
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (hash_descriptor[x].name == NULL) {
+ XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor));
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return x;
+ }
+ }
+
+ /* no spot */
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return -1;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_register_prng.c b/Sources/libtomcrypt/misc/crypt/crypt_register_prng.c
new file mode 100644
index 00000000..08e056b5
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_register_prng.c
@@ -0,0 +1,42 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_register_prng.c
+ Register a PRNG, Tom St Denis
+*/
+
+/**
+ Register a PRNG with the descriptor table
+ @param prng The PRNG you wish to register
+ @return value >= 0 if successfully added (or already present), -1 if unsuccessful
+*/
+int register_prng(const struct ltc_prng_descriptor *prng)
+{
+ int x;
+
+ LTC_ARGCHK(prng != NULL);
+
+ /* is it already registered? */
+ LTC_MUTEX_LOCK(<c_prng_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) {
+ LTC_MUTEX_UNLOCK(<c_prng_mutex);
+ return x;
+ }
+ }
+
+ /* find a blank spot */
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (prng_descriptor[x].name == NULL) {
+ XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor));
+ LTC_MUTEX_UNLOCK(<c_prng_mutex);
+ return x;
+ }
+ }
+
+ /* no spot */
+ LTC_MUTEX_UNLOCK(<c_prng_mutex);
+ return -1;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_sizes.c b/Sources/libtomcrypt/misc/crypt/crypt_sizes.c
new file mode 100644
index 00000000..26f2d13f
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_sizes.c
@@ -0,0 +1,354 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_sizes.c
+
+ Make various struct sizes available to dynamic languages
+ like Python - Larry Bugbee, February 2013
+
+ LB - Dec 2013 - revised to include compiler define options
+*/
+
+
+typedef struct {
+ const char *name;
+ const unsigned int size;
+} crypt_size;
+
+#define SZ_STRINGIFY_S(s) { #s, sizeof(struct s) }
+#define SZ_STRINGIFY_T(s) { #s, sizeof(s) }
+
+static const crypt_size s_crypt_sizes[] = {
+ /* hash state sizes */
+ SZ_STRINGIFY_S(ltc_hash_descriptor),
+ SZ_STRINGIFY_T(hash_state),
+#ifdef LTC_CHC_HASH
+ SZ_STRINGIFY_S(chc_state),
+#endif
+#ifdef LTC_WHIRLPOOL
+ SZ_STRINGIFY_S(whirlpool_state),
+#endif
+#ifdef LTC_SHA3
+ SZ_STRINGIFY_S(sha3_state),
+#endif
+#ifdef LTC_SHA512
+ SZ_STRINGIFY_S(sha512_state),
+#endif
+#ifdef LTC_SHA256
+ SZ_STRINGIFY_S(sha256_state),
+#endif
+#ifdef LTC_SHA1
+ SZ_STRINGIFY_S(sha1_state),
+#endif
+#ifdef LTC_MD5
+ SZ_STRINGIFY_S(md5_state),
+#endif
+#ifdef LTC_MD4
+ SZ_STRINGIFY_S(md4_state),
+#endif
+#ifdef LTC_MD2
+ SZ_STRINGIFY_S(md2_state),
+#endif
+#ifdef LTC_TIGER
+ SZ_STRINGIFY_S(tiger_state),
+#endif
+#ifdef LTC_RIPEMD128
+ SZ_STRINGIFY_S(rmd128_state),
+#endif
+#ifdef LTC_RIPEMD160
+ SZ_STRINGIFY_S(rmd160_state),
+#endif
+#ifdef LTC_RIPEMD256
+ SZ_STRINGIFY_S(rmd256_state),
+#endif
+#ifdef LTC_RIPEMD320
+ SZ_STRINGIFY_S(rmd320_state),
+#endif
+#ifdef LTC_BLAKE2S
+ SZ_STRINGIFY_S(blake2s_state),
+#endif
+#ifdef LTC_BLAKE2B
+ SZ_STRINGIFY_S(blake2b_state),
+#endif
+
+ /* block cipher key sizes */
+ SZ_STRINGIFY_S(ltc_cipher_descriptor),
+ SZ_STRINGIFY_T(symmetric_key),
+#ifdef LTC_ANUBIS
+ SZ_STRINGIFY_S(anubis_key),
+#endif
+#ifdef LTC_CAMELLIA
+ SZ_STRINGIFY_S(camellia_key),
+#endif
+#ifdef LTC_BLOWFISH
+ SZ_STRINGIFY_S(blowfish_key),
+#endif
+#ifdef LTC_CAST5
+ SZ_STRINGIFY_S(cast5_key),
+#endif
+#ifdef LTC_DES
+ SZ_STRINGIFY_S(des_key),
+ SZ_STRINGIFY_S(des3_key),
+#endif
+#ifdef LTC_SM4
+ SZ_STRINGIFY_S(sm4_key),
+#endif
+#ifdef LTC_IDEA
+ SZ_STRINGIFY_S(idea_key),
+#endif
+#ifdef LTC_KASUMI
+ SZ_STRINGIFY_S(kasumi_key),
+#endif
+#ifdef LTC_KHAZAD
+ SZ_STRINGIFY_S(khazad_key),
+#endif
+#ifdef LTC_KSEED
+ SZ_STRINGIFY_S(kseed_key),
+#endif
+#ifdef LTC_MULTI2
+ SZ_STRINGIFY_S(multi2_key),
+#endif
+#ifdef LTC_NOEKEON
+ SZ_STRINGIFY_S(noekeon_key),
+#endif
+#ifdef LTC_RC2
+ SZ_STRINGIFY_S(rc2_key),
+#endif
+#ifdef LTC_RC5
+ SZ_STRINGIFY_S(rc5_key),
+#endif
+#ifdef LTC_RC6
+ SZ_STRINGIFY_S(rc6_key),
+#endif
+#ifdef LTC_SERPENT
+ SZ_STRINGIFY_S(serpent_key),
+#endif
+#ifdef LTC_SKIPJACK
+ SZ_STRINGIFY_S(skipjack_key),
+#endif
+#ifdef LTC_XTEA
+ SZ_STRINGIFY_S(xtea_key),
+#endif
+#ifdef LTC_RIJNDAEL
+ SZ_STRINGIFY_S(rijndael_key),
+#endif
+#ifdef LTC_SAFER
+ SZ_STRINGIFY_S(safer_key),
+#endif
+#ifdef LTC_SAFERP
+ SZ_STRINGIFY_S(saferp_key),
+#endif
+#ifdef LTC_TWOFISH
+ SZ_STRINGIFY_S(twofish_key),
+#endif
+
+ /* mode sizes */
+#ifdef LTC_ECB_MODE
+ SZ_STRINGIFY_T(symmetric_ECB),
+#endif
+#ifdef LTC_CFB_MODE
+ SZ_STRINGIFY_T(symmetric_CFB),
+#endif
+#ifdef LTC_OFB_MODE
+ SZ_STRINGIFY_T(symmetric_OFB),
+#endif
+#ifdef LTC_CBC_MODE
+ SZ_STRINGIFY_T(symmetric_CBC),
+#endif
+#ifdef LTC_CTR_MODE
+ SZ_STRINGIFY_T(symmetric_CTR),
+#endif
+#ifdef LTC_LRW_MODE
+ SZ_STRINGIFY_T(symmetric_LRW),
+#endif
+#ifdef LTC_F8_MODE
+ SZ_STRINGIFY_T(symmetric_F8),
+#endif
+#ifdef LTC_XTS_MODE
+ SZ_STRINGIFY_T(symmetric_xts),
+#endif
+
+ /* stream cipher sizes */
+#ifdef LTC_CHACHA
+ SZ_STRINGIFY_T(chacha_state),
+#endif
+#ifdef LTC_SALSA20
+ SZ_STRINGIFY_T(salsa20_state),
+#endif
+#ifdef LTC_SOSEMANUK
+ SZ_STRINGIFY_T(sosemanuk_state),
+#endif
+#ifdef LTC_RABBIT
+ SZ_STRINGIFY_T(rabbit_state),
+#endif
+#ifdef LTC_RC4_STREAM
+ SZ_STRINGIFY_T(rc4_state),
+#endif
+#ifdef LTC_SOBER128_STREAM
+ SZ_STRINGIFY_T(sober128_state),
+#endif
+
+ /* MAC sizes -- no states for ccm, lrw */
+#ifdef LTC_HMAC
+ SZ_STRINGIFY_T(hmac_state),
+#endif
+#ifdef LTC_OMAC
+ SZ_STRINGIFY_T(omac_state),
+#endif
+#ifdef LTC_PMAC
+ SZ_STRINGIFY_T(pmac_state),
+#endif
+#ifdef LTC_POLY1305
+ SZ_STRINGIFY_T(poly1305_state),
+#endif
+#ifdef LTC_EAX_MODE
+ SZ_STRINGIFY_T(eax_state),
+#endif
+#ifdef LTC_OCB_MODE
+ SZ_STRINGIFY_T(ocb_state),
+#endif
+#ifdef LTC_OCB3_MODE
+ SZ_STRINGIFY_T(ocb3_state),
+#endif
+#ifdef LTC_CCM_MODE
+ SZ_STRINGIFY_T(ccm_state),
+#endif
+#ifdef LTC_GCM_MODE
+ SZ_STRINGIFY_T(gcm_state),
+#endif
+#ifdef LTC_PELICAN
+ SZ_STRINGIFY_T(pelican_state),
+#endif
+#ifdef LTC_XCBC
+ SZ_STRINGIFY_T(xcbc_state),
+#endif
+#ifdef LTC_F9_MODE
+ SZ_STRINGIFY_T(f9_state),
+#endif
+#ifdef LTC_CHACHA20POLY1305_MODE
+ SZ_STRINGIFY_T(chacha20poly1305_state),
+#endif
+
+ /* asymmetric keys */
+#ifdef LTC_MRSA
+ SZ_STRINGIFY_T(rsa_key),
+#endif
+#ifdef LTC_MDSA
+ SZ_STRINGIFY_T(dsa_key),
+#endif
+#ifdef LTC_MDH
+ SZ_STRINGIFY_T(dh_key),
+#endif
+#ifdef LTC_MECC
+ SZ_STRINGIFY_T(ltc_ecc_curve),
+ SZ_STRINGIFY_T(ecc_point),
+ SZ_STRINGIFY_T(ecc_key),
+#endif
+
+ /* DER handling */
+#ifdef LTC_DER
+ SZ_STRINGIFY_T(ltc_asn1_list), /* a list entry */
+ SZ_STRINGIFY_T(ltc_utctime),
+ SZ_STRINGIFY_T(ltc_generalizedtime),
+#endif
+
+ /* prng state sizes */
+ SZ_STRINGIFY_S(ltc_prng_descriptor),
+ SZ_STRINGIFY_T(prng_state),
+#ifdef LTC_FORTUNA
+ SZ_STRINGIFY_S(fortuna_prng),
+#endif
+#ifdef LTC_CHACHA20_PRNG
+ SZ_STRINGIFY_S(chacha20_prng),
+#endif
+#ifdef LTC_RC4
+ SZ_STRINGIFY_S(rc4_prng),
+#endif
+#ifdef LTC_SOBER128
+ SZ_STRINGIFY_S(sober128_prng),
+#endif
+#ifdef LTC_YARROW
+ SZ_STRINGIFY_S(yarrow_prng),
+#endif
+ /* sprng has no state as it uses other potentially available sources */
+ /* like /dev/random. See Developers Guide for more info. */
+
+#ifdef LTC_ADLER32
+ SZ_STRINGIFY_T(adler32_state),
+#endif
+#ifdef LTC_CRC32
+ SZ_STRINGIFY_T(crc32_state),
+#endif
+
+ SZ_STRINGIFY_T(ltc_mp_digit),
+ SZ_STRINGIFY_T(ltc_math_descriptor)
+
+};
+
+/* crypt_get_size()
+ * sizeout will be the size (bytes) of the named struct or union
+ * return -1 if named item not found
+ */
+int crypt_get_size(const char* namein, unsigned int *sizeout) {
+ int i;
+ int count = sizeof(s_crypt_sizes) / sizeof(s_crypt_sizes[0]);
+ for (i=0; i *names_list_size) {
+ return -1;
+ }
+ /* build the names list */
+ ptr = names_list;
+ for (i=0; i total_len) return -1;
+ total_len -= number_len;
+ ptr += number_len;
+ }
+ /* to remove the trailing new-line */
+ ptr -= 1;
+ *ptr = 0;
+ }
+ return 0;
+}
+
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_unregister_cipher.c b/Sources/libtomcrypt/misc/crypt/crypt_unregister_cipher.c
new file mode 100644
index 00000000..bebf9206
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_unregister_cipher.c
@@ -0,0 +1,33 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_unregister_cipher.c
+ Unregister a cipher, Tom St Denis
+*/
+
+/**
+ Unregister a cipher from the descriptor table
+ @param cipher The cipher descriptor to remove
+ @return CRYPT_OK on success
+*/
+int unregister_cipher(const struct ltc_cipher_descriptor *cipher)
+{
+ int x;
+
+ LTC_ARGCHK(cipher != NULL);
+
+ /* is it already registered? */
+ LTC_MUTEX_LOCK(<c_cipher_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (XMEMCMP(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)) == 0) {
+ cipher_descriptor[x].name = NULL;
+ cipher_descriptor[x].ID = 255;
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return CRYPT_OK;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_cipher_mutex);
+ return CRYPT_ERROR;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_unregister_hash.c b/Sources/libtomcrypt/misc/crypt/crypt_unregister_hash.c
new file mode 100644
index 00000000..c2374d01
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_unregister_hash.c
@@ -0,0 +1,32 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_unregister_hash.c
+ Unregister a hash, Tom St Denis
+*/
+
+/**
+ Unregister a hash from the descriptor table
+ @param hash The hash descriptor to remove
+ @return CRYPT_OK on success
+*/
+int unregister_hash(const struct ltc_hash_descriptor *hash)
+{
+ int x;
+
+ LTC_ARGCHK(hash != NULL);
+
+ /* is it already registered? */
+ LTC_MUTEX_LOCK(<c_hash_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {
+ hash_descriptor[x].name = NULL;
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return CRYPT_OK;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_hash_mutex);
+ return CRYPT_ERROR;
+}
diff --git a/Sources/libtomcrypt/misc/crypt/crypt_unregister_prng.c b/Sources/libtomcrypt/misc/crypt/crypt_unregister_prng.c
new file mode 100644
index 00000000..1aa11e00
--- /dev/null
+++ b/Sources/libtomcrypt/misc/crypt/crypt_unregister_prng.c
@@ -0,0 +1,32 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file crypt_unregister_prng.c
+ Unregister a PRNG, Tom St Denis
+*/
+
+/**
+ Unregister a PRNG from the descriptor table
+ @param prng The PRNG descriptor to remove
+ @return CRYPT_OK on success
+*/
+int unregister_prng(const struct ltc_prng_descriptor *prng)
+{
+ int x;
+
+ LTC_ARGCHK(prng != NULL);
+
+ /* is it already registered? */
+ LTC_MUTEX_LOCK(<c_prng_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) {
+ prng_descriptor[x].name = NULL;
+ LTC_MUTEX_UNLOCK(<c_prng_mutex);
+ return CRYPT_OK;
+ }
+ }
+ LTC_MUTEX_UNLOCK(<c_prng_mutex);
+ return CRYPT_ERROR;
+}
diff --git a/Sources/libtomcrypt/misc/error_to_string.c b/Sources/libtomcrypt/misc/error_to_string.c
new file mode 100644
index 00000000..923636e5
--- /dev/null
+++ b/Sources/libtomcrypt/misc/error_to_string.c
@@ -0,0 +1,72 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file error_to_string.c
+ Convert error codes to ASCII strings, Tom St Denis
+*/
+
+static const char * const err_2_str[] =
+{
+ "CRYPT_OK",
+ "CRYPT_ERROR",
+ "Non-fatal 'no-operation' requested.",
+
+ "Invalid key size.",
+ "Invalid number of rounds for block cipher.",
+ "Algorithm failed test vectors.",
+
+ "Buffer overflow.",
+ "Invalid input packet.",
+
+ "Invalid number of bits for a PRNG.",
+ "Error reading the PRNG.",
+
+ "Invalid cipher specified.",
+ "Invalid hash specified.",
+ "Invalid PRNG specified.",
+
+ "Out of memory.",
+
+ "Invalid PK key or key type specified for function.",
+ "A private PK key is required.",
+
+ "Invalid argument provided.",
+ "File Not Found",
+
+ "Invalid PK type.",
+
+ "An overflow of a value was detected/prevented.",
+
+ "An ASN.1 decoding error occurred.",
+
+ "The input was longer than expected.",
+
+ "Invalid sized parameter.",
+
+ "Invalid size for prime.",
+
+ "Invalid padding.",
+
+ "Hash applied to too many bits.",
+
+ "Password context to decrypt key file is missing.",
+
+ "The PEM header was not recognized",
+};
+
+/**
+ Convert an LTC error code to ASCII
+ @param err The error code
+ @return A pointer to the ASCII NUL terminated string for the error or "Invalid error code." if the err code was not valid.
+*/
+const char *error_to_string(int err)
+{
+ if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
+ return "Invalid error code.";
+ }
+ return err_2_str[err];
+}
+
diff --git a/Sources/libtomcrypt/misc/hkdf/hkdf.c b/Sources/libtomcrypt/misc/hkdf/hkdf.c
new file mode 100644
index 00000000..86b4ee8d
--- /dev/null
+++ b/Sources/libtomcrypt/misc/hkdf/hkdf.c
@@ -0,0 +1,135 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include
+#include
+#include
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_HKDF
+
+/* This is mostly just a wrapper around hmac_memory */
+int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ /* libtomcrypt chokes on a zero length HMAC key, so we need to check for
+ that. HMAC specifies that keys shorter than the hash's blocksize are
+ 0 padded to the block size. HKDF specifies that a NULL salt is to be
+ substituted with a salt comprised of hashLen 0 bytes. HMAC's padding
+ means that in either case the HMAC is actually using a blocksize long
+ zero filled key. Unless blocksize < hashLen (which wouldn't make any
+ sense), we can use a single 0 byte as the HMAC key and still generate
+ valid results for HKDF. */
+ if (salt == NULL || saltlen == 0) {
+ return hmac_memory(hash_idx, (const unsigned char *)"", 1, in, inlen, out, outlen);
+ }
+ return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen);
+}
+
+int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long outlen)
+{
+ unsigned long hashsize;
+ int err;
+ unsigned char N;
+ unsigned long Noutlen, outoff;
+
+ unsigned char *T, *dat;
+ unsigned long Tlen, datlen;
+
+ /* make sure hash descriptor is valid */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ hashsize = hash_descriptor[hash_idx].hashsize;
+
+ /* RFC5869 parameter restrictions */
+ if (inlen < hashsize || outlen > hashsize * 255) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (info == NULL && infolen != 0) {
+ return CRYPT_INVALID_ARG;
+ }
+ LTC_ARGCHK(out != NULL);
+
+ Tlen = hashsize + infolen + 1;
+ T = XMALLOC(Tlen); /* Replace with static buffer? */
+ if (T == NULL) {
+ return CRYPT_MEM;
+ }
+ if (info != NULL) {
+ XMEMCPY(T + hashsize, info, infolen);
+ }
+
+ /* HMAC data T(1) doesn't include a previous hash value */
+ dat = T + hashsize;
+ datlen = Tlen - hashsize;
+
+ N = 0;
+ outoff = 0; /* offset in out to write to */
+ while (1) { /* an exit condition breaks mid-loop */
+ Noutlen = MIN(hashsize, outlen - outoff);
+ T[Tlen - 1] = ++N;
+ if ((err = hmac_memory(hash_idx, in, inlen, dat, datlen,
+ out + outoff, &Noutlen)) != CRYPT_OK) {
+ zeromem(T, Tlen);
+ XFREE(T);
+ return err;
+ }
+ outoff += Noutlen;
+
+ if (outoff >= outlen) { /* loop exit condition */
+ break;
+ }
+
+ /* All subsequent HMAC data T(N) DOES include the previous hash value */
+ XMEMCPY(T, out + hashsize * (N-1), hashsize);
+ if (N == 1) {
+ dat = T;
+ datlen = Tlen;
+ }
+ }
+ zeromem(T, Tlen);
+ XFREE(T);
+ return CRYPT_OK;
+}
+
+/* all in one step */
+int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen,
+ const unsigned char *info, unsigned long infolen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long outlen)
+{
+ unsigned long hashsize;
+ int err;
+ unsigned char *extracted;
+
+ /* make sure hash descriptor is valid */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ hashsize = hash_descriptor[hash_idx].hashsize;
+
+ extracted = XMALLOC(hashsize); /* replace with static buffer? */
+ if (extracted == NULL) {
+ return CRYPT_MEM;
+ }
+ if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) {
+ zeromem(extracted, hashsize);
+ XFREE(extracted);
+ return err;
+ }
+ err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen);
+ zeromem(extracted, hashsize);
+ XFREE(extracted);
+ return err;
+}
+#endif /* LTC_HKDF */
+
+
+/* vim: set ts=2 sw=2 et ai si: */
diff --git a/Sources/libtomcrypt/misc/hkdf/hkdf_test.c b/Sources/libtomcrypt/misc/hkdf/hkdf_test.c
new file mode 100644
index 00000000..99a970ce
--- /dev/null
+++ b/Sources/libtomcrypt/misc/hkdf/hkdf_test.c
@@ -0,0 +1,284 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file hkdf_test.c
+ LTC_HKDF support, self-test, Steffen Jaeckel
+*/
+
+#ifdef LTC_HKDF
+
+/*
+ TEST CASES SOURCE:
+
+Internet Engineering Task Force (IETF) H. Krawczyk
+Request for Comments: 5869 IBM Research
+Category: Informational P. Eronen
+ISSN: 2070-1721 Nokia
+ May 2010
+Appendix A. Test Vectors
+*/
+
+/**
+ LTC_HKDF self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled.
+*/
+int hkdf_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ unsigned char OKM[82];
+ int i;
+
+ static const struct hkdf_test_case {
+ int num;
+ const char* Hash;
+ unsigned char IKM[80];
+ unsigned long IKM_l;
+ unsigned char salt[80];
+ unsigned long salt_l;
+ unsigned char info[80];
+ unsigned long info_l;
+ unsigned char PRK[32];
+ unsigned long PRK_l;
+ unsigned char OKM[82];
+ unsigned long OKM_l;
+ } cases[] = {
+#ifdef LTC_SHA256
+ /*
+ Basic test case with SHA-256
+
+ Hash = SHA-256
+ IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets)
+ salt = 0x000102030405060708090a0b0c (13 octets)
+ info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets)
+ L = 42
+
+ PRK = 0x077709362c2e32df0ddc3f0dc47bba63
+ 90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets)
+ OKM = 0x3cb25f25faacd57a90434f64d0362f2a
+ 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
+ 34007208d5b887185865 (42 octets)
+ */
+ {1, "sha256",
+ {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22,
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13,
+ {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9}, 10,
+ {0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf,
+ 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63,
+ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31,
+ 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}, 32,
+ {0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
+ 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
+ 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
+ 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
+ 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
+ 0x58, 0x65}, 42},
+#ifdef LTC_TEST_EXT
+ /* Test with SHA-256 and longer inputs/outputs */
+ {2, "sha256",
+ {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,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80,
+ {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80,
+ {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80,
+ {0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a,
+ 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c,
+ 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01,
+ 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44}, 32,
+ {0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1,
+ 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
+ 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
+ 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
+ 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72,
+ 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
+ 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
+ 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
+ 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
+ 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
+ 0x1d, 0x87}, 82},
+ /* Test with SHA-256 and zero length salt/info */
+ {3, "sha256",
+ {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22,
+ {0}, 0,
+ {0}, 0,
+ {0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16,
+ 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf,
+ 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77,
+ 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}, 32,
+ {0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
+ 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
+ 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
+ 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
+ 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a,
+ 0x96, 0xc8}, 42},
+#endif /* LTC_TEST_EXT */
+#endif /* LTC_SHA256 */
+#ifdef LTC_SHA1
+ /* Basic test case with SHA-1 */
+ {4, "sha1",
+ {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b}, 11,
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13,
+ {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9}, 10,
+ {0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f,
+ 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b,
+ 0xaa, 0x2b, 0xa2, 0x43}, 20,
+ {0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69,
+ 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81,
+ 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
+ 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2,
+ 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3,
+ 0xf8, 0x96}, 42},
+#ifdef LTC_TEST_EXT
+ /* Test with SHA-1 and longer inputs/outputs */
+ {5, "sha1",
+ {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,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80,
+ {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80,
+ {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80,
+ {0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59,
+ 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a,
+ 0x22, 0x4c, 0xfa, 0xf6}, 20,
+ {0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7,
+ 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb,
+ 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
+ 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe,
+ 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3,
+ 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
+ 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed,
+ 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e,
+ 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
+ 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52,
+ 0xd3, 0xb4}, 82},
+ /* Test with SHA-1 and zero-length salt/info */
+ {6, "sha1",
+ {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22,
+ {0}, 0,
+ {0}, 0,
+ {0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28,
+ 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a,
+ 0xa0, 0xd3, 0x2d, 0x01}, 20,
+ {0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61,
+ 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06,
+ 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
+ 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0,
+ 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3,
+ 0x49, 0x18}, 42},
+ /* Test with SHA-1, salt not provided (defaults to HashLen zero octets),
+ zero-length info */
+ {7, "sha1",
+ {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 22,
+ {0}, 0, /* pass a null pointer */
+ {0}, 0,
+ {0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c,
+ 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e,
+ 0x73, 0x13, 0x85, 0xdd}, 20,
+ {0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3,
+ 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a,
+ 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
+ 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5,
+ 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac,
+ 0xfc, 0x48}, 42},
+#endif /* LTC_TEST_EXT */
+#endif /* LTC_SHA1 */
+ };
+
+ int err;
+ int tested=0,failed=0;
+ for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
+ int hash = find_hash(cases[i].Hash);
+ if (hash == -1) continue;
+ ++tested;
+ if((err = hkdf(hash, cases[i].salt, cases[i].salt_l,
+ cases[i].info, cases[i].info_l,
+ cases[i].IKM, cases[i].IKM_l,
+ OKM, cases[i].OKM_l)) != CRYPT_OK) {
+#if defined(LTC_TEST_DBG) && (LTC_TEST_DBG > 1)
+ printf("LTC_HKDF-%s test #%d, %s\n", cases[i].Hash, i, error_to_string(err));
+#endif
+ return err;
+ }
+
+ if(compare_testvector(OKM, cases[i].OKM_l, cases[i].OKM, (size_t)cases[i].OKM_l, "HKDF", cases[i].num)) {
+ failed++;
+ }
+ }
+
+ if (failed != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ if (tested == 0) {
+ return CRYPT_NOP;
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/misc/mem_neq.c b/Sources/libtomcrypt/misc/mem_neq.c
new file mode 100644
index 00000000..8078a0a8
--- /dev/null
+++ b/Sources/libtomcrypt/misc/mem_neq.c
@@ -0,0 +1,53 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file mem_neq.c
+ Compare two blocks of memory for inequality in constant time.
+ Steffen Jaeckel
+*/
+
+/**
+ Compare two blocks of memory for inequality in constant time.
+
+ The usage is similar to that of standard memcmp, but you can only test
+ if the memory is equal or not - you can not determine by how much the
+ first different byte differs.
+
+ This function shall be used to compare results of cryptographic
+ operations where inequality means most likely usage of a wrong key.
+ The execution time has therefore to be constant as otherwise
+ timing attacks could be possible.
+
+ @param a The first memory region
+ @param b The second memory region
+ @param len The length of the area to compare (octets)
+
+ @return 0 when a and b are equal for len bytes, 1 they are not equal.
+*/
+int mem_neq(const void *a, const void *b, size_t len)
+{
+ unsigned char ret = 0;
+ const unsigned char* pa;
+ const unsigned char* pb;
+
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+
+ pa = a;
+ pb = b;
+
+ while (len-- > 0) {
+ ret |= *pa ^ *pb;
+ ++pa;
+ ++pb;
+ }
+
+ ret |= ret >> 4;
+ ret |= ret >> 2;
+ ret |= ret >> 1;
+ ret &= 1;
+
+ return ret;
+}
diff --git a/Sources/libtomcrypt/misc/padding/padding_depad.c b/Sources/libtomcrypt/misc/padding/padding_depad.c
new file mode 100644
index 00000000..e3f71511
--- /dev/null
+++ b/Sources/libtomcrypt/misc/padding/padding_depad.c
@@ -0,0 +1,90 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_PADDING
+
+/**
+ Remove padding from your data
+
+ This depads your data.
+
+ @param data The data to depad
+ @param length [in/out] The size of the data before/after (removing padding)
+ @param mode One of the LTC_PAD_xx flags
+ @return CRYPT_OK on success
+*/
+int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode)
+{
+ unsigned long padded_length, unpadded_length, n;
+ unsigned char pad;
+ enum padding_type type;
+
+ LTC_ARGCHK(data != NULL);
+ LTC_ARGCHK(length != NULL);
+
+ padded_length = *length;
+
+ type = mode & LTC_PAD_MASK;
+
+ if (type < LTC_PAD_ONE_AND_ZERO) {
+ pad = data[padded_length - 1];
+
+ if (pad > padded_length || pad == 0) return CRYPT_INVALID_ARG;
+
+ unpadded_length = padded_length - pad;
+ } else {
+ /* init pad to calm old compilers */
+ pad = 0x0;
+ unpadded_length = padded_length;
+ }
+
+ switch (type) {
+ case LTC_PAD_ANSI_X923:
+ pad = 0x0;
+ /* FALLTHROUGH */
+ case LTC_PAD_PKCS7:
+ for (n = unpadded_length; n < padded_length - 1; ++n) {
+ if (data[n] != pad) return CRYPT_INVALID_PACKET;
+ }
+ break;
+#ifdef LTC_RNG_GET_BYTES
+ case LTC_PAD_ISO_10126:
+ /* nop */
+ break;
+#endif
+ case LTC_PAD_SSH:
+ pad = 0x1;
+ for (n = unpadded_length; n < padded_length; ++n) {
+ if (data[n] != pad++) return CRYPT_INVALID_PACKET;
+ }
+ break;
+ case LTC_PAD_ONE_AND_ZERO:
+ while (unpadded_length > 0 && data[unpadded_length - 1] != 0x80) {
+ if (data[unpadded_length - 1] != 0x0) return CRYPT_INVALID_PACKET;
+ unpadded_length--;
+ }
+ if (unpadded_length == 0) return CRYPT_INVALID_PACKET;
+ unpadded_length--;
+ if (data[unpadded_length] != 0x80) return CRYPT_INVALID_PACKET;
+ break;
+ case LTC_PAD_ZERO:
+ case LTC_PAD_ZERO_ALWAYS:
+ while (unpadded_length > 0 && data[unpadded_length - 1] == 0x0) {
+ unpadded_length--;
+ }
+ if (type == LTC_PAD_ZERO_ALWAYS) {
+ if (unpadded_length == padded_length) return CRYPT_INVALID_PACKET;
+ if (data[unpadded_length] != 0x0) return CRYPT_INVALID_PACKET;
+ }
+ break;
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+
+ *length = unpadded_length;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/padding/padding_pad.c b/Sources/libtomcrypt/misc/padding/padding_pad.c
new file mode 100644
index 00000000..7d8bbbad
--- /dev/null
+++ b/Sources/libtomcrypt/misc/padding/padding_pad.c
@@ -0,0 +1,151 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_PADDING
+
+/**
+ Determine the to-be-padded length.
+
+ @param length [in/out] The size of the data before/after padding
+ @param mode Mask of (LTC_PAD_xxx | block_length)
+ @return CRYPT_OK on success
+*/
+static int s_padding_padded_length(unsigned long *length, unsigned long mode)
+{
+ enum padding_type padding;
+ unsigned char pad, block_length, r, t;
+
+ LTC_ARGCHK(length != NULL);
+
+ block_length = mode & 0xff;
+ padding = mode & LTC_PAD_MASK;
+ r = *length % block_length;
+
+ switch (padding) {
+ case LTC_PAD_ZERO:
+ if (r == 0) {
+ t = 0;
+ break;
+ }
+ /* FALLTHROUGH */
+ case LTC_PAD_PKCS7:
+ case LTC_PAD_ONE_AND_ZERO:
+ case LTC_PAD_ZERO_ALWAYS:
+ case LTC_PAD_SSH:
+ t = 1;
+ break;
+#ifdef LTC_RNG_GET_BYTES
+ case LTC_PAD_ISO_10126:
+ do {
+ if (rng_get_bytes(&t, sizeof(t), NULL) != sizeof(t)) {
+ return CRYPT_ERROR_READPRNG;
+ }
+ t %= (256 / block_length);
+ } while (t == 0);
+ break;
+#endif
+ case LTC_PAD_ANSI_X923:
+ if (block_length != 16) {
+ return CRYPT_INVALID_ARG;
+ }
+ t = 1;
+ break;
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+
+ pad = (t * block_length) - r;
+
+ if ((pad == 0) && (padding != LTC_PAD_ZERO)) {
+ pad = block_length;
+ }
+
+ *length += pad;
+
+ return CRYPT_OK;
+}
+
+/**
+ Add padding to data.
+
+ This pads your data.
+
+ @param data The data to depad
+ @param length The size of the data before padding
+ @param padded_length [in/out] The size of the data available/after padding
+ @param mode One of the LTC_PAD_xx flags
+ @return CRYPT_OK on success
+*/
+int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode)
+{
+ unsigned long l, n;
+ enum padding_type type;
+ int err;
+ unsigned char diff, pad;
+
+ LTC_ARGCHK(data != NULL);
+ LTC_ARGCHK(padded_length != NULL);
+
+ l = length;
+ if ((err = s_padding_padded_length(&l, mode)) != CRYPT_OK) {
+ return err;
+ }
+
+ type = mode & LTC_PAD_MASK;
+
+ if (*padded_length < l) {
+#ifdef LTC_RNG_GET_BYTES
+ if (type != LTC_PAD_ISO_10126) {
+ *padded_length = l;
+ } else {
+ *padded_length = length + 256;
+ }
+#else
+ *padded_length = l;
+#endif
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (l - length > 255) return CRYPT_INVALID_ARG;
+ diff = (unsigned char)(l - length);
+
+ switch (type) {
+ case LTC_PAD_PKCS7:
+ XMEMSET(&data[length], diff, diff);
+ break;
+#ifdef LTC_RNG_GET_BYTES
+ case LTC_PAD_ISO_10126:
+ if (rng_get_bytes(&data[length], diff-1u, NULL) != diff-1u) {
+ return CRYPT_ERROR_READPRNG;
+ }
+ data[l-1] = diff;
+ break;
+#endif
+ case LTC_PAD_ANSI_X923:
+ XMEMSET(&data[length], 0, diff-1);
+ data[l-1] = diff;
+ break;
+ case LTC_PAD_SSH:
+ pad = 0x1;
+ for (n = length; n < l; ++n) {
+ data[n] = pad++;
+ }
+ break;
+ case LTC_PAD_ONE_AND_ZERO:
+ XMEMSET(&data[length + 1], 0, diff);
+ data[length] = 0x80;
+ break;
+ case LTC_PAD_ZERO:
+ case LTC_PAD_ZERO_ALWAYS:
+ XMEMSET(&data[length], 0, diff);
+ break;
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+ *padded_length = l;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/password_free.c b/Sources/libtomcrypt/misc/password_free.c
new file mode 100644
index 00000000..e88b700c
--- /dev/null
+++ b/Sources/libtomcrypt/misc/password_free.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file password_free.c
+ Free the password inside a `struct password`, Steffen Jaeckel
+*/
+
+/**
+ Free a password
+ @param pw The password to be free'd
+ @param ctx The password context
+*/
+void password_free(struct password *pw, const struct password_ctx *ctx)
+{
+ if (!ctx || !pw || !pw->pw)
+ return;
+
+ zeromem(pw->pw, pw->l);
+ if (ctx->free) {
+ ctx->free(pw->pw);
+ } else {
+ XFREE(pw->pw);
+ }
+ pw->pw = NULL;
+ pw->l = 0;
+}
diff --git a/Sources/libtomcrypt/misc/pbes/pbes.c b/Sources/libtomcrypt/misc/pbes/pbes.c
new file mode 100644
index 00000000..b4231234
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pbes/pbes.c
@@ -0,0 +1,73 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_PBES
+
+/**
+ Decrypt Data encrypted via either PBES1 or PBES2
+
+ @param arg The according PBES parameters
+ @param dec_data [out] The decrypted data
+ @param dec_size [in/out] The length of the encrypted resp. decrypted data
+ @return CRYPT_OK on success
+*/
+int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size)
+{
+ int err, hid, cid;
+ unsigned char k[32], *iv;
+ unsigned long klen, keylen, dlen;
+ long diff;
+ symmetric_CBC cbc;
+
+ LTC_ARGCHK(arg != NULL);
+ LTC_ARGCHK(arg->type.kdf != NULL);
+ LTC_ARGCHK(dec_data != NULL);
+ LTC_ARGCHK(dec_size != NULL);
+
+ hid = find_hash(arg->type.h);
+ if (hid == -1) return CRYPT_INVALID_HASH;
+ cid = find_cipher(arg->type.c);
+ if (cid == -1) return CRYPT_INVALID_CIPHER;
+
+ klen = arg->type.keylen;
+
+ /* RC2 special case */
+ if (arg->key_bits != 0) {
+ /* We can't handle odd lengths of Key Bits */
+ if ((arg->key_bits % 8) != 0) return CRYPT_INVALID_KEYSIZE;
+ /* Internally we use bytes, not bits */
+ klen = arg->key_bits / 8;
+ }
+ keylen = klen;
+
+ if (arg->iv != NULL) {
+ iv = arg->iv->data;
+ } else {
+ iv = k + klen;
+ klen += arg->type.blocklen;
+ }
+
+ if (klen > sizeof(k)) return CRYPT_INVALID_ARG;
+
+ if ((err = arg->type.kdf(&arg->pw, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
+ dlen = arg->enc_data->size;
+ if ((err = padding_depad(dec_data, &dlen, LTC_PAD_PKCS7)) != CRYPT_OK) goto LBL_ERROR;
+ diff = (long)arg->enc_data->size - (long)dlen;
+ if ((diff <= 0) || (diff > cipher_descriptor[cid].block_length)) {
+ err = CRYPT_PK_INVALID_PADDING;
+ goto LBL_ERROR;
+ }
+ *dec_size = dlen;
+ return CRYPT_OK;
+
+LBL_ERROR:
+ zeromem(k, sizeof(k));
+ zeromem(dec_data, *dec_size);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/pbes/pbes1.c b/Sources/libtomcrypt/misc/pbes/pbes1.c
new file mode 100644
index 00000000..36e09070
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pbes/pbes1.c
@@ -0,0 +1,117 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_PBES
+
+static int s_pkcs_5_alg1_wrap(const struct password *pwd,
+ const unsigned char *salt, unsigned long salt_len,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen)
+{
+ LTC_UNUSED_PARAM(salt_len);
+ return pkcs_5_alg1(pwd->pw, pwd->l, salt, iteration_count, hash_idx, out, outlen);
+}
+
+static int s_pkcs_12_wrap(const struct password *pwd,
+ const unsigned char *salt, unsigned long salt_len,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen)
+{
+ int err;
+ /* convert password to unicode/utf16-be */
+ unsigned long pwlen = pwd->l * 2;
+ unsigned char* pw;
+ if (*outlen < 32) return CRYPT_INVALID_ARG;
+ pw = XMALLOC(pwlen + 2);
+ if (pw == NULL) return CRYPT_MEM;
+ if ((err = pkcs12_utf8_to_utf16(pwd->pw, pwd->l, pw, &pwlen)) != CRYPT_OK) goto LBL_ERROR;
+ pw[pwlen++] = 0;
+ pw[pwlen++] = 0;
+ /* derive KEY */
+ if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 1, out, 24)) != CRYPT_OK) goto LBL_ERROR;
+ /* derive IV */
+ if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 2, out+24, 8)) != CRYPT_OK) goto LBL_ERROR;
+
+ *outlen = 32;
+LBL_ERROR:
+ zeromem(pw, pwlen);
+ XFREE(pw);
+ return err;
+}
+
+static const pbes_properties s_pbes1_types[] = {
+ { s_pkcs_5_alg1_wrap, "md2", "des", 8, 8 },
+ { s_pkcs_5_alg1_wrap, "md2", "rc2", 8, 8 },
+ { s_pkcs_5_alg1_wrap, "md5", "des", 8, 8 },
+ { s_pkcs_5_alg1_wrap, "md5", "rc2", 8, 8 },
+ { s_pkcs_5_alg1_wrap, "sha1", "des", 8, 8 },
+ { s_pkcs_5_alg1_wrap, "sha1", "rc2", 8, 8 },
+ { s_pkcs_12_wrap, "sha1", "3des", 24, 8 },
+};
+
+typedef struct {
+ const pbes_properties *data;
+ const char *oid;
+} oid_to_pbes;
+
+static const oid_to_pbes s_pbes1_list[] = {
+ { &s_pbes1_types[0], "1.2.840.113549.1.5.1" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */
+ { &s_pbes1_types[1], "1.2.840.113549.1.5.4" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */
+ { &s_pbes1_types[2], "1.2.840.113549.1.5.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */
+ { &s_pbes1_types[3], "1.2.840.113549.1.5.6" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */
+ { &s_pbes1_types[4], "1.2.840.113549.1.5.10" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */
+ { &s_pbes1_types[5], "1.2.840.113549.1.5.11" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */
+ { &s_pbes1_types[6], "1.2.840.113549.1.12.1.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */
+ { 0 },
+};
+
+static int s_pbes1_from_oid(const ltc_asn1_list *oid, pbes_properties *res)
+{
+ unsigned int i;
+ for (i = 0; s_pbes1_list[i].data != NULL; ++i) {
+ if (pk_oid_cmp_with_asn1(s_pbes1_list[i].oid, oid) == CRYPT_OK) {
+ if (res != NULL) *res = *s_pbes1_list[i].data;
+ return CRYPT_OK;
+ }
+ }
+ return CRYPT_INVALID_ARG;
+}
+
+/**
+ Extract PBES1 parameters
+
+ @param s The start of the sequence with potential PBES1 parameters
+ @param res Pointer to where the extracted parameters should be stored
+ @return CRYPT_OK on success
+*/
+int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res)
+{
+ int err;
+
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ if ((err = s_pbes1_from_oid(s, &res->type)) != CRYPT_OK) return err;
+
+ if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
+ !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_OCTET_STRING) ||
+ !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_INTEGER)) {
+ return CRYPT_INVALID_PACKET;
+ }
+ /* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC:
+ * 0:d=0 hl=4 l= 329 cons: SEQUENCE
+ * 4:d=1 hl=2 l= 27 cons: SEQUENCE
+ * 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3) (== *s)
+ * 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam)
+ * 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt)
+ * 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations)
+ * 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
+ */
+ res->salt = s->next->child;
+ res->iterations = mp_get_int(s->next->child->next->data);
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/pbes/pbes2.c b/Sources/libtomcrypt/misc/pbes/pbes2.c
new file mode 100644
index 00000000..e3eeb94a
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pbes/pbes2.c
@@ -0,0 +1,206 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_PBES
+
+static const char * const s_oid_pbes2 = "1.2.840.113549.1.5.13";
+static const char * const s_oid_pbkdf2 = "1.2.840.113549.1.5.12";
+
+typedef struct {
+ const char *oid;
+ const char *id;
+} oid_id_st;
+
+static const oid_id_st s_hmac_oid_names[] = {
+ { "1.2.840.113549.2.7", "sha1" },
+ { "1.2.840.113549.2.8", "sha224" },
+ { "1.2.840.113549.2.9", "sha256" },
+ { "1.2.840.113549.2.10", "sha384" },
+ { "1.2.840.113549.2.11", "sha512" },
+ { "1.2.840.113549.2.12", "sha512-224" },
+ { "1.2.840.113549.2.13", "sha512-256" },
+};
+
+static int s_pkcs_5_alg2_wrap(const struct password *pwd,
+ const unsigned char *salt, unsigned long salt_len,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen)
+{
+ return pkcs_5_alg2(pwd->pw, pwd->l, salt, salt_len, iteration_count, hash_idx, out, outlen);
+}
+
+static const pbes_properties s_pbes2_default_types[] = {
+ { s_pkcs_5_alg2_wrap, "sha1", "des", 8, 0 },
+ { s_pkcs_5_alg2_wrap, "sha1", "rc2", 4, 0 },
+ { s_pkcs_5_alg2_wrap, "sha1", "3des", 24, 0 },
+ { s_pkcs_5_alg2_wrap, "sha1", "aes", 16, 0 },
+ { s_pkcs_5_alg2_wrap, "sha1", "aes", 24, 0 },
+ { s_pkcs_5_alg2_wrap, "sha1", "aes", 32, 0 },
+};
+
+typedef struct {
+ const pbes_properties *data;
+ const char* oid;
+} oid_to_pbes;
+
+static const oid_to_pbes s_pbes2_list[] = {
+ { &s_pbes2_default_types[0], "1.3.14.3.2.7" }, /* http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */
+ { &s_pbes2_default_types[1], "1.2.840.113549.3.2" }, /* http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */
+ { &s_pbes2_default_types[2], "1.2.840.113549.3.7" }, /* http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */
+ { &s_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2 aes128-CBC */
+ { &s_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */
+ { &s_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */
+};
+
+static int s_pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res)
+{
+ unsigned int i;
+ for (i = 0; i < sizeof(s_pbes2_list)/sizeof(s_pbes2_list[0]); ++i) {
+ if (pk_oid_cmp_with_asn1(s_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) {
+ *res = *s_pbes2_list[i].data;
+ break;
+ }
+ }
+ if (res->c == NULL) return CRYPT_INVALID_CIPHER;
+ if (hmac_oid != NULL) {
+ for (i = 0; i < sizeof(s_hmac_oid_names)/sizeof(s_hmac_oid_names[0]); ++i) {
+ if (pk_oid_cmp_with_asn1(s_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) {
+ res->h = s_hmac_oid_names[i].id;
+ return CRYPT_OK;
+ }
+ }
+ return CRYPT_INVALID_HASH;
+ }
+ return CRYPT_OK;
+}
+
+
+/**
+ Extract PBES2 parameters
+
+ @param s The start of the sequence with potential PBES2 parameters
+ @param res Pointer to where the extracted parameters should be stored
+ @return CRYPT_OK on success
+*/
+int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res)
+{
+ unsigned long klen;
+ ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac;
+ int err;
+
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ if ((err = pk_oid_cmp_with_asn1(s_oid_pbes2, s)) != CRYPT_OK) return err;
+
+ if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
+ !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) ||
+ !LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) ||
+ !LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) ||
+ !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) ||
+ !LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
+ return CRYPT_INVALID_PACKET;
+ }
+ /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc:
+ * 0:d=0 hl=4 l= 380 cons: SEQUENCE
+ * 4:d=1 hl=2 l= 78 cons: SEQUENCE
+ * 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13) (== *s)
+ * 17:d=2 hl=2 l= 65 cons: SEQUENCE
+ * 19:d=3 hl=2 l= 41 cons: SEQUENCE
+ * 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2 (== *lkdf)
+ * 32:d=4 hl=2 l= 28 cons: SEQUENCE
+ * 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt)
+ * 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== res->iterations, *liter)
+ * 48:d=5 hl=2 l= 12 cons: SEQUENCE (== *loptseq - this sequence is optional, may be missing)
+ * 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256 (== *lhmac)
+ * 60:d=6 hl=2 l= 0 prim: NULL
+ * 62:d=3 hl=2 l= 20 cons: SEQUENCE
+ * 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc (== *lenc)
+ * 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A
+ * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
+ */
+ lkdf = s->next->child->child;
+ lenc = s->next->child->next->child;
+
+ if ((err = pk_oid_cmp_with_asn1(s_oid_pbkdf2, lkdf)) != CRYPT_OK) return err;
+
+ if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) ||
+ !LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) ||
+ !LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ liter = lkdf->next->child->next;
+ loptseq = liter->next;
+ res->salt = lkdf->next->child;
+ res->iterations = mp_get_int(liter->data);
+
+ /* There's an optional INTEGER keyLength after the iterations, skip that if it's there.
+ * c.f. RFC 2898 A.2 PBKDF2 */
+ if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) {
+ loptseq = loptseq->next;
+ }
+
+ /* this sequence is optional */
+ lhmac = NULL;
+ if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) &&
+ LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
+ lhmac = loptseq->child;
+ }
+ if ((err = s_pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err;
+
+ if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) {
+ /* 'NON-RC2'-CBC */
+ res->iv = lenc->next;
+ } else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) {
+ /* RC2-CBC is a bit special ...
+ *
+ * RC2-CBC-Parameter ::= SEQUENCE {
+ * rc2ParameterVersion INTEGER OPTIONAL,
+ * iv OCTET STRING (SIZE(8)) }
+ */
+ if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) &&
+ LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) {
+ klen = mp_get_int(lenc->next->child->data);
+ res->iv = lenc->next->child->next;
+ /*
+ * Effective Key Bits Encoding
+ * 40 160
+ * 64 120
+ * 128 58
+ * b >= 256 b
+ */
+ switch (klen) {
+ case 160:
+ res->key_bits = 40;
+ break;
+ case 120:
+ res->key_bits = 64;
+ break;
+ case 58:
+ res->key_bits = 128;
+ break;
+ default:
+ /* We don't handle undefined Key Bits */
+ if (klen < 256) return CRYPT_INVALID_KEYSIZE;
+
+ res->key_bits = klen;
+ break;
+ }
+ } else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) {
+ res->iv = lenc->next->child;
+ /*
+ * If the rc2ParameterVersion field is omitted, the "effective key bits"
+ * defaults to 32.
+ */
+ res->key_bits = 32;
+ } else {
+ return CRYPT_INVALID_PACKET;
+ }
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/pem/pem.c b/Sources/libtomcrypt/misc/pem/pem.c
new file mode 100644
index 00000000..d8153693
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pem/pem.c
@@ -0,0 +1,336 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pem.c
+ Const declarations for PEM, Steffen Jaeckel
+*/
+
+#ifdef LTC_PEM
+
+const struct pem_header_id pem_std_headers[] = {
+ {
+ /* PKCS#8 encrypted */
+ SET_CSTR(.start, "-----BEGIN ENCRYPTED PRIVATE KEY-----"),
+ SET_CSTR(.end, "-----END ENCRYPTED PRIVATE KEY-----"),
+ .has_more_headers = no,
+ .flags = pf_encrypted_pkcs8,
+ },
+ {
+ /* PKCS#8 plain */
+ SET_CSTR(.start, "-----BEGIN PRIVATE KEY-----"),
+ SET_CSTR(.end, "-----END PRIVATE KEY-----"),
+ .has_more_headers = no,
+ .flags = pf_pkcs8,
+ },
+ {
+ /* X.509 Certificates */
+ SET_CSTR(.start, "-----BEGIN CERTIFICATE-----"),
+ SET_CSTR(.end, "-----END CERTIFICATE-----"),
+ .has_more_headers = no,
+ .flags = pf_x509,
+ },
+ {
+ /* Regular (plain) public keys */
+ SET_CSTR(.start, "-----BEGIN PUBLIC KEY-----"),
+ SET_CSTR(.end, "-----END PUBLIC KEY-----"),
+ .has_more_headers = no,
+ .flags = pf_public,
+ },
+ {
+ SET_CSTR(.start, "-----BEGIN RSA PUBLIC KEY-----"),
+ SET_CSTR(.end, "-----END RSA PUBLIC KEY-----"),
+ .has_more_headers = no,
+ .pka = LTC_PKA_RSA,
+ .flags = pf_public,
+ },
+ /* Regular plain or encrypted private keys */
+ {
+ SET_CSTR(.start, "-----BEGIN RSA PRIVATE KEY-----"),
+ SET_CSTR(.end, "-----END RSA PRIVATE KEY-----"),
+ .has_more_headers = maybe,
+ .pka = LTC_PKA_RSA,
+ },
+ {
+ SET_CSTR(.start, "-----BEGIN EC PRIVATE KEY-----"),
+ SET_CSTR(.end, "-----END EC PRIVATE KEY-----"),
+ .has_more_headers = maybe,
+ .pka = LTC_PKA_EC,
+ },
+ {
+ SET_CSTR(.start, "-----BEGIN DSA PRIVATE KEY-----"),
+ SET_CSTR(.end, "-----END DSA PRIVATE KEY-----"),
+ .has_more_headers = maybe,
+ .pka = LTC_PKA_DSA,
+ },
+};
+const unsigned long pem_std_headers_num = sizeof(pem_std_headers)/sizeof(pem_std_headers[0]);
+
+/* Encrypted PEM files */
+const struct str pem_proc_type_encrypted = { SET_CSTR(, "Proc-Type: 4,ENCRYPTED") };
+#if defined(LTC_SSH)
+const struct str pem_ssh_comment = { SET_CSTR(, "Comment: ") };
+#endif
+const struct str pem_dek_info_start = { SET_CSTR(, "DEK-Info: ") };
+const struct blockcipher_info pem_dek_infos[] =
+ {
+ { .name = "AES-128-CBC,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cbc, },
+ { .name = "AES-192-CBC,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cbc, },
+ { .name = "AES-256-CBC,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cbc, },
+ { .name = "AES-128-CFB,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cfb, },
+ { .name = "AES-192-CFB,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cfb, },
+ { .name = "AES-256-CFB,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cfb, },
+ { .name = "AES-128-CFB1,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cfb1, },
+ { .name = "AES-192-CFB1,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cfb1, },
+ { .name = "AES-256-CFB1,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cfb1, },
+ { .name = "AES-128-CFB8,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cfb8, },
+ { .name = "AES-192-CFB8,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cfb8, },
+ { .name = "AES-256-CFB8,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cfb8, },
+ { .name = "AES-128-CTR,", .algo = "aes", .keylen = 128 / 8, .mode = cm_ctr, },
+ { .name = "AES-192-CTR,", .algo = "aes", .keylen = 192 / 8, .mode = cm_ctr, },
+ { .name = "AES-256-CTR,", .algo = "aes", .keylen = 256 / 8, .mode = cm_ctr, },
+ { .name = "AES-128-OFB,", .algo = "aes", .keylen = 128 / 8, .mode = cm_ofb, },
+ { .name = "AES-192-OFB,", .algo = "aes", .keylen = 192 / 8, .mode = cm_ofb, },
+ { .name = "AES-256-OFB,", .algo = "aes", .keylen = 256 / 8, .mode = cm_ofb, },
+ { .name = "BF-CBC,", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_cbc, },
+ { .name = "BF-CFB,", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_cfb, },
+ { .name = "BF-OFB,", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_ofb, },
+ { .name = "CAMELLIA-128-CBC,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cbc, },
+ { .name = "CAMELLIA-192-CBC,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cbc, },
+ { .name = "CAMELLIA-256-CBC,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cbc, },
+ { .name = "CAMELLIA-128-CFB,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cfb, },
+ { .name = "CAMELLIA-192-CFB,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cfb, },
+ { .name = "CAMELLIA-256-CFB,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cfb, },
+ { .name = "CAMELLIA-128-CFB1,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cfb1, },
+ { .name = "CAMELLIA-192-CFB1,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cfb1, },
+ { .name = "CAMELLIA-256-CFB1,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cfb1, },
+ { .name = "CAMELLIA-128-CFB8,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cfb8, },
+ { .name = "CAMELLIA-192-CFB8,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cfb8, },
+ { .name = "CAMELLIA-256-CFB8,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cfb8, },
+ { .name = "CAMELLIA-128-CTR,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_ctr, },
+ { .name = "CAMELLIA-192-CTR,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_ctr, },
+ { .name = "CAMELLIA-256-CTR,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_ctr, },
+ { .name = "CAMELLIA-128-OFB,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_ofb, },
+ { .name = "CAMELLIA-192-OFB,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_ofb, },
+ { .name = "CAMELLIA-256-OFB,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_ofb, },
+ { .name = "CAST5-CBC,", .algo = "cast5", .keylen = 128 / 8, .mode = cm_cbc, },
+ { .name = "CAST5-CFB,", .algo = "cast5", .keylen = 128 / 8, .mode = cm_cfb, },
+ { .name = "CAST5-OFB,", .algo = "cast5", .keylen = 128 / 8, .mode = cm_ofb, },
+ { .name = "ChaCha20,", .algo = "chacha20", .keylen = 256 / 8, .mode = cm_stream, },
+ { .name = "DES-EDE-CBC,", .algo = "3des", .keylen = 128 / 8, .mode = cm_cbc, },
+ { .name = "DES-EDE-CFB,", .algo = "3des", .keylen = 128 / 8, .mode = cm_cfb, },
+ { .name = "DES-EDE-OFB,", .algo = "3des", .keylen = 128 / 8, .mode = cm_ofb, },
+ { .name = "DES-EDE3-CBC,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cbc, },
+ { .name = "DES-EDE3-CFB,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cfb, },
+ { .name = "DES-EDE3-CFB1,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cfb1, },
+ { .name = "DES-EDE3-CFB8,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cfb8, },
+ { .name = "DES-EDE3-OFB,", .algo = "3des", .keylen = 192 / 8, .mode = cm_ofb, },
+ { .name = "DES-CBC,", .algo = "des", .keylen = 64 / 8, .mode = cm_cbc, },
+ { .name = "DES-CFB,", .algo = "des", .keylen = 64 / 8, .mode = cm_cfb, },
+ { .name = "DES-CFB1,", .algo = "des", .keylen = 64 / 8, .mode = cm_cfb1, },
+ { .name = "DES-CFB8,", .algo = "des", .keylen = 64 / 8, .mode = cm_cfb8, },
+ { .name = "DES-OFB,", .algo = "des", .keylen = 64 / 8, .mode = cm_ofb, },
+ { .name = "DESX-CBC,", .algo = "desx", .keylen = 192 / 8, .mode = cm_cbc, },
+ { .name = "IDEA-CBC,", .algo = "idea", .keylen = 128 / 8, .mode = cm_cbc, },
+ { .name = "IDEA-CFB,", .algo = "idea", .keylen = 128 / 8, .mode = cm_cfb, },
+ { .name = "IDEA-OFB,", .algo = "idea", .keylen = 128 / 8, .mode = cm_ofb, },
+ { .name = "RC5-CBC,", .algo = "rc5", .keylen = 128 / 8, .mode = cm_cbc, },
+ { .name = "RC5-CFB,", .algo = "rc5", .keylen = 128 / 8, .mode = cm_cfb, },
+ { .name = "RC5-OFB,", .algo = "rc5", .keylen = 128 / 8, .mode = cm_ofb, },
+ { .name = "RC2-40-CBC,", .algo = "rc2", .keylen = 40 / 8, .mode = cm_cbc, },
+ { .name = "RC2-64-CBC,", .algo = "rc2", .keylen = 64 / 8, .mode = cm_cbc, },
+ { .name = "RC2-CBC,", .algo = "rc2", .keylen = 128 / 8, .mode = cm_cbc, },
+ { .name = "RC2-CFB,", .algo = "rc2", .keylen = 128 / 8, .mode = cm_cfb, },
+ { .name = "RC2-OFB,", .algo = "rc2", .keylen = 128 / 8, .mode = cm_ofb, },
+ { .name = "SEED-CBC,", .algo = "seed", .keylen = 128 / 8, .mode = cm_cbc, },
+ { .name = "SEED-CFB,", .algo = "seed", .keylen = 128 / 8, .mode = cm_cfb, },
+ { .name = "SEED-OFB,", .algo = "seed", .keylen = 128 / 8, .mode = cm_ofb, },
+ };
+const unsigned long pem_dek_infos_num = sizeof(pem_dek_infos)/sizeof(pem_dek_infos[0]);
+
+int pem_decrypt(unsigned char *data, unsigned long *datalen,
+ unsigned char *key, unsigned long keylen,
+ unsigned char *iv, unsigned long ivlen,
+ unsigned char *tag, unsigned long taglen,
+ const struct blockcipher_info *info,
+ enum padding_type padding)
+{
+ int err, cipher = -1;
+ struct {
+ union {
+#ifdef LTC_CBC_MODE
+ symmetric_CBC cbc;
+#endif
+#ifdef LTC_CFB_MODE
+ symmetric_CFB cfb;
+#endif
+#ifdef LTC_CTR_MODE
+ symmetric_CTR ctr;
+#endif
+#ifdef LTC_OFB_MODE
+ symmetric_OFB ofb;
+#endif
+ } ctx;
+ } s;
+ enum cipher_mode mode = info->mode & cm_modes;
+
+ if (mode != cm_stream) {
+ cipher = find_cipher(info->algo);
+ if (cipher == -1) {
+ return CRYPT_INVALID_CIPHER;
+ }
+ }
+
+ switch (info->mode) {
+ case cm_cbc:
+#ifdef LTC_CBC_MODE
+ LTC_ARGCHK(ivlen == (unsigned long)cipher_descriptor[cipher].block_length);
+
+ if ((err = cbc_start(cipher, iv, key, keylen, 0, &s.ctx.cbc)) != CRYPT_OK) {
+ goto error_out;
+ }
+ if ((err = cbc_decrypt(data, data, *datalen, &s.ctx.cbc)) != CRYPT_OK) {
+ goto error_out;
+ }
+ if ((err = cbc_done(&s.ctx.cbc)) != CRYPT_OK) {
+ goto error_out;
+ }
+
+ if ((err = padding_depad(data, datalen, padding | s.ctx.cbc.blocklen)) != CRYPT_OK) {
+ goto error_out;
+ }
+#else
+ return CRYPT_INVALID_CIPHER;
+#endif
+ break;
+ case cm_cfb:
+ case cm_cfb1:
+ case cm_cfb8:
+#ifdef LTC_CFB_MODE
+ if (info->mode == cm_cfb) {
+ if ((err = cfb_start(cipher, iv, key, keylen, 0, &s.ctx.cfb)) != CRYPT_OK) {
+ goto error_out;
+ }
+ } else {
+ if ((err = cfb_start_ex(cipher, iv, key, keylen, 0, info->mode == cm_cfb1 ? 1 : 8, &s.ctx.cfb)) != CRYPT_OK) {
+ goto error_out;
+ }
+ }
+ if ((err = cfb_decrypt(data, data, *datalen, &s.ctx.cfb)) != CRYPT_OK) {
+ goto error_out;
+ }
+ if ((err = cfb_done(&s.ctx.cfb)) != CRYPT_OK) {
+ goto error_out;
+ }
+#else
+ return CRYPT_INVALID_CIPHER;
+#endif
+ break;
+ case cm_ctr:
+#ifdef LTC_CTR_MODE
+ if ((err = ctr_start(cipher, iv, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &s.ctx.ctr)) != CRYPT_OK) {
+ goto error_out;
+ }
+ if ((err = ctr_decrypt(data, data, *datalen, &s.ctx.ctr)) != CRYPT_OK) {
+ goto error_out;
+ }
+ if ((err = ctr_done(&s.ctx.ctr)) != CRYPT_OK) {
+ goto error_out;
+ }
+#else
+ return CRYPT_INVALID_CIPHER;
+#endif
+ break;
+ case cm_ofb:
+#ifdef LTC_OFB_MODE
+ if ((err = ofb_start(cipher, iv, key, keylen, 0, &s.ctx.ofb)) != CRYPT_OK) {
+ goto error_out;
+ }
+ if ((err = ofb_decrypt(data, data, *datalen, &s.ctx.ofb)) != CRYPT_OK) {
+ goto error_out;
+ }
+ if ((err = ofb_done(&s.ctx.ofb)) != CRYPT_OK) {
+ goto error_out;
+ }
+#else
+ return CRYPT_INVALID_CIPHER;
+#endif
+ break;
+ case cm_gcm:
+#ifdef LTC_GCM_MODE
+ if ((err = gcm_memory(cipher,
+ key, keylen,
+ iv, ivlen,
+ NULL, 0,
+ data, *datalen, data,
+ tag, &taglen,
+ GCM_DECRYPT)) != CRYPT_OK) {
+ goto error_out;
+ }
+#else
+ LTC_UNUSED_PARAM(tag);
+ LTC_UNUSED_PARAM(taglen);
+ return CRYPT_INVALID_CIPHER;
+#endif
+ break;
+ case cm_stream:
+#ifdef LTC_CHACHA
+ LTC_ARGCHK(ivlen == 16);
+
+ if ((err = chacha_memory(key, keylen, 20,
+ iv, ivlen, 0,
+ data, *datalen, data)) != CRYPT_OK) {
+ goto error_out;
+ }
+#else
+ return CRYPT_INVALID_CIPHER;
+#endif
+ break;
+ case cm_stream_openssh:
+#ifdef LTC_CHACHA20POLY1305_MODE
+ if ((err = chacha20poly1305_memory(key, 32,
+ iv, ivlen,
+ NULL, 0,
+ data, *datalen, data,
+ tag, &taglen,
+ CHACHA20POLY1305_DECRYPT | CHACHA20POLY1305_OPENSSH_COMPAT)) != CRYPT_OK) {
+ goto error_out;
+ }
+#else
+ return CRYPT_INVALID_CIPHER;
+#endif
+ break;
+ default:
+ err = CRYPT_INVALID_ARG;
+ break;
+ }
+
+error_out:
+ return err;
+}
+
+int pem_decode_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx)
+{
+ int err = pem_decode_pkcs_filehandle(f, k, pw_ctx);
+ if (err == CRYPT_OK || err != CRYPT_UNKNOWN_PEM)
+ return err;
+#if defined(LTC_SSH)
+ rewind(f);
+ err = pem_decode_openssh_filehandle(f, k, pw_ctx);
+#endif
+ return err;
+}
+
+int pem_decode(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx)
+{
+ int err = pem_decode_pkcs(buf, len, k, pw_ctx);
+ if (err == CRYPT_OK || err != CRYPT_UNKNOWN_PEM)
+ return err;
+#if defined(LTC_SSH)
+ err = pem_decode_openssh(buf, len, k, pw_ctx);
+#endif
+ return err;
+}
+
+#endif /* LTC_PEM */
diff --git a/Sources/libtomcrypt/misc/pem/pem_pkcs.c b/Sources/libtomcrypt/misc/pem/pem_pkcs.c
new file mode 100644
index 00000000..f3d5bd8d
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pem/pem_pkcs.c
@@ -0,0 +1,292 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pem_decode.c
+ Decode a PEM file, Steffen Jaeckel
+*/
+
+#ifdef LTC_PEM
+
+extern const struct pem_header_id pem_std_headers[];
+extern const unsigned long pem_std_headers_num;
+
+static int s_decrypt_pem(unsigned char *pem, unsigned long *l, const struct pem_headers *hdr)
+{
+ unsigned char iv[MAXBLOCKSIZE], key[MAXBLOCKSIZE];
+ unsigned long ivlen, klen;
+ int err;
+
+ if (hdr->info.keylen > sizeof(key)) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ if (!hdr->pw->pw) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ ivlen = sizeof(iv);
+ if ((err = base16_decode(hdr->info.iv, XSTRLEN(hdr->info.iv), iv, &ivlen)) != CRYPT_OK) {
+ return err;
+ }
+ klen = hdr->info.keylen;
+ if ((err = pkcs_5_alg1_openssl(hdr->pw->pw, hdr->pw->l, iv, 1, find_hash("md5"), key, &klen))) {
+ return err;
+ }
+
+ err = pem_decrypt(pem, l, key, klen, iv, ivlen, NULL, 0, &hdr->info, LTC_PAD_PKCS7);
+
+ zeromem(key, sizeof(key));
+ zeromem(iv, sizeof(iv));
+ return err;
+}
+
+static int s_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka)
+{
+ der_flexi_check flexi_should[4];
+ ltc_asn1_list *seqid, *id;
+ enum ltc_oid_id oid_id;
+ int err;
+ unsigned long n = 0;
+ LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seqid);
+ LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_BIT_STRING, NULL);
+ LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
+ if ((err = der_flexi_sequence_cmp(pub, flexi_should)) != CRYPT_OK) {
+ return err;
+ }
+ n = 0;
+ LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OBJECT_IDENTIFIER, &id);
+ LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
+ err = der_flexi_sequence_cmp(seqid, flexi_should);
+ if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
+ return err;
+ }
+ if ((err = pk_get_oid_from_asn1(id, &oid_id)) != CRYPT_OK) {
+ return err;
+ }
+ return pk_get_pka_id(oid_id, pka);
+}
+
+typedef int (*import_fn)(const unsigned char *, unsigned long, void*);
+
+static const import_fn s_import_x509_fns[LTC_PKA_NUM] = {
+#ifdef LTC_MRSA
+ [LTC_PKA_RSA] = (import_fn)rsa_import_x509,
+#endif
+#ifdef LTC_MECC
+ [LTC_PKA_EC] = (import_fn)ecc_import_x509,
+#endif
+#ifdef LTC_CURVE25519
+ [LTC_PKA_X25519] = (import_fn)x25519_import_x509,
+ [LTC_PKA_ED25519] = (import_fn)ed25519_import_x509,
+#endif
+};
+
+static int s_import_x509(unsigned char *pem, unsigned long l, ltc_pka_key *k)
+{
+ enum ltc_pka_id pka = LTC_PKA_UNDEF;
+ ltc_asn1_list *d, *spki;
+ int err;
+ if ((err = x509_decode_spki(pem, l, &d, &spki)) != CRYPT_OK) {
+ return err;
+ }
+ err = s_get_pka(spki, &pka);
+ der_free_sequence_flexi(d);
+ if (err != CRYPT_OK) {
+ return err;
+ }
+ if (pka < 0
+ || pka > sizeof(s_import_x509_fns)/sizeof(s_import_x509_fns[0])
+ || s_import_x509_fns[pka] == NULL) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+ if ((err = s_import_x509_fns[pka](pem, l, &k->u)) == CRYPT_OK) {
+ k->id = pka;
+ }
+ return err;
+}
+
+static int s_import_pkcs8(unsigned char *pem, unsigned long l, ltc_pka_key *k, const password_ctx *pw_ctx)
+{
+ int err;
+ enum ltc_oid_id pka;
+ ltc_asn1_list *alg_id, *priv_key;
+ ltc_asn1_list *p8_asn1 = NULL;
+ if ((err = pkcs8_decode_flexi(pem, l, pw_ctx, &p8_asn1)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ if ((err = pkcs8_get_children(p8_asn1, &pka, &alg_id, &priv_key)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ switch (pka) {
+#ifdef LTC_MDH
+ case LTC_OID_DH:
+ err = dh_import_pkcs8_asn1(alg_id, priv_key, &k->u.dh);
+ k->id = LTC_PKA_DH;
+ break;
+#endif
+#ifdef LTC_MDSA
+ case LTC_OID_DSA:
+ err = dsa_import_pkcs8_asn1(alg_id, priv_key, &k->u.dsa);
+ k->id = LTC_PKA_DSA;
+ break;
+#endif
+#ifdef LTC_MRSA
+ case LTC_OID_RSA:
+ err = rsa_import_pkcs8_asn1(alg_id, priv_key, &k->u.rsa);
+ k->id = LTC_PKA_RSA;
+ break;
+#endif
+#ifdef LTC_MECC
+ case LTC_OID_EC:
+ err = ecc_import_pkcs8_asn1(alg_id, priv_key, &k->u.ecc);
+ k->id = LTC_PKA_EC;
+ break;
+#endif
+#ifdef LTC_CURVE25519
+ case LTC_OID_X25519:
+ err = x25519_import_pkcs8_asn1(alg_id, priv_key, &k->u.x25519);
+ k->id = LTC_PKA_X25519;
+ break;
+ case LTC_OID_ED25519:
+ err = ed25519_import_pkcs8_asn1(alg_id, priv_key, &k->u.ed25519);
+ k->id = LTC_PKA_ED25519;
+ break;
+#endif
+ default:
+ err = CRYPT_PK_INVALID_TYPE;
+ }
+
+cleanup:
+ if (p8_asn1) {
+ der_sequence_free(p8_asn1);
+ }
+ return err;
+}
+
+static int s_extract_pka(unsigned char *pem, unsigned long w, enum ltc_pka_id *pka)
+{
+ ltc_asn1_list *pub;
+ int err = CRYPT_ERROR;
+ if ((err = der_decode_sequence_flexi(pem, &w, &pub)) != CRYPT_OK) {
+ return err;
+ }
+ err = s_get_pka(pub, pka);
+ der_sequence_free(pub);
+ return err;
+}
+
+static const import_fn s_import_openssl_fns[LTC_PKA_NUM] = {
+#ifdef LTC_MRSA
+ [LTC_PKA_RSA] = (import_fn)rsa_import,
+#endif
+#ifdef LTC_MDSA
+ [LTC_PKA_DSA] = (import_fn)dsa_import,
+#endif
+#ifdef LTC_MECC
+ [LTC_PKA_EC] = (import_fn)ecc_import_openssl,
+#endif
+#ifdef LTC_CURVE25519
+ [LTC_PKA_X25519] = (import_fn)x25519_import,
+ [LTC_PKA_ED25519] = (import_fn)ed25519_import,
+#endif
+};
+
+static int s_decode(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx)
+{
+ unsigned char *pem = NULL;
+ unsigned long w, l, n;
+ int err = CRYPT_ERROR;
+ struct pem_headers hdr = { 0 };
+ struct password pw = { 0 };
+ enum ltc_pka_id pka;
+ XMEMSET(k, 0, sizeof(*k));
+ w = LTC_PEM_READ_BUFSIZE * 2;
+retry:
+ pem = XREALLOC(pem, w);
+ for (n = 0; n < pem_std_headers_num; ++n) {
+ hdr.id = &pem_std_headers[n];
+ err = pem_read(pem, &w, &hdr, g);
+ if (err == CRYPT_BUFFER_OVERFLOW) {
+ goto retry;
+ } else if (err == CRYPT_OK) {
+ break;
+ } else if (err != CRYPT_UNKNOWN_PEM) {
+ goto cleanup;
+ }
+ hdr.id = NULL;
+ }
+ /* id not found */
+ if (hdr.id == NULL)
+ goto cleanup;
+ l = w;
+ if (hdr.id->flags & pf_pkcs8) {
+ err = s_import_pkcs8(pem, l, k, pw_ctx);
+ goto cleanup;
+ } else if (hdr.id->flags == pf_x509) {
+ err = s_import_x509(pem, l, k);
+ goto cleanup;
+ } else if ((hdr.id->flags & pf_public) && hdr.id->pka == LTC_PKA_UNDEF) {
+ if ((err = s_extract_pka(pem, w, &pka)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ } else if (hdr.encrypted) {
+ if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) {
+ err = CRYPT_PW_CTX_MISSING;
+ goto cleanup;
+ }
+
+ hdr.pw = &pw;
+ if (pw_ctx->callback(&hdr.pw->pw, &hdr.pw->l, pw_ctx->userdata)) {
+ err = CRYPT_ERROR;
+ goto cleanup;
+ }
+
+ if ((err = s_decrypt_pem(pem, &l, &hdr)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ pka = hdr.id->pka;
+ } else {
+ pka = hdr.id->pka;
+ }
+
+ if (pka < 0
+ || pka > sizeof(s_import_openssl_fns)/sizeof(s_import_openssl_fns[0])
+ || s_import_openssl_fns[pka] == NULL) {
+ err = CRYPT_PK_INVALID_TYPE;
+ goto cleanup;
+ }
+ if ((err = s_import_openssl_fns[pka](pem, l, &k->u)) == CRYPT_OK) {
+ k->id = pka;
+ }
+
+cleanup:
+ password_free(hdr.pw, pw_ctx);
+ XFREE(pem);
+ return err;
+}
+
+#ifndef LTC_NO_FILE
+int pem_decode_pkcs_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx)
+{
+ LTC_ARGCHK(f != NULL);
+ LTC_ARGCHK(k != NULL);
+ {
+ struct get_char g = { .get = pem_get_char_from_file, .data.f = f };
+ return s_decode(&g, k, pw_ctx);
+ }
+}
+#endif /* LTC_NO_FILE */
+
+int pem_decode_pkcs(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx)
+{
+ LTC_ARGCHK(buf != NULL);
+ LTC_ARGCHK(len != 0);
+ LTC_ARGCHK(k != NULL);
+ {
+ struct get_char g = { .get = pem_get_char_from_buf, SET_BUFP(.data.buf, buf, len) };
+ return s_decode(&g, k, pw_ctx);
+ }
+}
+
+#endif /* LTC_PEM */
diff --git a/Sources/libtomcrypt/misc/pem/pem_read.c b/Sources/libtomcrypt/misc/pem/pem_read.c
new file mode 100644
index 00000000..3625b1a2
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pem/pem_read.c
@@ -0,0 +1,244 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pem_read.c
+ Read and interpret a PEM file, Steffen Jaeckel
+*/
+
+#ifdef LTC_PEM
+
+extern const struct str pem_proc_type_encrypted;
+#ifdef LTC_SSH
+extern const struct str pem_ssh_comment;
+#endif
+extern const struct str pem_dek_info_start;
+extern const struct blockcipher_info pem_dek_infos[];
+extern const unsigned long pem_dek_infos_num;
+
+#ifndef LTC_NO_FILE
+int pem_get_char_from_file(struct get_char *g)
+{
+ return getc(g->data.f);
+}
+#endif /* LTC_NO_FILE */
+
+int pem_get_char_from_buf(struct get_char *g)
+{
+ int ret;
+ if (g->data.buf.work == g->data.buf.end) {
+ return -1;
+ }
+ ret = *g->data.buf.work;
+ g->data.buf.work++;
+ return ret;
+}
+
+static void s_unget_line(char *buf, unsigned long buflen, struct get_char *g)
+{
+ if (buflen > sizeof(g->unget_buf_))
+ return;
+ g->unget_buf.p = g->unget_buf_;
+ COPY_STR(g->unget_buf, buf, buflen);
+}
+
+static void s_tts(char *buf, unsigned long *buflen)
+{
+ while(1) {
+ unsigned long blen = *buflen;
+ if (blen < 2)
+ return;
+ blen--;
+ switch (buf[blen]) {
+ case ' ':
+ case '\t':
+ buf[blen] = '\0';
+ *buflen = blen;
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+static char* s_get_line(char *buf, unsigned long *buflen, struct get_char *g)
+{
+ unsigned long blen = 0;
+ int c = -1, c_;
+ if (g->unget_buf.p) {
+ if (*buflen < g->unget_buf.len) {
+ return NULL;
+ }
+ XMEMCPY(buf, g->unget_buf.p, g->unget_buf.len);
+ *buflen = g->unget_buf.len;
+ RESET_STR(g->unget_buf);
+ return buf;
+ }
+ while(blen < *buflen) {
+ c_ = c;
+ c = g->get(g);
+ if (c == '\n') {
+ buf[blen] = '\0';
+ if (c_ == '\r') {
+ buf[--blen] = '\0';
+ }
+ s_tts(buf, &blen);
+ *buflen = blen;
+ return buf;
+ }
+ if (c == -1 || c == '\0') {
+ buf[blen] = '\0';
+ s_tts(buf, &blen);
+ *buflen = blen;
+ return buf;
+ }
+ buf[blen] = c;
+ blen++;
+ }
+ return NULL;
+}
+
+static LTC_INLINE int s_fits_buf(void *dest, unsigned long to_write, void *end)
+{
+ unsigned char *d = dest;
+ unsigned char *e = end;
+ unsigned char *w = d + to_write;
+ if (w < d || w > e)
+ return 0;
+ return 1;
+}
+
+static int s_pem_decode_headers(struct pem_headers *hdr, struct get_char *g)
+{
+ char buf[LTC_PEM_DECODE_BUFSZ], *alg_start;
+ unsigned long slen, tmplen, n;
+ int has_more_headers = hdr->id->has_more_headers == no ? 0 : 3;
+
+ /* Make sure the PEM has the appropriate extension headers if required.
+ *
+ * ```
+ * Proc-Type: 4,ENCRYPTED[\r]\n
+ * DEK-Info: ,[\r]\n
+ * [\r]\n
+ * ```
+ */
+ while (has_more_headers) {
+ slen = sizeof(buf);
+ if (!s_get_line(buf, &slen, g) || (has_more_headers > 1 && slen == 0)) {
+ return CRYPT_INVALID_PACKET;
+ }
+ switch (has_more_headers) {
+ case 3:
+ if (XMEMCMP(buf, pem_proc_type_encrypted.p, pem_proc_type_encrypted.len)) {
+#ifdef LTC_SSH
+ if (XMEMCMP(buf, pem_ssh_comment.p, pem_ssh_comment.len))
+#endif
+ s_unget_line(buf, slen, g);
+ if (hdr->id->has_more_headers == maybe)
+ return CRYPT_OK;
+ else
+ return CRYPT_INVALID_PACKET;
+ }
+ hdr->encrypted = 1;
+ break;
+ case 2:
+ hdr->info.algo = NULL;
+ if (XMEMCMP(buf, pem_dek_info_start.p, pem_dek_info_start.len))
+ return CRYPT_INVALID_PACKET;
+ alg_start = &buf[pem_dek_info_start.len];
+ for (n = 0; n < pem_dek_infos_num; ++n) {
+ unsigned long namelen = XSTRLEN(pem_dek_infos[n].name);
+ if (slen >= namelen + pem_dek_info_start.len && !XMEMCMP(alg_start, pem_dek_infos[n].name, namelen)) {
+ char *iv = alg_start + namelen;
+ hdr->info = pem_dek_infos[n];
+ tmplen = XSTRLEN(iv);
+ if (tmplen > sizeof(hdr->info.iv))
+ return CRYPT_INVALID_KEYSIZE;
+ XMEMCPY(hdr->info.iv, iv, tmplen);
+ break;
+ }
+ }
+ if (hdr->info.algo == NULL) {
+ return CRYPT_INVALID_CIPHER;
+ }
+ break;
+ case 1:
+ /* Make sure that there's an empty line in between */
+ if (buf[0] != '\0')
+ return CRYPT_INVALID_PACKET;
+ break;
+ default:
+ return CRYPT_INVALID_CIPHER;
+ }
+ has_more_headers--;
+ }
+ return CRYPT_OK;
+}
+
+int pem_read(void *pem, unsigned long *w, struct pem_headers *hdr, struct get_char *g)
+{
+ char buf[LTC_PEM_DECODE_BUFSZ];
+ char *wpem = pem;
+ char *end = wpem + *w;
+ unsigned long slen, linelen;
+ int err, hdr_ok = 0;
+ int would_overflow = 0;
+ unsigned char empty_lines = 0;
+
+ linelen = sizeof(buf);
+ if (s_get_line(buf, &linelen, g) == NULL) {
+ return CRYPT_INVALID_PACKET;
+ }
+ if (hdr->id->start.len != linelen || XMEMCMP(buf, hdr->id->start.p, hdr->id->start.len)) {
+ s_unget_line(buf, linelen, g);
+ return CRYPT_UNKNOWN_PEM;
+ }
+
+ hdr->encrypted = hdr->id->flags & pf_encrypted;
+ if ((err = s_pem_decode_headers(hdr, g)) != CRYPT_OK)
+ return err;
+
+ /* Read the base64 encoded part of the PEM */
+ slen = sizeof(buf);
+ while (s_get_line(buf, &slen, g)) {
+ if (slen == hdr->id->end.len && !XMEMCMP(buf, hdr->id->end.p, slen)) {
+ hdr_ok = 1;
+ break;
+ }
+ if (!slen) {
+ if (empty_lines)
+ break;
+ empty_lines++;
+ }
+ if (!would_overflow && s_fits_buf(wpem, slen, end)) {
+ XMEMCPY(wpem, buf, slen);
+ } else {
+ would_overflow = 1;
+ }
+ wpem += slen;
+ slen = sizeof(buf);
+ }
+ if (!hdr_ok)
+ return CRYPT_INVALID_PACKET;
+
+ if (would_overflow || !s_fits_buf(wpem, 1, end)) {
+ /* NUL termination */
+ wpem++;
+ /* prevent a wrap-around */
+ if (wpem < (char*)pem)
+ return CRYPT_OVERFLOW;
+ *w = wpem - (char*)pem;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ *w = wpem - (char*)pem;
+ *wpem++ = '\0';
+
+ if ((err = base64_strict_decode(pem, *w, pem, w)) != CRYPT_OK) {
+ return err;
+ }
+ return CRYPT_OK;
+}
+
+#endif /* LTC_PEM */
diff --git a/Sources/libtomcrypt/misc/pem/pem_ssh.c b/Sources/libtomcrypt/misc/pem/pem_ssh.c
new file mode 100644
index 00000000..2ec386bd
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pem/pem_ssh.c
@@ -0,0 +1,855 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pem_ssh.c
+ SSH specific functionality to process PEM files, Steffen Jaeckel
+
+ The basic format of the key is described here:
+ https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
+*/
+
+#if defined(LTC_PEM_SSH)
+
+/* Table as of
+ * https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-17
+ */
+const struct blockcipher_info ssh_ciphers[] =
+{
+ { .name = "none", .algo = "", .keylen = 0, .mode = cm_none },
+ { .name = "aes128-cbc", .algo = "aes", .keylen = 128 / 8, .mode = cm_cbc },
+ { .name = "aes128-ctr", .algo = "aes", .keylen = 128 / 8, .mode = cm_ctr },
+ { .name = "aes192-cbc", .algo = "aes", .keylen = 192 / 8, .mode = cm_cbc },
+ { .name = "aes192-ctr", .algo = "aes", .keylen = 192 / 8, .mode = cm_ctr },
+ { .name = "aes256-cbc", .algo = "aes", .keylen = 256 / 8, .mode = cm_cbc },
+ { .name = "aes256-ctr", .algo = "aes", .keylen = 256 / 8, .mode = cm_ctr },
+ { .name = "aes128-gcm@openssh.com", .algo = "aes", .keylen = 128 / 8, .mode = cm_gcm },
+ { .name = "aes256-gcm@openssh.com", .algo = "aes", .keylen = 256 / 8, .mode = cm_gcm },
+ { .name = "blowfish128-cbc", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_cbc },
+ { .name = "blowfish128-ctr", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_ctr },
+ /* The algo name doesn't matter, it's only used in pem-info */
+ { .name = "chacha20-poly1305@openssh.com", .algo = "c20p1305", .keylen = 256 / 8, .mode = cm_stream | cm_openssh },
+ { .name = "des-cbc", .algo = "des", .keylen = 64 / 8, .mode = cm_cbc },
+ { .name = "3des-cbc", .algo = "3des", .keylen = 192 / 8, .mode = cm_cbc },
+ { .name = "3des-ctr", .algo = "3des", .keylen = 192 / 8, .mode = cm_ctr },
+ { .name = "serpent128-cbc", .algo = "serpent", .keylen = 128 / 8, .mode = cm_cbc },
+ { .name = "serpent128-ctr", .algo = "serpent", .keylen = 128 / 8, .mode = cm_ctr },
+ { .name = "serpent192-cbc", .algo = "serpent", .keylen = 192 / 8, .mode = cm_cbc },
+ { .name = "serpent192-ctr", .algo = "serpent", .keylen = 192 / 8, .mode = cm_ctr },
+ { .name = "serpent256-cbc", .algo = "serpent", .keylen = 256 / 8, .mode = cm_cbc },
+ { .name = "serpent256-ctr", .algo = "serpent", .keylen = 256 / 8, .mode = cm_ctr },
+ { .name = "twofish128-cbc", .algo = "twofish", .keylen = 128 / 8, .mode = cm_cbc },
+ { .name = "twofish128-ctr", .algo = "twofish", .keylen = 128 / 8, .mode = cm_ctr },
+ { .name = "twofish192-cbc", .algo = "twofish", .keylen = 192 / 8, .mode = cm_cbc },
+ { .name = "twofish192-ctr", .algo = "twofish", .keylen = 192 / 8, .mode = cm_ctr },
+ { .name = "twofish-cbc", .algo = "twofish", .keylen = 256 / 8, .mode = cm_cbc },
+ { .name = "twofish256-cbc", .algo = "twofish", .keylen = 256 / 8, .mode = cm_cbc },
+ { .name = "twofish256-ctr", .algo = "twofish", .keylen = 256 / 8, .mode = cm_ctr },
+};
+const unsigned long ssh_ciphers_num = sizeof(ssh_ciphers)/sizeof(ssh_ciphers[0]);
+
+struct kdf_options {
+ const char *name;
+ const struct blockcipher_info *cipher;
+ unsigned char salt[64];
+ unsigned long saltlen;
+ ulong32 num_rounds;
+ struct password pw;
+};
+
+#ifdef LTC_MECC
+static int s_ssh_find_ecc(const char *pka, const ltc_ecc_curve **curve)
+{
+ int err;
+ const char* prefix = "ecdsa-sha2-";
+ unsigned long prefixlen = XSTRLEN(prefix);
+ if (strstr(pka, prefix) == NULL) return CRYPT_PK_INVALID_TYPE;
+ if ((err = ecc_find_curve(pka + prefixlen, curve)) != CRYPT_OK) return err;
+ return CRYPT_OK;
+}
+
+static int s_ssh_find_init_ecc(const char *pka, ltc_pka_key *key)
+{
+ int err;
+ const ltc_ecc_curve *cu;
+ if ((err = s_ssh_find_ecc(pka, &cu)) != CRYPT_OK) return err;
+ return ecc_set_curve(cu, &key->u.ecc);
+}
+
+static int s_ssh_decode_ecdsa(const unsigned char *in, unsigned long *inlen, ltc_pka_key *pka_key, enum pem_flags type)
+{
+ int err;
+ unsigned char groupname[64], buf0[512], buf1[512];
+ unsigned long groupnamelen = sizeof(groupname), buf0len = sizeof(buf0), buf1len = sizeof(buf1);
+ unsigned long remaining, cur_len, keylen;
+ const unsigned char *p, *key;
+
+ p = in;
+ cur_len = *inlen;
+ remaining = *inlen;
+
+ err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_STRING, groupname, &groupnamelen,
+ LTC_SSHDATA_STRING, buf0, &buf0len,
+ LTC_SSHDATA_STRING, buf1, &buf1len,
+ LTC_SSHDATA_EOL, NULL);
+ if (err == CRYPT_OK) {
+ key = buf1;
+ keylen = buf1len;
+ } else if (err == CRYPT_BUFFER_OVERFLOW && buf0len != sizeof(buf0) && buf1len == sizeof(buf1)) {
+ key = buf0;
+ keylen = buf0len;
+ } else {
+ goto cleanup;
+ }
+
+ remaining -= cur_len;
+ cur_len = remaining;
+
+ err = ecc_set_key(key, keylen, type == pf_public ? PK_PUBLIC : PK_PRIVATE, &pka_key->u.ecc);
+
+cleanup:
+ zeromem(groupname, sizeof(groupname));
+ zeromem(buf0, sizeof(buf0));
+ zeromem(buf1, sizeof(buf1));
+ if (err == CRYPT_OK) {
+ pka_key->id = LTC_PKA_EC;
+ *inlen -= remaining;
+ }
+
+ return err;
+}
+#endif
+
+#ifdef LTC_CURVE25519
+static int s_ssh_decode_ed25519(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, enum pem_flags type)
+{
+ int err;
+ unsigned char pubkey[64], privkey[96];
+ unsigned long pubkeylen = sizeof(pubkey), privkeylen = sizeof(privkey);
+ unsigned long remaining, cur_len;
+ const unsigned char *p;
+
+ p = in;
+ cur_len = *inlen;
+ remaining = *inlen;
+
+ if ((err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_STRING, pubkey, &pubkeylen,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ goto cleanup;
+ }
+
+ if (type == pf_public) {
+ if ((err = ed25519_import_raw(pubkey, pubkeylen, PK_PUBLIC, &key->u.ed25519)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ key->id = LTC_PKA_ED25519;
+ goto cleanup;
+ }
+
+ p += cur_len;
+ remaining -= cur_len;
+ cur_len = remaining;
+
+ if ((err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_STRING, privkey, &privkeylen,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ if ((err = ed25519_import_raw(privkey, privkeylen, PK_PRIVATE, &key->u.ed25519)) != CRYPT_OK) {
+ goto cleanup;
+ }
+
+ key->id = LTC_PKA_ED25519;
+
+cleanup:
+ zeromem(pubkey, sizeof(pubkey));
+ zeromem(privkey, sizeof(privkey));
+ if (err == CRYPT_OK) {
+ remaining -= cur_len;
+ *inlen -= remaining;
+ }
+
+ return err;
+}
+#endif
+
+#ifdef LTC_MRSA
+static int s_ssh_decode_dsa(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, enum pem_flags type)
+{
+ int err, stat;
+ unsigned long remaining, cur_len;
+ const unsigned char *p;
+ if ((err = dsa_int_init(&key->u.dsa)) != CRYPT_OK) {
+ return err;
+ }
+
+ p = in;
+ cur_len = *inlen;
+ remaining = *inlen;
+
+ if ((err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_MPINT, key->u.dsa.p,
+ LTC_SSHDATA_MPINT, key->u.dsa.q,
+ LTC_SSHDATA_MPINT, key->u.dsa.g,
+ LTC_SSHDATA_MPINT, key->u.dsa.y,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ key->u.dsa.qord = mp_unsigned_bin_size(key->u.dsa.q);
+ if ((err = dsa_int_validate_pqg(&key->u.dsa, &stat)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ if (stat == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto cleanup;
+ }
+
+ if (type == pf_public) {
+ key->id = LTC_PKA_DSA;
+ key->u.dsa.type = PK_PUBLIC;
+ goto cleanup;
+ }
+
+ p += cur_len;
+ remaining -= cur_len;
+ cur_len = remaining;
+
+ if ((err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_MPINT, key->u.dsa.x,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ goto cleanup;
+ }
+
+ key->id = LTC_PKA_DSA;
+ key->u.dsa.type = PK_PRIVATE;
+
+cleanup:
+ if (err != CRYPT_OK) {
+ dsa_free(&key->u.dsa);
+ } else {
+ remaining -= cur_len;
+ *inlen -= remaining;
+ }
+
+ return err;
+
+}
+#endif
+
+#ifdef LTC_MRSA
+static int s_ssh_decode_rsa(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, enum pem_flags type)
+{
+ int err;
+ void *tmp1, *tmp2;
+ unsigned long remaining, cur_len;
+ const unsigned char *p;
+
+ if ((err = rsa_init(&key->u.rsa)) != CRYPT_OK) {
+ return err;
+ }
+
+ p = in;
+ cur_len = *inlen;
+ remaining = *inlen;
+
+ /* ssh-rsa public and private keys contain `e` and `N` in a different order
+ * public contains `e`, then `N`
+ * private contains `N`, then `e`
+ * change the order later on if we import a public key */
+ if ((err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_MPINT, key->u.rsa.N,
+ LTC_SSHDATA_MPINT, key->u.rsa.e,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ goto cleanup;
+ }
+
+ p += cur_len;
+ remaining -= cur_len;
+ cur_len = remaining;
+
+ if (type == pf_public) {
+ /* c.f. comment above */
+ void *exch = key->u.rsa.N;
+ key->u.rsa.N = key->u.rsa.e;
+ key->u.rsa.e = exch;
+ key->id = LTC_PKA_RSA;
+ key->u.rsa.type = PK_PUBLIC;
+ *inlen -= remaining;
+ goto cleanup;
+ }
+
+ if ((err = mp_init_multi(&tmp1, &tmp2, NULL)) != CRYPT_OK) {
+ goto cleanup;
+ }
+
+ if ((err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_MPINT, key->u.rsa.d,
+ LTC_SSHDATA_MPINT, key->u.rsa.qP,
+ LTC_SSHDATA_MPINT, key->u.rsa.p,
+ LTC_SSHDATA_MPINT, key->u.rsa.q,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ goto cleanup_tmps;
+ }
+
+ if ((err = mp_sub_d(key->u.rsa.p, 1, tmp1)) != CRYPT_OK) { goto cleanup_tmps; } /* tmp1 = q-1 */
+ if ((err = mp_sub_d(key->u.rsa.q, 1, tmp2)) != CRYPT_OK) { goto cleanup_tmps; } /* tmp2 = p-1 */
+ if ((err = mp_mod(key->u.rsa.d, tmp1, key->u.rsa.dP)) != CRYPT_OK) { goto cleanup_tmps; } /* dP = d mod p-1 */
+ if ((err = mp_mod(key->u.rsa.d, tmp2, key->u.rsa.dQ)) != CRYPT_OK) { goto cleanup_tmps; } /* dQ = d mod q-1 */
+
+ key->id = LTC_PKA_RSA;
+ key->u.rsa.type = PK_PRIVATE;
+
+cleanup_tmps:
+ mp_clear_multi(tmp2, tmp1, NULL);
+cleanup:
+ if (err != CRYPT_OK) {
+ rsa_free(&key->u.rsa);
+ } else {
+ remaining -= cur_len;
+ *inlen -= remaining;
+ }
+
+ return err;
+}
+#endif
+
+struct ssh_pka {
+ struct str name;
+ enum ltc_pka_id id;
+ int (*find)(const char*, const ltc_ecc_curve **);
+ int (*init)(const char*, ltc_pka_key*);
+ int (*decode)(const unsigned char*, unsigned long*, ltc_pka_key*, enum pem_flags);
+};
+
+struct ssh_pka ssh_pkas[] = {
+#ifdef LTC_CURVE25519
+ { SET_CSTR(.name, "ssh-ed25519"),
+ LTC_PKA_ED25519,
+ NULL,
+ NULL,
+ s_ssh_decode_ed25519 },
+#endif
+#ifdef LTC_MRSA
+ { SET_CSTR(.name, "ssh-rsa"),
+ LTC_PKA_RSA,
+ NULL,
+ NULL,
+ s_ssh_decode_rsa },
+#endif
+#ifdef LTC_MDSA
+ { SET_CSTR(.name, "ssh-dss"),
+ LTC_PKA_DSA,
+ NULL,
+ NULL,
+ s_ssh_decode_dsa },
+#endif
+#ifdef LTC_MECC
+ { { NULL, 0 },
+ LTC_PKA_EC,
+ s_ssh_find_ecc,
+ s_ssh_find_init_ecc,
+ s_ssh_decode_ecdsa },
+#endif
+};
+
+static int s_decode_key(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, char **comment, enum pem_flags type)
+{
+ int err;
+ ulong32 check1, check2;
+ unsigned char pka[64];
+ unsigned long pkalen = sizeof(pka);
+ unsigned long remaining, cur_len;
+ const unsigned char *p;
+ unsigned long n;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ p = in;
+ cur_len = *inlen;
+ remaining = *inlen;
+
+ if (type != pf_public) {
+ if ((err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_UINT32, &check1,
+ LTC_SSHDATA_UINT32, &check2,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ return err;
+ }
+ if (check1 != check2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ p += cur_len;
+ remaining -= cur_len;
+ cur_len = remaining;
+ }
+ if ((err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_STRING, pka, &pkalen,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ p += cur_len;
+ remaining -= cur_len;
+ cur_len = remaining;
+
+ for (n = 0; n < sizeof(ssh_pkas)/sizeof(ssh_pkas[0]); ++n) {
+ if (ssh_pkas[n].name.p != NULL) {
+ if (pkalen != ssh_pkas[n].name.len
+ || XMEMCMP(pka, ssh_pkas[n].name.p, ssh_pkas[n].name.len) != 0) continue;
+ } else {
+ if ((ssh_pkas[n].init == NULL) ||
+ (ssh_pkas[n].init((char*)pka, key) != CRYPT_OK)) continue;
+ }
+ if ((err = ssh_pkas[n].decode(p, &cur_len, key, type)) != CRYPT_OK) {
+ return err;
+ }
+ break;
+ }
+ if (n == sizeof(ssh_pkas)/sizeof(ssh_pkas[0])) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ p += cur_len;
+ remaining -= cur_len;
+ cur_len = remaining;
+
+ if (cur_len != 0 && comment) {
+ unsigned long commentlen = cur_len;
+ char *c = XMALLOC(commentlen);
+ if (c == NULL) {
+ return CRYPT_MEM;
+ }
+ if ((err = ssh_decode_sequence_multi(p, &cur_len,
+ LTC_SSHDATA_STRING, c, &commentlen,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ return err;
+ }
+ if (commentlen == 0) {
+ XFREE(c);
+ } else {
+ *comment = c;
+ }
+ }
+
+ p += cur_len;
+ remaining -= cur_len;
+
+ return remaining ? padding_depad(p, &remaining, LTC_PAD_SSH) : CRYPT_OK;
+}
+
+static LTC_INLINE void skip_spaces(char **r, unsigned long *l)
+{
+ while(*l && (**r == ' ' || **r == '\t')) {
+ (*r)++;
+ (*l)--;
+ }
+}
+
+static LTC_INLINE void skip_chars(char **r, unsigned long *l)
+{
+ while(*l && (**r != ' ' && **r != '\t')) {
+ (*l)--;
+ if (**r == '\n' || **r == '\r') {
+ *l = 0;
+ } else {
+ (*r)++;
+ }
+ }
+}
+
+static LTC_INLINE void skip_to_eol(char **r, unsigned long *l)
+{
+ while(*l && (**r != '\n' && **r != '\r')) {
+ (*l)--;
+ (*r)++;
+ }
+}
+
+static int s_parse_line(char *line, unsigned long *len, ltc_pka_key *key, char **comment)
+{
+ int err;
+ unsigned long n, rlen, olen;
+ enum authorized_keys_elements {
+ ake_algo_name = 0,
+ ake_b64_encoded_key = 1,
+ ake_comment = 2
+ };
+ struct str elements[3] = { 0 };
+ char *r = line;
+ unsigned char *buf = NULL;
+
+ rlen = *len;
+ /* Chop up string into the three authorized_keys_elements */
+ for (n = 0; n < sizeof(elements)/sizeof(elements[0]) && rlen; ++n) {
+ skip_spaces(&r, &rlen);
+ elements[n].p = r;
+ if (n != 2)
+ skip_chars(&r, &rlen);
+ else
+ skip_to_eol(&r, &rlen);
+ elements[n].len = r - elements[n].p;
+ *r = '\0';
+ r++;
+ }
+
+ for (n = 0; n < sizeof(ssh_pkas)/sizeof(ssh_pkas[0]); ++n) {
+ if (ssh_pkas[n].name.p != NULL) {
+ if (elements[ake_algo_name].len != ssh_pkas[n].name.len
+ || XMEMCMP(elements[ake_algo_name].p, ssh_pkas[n].name.p, ssh_pkas[n].name.len) != 0) continue;
+ } else {
+ if ((ssh_pkas[n].find == NULL) ||
+ (ssh_pkas[n].find(elements[ake_algo_name].p, NULL) != CRYPT_OK)) continue;
+ }
+ olen = elements[ake_b64_encoded_key].len;
+ buf = XMALLOC(olen);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+ if ((err = base64_strict_decode(elements[ake_b64_encoded_key].p, elements[ake_b64_encoded_key].len, buf, &olen)) == CRYPT_OK) {
+ err = s_decode_key(buf, &olen, key, comment, pf_public);
+ if (err == CRYPT_OK && key->id != ssh_pkas[n].id) {
+ err = CRYPT_PK_INVALID_TYPE;
+ }
+ }
+ XFREE(buf);
+
+ if (err == CRYPT_OK) {
+ /* Only use the comment that was maybe in the text we just processed, in case when
+ * there was no comment inside the SSH key.
+ */
+ if (*comment == NULL && elements[ake_comment].p) {
+ *comment = XMALLOC(elements[ake_comment].len + 1);
+ if (*comment == NULL) {
+ return CRYPT_MEM;
+ }
+ XMEMCPY(*comment, elements[ake_comment].p, elements[ake_comment].len);
+ (*comment)[elements[ake_comment].len] = '\0';
+ }
+ *len = r - line;
+ return CRYPT_OK;
+ }
+ }
+ return CRYPT_PK_INVALID_TYPE;
+}
+
+static int s_read_authorized_keys(const void *buf, unsigned long len, ssh_authorized_key_cb cb, void *ctx)
+{
+ char *s;
+ int err;
+ unsigned long clen = len;
+ ltc_pka_key *key = XCALLOC(1, sizeof(*key));
+ char *comment = NULL;
+ void *cpy = XMALLOC(len);
+ if (key == NULL || cpy == NULL) {
+ if (cpy)
+ XFREE(cpy);
+ if (key)
+ XFREE(key);
+ return CRYPT_MEM;
+ }
+ XMEMCPY(cpy, buf, len);
+ s = cpy;
+ while (clen && (err = s_parse_line(s, &clen, key, &comment)) == CRYPT_OK) {
+ if (cb(key, comment, ctx)) {
+ break;
+ }
+ s += clen;
+ len -= clen;
+ clen = len;
+ key = XCALLOC(1, sizeof(*key));
+ if (key == NULL) {
+ err = CRYPT_MEM;
+ break;
+ }
+ if (comment) {
+ XFREE(comment);
+ comment = NULL;
+ }
+ }
+ if (comment)
+ XFREE(comment);
+ if (cpy)
+ XFREE(cpy);
+ if (key)
+ XFREE(key);
+ return err;
+}
+
+static int s_decrypt_private_keys(unsigned char *in, unsigned long *inlen,
+ unsigned char *tag, unsigned long taglen,
+ struct kdf_options *opts)
+{
+ int err, cipher;
+ unsigned long symkey_len, iv_len;
+ unsigned char symkey[MAXBLOCKSIZE], *iv, iv_[8] = { 0 };
+ enum cipher_mode mode = opts->cipher->mode & cm_modes;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(opts != NULL);
+
+ if (mode != cm_stream) {
+ cipher = find_cipher(opts->cipher->algo);
+ if (cipher == -1) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ iv = symkey + opts->cipher->keylen;
+ iv_len = mode == cm_gcm ? 12 : cipher_descriptor[cipher].block_length;
+ symkey_len = opts->cipher->keylen + iv_len;
+ } else {
+ iv = iv_;
+ iv_len = sizeof(iv_);
+ symkey_len = 64;
+ }
+
+ if (sizeof(symkey) < symkey_len) {
+ return CRYPT_OVERFLOW;
+ }
+
+ if ((err = bcrypt_pbkdf_openbsd(opts->pw.pw, opts->pw.l, opts->salt, opts->saltlen,
+ opts->num_rounds, find_hash("sha512"), symkey, &symkey_len)) != CRYPT_OK) {
+ return err;
+ }
+ err = pem_decrypt(in, inlen,
+ symkey, opts->cipher->keylen,
+ iv, iv_len,
+ tag, taglen,
+ opts->cipher, LTC_PAD_SSH);
+ zeromem(symkey, sizeof(symkey));
+
+ return err;
+}
+
+static int s_decode_header(unsigned char *in, unsigned long *inlen, struct kdf_options *opts)
+{
+ int err;
+ unsigned char ciphername[64], kdfname[64], kdfoptions[128], pubkey1[2048];
+ unsigned long ciphernamelen = sizeof(ciphername), kdfnamelen = sizeof(kdfname);
+ unsigned long kdfoptionslen = sizeof(kdfoptions), pubkey1len = sizeof(pubkey1);
+ ulong32 num_keys;
+ unsigned long i;
+
+ void *magic = strstr((const char*)in, "openssh-key-v1");
+ unsigned long slen = XSTRLEN("openssh-key-v1");
+ unsigned char *start = &in[slen + 1];
+ unsigned long len = *inlen - slen - 1;
+
+ if (magic == NULL || magic != in) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ if ((err = ssh_decode_sequence_multi(start, &len,
+ LTC_SSHDATA_STRING, ciphername, &ciphernamelen,
+ LTC_SSHDATA_STRING, kdfname, &kdfnamelen,
+ LTC_SSHDATA_STRING, kdfoptions, &kdfoptionslen,
+ LTC_SSHDATA_UINT32, &num_keys,
+ LTC_SSHDATA_STRING, pubkey1, &pubkey1len,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ return err;
+ }
+ if (num_keys != 1) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ *inlen = len + slen + 1;
+
+ for (i = 0; i < ssh_ciphers_num; ++i) {
+ if (XSTRCMP((char*)ciphername, ssh_ciphers[i].name) == 0) {
+ opts->cipher = &ssh_ciphers[i];
+ break;
+ }
+ }
+ if (opts->cipher == NULL) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ if (XSTRCMP((char*)kdfname, "none") == 0) {
+ /* NOP */
+ opts->name = "none";
+ } else if (XSTRCMP((char*)kdfname, "bcrypt") == 0) {
+ opts->name = "bcrypt";
+ opts->saltlen = sizeof(opts->salt);
+ len = kdfoptionslen;
+ if ((err = ssh_decode_sequence_multi(kdfoptions, &len,
+ LTC_SSHDATA_STRING, opts->salt, &opts->saltlen,
+ LTC_SSHDATA_UINT32, &opts->num_rounds,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ return err;
+ }
+ if (len != kdfoptionslen) {
+ return CRYPT_INPUT_TOO_LONG;
+ }
+ } else {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ return err;
+}
+
+
+static const struct pem_header_id pem_openssh[] = {
+ {
+ SET_CSTR(.start, "-----BEGIN OPENSSH PRIVATE KEY-----"),
+ SET_CSTR(.end, "-----END OPENSSH PRIVATE KEY-----"),
+ .has_more_headers = no
+ },
+ {
+ SET_CSTR(.start, "---- BEGIN SSH2 PUBLIC KEY ----"),
+ SET_CSTR(.end, "---- END SSH2 PUBLIC KEY ----"),
+ .has_more_headers = maybe,
+ .flags = pf_public
+ },
+};
+static const unsigned long pem_openssh_num = sizeof(pem_openssh)/sizeof(pem_openssh[0]);
+
+static int s_decode_openssh(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx)
+{
+ unsigned char *pem = NULL, *p, *privkey = NULL, *tag;
+ unsigned long n, w, l, privkey_len, taglen;
+ int err;
+ struct pem_headers hdr;
+ struct kdf_options opts = { 0 };
+ XMEMSET(k, 0, sizeof(*k));
+ w = LTC_PEM_READ_BUFSIZE * 2;
+retry:
+ pem = XREALLOC(pem, w);
+ for (n = 0; n < pem_openssh_num; ++n) {
+ hdr.id = &pem_openssh[n];
+ err = pem_read(pem, &w, &hdr, g);
+ if (err == CRYPT_BUFFER_OVERFLOW) {
+ goto retry;
+ } else if (err == CRYPT_OK) {
+ break;
+ } else if (err != CRYPT_UNKNOWN_PEM) {
+ goto cleanup;
+ }
+ hdr.id = NULL;
+ }
+ /* id not found */
+ if (hdr.id == NULL) {
+ goto cleanup;
+ }
+ p = pem;
+ l = w;
+ if (hdr.id->flags != pf_public) {
+ if ((err = s_decode_header(pem, &w, &opts)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ p = pem + w;
+ l -= w;
+ w = l;
+
+ privkey_len = l;
+ privkey = XMALLOC(privkey_len);
+ if (privkey == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = ssh_decode_sequence_multi(p, &w,
+ LTC_SSHDATA_STRING, privkey, &privkey_len,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) {
+ goto cleanup;
+ }
+
+ if (XSTRCMP(opts.name, "none") != 0) {
+ if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) {
+ err = CRYPT_PW_CTX_MISSING;
+ goto cleanup;
+ }
+ if (pw_ctx->callback(&opts.pw.pw, &opts.pw.l, pw_ctx->userdata)) {
+ err = CRYPT_ERROR;
+ goto cleanup;
+ }
+ tag = p + w;
+ taglen = l - w;
+ w = privkey_len;
+ if ((err = s_decrypt_private_keys(privkey, &privkey_len,
+ tag, taglen,
+ &opts)) != CRYPT_OK) {
+ goto cleanup;
+ }
+ zeromem(opts.pw.pw, opts.pw.l);
+ }
+
+ p = privkey;
+ w = privkey_len;
+ }
+ if ((err = s_decode_key(p, &w, k, NULL, hdr.id->flags)) != CRYPT_OK) {
+ goto cleanup;
+ }
+
+cleanup:
+ password_free(&opts.pw, pw_ctx);
+ if (privkey) {
+ zeromem(privkey, privkey_len);
+ XFREE(privkey);
+ }
+ XFREE(pem);
+ return err;
+}
+
+#ifndef LTC_NO_FILE
+int pem_decode_openssh_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx)
+{
+ LTC_ARGCHK(f != NULL);
+ LTC_ARGCHK(k != NULL);
+ {
+ struct get_char g = { .get = pem_get_char_from_file, .data.f = f };
+ return s_decode_openssh(&g, k, pw_ctx);
+ }
+}
+
+int ssh_read_authorized_keys_filehandle(FILE *f, ssh_authorized_key_cb cb, void *ctx)
+{
+ size_t tot_data;
+ void *buf;
+ int err;
+
+ LTC_ARGCHK(f != NULL);
+ LTC_ARGCHK(cb != NULL);
+
+ fseek(f, 0, SEEK_END);
+ tot_data = ftell(f);
+ rewind(f);
+ buf = XMALLOC(tot_data);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+ if (fread(buf, 1, tot_data, f) != tot_data) {
+ err = CRYPT_ERROR;
+ } else {
+ err = s_read_authorized_keys(buf, tot_data, cb, ctx);
+ }
+ XFREE(buf);
+
+ return err;
+}
+#endif /* LTC_NO_FILE */
+
+int pem_decode_openssh(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx)
+{
+ LTC_ARGCHK(buf != NULL);
+ LTC_ARGCHK(len != 0);
+ LTC_ARGCHK(k != NULL);
+ {
+ struct get_char g = { .get = pem_get_char_from_buf, SET_BUFP(.data.buf, buf, len) };
+ return s_decode_openssh(&g, k, pw_ctx);
+ }
+}
+
+int ssh_read_authorized_keys(const void *buf, unsigned long len, ssh_authorized_key_cb cb, void *ctx)
+{
+ LTC_ARGCHK(buf != NULL);
+ LTC_ARGCHK(len != 0);
+ LTC_ARGCHK(cb != NULL);
+
+ return s_read_authorized_keys(buf, len, cb, ctx);
+}
+#endif /* defined(LTC_PEM_SSH) */
diff --git a/Sources/libtomcrypt/misc/pkcs12/pkcs12_kdf.c b/Sources/libtomcrypt/misc/pkcs12/pkcs12_kdf.c
new file mode 100644
index 00000000..1739af73
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pkcs12/pkcs12_kdf.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_PKCS_12
+
+int pkcs12_kdf( int hash_id,
+ const unsigned char *pw, unsigned long pwlen,
+ const unsigned char *salt, unsigned long saltlen,
+ unsigned int iterations, unsigned char purpose,
+ unsigned char *out, unsigned long outlen)
+{
+ unsigned long u = hash_descriptor[hash_id].hashsize;
+ unsigned long v = hash_descriptor[hash_id].blocksize;
+ unsigned long c = (outlen + u - 1) / u;
+ unsigned long Slen = ((saltlen + v - 1) / v) * v;
+ unsigned long Plen = ((pwlen + v - 1) / v) * v;
+ unsigned long k = (Plen + Slen) / v;
+ unsigned long Alen, keylen = 0;
+ unsigned int tmp, i, j, n;
+ unsigned char ch;
+ unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE];
+ unsigned char *I, *key;
+ int err = CRYPT_ERROR;
+
+ LTC_ARGCHK(pw != NULL);
+ LTC_ARGCHK(salt != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ key = XMALLOC(u * c);
+ I = XMALLOC(Plen + Slen);
+ if (key == NULL || I == NULL) goto DONE;
+ zeromem(key, u * c);
+
+ for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */
+ for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen];
+ for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */
+
+ for (i = 0; i < c; i++) {
+ Alen = sizeof(A);
+ err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, LTC_NULL); /* A = HASH(D || I) */
+ if (err != CRYPT_OK) goto DONE;
+ for (j = 1; j < iterations; j++) {
+ err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */
+ if (err != CRYPT_OK) goto DONE;
+ }
+ /* fill buffer B with A */
+ for (j = 0; j < v; j++) B[j] = A[j % Alen];
+ /* B += 1 */
+ for (j = v; j > 0; j--) {
+ if (++B[j - 1] != 0) break;
+ }
+ /* I_n += B */
+ for (n = 0; n < k; n++) {
+ ch = 0;
+ for (j = v; j > 0; j--) {
+ tmp = I[n * v + j - 1] + B[j - 1] + ch;
+ ch = (unsigned char)((tmp >> 8) & 0xFF);
+ I[n * v + j - 1] = (unsigned char)(tmp & 0xFF);
+ }
+ }
+ /* store derived key block */
+ XMEMCPY(&key[keylen], A, Alen);
+ keylen += Alen;
+ }
+
+ XMEMCPY(out, key, outlen);
+ err = CRYPT_OK;
+DONE:
+ if (I) {
+ zeromem(I, Plen + Slen);
+ XFREE(I);
+ }
+ if (key) {
+ zeromem(key, u * c);
+ XFREE(key);
+ }
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/pkcs12/pkcs12_utf8_to_utf16.c b/Sources/libtomcrypt/misc/pkcs12/pkcs12_utf8_to_utf16.c
new file mode 100644
index 00000000..bcf2023b
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pkcs12/pkcs12_utf8_to_utf16.c
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_PKCS_12
+
+int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen) {
+ unsigned long len = 0;
+ const unsigned char* in_end = in + inlen;
+ const ulong32 offset[6] = {
+ 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL
+ };
+ int err = CRYPT_ERROR;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ while (in < in_end) {
+ ulong32 ch = 0;
+ unsigned short extra = 0; /* 0 */
+ if (*in >= 192) extra++; /* 1 */
+ if (*in >= 224) extra++; /* 2 */
+ if (*in >= 240) extra++; /* 3 */
+ if (*in >= 248) extra++; /* 4 */
+ if (*in >= 252) extra++; /* 5 */
+ if (in + extra >= in_end) goto ERROR;
+ switch (extra) {
+ case 5: ch += *in++; ch <<= 6;
+ /* FALLTHROUGH */
+ case 4: ch += *in++; ch <<= 6;
+ /* FALLTHROUGH */
+ case 3: ch += *in++; ch <<= 6;
+ /* FALLTHROUGH */
+ case 2: ch += *in++; ch <<= 6;
+ /* FALLTHROUGH */
+ case 1: ch += *in++; ch <<= 6;
+ /* FALLTHROUGH */
+ case 0: ch += *in++;
+ }
+ ch -= offset[extra];
+ if (ch > 0xFFFF) goto ERROR;
+ if (*outlen >= len + 2) {
+ out[len] = (unsigned short)((ch >> 8) & 0xFF);
+ out[len + 1] = (unsigned char)(ch & 0xFF);
+ }
+ len += 2;
+ }
+
+ err = len > *outlen ? CRYPT_BUFFER_OVERFLOW : CRYPT_OK;
+ *outlen = len;
+ERROR:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/pkcs5/pkcs_5_1.c b/Sources/libtomcrypt/misc/pkcs5/pkcs_5_1.c
new file mode 100644
index 00000000..ea9c19ce
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pkcs5/pkcs_5_1.c
@@ -0,0 +1,185 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs_5_1.c
+ PKCS #5, Algorithm #1, Tom St Denis
+*/
+#ifdef LTC_PKCS_5
+/**
+ Execute PKCS #5 v1 in strict or OpenSSL EVP_BytesToKey()-compat mode.
+
+ PKCS#5 v1 specifies that the output key length can be no larger than
+ the hash output length. OpenSSL unilaterally extended that by repeating
+ the hash process on a block-by-block basis for as long as needed to make
+ bigger keys. If you want to be compatible with KDF for e.g. "openssl enc",
+ you'll want that.
+
+ If you want strict PKCS behavior, turn openssl_compat off. Or (more
+ likely), use one of the convenience functions below.
+
+ @param password The password (or key)
+ @param password_len The length of the password (octet)
+ @param salt The salt (or nonce) which is 8 octets long
+ @param iteration_count The PKCS #5 v1 iteration count
+ @param hash_idx The index of the hash desired
+ @param out [out] The destination for this algorithm
+ @param outlen [in/out] The max size and resulting size of the algorithm output
+ @param openssl_compat [in] Whether or not to grow the key to the buffer size ala OpenSSL
+ @return CRYPT_OK if successful
+*/
+static int s_pkcs_5_alg1_common(const unsigned char *password,
+ unsigned long password_len,
+ const unsigned char *salt,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen,
+ int openssl_compat)
+{
+ int err;
+ unsigned long x;
+ hash_state *md;
+ unsigned char *buf;
+ /* Storage vars in case we need to support > hashsize (OpenSSL compat) */
+ unsigned long block = 0, iter;
+ /* How many bytes to put in the outbut buffer (convenience calc) */
+ unsigned long outidx = 0, nb = 0;
+
+ LTC_ARGCHK(password != NULL);
+ LTC_ARGCHK(salt != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (iteration_count <= 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* test hash IDX */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* allocate memory */
+ md = XMALLOC(sizeof(hash_state));
+ buf = XMALLOC(MAXBLOCKSIZE);
+ if (md == NULL || buf == NULL) {
+ if (md != NULL) {
+ XFREE(md);
+ }
+ if (buf != NULL) {
+ XFREE(buf);
+ }
+ return CRYPT_MEM;
+ }
+
+ while(block * hash_descriptor[hash_idx].hashsize < *outlen) {
+
+ /* hash initial (maybe previous hash) + password + salt */
+ if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* in OpenSSL mode, we first hash the previous result for blocks 2-n */
+ if (openssl_compat && block) {
+ if ((err = hash_descriptor[hash_idx].process(md, buf, hash_descriptor[hash_idx].hashsize)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+ if ((err = hash_descriptor[hash_idx].process(md, password, password_len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(md, salt, 8)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ iter = iteration_count;
+ while (--iter) {
+ /* code goes here. */
+ x = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* limit the size of the copy to however many bytes we have left in
+ the output buffer (and how many bytes we have to copy) */
+ outidx = block*hash_descriptor[hash_idx].hashsize;
+ nb = hash_descriptor[hash_idx].hashsize;
+ if(outidx+nb > *outlen) {
+ nb = *outlen - outidx;
+ }
+ if(nb > 0) {
+ XMEMCPY(out+outidx, buf, nb);
+ }
+
+ block++;
+ if (!openssl_compat) {
+ break;
+ }
+ }
+ /* In strict mode, we always return the hashsize, in compat we filled it
+ as much as was requested, so we leave it alone. */
+ if(!openssl_compat) {
+ *outlen = hash_descriptor[hash_idx].hashsize;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, MAXBLOCKSIZE);
+ zeromem(md, sizeof(hash_state));
+#endif
+
+ XFREE(buf);
+ XFREE(md);
+
+ return err;
+}
+
+/**
+ Execute PKCS #5 v1 - Strict mode (no OpenSSL-compatible extension)
+ @param password The password (or key)
+ @param password_len The length of the password (octet)
+ @param salt The salt (or nonce) which is 8 octets long
+ @param iteration_count The PKCS #5 v1 iteration count
+ @param hash_idx The index of the hash desired
+ @param out [out] The destination for this algorithm
+ @param outlen [in/out] The max size and resulting size of the algorithm output
+ @return CRYPT_OK if successful
+*/
+int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
+ const unsigned char *salt,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen)
+{
+ return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count,
+ hash_idx, out, outlen, 0);
+}
+
+/**
+ Execute PKCS #5 v1 - OpenSSL-extension-compatible mode
+
+ Use this one if you need to derive keys as "openssl enc" does by default.
+ OpenSSL (for better or worse), uses MD5 as the hash and iteration_count=1.
+ @param password The password (or key)
+ @param password_len The length of the password (octet)
+ @param salt The salt (or nonce) which is 8 octets long
+ @param iteration_count The PKCS #5 v1 iteration count
+ @param hash_idx The index of the hash desired
+ @param out [out] The destination for this algorithm
+ @param outlen [in/out] The max size and resulting size of the algorithm output
+ @return CRYPT_OK if successful
+*/
+int pkcs_5_alg1_openssl(const unsigned char *password,
+ unsigned long password_len,
+ const unsigned char *salt,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen)
+{
+ return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count,
+ hash_idx, out, outlen, 1);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/pkcs5/pkcs_5_2.c b/Sources/libtomcrypt/misc/pkcs5/pkcs_5_2.c
new file mode 100644
index 00000000..61ebd006
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pkcs5/pkcs_5_2.c
@@ -0,0 +1,121 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs_5_2.c
+ PKCS #5, Algorithm #2, Tom St Denis
+*/
+#ifdef LTC_PKCS_5
+
+/**
+ Execute PKCS #5 v2
+ @param password The input password (or key)
+ @param password_len The length of the password (octets)
+ @param salt The salt (or nonce)
+ @param salt_len The length of the salt (octets)
+ @param iteration_count # of iterations desired for PKCS #5 v2 [read specs for more]
+ @param hash_idx The index of the hash desired
+ @param out [out] The destination for this algorithm
+ @param outlen [in/out] The max size and resulting size of the algorithm output
+ @return CRYPT_OK if successful
+*/
+int pkcs_5_alg2(const unsigned char *password, unsigned long password_len,
+ const unsigned char *salt, unsigned long salt_len,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen)
+{
+ int err, itts;
+ ulong32 blkno;
+ unsigned long stored, left, x, y;
+ unsigned char *buf[2];
+ hmac_state *hmac;
+
+ LTC_ARGCHK(password != NULL);
+ LTC_ARGCHK(salt != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (iteration_count <= 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* test hash IDX */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ buf[0] = XMALLOC(MAXBLOCKSIZE * 2);
+ hmac = XMALLOC(sizeof(hmac_state));
+ if (hmac == NULL || buf[0] == NULL) {
+ if (hmac != NULL) {
+ XFREE(hmac);
+ }
+ if (buf[0] != NULL) {
+ XFREE(buf[0]);
+ }
+ return CRYPT_MEM;
+ }
+ /* buf[1] points to the second block of MAXBLOCKSIZE bytes */
+ buf[1] = buf[0] + MAXBLOCKSIZE;
+
+ left = *outlen;
+ blkno = 1;
+ stored = 0;
+ while (left != 0) {
+ /* process block number blkno */
+ zeromem(buf[0], MAXBLOCKSIZE*2);
+
+ /* store current block number and increment for next pass */
+ STORE32H(blkno, buf[1]);
+ ++blkno;
+
+ /* get PRF(P, S||int(blkno)) */
+ if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x = MAXBLOCKSIZE;
+ if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* now compute repeated and XOR it in buf[1] */
+ XMEMCPY(buf[1], buf[0], x);
+ for (itts = 1; itts < iteration_count; ++itts) {
+ if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ for (y = 0; y < x; y++) {
+ buf[1][y] ^= buf[0][y];
+ }
+ }
+
+ /* now emit upto x bytes of buf[1] to output */
+ for (y = 0; y < x && left != 0; ++y) {
+ out[stored++] = buf[1][y];
+ --left;
+ }
+ }
+ *outlen = stored;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf[0], MAXBLOCKSIZE*2);
+ zeromem(hmac, sizeof(hmac_state));
+#endif
+
+ XFREE(hmac);
+ XFREE(buf[0]);
+
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/misc/pkcs5/pkcs_5_test.c b/Sources/libtomcrypt/misc/pkcs5/pkcs_5_test.c
new file mode 100644
index 00000000..f90c0eef
--- /dev/null
+++ b/Sources/libtomcrypt/misc/pkcs5/pkcs_5_test.c
@@ -0,0 +1,224 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file hkdf_test.c
+ PKCS #5 support, self-test, Steffen Jaeckel
+*/
+
+#ifdef LTC_PKCS_5
+
+/*
+ TEST CASES SOURCE:
+
+Internet Engineering Task Force (IETF) S. Josefsson
+Request for Comments: 6070 SJD AB
+Category: Informational January 2011
+ISSN: 2070-1721
+*/
+
+/**
+ PKCS #5 self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled.
+*/
+int pkcs_5_test (void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+
+ typedef struct {
+ const char* P;
+ unsigned long P_len;
+ const char* S;
+ unsigned long S_len;
+ int c;
+ unsigned long dkLen;
+ unsigned char DK[40];
+ } case_item;
+
+ static const case_item cases_5_2[] = {
+ {
+ "password",
+ 8,
+ "salt",
+ 4,
+ 1,
+ 20,
+ { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
+ 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
+ 0x2f, 0xe0, 0x37, 0xa6 }
+ },
+ {
+ "password",
+ 8,
+ "salt",
+ 4,
+ 2,
+ 20,
+ { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
+ 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
+ 0xd8, 0xde, 0x89, 0x57 }
+ },
+#ifdef LTC_TEST_EXT
+ {
+ "password",
+ 8,
+ "salt",
+ 4,
+ 4096,
+ 20,
+ { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
+ 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
+ 0x65, 0xa4, 0x29, 0xc1 }
+ },
+ {
+ "password",
+ 8,
+ "salt",
+ 4,
+ 16777216,
+ 20,
+ { 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
+ 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
+ 0x26, 0x34, 0xe9, 0x84 }
+ },
+ {
+ "passwordPASSWORDpassword",
+ 25,
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+ 36,
+ 4096,
+ 25,
+ { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
+ 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
+ 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
+ 0x38 }
+ },
+ {
+ "pass\0word",
+ 9,
+ "sa\0lt",
+ 5,
+ 4096,
+ 16,
+ { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
+ 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }
+ },
+#endif /* LTC_TEST_EXT */
+ };
+
+ static const case_item cases_5_1[] = {
+ {
+ "password",
+ 8,
+ "saltsalt", /* must be 8 octects */
+ 8, /* ignored by alg1 */
+ 1,
+ 20,
+ { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c,
+ 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 }
+ },
+ };
+
+ static const case_item cases_5_1o[] = {
+ {
+ "password",
+ 8,
+ "saltsalt", /* must be 8 octects */
+ 8, /* ignored by alg1_openssl */
+ 1,
+ 20,
+ { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c,
+ 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 }
+
+ },
+ {
+ "password",
+ 8,
+ "saltsalt", /* must be 8 octects */
+ 8, /* ignored by alg1_openssl */
+ 1,
+ 30,
+ { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c,
+ 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44,
+ 0xf0, 0xbf, 0xf4, 0xc1, 0x2c, 0xf3, 0x59, 0x6f, 0xc0, 0x0b }
+
+ }
+ };
+
+ unsigned char DK[40];
+ unsigned long dkLen;
+ int i, err;
+ int tested=0, failed=0;
+ int hash = find_hash("sha1");
+ if (hash == -1)
+ {
+#ifdef LTC_TEST_DBG
+ printf("PKCS#5 test failed: 'sha1' hash not found\n");
+#endif
+ return CRYPT_ERROR;
+ }
+
+ /* testing alg 2 */
+ for(i=0; i < (int)(sizeof(cases_5_2) / sizeof(cases_5_2[0])); i++) {
+ ++tested;
+ dkLen = cases_5_2[i].dkLen;
+ if((err = pkcs_5_alg2((unsigned char*)cases_5_2[i].P, cases_5_2[i].P_len,
+ (unsigned char*)cases_5_2[i].S, cases_5_2[i].S_len,
+ cases_5_2[i].c, hash,
+ DK, &dkLen)) != CRYPT_OK) {
+ LTC_UNUSED_PARAM(err);
+#ifdef LTC_TEST_DBG
+ printf("\npkcs_5_alg2() #%d: Failed/1 (%s)\n", i, error_to_string(err));
+#endif
+ ++failed;
+ }
+ else if (compare_testvector(DK, dkLen, cases_5_2[i].DK, cases_5_2[i].dkLen, "PKCS#5_2", i)) {
+ ++failed;
+ }
+ }
+
+ /* testing alg 1 */
+ for(i=0; i < (int)(sizeof(cases_5_1) / sizeof(case_item)); i++, tested++) {
+ dkLen = cases_5_1[i].dkLen;
+ if((err = pkcs_5_alg1((unsigned char*)cases_5_1[i].P, cases_5_1[i].P_len,
+ (unsigned char*)cases_5_1[i].S,
+ cases_5_1[i].c, hash,
+ DK, &dkLen)) != CRYPT_OK) {
+ LTC_UNUSED_PARAM(err);
+#ifdef LTC_TEST_DBG
+ printf("\npkcs_5_alg1() #%d: Failed/1 (%s)\n", i, error_to_string(err));
+#endif
+ ++failed;
+ }
+ else if (compare_testvector(DK, dkLen, cases_5_1[i].DK, cases_5_1[i].dkLen, "PKCS#5_1", i)) {
+ ++failed;
+ }
+ }
+
+ /* testing alg 1_openssl */
+ for(i = 0; i < (int)(sizeof(cases_5_1o) / sizeof(cases_5_1o[0])); i++, tested++) {
+ dkLen = cases_5_1o[i].dkLen;
+ if ((err = pkcs_5_alg1_openssl((unsigned char*)cases_5_1o[i].P, cases_5_1o[i].P_len,
+ (unsigned char*)cases_5_1o[i].S,
+ cases_5_1o[i].c, hash,
+ DK, &dkLen)) != CRYPT_OK) {
+ LTC_UNUSED_PARAM(err);
+#ifdef LTC_TEST_DBG
+ printf("\npkcs_5_alg1_openssl() #%d: Failed/1 (%s)\n", i, error_to_string(err));
+#endif
+ ++failed;
+ }
+ else if (compare_testvector(DK, dkLen, cases_5_1o[i].DK, cases_5_1o[i].dkLen, "PKCS#5_1o", i)) {
+ ++failed;
+ }
+ }
+
+ return (failed != 0) ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK;
+ #endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/misc/ssh/ssh_decode_sequence_multi.c b/Sources/libtomcrypt/misc/ssh/ssh_decode_sequence_multi.c
new file mode 100644
index 00000000..3aa0e081
--- /dev/null
+++ b/Sources/libtomcrypt/misc/ssh/ssh_decode_sequence_multi.c
@@ -0,0 +1,165 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+/**
+ @file ssh_decode_sequence_multi.c
+ SSH data type representation as per RFC4251, Russ Williams
+*/
+
+#ifdef LTC_SSH
+
+/**
+ Decode a SSH sequence using a VA list
+ @param in The input buffer
+ @param inlen [in/out] The length of the input buffer and on output the amount of decoded data
+ @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long*)
+ @return CRYPT_OK on success
+*/
+int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...)
+{
+ int err;
+ va_list args;
+ ssh_data_type type;
+ void *vdata;
+ unsigned char *cdata;
+ char *sdata;
+ ulong32 *u32data;
+ ulong64 *u64data;
+ unsigned long *bufsize;
+ ulong32 size;
+ unsigned long remaining;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+
+ remaining = *inlen;
+ /* Decode values from buffer */
+ va_start(args, inlen);
+ while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
+ /* Size of length field */
+ if (type == LTC_SSHDATA_STRING ||
+ type == LTC_SSHDATA_NAMELIST ||
+ type == LTC_SSHDATA_MPINT)
+ {
+ /* Check we'll not read too far */
+ if (remaining < 4) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto error;
+ }
+ }
+
+ /* Calculate (or read) length of data */
+ size = 0xFFFFFFFFU;
+ switch (type) {
+ case LTC_SSHDATA_BYTE:
+ case LTC_SSHDATA_BOOLEAN:
+ size = 1;
+ break;
+ case LTC_SSHDATA_UINT32:
+ size = 4;
+ break;
+ case LTC_SSHDATA_UINT64:
+ size = 8;
+ break;
+ case LTC_SSHDATA_STRING:
+ case LTC_SSHDATA_NAMELIST:
+ case LTC_SSHDATA_MPINT:
+ LOAD32H(size, in);
+ in += 4;
+ remaining -= 4;
+ break;
+
+ case LTC_SSHDATA_EOL:
+ /* Should never get here */
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+
+ /* Check we'll not read too far */
+ if (remaining < size) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto error;
+ } else {
+ remaining -= size;
+ }
+
+ vdata = va_arg(args, void*);
+ if (vdata == NULL) {
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+
+ /* Read data */
+ switch (type) {
+ case LTC_SSHDATA_BYTE:
+ cdata = vdata;
+ *cdata = *in++;
+ break;
+ case LTC_SSHDATA_BOOLEAN:
+ cdata = vdata;
+ /*
+ The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be
+ interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1.
+ */
+ *cdata = (*in++)?1:0;
+ break;
+ case LTC_SSHDATA_UINT32:
+ u32data = vdata;
+ LOAD32H(*u32data, in);
+ in += 4;
+ break;
+ case LTC_SSHDATA_UINT64:
+ u64data = vdata;
+ LOAD64H(*u64data, in);
+ in += 8;
+ break;
+ case LTC_SSHDATA_STRING:
+ case LTC_SSHDATA_NAMELIST:
+ sdata = vdata;
+ bufsize = va_arg(args, unsigned long*);
+ if (bufsize == NULL) {
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+ if (size + 1 >= *bufsize) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto error;
+ }
+ if (size > 0) {
+ XMEMCPY(sdata, (const char *)in, size);
+ }
+ sdata[size] = '\0';
+ *bufsize = size;
+ in += size;
+ break;
+ case LTC_SSHDATA_MPINT:
+ if (size == 0) {
+ if ((err = mp_set(vdata, 0)) != CRYPT_OK) { goto error; }
+ } else if ((in[0] & 0x80) != 0) {
+ /* Negative number - not supported */
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ } else {
+ if ((err = mp_read_unsigned_bin(vdata, (unsigned char *)in, size)) != CRYPT_OK) { goto error; }
+ }
+ in += size;
+ break;
+
+ case LTC_SSHDATA_EOL:
+ /* Should never get here */
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+ }
+ err = CRYPT_OK;
+
+ *inlen -= remaining;
+
+error:
+ va_end(args);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/ssh/ssh_encode_sequence_multi.c b/Sources/libtomcrypt/misc/ssh/ssh_encode_sequence_multi.c
new file mode 100644
index 00000000..4bec5e12
--- /dev/null
+++ b/Sources/libtomcrypt/misc/ssh/ssh_encode_sequence_multi.c
@@ -0,0 +1,158 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+/**
+ @file ssh_encode_sequence_multi.c
+ SSH data type representation as per RFC4251, Russ Williams
+*/
+
+#ifdef LTC_SSH
+
+/**
+ Encode a SSH sequence using a VA list
+ @param out [out] Destination for data
+ @param outlen [in/out] Length of buffer and resulting length of output
+ @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long)
+ @return CRYPT_OK on success
+*/
+int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
+{
+ int err;
+ va_list args;
+ ulong32 size;
+ ssh_data_type type;
+ void *vdata;
+ const char *sdata;
+ int idata;
+ ulong32 u32data;
+ ulong64 u64data;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* Check values and calculate output size */
+ size = 0;
+ va_start(args, outlen);
+ while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
+ switch (type) {
+ case LTC_SSHDATA_BYTE:
+ case LTC_SSHDATA_BOOLEAN: /* Both stored as 1 byte */
+ LTC_UNUSED_PARAM( va_arg(args, int) );
+ size++;
+ break;
+ case LTC_SSHDATA_UINT32:
+ LTC_UNUSED_PARAM( va_arg(args, ulong32) );
+ size += 4;
+ break;
+ case LTC_SSHDATA_UINT64:
+ LTC_UNUSED_PARAM( va_arg(args, ulong64) );
+ size += 8;
+ break;
+ case LTC_SSHDATA_STRING:
+ case LTC_SSHDATA_NAMELIST:
+ LTC_UNUSED_PARAM( va_arg(args, char*) );
+ size += va_arg(args, unsigned long);
+ size += 4;
+ break;
+ case LTC_SSHDATA_MPINT:
+ vdata = va_arg(args, void*);
+ /* Calculate size */
+ size += 4;
+ if (mp_iszero(vdata) != LTC_MP_YES) {
+ size += mp_unsigned_bin_size(vdata);
+ if ((mp_count_bits(vdata) & 7) == 0) size++; /* Zero padding if high bit set */
+ }
+ break;
+
+ case LTC_SSHDATA_EOL: /* Should never get here */
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+ }
+ va_end(args);
+
+ /* Check we have sufficient space */
+ if (*outlen < size) {
+ *outlen = size;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto errornoargs;
+ }
+ *outlen = size;
+
+ /* Encode values into buffer */
+ va_start(args, outlen);
+ while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
+ switch (type) {
+ case LTC_SSHDATA_BYTE:
+ idata = va_arg(args, int);
+
+ *out++ = (unsigned char)(idata & 255);
+ break;
+ case LTC_SSHDATA_BOOLEAN:
+ idata = va_arg(args, int);
+
+ /*
+ The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be
+ interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1.
+ */
+ *out++ = (idata)?1:0;
+ break;
+ case LTC_SSHDATA_UINT32:
+ u32data = va_arg(args, ulong32);
+ STORE32H(u32data, out);
+ out += 4;
+ break;
+ case LTC_SSHDATA_UINT64:
+ u64data = va_arg(args, ulong64);
+ STORE64H(u64data, out);
+ out += 8;
+ break;
+ case LTC_SSHDATA_STRING:
+ case LTC_SSHDATA_NAMELIST:
+ sdata = va_arg(args, char*);
+ size = va_arg(args, unsigned long);
+ STORE32H(size, out);
+ out += 4;
+ XMEMCPY(out, sdata, size);
+ out += size;
+ break;
+ case LTC_SSHDATA_MPINT:
+ vdata = va_arg(args, void*);
+ if (mp_iszero(vdata) == LTC_MP_YES) {
+ STORE32H(0, out);
+ out += 4;
+ } else {
+ size = mp_unsigned_bin_size(vdata);
+ if ((mp_count_bits(vdata) & 7) == 0) {
+ /* Zero padding if high bit set */
+ STORE32H(size+1, out);
+ out += 4;
+ *out++ = 0;
+ } else {
+ STORE32H(size, out);
+ out += 4;
+ }
+ if (mp_to_unsigned_bin(vdata, out) != CRYPT_OK) {
+ err = CRYPT_ERROR;
+ goto error;
+ }
+ out += size;
+ }
+ break;
+
+ case LTC_SSHDATA_EOL: /* Should never get here */
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+ }
+ err = CRYPT_OK;
+
+error:
+ va_end(args);
+errornoargs:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/misc/zeromem.c b/Sources/libtomcrypt/misc/zeromem.c
new file mode 100644
index 00000000..7d149948
--- /dev/null
+++ b/Sources/libtomcrypt/misc/zeromem.c
@@ -0,0 +1,22 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file zeromem.c
+ Zero a block of memory, Tom St Denis
+*/
+
+/**
+ Zero a block of memory
+ @param out The destination of the area to zero
+ @param outlen The length of the area to zero (octets)
+*/
+void zeromem(volatile void *out, size_t outlen)
+{
+ volatile char *mem = out;
+ LTC_ARGCHKVD(out != NULL);
+ while (outlen-- > 0) {
+ *mem++ = '\0';
+ }
+}
diff --git a/Sources/libtomcrypt/modes/cbc/cbc_decrypt.c b/Sources/libtomcrypt/modes/cbc/cbc_decrypt.c
new file mode 100644
index 00000000..5fa3ee36
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cbc/cbc_decrypt.c
@@ -0,0 +1,84 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cbc_decrypt.c
+ CBC implementation, encrypt block, Tom St Denis
+*/
+
+
+#ifdef LTC_CBC_MODE
+
+/**
+ CBC decrypt
+ @param ct Ciphertext
+ @param pt [out] Plaintext
+ @param len The number of bytes to process (must be multiple of block length)
+ @param cbc CBC state
+ @return CRYPT_OK if successful
+*/
+int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc)
+{
+ int x, err;
+ unsigned char tmp[16];
+#ifdef LTC_FAST
+ LTC_FAST_TYPE tmpy;
+#else
+ unsigned char tmpy;
+#endif
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(cbc != NULL);
+
+ if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* is blocklen valid? */
+ if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV) || cbc->blocklen > (int)sizeof(tmp)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (len % cbc->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+#ifdef LTC_FAST
+ if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ if (cipher_descriptor[cbc->cipher].accel_cbc_decrypt != NULL) {
+ return cipher_descriptor[cbc->cipher].accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key);
+ }
+ while (len) {
+ /* decrypt */
+ if ((err = cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* xor IV against plaintext */
+#if defined(LTC_FAST)
+ for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) {
+ tmpy = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)tmp + x));
+ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x));
+ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) = tmpy;
+ }
+#else
+ for (x = 0; x < cbc->blocklen; x++) {
+ tmpy = tmp[x] ^ cbc->IV[x];
+ cbc->IV[x] = ct[x];
+ pt[x] = tmpy;
+ }
+#endif
+
+ ct += cbc->blocklen;
+ pt += cbc->blocklen;
+ len -= cbc->blocklen;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/cbc/cbc_done.c b/Sources/libtomcrypt/modes/cbc/cbc_done.c
new file mode 100644
index 00000000..985551ff
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cbc/cbc_done.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cbc_done.c
+ CBC implementation, finish chain, Tom St Denis
+*/
+
+#ifdef LTC_CBC_MODE
+
+/** Terminate the chain
+ @param cbc The CBC chain to terminate
+ @return CRYPT_OK on success
+*/
+int cbc_done(symmetric_CBC *cbc)
+{
+ int err;
+ LTC_ARGCHK(cbc != NULL);
+
+ if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ cipher_descriptor[cbc->cipher].done(&cbc->key);
+ return CRYPT_OK;
+}
+
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/cbc/cbc_encrypt.c b/Sources/libtomcrypt/modes/cbc/cbc_encrypt.c
new file mode 100644
index 00000000..50d91c42
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cbc/cbc_encrypt.c
@@ -0,0 +1,85 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cbc_encrypt.c
+ CBC implementation, encrypt block, Tom St Denis
+*/
+
+
+#ifdef LTC_CBC_MODE
+
+/**
+ CBC encrypt
+ @param pt Plaintext
+ @param ct [out] Ciphertext
+ @param len The number of bytes to process (must be multiple of block length)
+ @param cbc CBC state
+ @return CRYPT_OK if successful
+*/
+int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc)
+{
+ int x, err;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(cbc != NULL);
+
+ if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* is blocklen valid? */
+ if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (len % cbc->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+#ifdef LTC_FAST
+ if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ if (cipher_descriptor[cbc->cipher].accel_cbc_encrypt != NULL) {
+ return cipher_descriptor[cbc->cipher].accel_cbc_encrypt(pt, ct, len / cbc->blocklen, cbc->IV, &cbc->key);
+ }
+ while (len) {
+ /* xor IV against plaintext */
+#if defined(LTC_FAST)
+ for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x));
+ }
+#else
+ for (x = 0; x < cbc->blocklen; x++) {
+ cbc->IV[x] ^= pt[x];
+ }
+#endif
+
+ /* encrypt */
+ if ((err = cipher_descriptor[cbc->cipher].ecb_encrypt(cbc->IV, ct, &cbc->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* store IV [ciphertext] for a future block */
+#if defined(LTC_FAST)
+ for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x));
+ }
+#else
+ for (x = 0; x < cbc->blocklen; x++) {
+ cbc->IV[x] = ct[x];
+ }
+#endif
+
+ ct += cbc->blocklen;
+ pt += cbc->blocklen;
+ len -= cbc->blocklen;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/cbc/cbc_getiv.c b/Sources/libtomcrypt/modes/cbc/cbc_getiv.c
new file mode 100644
index 00000000..7af2cf17
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cbc/cbc_getiv.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cbc_getiv.c
+ CBC implementation, get IV, Tom St Denis
+*/
+
+#ifdef LTC_CBC_MODE
+
+/**
+ Get the current initialization vector
+ @param IV [out] The destination of the initialization vector
+ @param len [in/out] The max size and resulting size of the initialization vector
+ @param cbc The CBC state
+ @return CRYPT_OK if successful
+*/
+int cbc_getiv(unsigned char *IV, unsigned long *len, const symmetric_CBC *cbc)
+{
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(len != NULL);
+ LTC_ARGCHK(cbc != NULL);
+ if ((unsigned long)cbc->blocklen > *len) {
+ *len = cbc->blocklen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ XMEMCPY(IV, cbc->IV, cbc->blocklen);
+ *len = cbc->blocklen;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/cbc/cbc_setiv.c b/Sources/libtomcrypt/modes/cbc/cbc_setiv.c
new file mode 100644
index 00000000..a9e91c3c
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cbc/cbc_setiv.c
@@ -0,0 +1,32 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cbc_setiv.c
+ CBC implementation, set IV, Tom St Denis
+*/
+
+
+#ifdef LTC_CBC_MODE
+
+/**
+ Set an initialization vector
+ @param IV The initialization vector
+ @param len The length of the vector (in octets)
+ @param cbc The CBC state
+ @return CRYPT_OK if successful
+*/
+int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc)
+{
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(cbc != NULL);
+ if (len != (unsigned long)cbc->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+ XMEMCPY(cbc->IV, IV, len);
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/modes/cbc/cbc_start.c b/Sources/libtomcrypt/modes/cbc/cbc_start.c
new file mode 100644
index 00000000..41567392
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cbc/cbc_start.c
@@ -0,0 +1,50 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cbc_start.c
+ CBC implementation, start chain, Tom St Denis
+*/
+
+#ifdef LTC_CBC_MODE
+
+/**
+ Initialize a CBC context
+ @param cipher The index of the cipher desired
+ @param IV The initialization vector
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param num_rounds Number of rounds in the cipher desired (0 for default)
+ @param cbc The CBC state to initialize
+ @return CRYPT_OK if successful
+*/
+int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_CBC *cbc)
+{
+ int x, err;
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(cbc != NULL);
+
+ /* bad param? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* setup cipher */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* copy IV */
+ cbc->blocklen = cipher_descriptor[cipher].block_length;
+ cbc->cipher = cipher;
+ for (x = 0; x < cbc->blocklen; x++) {
+ cbc->IV[x] = IV[x];
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/cfb/cfb_decrypt.c b/Sources/libtomcrypt/modes/cfb/cfb_decrypt.c
new file mode 100644
index 00000000..1c6d3fa4
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cfb/cfb_decrypt.c
@@ -0,0 +1,117 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cfb_decrypt.c
+ CFB implementation, decrypt data, Tom St Denis
+*/
+
+#ifdef LTC_CFB_MODE
+
+static LTC_INLINE void s_shift1left_64(unsigned char *b, unsigned char v)
+{
+ ulong64 bval;
+ LOAD64H(bval, b);
+ bval <<= 1;
+ bval |= v & 0x01u;
+ STORE64H(bval, b);
+}
+
+static LTC_INLINE void s_shift1left_128(unsigned char *b, unsigned char v)
+{
+ ulong64 bval[2];
+ LOAD64H(bval[0], b);
+ LOAD64H(bval[1], b + 8);
+ bval[0] <<= 1;
+ bval[0] |= (bval[1] >> 63) & 0x01u;
+ bval[1] <<= 1;
+ bval[1] |= v & 0x01u;
+ STORE64H(bval[0], b);
+ STORE64H(bval[1], b + 8);
+}
+
+/**
+ CFB decrypt
+ @param ct Ciphertext
+ @param pt [out] Plaintext
+ @param len Length of ciphertext (octets)
+ @param cfb CFB state
+ @return CRYPT_OK if successful
+*/
+int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb)
+{
+ int err;
+ ulong64 bitlen = len * 8, bits_per_round;
+ unsigned int cur_bit = 0;
+ unsigned char pt_ = 0, ct_ = 0;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(cfb != NULL);
+
+ if (bitlen < len) {
+ return CRYPT_OVERFLOW;
+ }
+
+ if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* is blocklen/padlen valid? */
+ if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) ||
+ cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ bits_per_round = cfb->width == 1 ? 1 : 8;
+
+ while (bitlen > 0) {
+ if (cfb->padlen == cfb->blocklen) {
+ if ((err = cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key)) != CRYPT_OK) {
+ return err;
+ }
+ cfb->padlen = 0;
+ }
+ switch (cfb->width) {
+ case 1:
+ if (cur_bit++ % 8 == 0) {
+ ct_ = *ct++;
+ pt_ = 0;
+ } else {
+ ct_ <<= 1;
+ pt_ <<= 1;
+ }
+ if (cfb->blocklen == 16)
+ s_shift1left_128(cfb->pad, ct_ >> 7);
+ else
+ s_shift1left_64(cfb->pad, ct_ >> 7);
+ pt_ |= ((ct_ ^ cfb->IV[0]) >> 7) & 0x01u;
+ cfb->padlen = cfb->blocklen;
+ if (cur_bit % 8 == 0) {
+ *pt++ = pt_;
+ cur_bit = 0;
+ }
+ break;
+ case 8:
+ XMEMMOVE(cfb->pad, cfb->pad + 1, cfb->blocklen - 1);
+ cfb->pad[cfb->blocklen - 1] = *ct;
+ *pt++ = *ct++ ^ cfb->IV[0];
+ cfb->padlen = cfb->blocklen;
+ break;
+ case 64:
+ case 128:
+ cfb->pad[cfb->padlen] = *ct;
+ *pt++ = *ct++ ^ cfb->IV[cfb->padlen];
+ ++(cfb->padlen);
+ break;
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+ bitlen -= bits_per_round;
+ }
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/modes/cfb/cfb_done.c b/Sources/libtomcrypt/modes/cfb/cfb_done.c
new file mode 100644
index 00000000..8f8f9cd0
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cfb/cfb_done.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cfb_done.c
+ CFB implementation, finish chain, Tom St Denis
+*/
+
+#ifdef LTC_CFB_MODE
+
+/** Terminate the chain
+ @param cfb The CFB chain to terminate
+ @return CRYPT_OK on success
+*/
+int cfb_done(symmetric_CFB *cfb)
+{
+ int err;
+ LTC_ARGCHK(cfb != NULL);
+
+ if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ cipher_descriptor[cfb->cipher].done(&cfb->key);
+ return CRYPT_OK;
+}
+
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/cfb/cfb_encrypt.c b/Sources/libtomcrypt/modes/cfb/cfb_encrypt.c
new file mode 100644
index 00000000..22f8dd2f
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cfb/cfb_encrypt.c
@@ -0,0 +1,116 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cfb_encrypt.c
+ CFB implementation, encrypt data, Tom St Denis
+*/
+
+#ifdef LTC_CFB_MODE
+
+static LTC_INLINE void s_shift1left_64(unsigned char *b, unsigned char v)
+{
+ ulong64 bval;
+ LOAD64H(bval, b);
+ bval <<= 1;
+ bval |= v & 0x01u;
+ STORE64H(bval, b);
+}
+
+static LTC_INLINE void s_shift1left_128(unsigned char *b, unsigned char v)
+{
+ ulong64 bval[2];
+ LOAD64H(bval[0], b);
+ LOAD64H(bval[1], b + 8);
+ bval[0] <<= 1;
+ bval[0] |= (bval[1] >> 63) & 0x01u;
+ bval[1] <<= 1;
+ bval[1] |= v & 0x01u;
+ STORE64H(bval[0], b);
+ STORE64H(bval[1], b + 8);
+}
+
+/**
+ CFB encrypt
+ @param pt Plaintext
+ @param ct [out] Ciphertext
+ @param len Length of plaintext (octets)
+ @param cfb CFB state
+ @return CRYPT_OK if successful
+*/
+int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb)
+{
+ int err;
+ ulong64 bitlen = len * 8, bits_per_round;
+ unsigned int cur_bit = 0;
+ unsigned char pt_ = 0, ct_ = 0;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(cfb != NULL);
+
+ if (bitlen < len) {
+ return CRYPT_OVERFLOW;
+ }
+
+ if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* is blocklen/padlen valid? */
+ if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) ||
+ cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ bits_per_round = cfb->width == 1 ? 1 : 8;
+
+ while (bitlen > 0) {
+ if (cfb->padlen == cfb->blocklen) {
+ if ((err = cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key)) != CRYPT_OK) {
+ return err;
+ }
+ cfb->padlen = 0;
+ }
+ switch (cfb->width) {
+ case 1:
+ if (cur_bit++ % 8 == 0) {
+ pt_ = *pt++;
+ ct_ = 0;
+ } else {
+ pt_ <<= 1;
+ ct_ <<= 1;
+ }
+ ct_ |= ((pt_ ^ cfb->IV[0]) >> 7) & 0x01u;
+ if (cfb->blocklen == 16)
+ s_shift1left_128(cfb->pad, ct_);
+ else
+ s_shift1left_64(cfb->pad, ct_);
+ cfb->padlen = cfb->blocklen;
+ if (cur_bit % 8 == 0) {
+ *ct++ = ct_;
+ cur_bit = 0;
+ }
+ break;
+ case 8:
+ XMEMMOVE(cfb->pad, cfb->pad + 1, cfb->blocklen - 1);
+ cfb->pad[cfb->blocklen - 1] = (*ct = *pt ^ cfb->IV[0]);
+ ++pt;
+ ++ct;
+ cfb->padlen = cfb->blocklen;
+ break;
+ case 64:
+ case 128:
+ cfb->pad[cfb->padlen] = (*ct = *pt ^ cfb->IV[cfb->padlen]);
+ ++pt;
+ ++ct;
+ ++(cfb->padlen);
+ break;
+ }
+ bitlen -= bits_per_round;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/cfb/cfb_getiv.c b/Sources/libtomcrypt/modes/cfb/cfb_getiv.c
new file mode 100644
index 00000000..ca72dd6f
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cfb/cfb_getiv.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cfb_getiv.c
+ CFB implementation, get IV, Tom St Denis
+*/
+
+#ifdef LTC_CFB_MODE
+
+/**
+ Get the current initialization vector
+ @param IV [out] The destination of the initialization vector
+ @param len [in/out] The max size and resulting size of the initialization vector
+ @param cfb The CFB state
+ @return CRYPT_OK if successful
+*/
+int cfb_getiv(unsigned char *IV, unsigned long *len, const symmetric_CFB *cfb)
+{
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(len != NULL);
+ LTC_ARGCHK(cfb != NULL);
+ if ((unsigned long)cfb->blocklen > *len) {
+ *len = cfb->blocklen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ XMEMCPY(IV, cfb->pad, cfb->blocklen);
+ *len = cfb->blocklen;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/cfb/cfb_setiv.c b/Sources/libtomcrypt/modes/cfb/cfb_setiv.c
new file mode 100644
index 00000000..60572de2
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cfb/cfb_setiv.c
@@ -0,0 +1,41 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cfb_setiv.c
+ CFB implementation, set IV, Tom St Denis
+*/
+
+#ifdef LTC_CFB_MODE
+
+/**
+ Set an initialization vector
+ @param IV The initialization vector
+ @param len The length of the vector (in octets)
+ @param cfb The CFB state
+ @return CRYPT_OK if successful
+*/
+int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb)
+{
+ int err;
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(cfb != NULL);
+
+ if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len != (unsigned long)cfb->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* force next block */
+ cfb->padlen = 0;
+ XMEMCPY(cfb->pad, IV, len);
+ return cipher_descriptor[cfb->cipher].ecb_encrypt(IV, cfb->IV, &cfb->key);
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/modes/cfb/cfb_start.c b/Sources/libtomcrypt/modes/cfb/cfb_start.c
new file mode 100644
index 00000000..c95a657c
--- /dev/null
+++ b/Sources/libtomcrypt/modes/cfb/cfb_start.c
@@ -0,0 +1,90 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file cfb_start.c
+ CFB implementation, start chain, Tom St Denis
+*/
+
+
+#ifdef LTC_CFB_MODE
+
+
+/**
+ Extended initialization of a CFB context
+ @param cipher The index of the cipher desired
+ @param IV The initialization vector
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param num_rounds Number of rounds in the cipher desired (0 for default)
+ @param width The width of the mode in bits (0 for default)
+ @param cfb The CFB state to initialize
+ @return CRYPT_OK if successful
+*/
+int cfb_start_ex(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, int width, symmetric_CFB *cfb)
+{
+ int x, err;
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(cfb != NULL);
+
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ switch (width) {
+ case 0:
+ width = cipher_descriptor[cipher].block_length * 8;
+ break;
+ case 1:
+ case 8:
+ LTC_ARGCHK(cipher_descriptor[cipher].block_length == 8
+ || cipher_descriptor[cipher].block_length == 16);
+ break;
+ case 64:
+ case 128:
+ LTC_ARGCHK(width == cipher_descriptor[cipher].block_length * 8);
+ break;
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* copy data */
+ cfb->cipher = cipher;
+ cfb->width = width;
+ cfb->blocklen = cipher_descriptor[cipher].block_length;
+ for (x = 0; x < cfb->blocklen; x++) {
+ cfb->pad[x] = IV[x];
+ }
+
+ /* init the cipher */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cfb->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* encrypt the IV */
+ cfb->padlen = 0;
+ return cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key);
+}
+
+/**
+ Initialize a CFB context
+ @param cipher The index of the cipher desired
+ @param IV The initialization vector
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param num_rounds Number of rounds in the cipher desired (0 for default)
+ @param cfb The CFB state to initialize
+ @return CRYPT_OK if successful
+*/
+int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_CFB *cfb)
+{
+ return cfb_start_ex(cipher, IV, key, keylen, num_rounds, 0, cfb);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ctr/ctr_decrypt.c b/Sources/libtomcrypt/modes/ctr/ctr_decrypt.c
new file mode 100644
index 00000000..a55a08fc
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ctr/ctr_decrypt.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ctr_decrypt.c
+ CTR implementation, decrypt data, Tom St Denis
+*/
+
+#ifdef LTC_CTR_MODE
+
+/**
+ CTR decrypt
+ @param ct Ciphertext
+ @param pt [out] Plaintext
+ @param len Length of ciphertext (octets)
+ @param ctr CTR state
+ @return CRYPT_OK if successful
+*/
+int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr)
+{
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(ctr != NULL);
+
+ return ctr_encrypt(ct, pt, len, ctr);
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/modes/ctr/ctr_done.c b/Sources/libtomcrypt/modes/ctr/ctr_done.c
new file mode 100644
index 00000000..f93d9717
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ctr/ctr_done.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ctr_done.c
+ CTR implementation, finish chain, Tom St Denis
+*/
+
+#ifdef LTC_CTR_MODE
+
+/** Terminate the chain
+ @param ctr The CTR chain to terminate
+ @return CRYPT_OK on success
+*/
+int ctr_done(symmetric_CTR *ctr)
+{
+ int err;
+ LTC_ARGCHK(ctr != NULL);
+
+ if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ cipher_descriptor[ctr->cipher].done(&ctr->key);
+ return CRYPT_OK;
+}
+
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ctr/ctr_encrypt.c b/Sources/libtomcrypt/modes/ctr/ctr_encrypt.c
new file mode 100644
index 00000000..b8c08f7a
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ctr/ctr_encrypt.c
@@ -0,0 +1,129 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ctr_encrypt.c
+ CTR implementation, encrypt data, Tom St Denis
+*/
+
+
+#ifdef LTC_CTR_MODE
+
+/**
+ CTR encrypt software implementation
+ @param pt Plaintext
+ @param ct [out] Ciphertext
+ @param len Length of plaintext (octets)
+ @param ctr CTR state
+ @return CRYPT_OK if successful
+*/
+static int s_ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
+{
+ int x, err;
+
+ while (len) {
+ /* is the pad empty? */
+ if (ctr->padlen == ctr->blocklen) {
+ /* increment counter */
+ if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {
+ /* little-endian */
+ for (x = 0; x < ctr->ctrlen; x++) {
+ ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
+ if (ctr->ctr[x] != (unsigned char)0) {
+ break;
+ }
+ }
+ } else {
+ /* big-endian */
+ for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) {
+ ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
+ if (ctr->ctr[x] != (unsigned char)0) {
+ break;
+ }
+ }
+ }
+
+ /* encrypt it */
+ if ((err = cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key)) != CRYPT_OK) {
+ return err;
+ }
+ ctr->padlen = 0;
+ }
+#ifdef LTC_FAST
+ if ((ctr->padlen == 0) && (len >= (unsigned long)ctr->blocklen)) {
+ for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) ^
+ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ctr->pad + x));
+ }
+ pt += ctr->blocklen;
+ ct += ctr->blocklen;
+ len -= ctr->blocklen;
+ ctr->padlen = ctr->blocklen;
+ continue;
+ }
+#endif
+ *ct++ = *pt++ ^ ctr->pad[ctr->padlen++];
+ --len;
+ }
+ return CRYPT_OK;
+}
+
+/**
+ CTR encrypt
+ @param pt Plaintext
+ @param ct [out] Ciphertext
+ @param len Length of plaintext (octets)
+ @param ctr CTR state
+ @return CRYPT_OK if successful
+*/
+int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
+{
+ int err, fr;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(ctr != NULL);
+
+ if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* is blocklen/padlen valid? */
+ if ((ctr->blocklen < 1) || (ctr->blocklen > (int)sizeof(ctr->ctr)) ||
+ (ctr->padlen < 0) || (ctr->padlen > (int)sizeof(ctr->pad))) {
+ return CRYPT_INVALID_ARG;
+ }
+
+#ifdef LTC_FAST
+ if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */
+ if ((cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL) && (len >= (unsigned long)ctr->blocklen)) {
+ if (ctr->padlen < ctr->blocklen) {
+ fr = ctr->blocklen - ctr->padlen;
+ if ((err = s_ctr_encrypt(pt, ct, fr, ctr)) != CRYPT_OK) {
+ return err;
+ }
+ pt += fr;
+ ct += fr;
+ len -= fr;
+ }
+
+ if (len >= (unsigned long)ctr->blocklen) {
+ if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) {
+ return err;
+ }
+ pt += (len / ctr->blocklen) * ctr->blocklen;
+ ct += (len / ctr->blocklen) * ctr->blocklen;
+ len %= ctr->blocklen;
+ }
+ }
+
+ return s_ctr_encrypt(pt, ct, len, ctr);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ctr/ctr_getiv.c b/Sources/libtomcrypt/modes/ctr/ctr_getiv.c
new file mode 100644
index 00000000..05277fae
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ctr/ctr_getiv.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ctr_getiv.c
+ CTR implementation, get IV, Tom St Denis
+*/
+
+#ifdef LTC_CTR_MODE
+
+/**
+ Get the current initialization vector
+ @param IV [out] The destination of the initialization vector
+ @param len [in/out] The max size and resulting size of the initialization vector
+ @param ctr The CTR state
+ @return CRYPT_OK if successful
+*/
+int ctr_getiv(unsigned char *IV, unsigned long *len, const symmetric_CTR *ctr)
+{
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(len != NULL);
+ LTC_ARGCHK(ctr != NULL);
+ if ((unsigned long)ctr->blocklen > *len) {
+ *len = ctr->blocklen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ XMEMCPY(IV, ctr->ctr, ctr->blocklen);
+ *len = ctr->blocklen;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ctr/ctr_setiv.c b/Sources/libtomcrypt/modes/ctr/ctr_setiv.c
new file mode 100644
index 00000000..be80f1a2
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ctr/ctr_setiv.c
@@ -0,0 +1,44 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ctr_setiv.c
+ CTR implementation, set IV, Tom St Denis
+*/
+
+#ifdef LTC_CTR_MODE
+
+/**
+ Set an initialization vector
+ @param IV The initialization vector
+ @param len The length of the vector (in octets)
+ @param ctr The CTR state
+ @return CRYPT_OK if successful
+*/
+int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr)
+{
+ int err;
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(ctr != NULL);
+
+ /* bad param? */
+ if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len != (unsigned long)ctr->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* set IV */
+ XMEMCPY(ctr->ctr, IV, len);
+
+ /* force next block */
+ ctr->padlen = 0;
+ return cipher_descriptor[ctr->cipher].ecb_encrypt(IV, ctr->pad, &ctr->key);
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/modes/ctr/ctr_start.c b/Sources/libtomcrypt/modes/ctr/ctr_start.c
new file mode 100644
index 00000000..0ccdfd22
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ctr/ctr_start.c
@@ -0,0 +1,89 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ctr_start.c
+ CTR implementation, start chain, Tom St Denis
+*/
+
+
+#ifdef LTC_CTR_MODE
+
+/**
+ Initialize a CTR context
+ @param cipher The index of the cipher desired
+ @param IV The initialization vector
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param num_rounds Number of rounds in the cipher desired (0 for default)
+ @param ctr_mode The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN)
+ @param ctr The CTR state to initialize
+ @return CRYPT_OK if successful
+*/
+int ctr_start( int cipher,
+ const unsigned char *IV,
+ const unsigned char *key, int keylen,
+ int num_rounds, int ctr_mode,
+ symmetric_CTR *ctr)
+{
+ int x, err;
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ctr != NULL);
+
+ /* bad param? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* ctrlen == counter width */
+ ctr->ctrlen = (ctr_mode & 255) ? (ctr_mode & 255) : cipher_descriptor[cipher].block_length;
+ if (ctr->ctrlen > cipher_descriptor[cipher].block_length) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) {
+ ctr->ctrlen = cipher_descriptor[cipher].block_length - ctr->ctrlen;
+ }
+
+ /* setup cipher */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* copy ctr */
+ ctr->blocklen = cipher_descriptor[cipher].block_length;
+ ctr->cipher = cipher;
+ ctr->padlen = 0;
+ ctr->mode = ctr_mode & 0x1000;
+ for (x = 0; x < ctr->blocklen; x++) {
+ ctr->ctr[x] = IV[x];
+ }
+
+ if (ctr_mode & LTC_CTR_RFC3686) {
+ /* increment the IV as per RFC 3686 */
+ if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {
+ /* little-endian */
+ for (x = 0; x < ctr->ctrlen; x++) {
+ ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
+ if (ctr->ctr[x] != (unsigned char)0) {
+ break;
+ }
+ }
+ } else {
+ /* big-endian */
+ for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) {
+ ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
+ if (ctr->ctr[x] != (unsigned char)0) {
+ break;
+ }
+ }
+ }
+ }
+
+ return cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ctr/ctr_test.c b/Sources/libtomcrypt/modes/ctr/ctr_test.c
new file mode 100644
index 00000000..df7e6493
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ctr/ctr_test.c
@@ -0,0 +1,73 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ctr_test.c
+ CTR implementation, Tests again RFC 3686, Tom St Denis
+*/
+
+#ifdef LTC_CTR_MODE
+
+int ctr_test(void)
+{
+#ifdef LTC_NO_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ int keylen, msglen;
+ unsigned char key[32], IV[16], pt[64], ct[64];
+ } tests[] = {
+/* 128-bit key, 16-byte pt */
+{
+ 16, 16,
+ {0xAE,0x68,0x52,0xF8,0x12,0x10,0x67,0xCC,0x4B,0xF7,0xA5,0x76,0x55,0x77,0xF3,0x9E },
+ {0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ {0x53,0x69,0x6E,0x67,0x6C,0x65,0x20,0x62,0x6C,0x6F,0x63,0x6B,0x20,0x6D,0x73,0x67 },
+ {0xE4,0x09,0x5D,0x4F,0xB7,0xA7,0xB3,0x79,0x2D,0x61,0x75,0xA3,0x26,0x13,0x11,0xB8 },
+},
+
+/* 128-bit key, 36-byte pt */
+{
+ 16, 36,
+ {0x76,0x91,0xBE,0x03,0x5E,0x50,0x20,0xA8,0xAC,0x6E,0x61,0x85,0x29,0xF9,0xA0,0xDC },
+ {0x00,0xE0,0x01,0x7B,0x27,0x77,0x7F,0x3F,0x4A,0x17,0x86,0xF0,0x00,0x00,0x00,0x00 },
+ {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,
+ 0x20,0x21,0x22,0x23},
+ {0xC1,0xCF,0x48,0xA8,0x9F,0x2F,0xFD,0xD9,0xCF,0x46,0x52,0xE9,0xEF,0xDB,0x72,0xD7,
+ 0x45,0x40,0xA4,0x2B,0xDE,0x6D,0x78,0x36,0xD5,0x9A,0x5C,0xEA,0xAE,0xF3,0x10,0x53,
+ 0x25,0xB2,0x07,0x2F },
+},
+};
+ int idx, err, x;
+ unsigned char buf[64];
+ symmetric_CTR ctr;
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((idx = find_cipher("aes")) == -1) {
+ if ((idx = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ if ((err = ctr_start(idx, tests[x].IV, tests[x].key, tests[x].keylen, 0, CTR_COUNTER_BIG_ENDIAN|LTC_CTR_RFC3686, &ctr)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = ctr_encrypt(tests[x].pt, buf, tests[x].msglen, &ctr)) != CRYPT_OK) {
+ return err;
+ }
+ ctr_done(&ctr);
+ if (compare_testvector(buf, tests[x].msglen, tests[x].ct, tests[x].msglen, "CTR", x)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
+
+
diff --git a/Sources/libtomcrypt/modes/ecb/ecb_decrypt.c b/Sources/libtomcrypt/modes/ecb/ecb_decrypt.c
new file mode 100644
index 00000000..30697791
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ecb/ecb_decrypt.c
@@ -0,0 +1,48 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ecb_decrypt.c
+ ECB implementation, decrypt a block, Tom St Denis
+*/
+
+#ifdef LTC_ECB_MODE
+
+/**
+ ECB decrypt
+ @param ct Ciphertext
+ @param pt [out] Plaintext
+ @param len The number of octets to process (must be multiple of the cipher block size)
+ @param ecb ECB state
+ @return CRYPT_OK if successful
+*/
+int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb)
+{
+ int err;
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(ecb != NULL);
+ if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (len % cipher_descriptor[ecb->cipher].block_length) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* check for accel */
+ if (cipher_descriptor[ecb->cipher].accel_ecb_decrypt != NULL) {
+ return cipher_descriptor[ecb->cipher].accel_ecb_decrypt(ct, pt, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key);
+ }
+ while (len) {
+ if ((err = cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key)) != CRYPT_OK) {
+ return err;
+ }
+ pt += cipher_descriptor[ecb->cipher].block_length;
+ ct += cipher_descriptor[ecb->cipher].block_length;
+ len -= cipher_descriptor[ecb->cipher].block_length;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ecb/ecb_done.c b/Sources/libtomcrypt/modes/ecb/ecb_done.c
new file mode 100644
index 00000000..e1c0c593
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ecb/ecb_done.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ecb_done.c
+ ECB implementation, finish chain, Tom St Denis
+*/
+
+#ifdef LTC_ECB_MODE
+
+/** Terminate the chain
+ @param ecb The ECB chain to terminate
+ @return CRYPT_OK on success
+*/
+int ecb_done(symmetric_ECB *ecb)
+{
+ int err;
+ LTC_ARGCHK(ecb != NULL);
+
+ if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ cipher_descriptor[ecb->cipher].done(&ecb->key);
+ return CRYPT_OK;
+}
+
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ecb/ecb_encrypt.c b/Sources/libtomcrypt/modes/ecb/ecb_encrypt.c
new file mode 100644
index 00000000..661d9942
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ecb/ecb_encrypt.c
@@ -0,0 +1,48 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ecb_encrypt.c
+ ECB implementation, encrypt a block, Tom St Denis
+*/
+
+#ifdef LTC_ECB_MODE
+
+/**
+ ECB encrypt
+ @param pt Plaintext
+ @param ct [out] Ciphertext
+ @param len The number of octets to process (must be multiple of the cipher block size)
+ @param ecb ECB state
+ @return CRYPT_OK if successful
+*/
+int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb)
+{
+ int err;
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(ecb != NULL);
+ if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (len % cipher_descriptor[ecb->cipher].block_length) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* check for accel */
+ if (cipher_descriptor[ecb->cipher].accel_ecb_encrypt != NULL) {
+ return cipher_descriptor[ecb->cipher].accel_ecb_encrypt(pt, ct, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key);
+ }
+ while (len) {
+ if ((err = cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key)) != CRYPT_OK) {
+ return err;
+ }
+ pt += cipher_descriptor[ecb->cipher].block_length;
+ ct += cipher_descriptor[ecb->cipher].block_length;
+ len -= cipher_descriptor[ecb->cipher].block_length;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ecb/ecb_start.c b/Sources/libtomcrypt/modes/ecb/ecb_start.c
new file mode 100644
index 00000000..d5bc28ef
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ecb/ecb_start.c
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ecb_start.c
+ ECB implementation, start chain, Tom St Denis
+*/
+
+
+#ifdef LTC_ECB_MODE
+
+/**
+ Initialize a ECB context
+ @param cipher The index of the cipher desired
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param num_rounds Number of rounds in the cipher desired (0 for default)
+ @param ecb The ECB state to initialize
+ @return CRYPT_OK if successful
+*/
+int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb)
+{
+ int err;
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ecb != NULL);
+
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+ ecb->cipher = cipher;
+ ecb->blocklen = cipher_descriptor[cipher].block_length;
+ return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/f8/f8_decrypt.c b/Sources/libtomcrypt/modes/f8/f8_decrypt.c
new file mode 100644
index 00000000..f9e3a54d
--- /dev/null
+++ b/Sources/libtomcrypt/modes/f8/f8_decrypt.c
@@ -0,0 +1,31 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f8_decrypt.c
+ F8 implementation, decrypt data, Tom St Denis
+*/
+
+#ifdef LTC_F8_MODE
+
+/**
+ F8 decrypt
+ @param ct Ciphertext
+ @param pt [out] Plaintext
+ @param len Length of ciphertext (octets)
+ @param f8 F8 state
+ @return CRYPT_OK if successful
+*/
+int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8)
+{
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(f8 != NULL);
+ return f8_encrypt(ct, pt, len, f8);
+}
+
+
+#endif
+
+
diff --git a/Sources/libtomcrypt/modes/f8/f8_done.c b/Sources/libtomcrypt/modes/f8/f8_done.c
new file mode 100644
index 00000000..7d25b049
--- /dev/null
+++ b/Sources/libtomcrypt/modes/f8/f8_done.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f8_done.c
+ F8 implementation, finish chain, Tom St Denis
+*/
+
+#ifdef LTC_F8_MODE
+
+/** Terminate the chain
+ @param f8 The F8 chain to terminate
+ @return CRYPT_OK on success
+*/
+int f8_done(symmetric_F8 *f8)
+{
+ int err;
+ LTC_ARGCHK(f8 != NULL);
+
+ if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ cipher_descriptor[f8->cipher].done(&f8->key);
+ return CRYPT_OK;
+}
+
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/f8/f8_encrypt.c b/Sources/libtomcrypt/modes/f8/f8_encrypt.c
new file mode 100644
index 00000000..671c9041
--- /dev/null
+++ b/Sources/libtomcrypt/modes/f8/f8_encrypt.c
@@ -0,0 +1,91 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f8_encrypt.c
+ F8 implementation, encrypt data, Tom St Denis
+*/
+
+#ifdef LTC_F8_MODE
+
+/**
+ F8 encrypt
+ @param pt Plaintext
+ @param ct [out] Ciphertext
+ @param len Length of plaintext (octets)
+ @param f8 F8 state
+ @return CRYPT_OK if successful
+*/
+int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8)
+{
+ int err, x;
+ unsigned char buf[MAXBLOCKSIZE];
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(f8 != NULL);
+ if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* is blocklen/padlen valid? */
+ if (f8->blocklen < 0 || f8->blocklen > (int)sizeof(f8->IV) ||
+ f8->padlen < 0 || f8->padlen > (int)sizeof(f8->IV)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ zeromem(buf, sizeof(buf));
+
+ /* make sure the pad is empty */
+ if (f8->padlen == f8->blocklen) {
+ /* xor of IV, MIV and blockcnt == what goes into cipher */
+ STORE32H(f8->blockcnt, (buf+(f8->blocklen-4)));
+ ++(f8->blockcnt);
+ for (x = 0; x < f8->blocklen; x++) {
+ f8->IV[x] ^= f8->MIV[x] ^ buf[x];
+ }
+ if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) {
+ return err;
+ }
+ f8->padlen = 0;
+ }
+
+#ifdef LTC_FAST
+ if (f8->padlen == 0) {
+ while (len >= (unsigned long)f8->blocklen) {
+ STORE32H(f8->blockcnt, (buf+(f8->blocklen-4)));
+ ++(f8->blockcnt);
+ for (x = 0; x < f8->blocklen; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&ct[x])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x]));
+ *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&f8->MIV[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&buf[x]));
+ }
+ if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) {
+ return err;
+ }
+ len -= x;
+ pt += x;
+ ct += x;
+ }
+ }
+#endif
+
+ while (len > 0) {
+ if (f8->padlen == f8->blocklen) {
+ /* xor of IV, MIV and blockcnt == what goes into cipher */
+ STORE32H(f8->blockcnt, (buf+(f8->blocklen-4)));
+ ++(f8->blockcnt);
+ for (x = 0; x < f8->blocklen; x++) {
+ f8->IV[x] ^= f8->MIV[x] ^ buf[x];
+ }
+ if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) {
+ return err;
+ }
+ f8->padlen = 0;
+ }
+ *ct++ = *pt++ ^ f8->IV[f8->padlen++];
+ --len;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/f8/f8_getiv.c b/Sources/libtomcrypt/modes/f8/f8_getiv.c
new file mode 100644
index 00000000..1a4e53f1
--- /dev/null
+++ b/Sources/libtomcrypt/modes/f8/f8_getiv.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ofb_getiv.c
+ F8 implementation, get IV, Tom St Denis
+*/
+
+#ifdef LTC_F8_MODE
+
+/**
+ Get the current initialization vector
+ @param IV [out] The destination of the initialization vector
+ @param len [in/out] The max size and resulting size of the initialization vector
+ @param f8 The F8 state
+ @return CRYPT_OK if successful
+*/
+int f8_getiv(unsigned char *IV, unsigned long *len, const symmetric_F8 *f8)
+{
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(len != NULL);
+ LTC_ARGCHK(f8 != NULL);
+ if ((unsigned long)f8->blocklen > *len) {
+ *len = f8->blocklen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ XMEMCPY(IV, f8->IV, f8->blocklen);
+ *len = f8->blocklen;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/f8/f8_setiv.c b/Sources/libtomcrypt/modes/f8/f8_setiv.c
new file mode 100644
index 00000000..51a80abc
--- /dev/null
+++ b/Sources/libtomcrypt/modes/f8/f8_setiv.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f8_setiv.c
+ F8 implementation, set IV, Tom St Denis
+*/
+
+#ifdef LTC_F8_MODE
+
+/**
+ Set an initialization vector
+ @param IV The initialization vector
+ @param len The length of the vector (in octets)
+ @param f8 The F8 state
+ @return CRYPT_OK if successful
+*/
+int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8)
+{
+ int err;
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(f8 != NULL);
+
+ if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len != (unsigned long)f8->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* force next block */
+ f8->padlen = 0;
+ return cipher_descriptor[f8->cipher].ecb_encrypt(IV, f8->IV, &f8->key);
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/modes/f8/f8_start.c b/Sources/libtomcrypt/modes/f8/f8_start.c
new file mode 100644
index 00000000..58f126f6
--- /dev/null
+++ b/Sources/libtomcrypt/modes/f8/f8_start.c
@@ -0,0 +1,86 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f8_start.c
+ F8 implementation, start chain, Tom St Denis
+*/
+
+
+#ifdef LTC_F8_MODE
+
+/**
+ Initialize an F8 context
+ @param cipher The index of the cipher desired
+ @param IV The initialization vector
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param salt_key The salting key for the IV
+ @param skeylen The length of the salting key (octets)
+ @param num_rounds Number of rounds in the cipher desired (0 for default)
+ @param f8 The F8 state to initialize
+ @return CRYPT_OK if successful
+*/
+int f8_start( int cipher, const unsigned char *IV,
+ const unsigned char *key, int keylen,
+ const unsigned char *salt_key, int skeylen,
+ int num_rounds, symmetric_F8 *f8)
+{
+ int x, err;
+ unsigned char tkey[MAXBLOCKSIZE];
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(salt_key != NULL);
+ LTC_ARGCHK(f8 != NULL);
+
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+#ifdef LTC_FAST
+ if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ /* copy details */
+ f8->blockcnt = 0;
+ f8->cipher = cipher;
+ f8->blocklen = cipher_descriptor[cipher].block_length;
+ f8->padlen = f8->blocklen;
+
+ /* now get key ^ salt_key [extend salt_ket with 0x55 as required to match length] */
+ zeromem(tkey, sizeof(tkey));
+ for (x = 0; x < keylen && x < (int)sizeof(tkey); x++) {
+ tkey[x] = key[x];
+ }
+ for (x = 0; x < skeylen && x < (int)sizeof(tkey); x++) {
+ tkey[x] ^= salt_key[x];
+ }
+ for (; x < keylen && x < (int)sizeof(tkey); x++) {
+ tkey[x] ^= 0x55;
+ }
+
+ /* now encrypt with tkey[0..keylen-1] the IV and use that as the IV */
+ if ((err = cipher_descriptor[cipher].setup(tkey, keylen, num_rounds, &f8->key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* encrypt IV */
+ if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(IV, f8->MIV, &f8->key)) != CRYPT_OK) {
+ cipher_descriptor[f8->cipher].done(&f8->key);
+ return err;
+ }
+ zeromem(tkey, sizeof(tkey));
+ zeromem(f8->IV, sizeof(f8->IV));
+
+ /* terminate this cipher */
+ cipher_descriptor[f8->cipher].done(&f8->key);
+
+ /* init the cipher */
+ return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &f8->key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/f8/f8_test_mode.c b/Sources/libtomcrypt/modes/f8/f8_test_mode.c
new file mode 100644
index 00000000..7b251755
--- /dev/null
+++ b/Sources/libtomcrypt/modes/f8/f8_test_mode.c
@@ -0,0 +1,64 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file f8_test_mode.c
+ F8 implementation, test, Tom St Denis
+*/
+
+
+#ifdef LTC_F8_MODE
+
+int f8_test_mode(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const unsigned char key[16] = { 0x23, 0x48, 0x29, 0x00, 0x84, 0x67, 0xbe, 0x18,
+ 0x6c, 0x3d, 0xe1, 0x4a, 0xae, 0x72, 0xd6, 0x2c };
+ static const unsigned char salt[4] = { 0x32, 0xf2, 0x87, 0x0d };
+ static const unsigned char IV[16] = { 0x00, 0x6e, 0x5c, 0xba, 0x50, 0x68, 0x1d, 0xe5,
+ 0x5c, 0x62, 0x15, 0x99, 0xd4, 0x62, 0x56, 0x4a };
+ static const unsigned char pt[39] = { 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x72, 0x61,
+ 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x65, 0x78, 0x74, 0x20, 0x62, 0x65, 0x73,
+ 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67 };
+ static const unsigned char ct[39] = { 0x01, 0x9c, 0xe7, 0xa2, 0x6e, 0x78, 0x54, 0x01,
+ 0x4a, 0x63, 0x66, 0xaa, 0x95, 0xd4, 0xee, 0xfd,
+ 0x1a, 0xd4, 0x17, 0x2a, 0x14, 0xf9, 0xfa, 0xf4,
+ 0x55, 0xb7, 0xf1, 0xd4, 0xb6, 0x2b, 0xd0, 0x8f,
+ 0x56, 0x2c, 0x0e, 0xef, 0x7c, 0x48, 0x02 };
+ unsigned char buf[39];
+ symmetric_F8 f8;
+ int err, idx;
+
+ idx = find_cipher("aes");
+ if (idx == -1) {
+ idx = find_cipher("rijndael");
+ if (idx == -1) return CRYPT_NOP;
+ }
+
+ /* initialize the context */
+ if ((err = f8_start(idx, IV, key, sizeof(key), salt, sizeof(salt), 0, &f8)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* encrypt block */
+ if ((err = f8_encrypt(pt, buf, sizeof(pt), &f8)) != CRYPT_OK) {
+ f8_done(&f8);
+ return err;
+ }
+ f8_done(&f8);
+
+ /* compare */
+ if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "f8", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/lrw/lrw_decrypt.c b/Sources/libtomcrypt/modes/lrw/lrw_decrypt.c
new file mode 100644
index 00000000..ba3b38a4
--- /dev/null
+++ b/Sources/libtomcrypt/modes/lrw/lrw_decrypt.c
@@ -0,0 +1,39 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file lrw_decrypt.c
+ LRW_MODE implementation, Decrypt blocks, Tom St Denis
+*/
+
+#ifdef LTC_LRW_MODE
+
+/**
+ LRW decrypt blocks
+ @param ct The ciphertext
+ @param pt [out] The plaintext
+ @param len The length in octets, must be a multiple of 16
+ @param lrw The LRW state
+*/
+int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw)
+{
+ int err;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(lrw != NULL);
+
+ if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (cipher_descriptor[lrw->cipher].accel_lrw_decrypt != NULL) {
+ return cipher_descriptor[lrw->cipher].accel_lrw_decrypt(ct, pt, len, lrw->IV, lrw->tweak, &lrw->key);
+ }
+
+ return lrw_process(ct, pt, len, LRW_DECRYPT, lrw);
+}
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/lrw/lrw_done.c b/Sources/libtomcrypt/modes/lrw/lrw_done.c
new file mode 100644
index 00000000..dc649a01
--- /dev/null
+++ b/Sources/libtomcrypt/modes/lrw/lrw_done.c
@@ -0,0 +1,31 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file lrw_done.c
+ LRW_MODE implementation, Free resources, Tom St Denis
+*/
+
+#ifdef LTC_LRW_MODE
+
+/**
+ Terminate a LRW state
+ @param lrw The state to terminate
+ @return CRYPT_OK if successful
+*/
+int lrw_done(symmetric_LRW *lrw)
+{
+ int err;
+
+ LTC_ARGCHK(lrw != NULL);
+
+ if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ cipher_descriptor[lrw->cipher].done(&lrw->key);
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/lrw/lrw_encrypt.c b/Sources/libtomcrypt/modes/lrw/lrw_encrypt.c
new file mode 100644
index 00000000..fde442b1
--- /dev/null
+++ b/Sources/libtomcrypt/modes/lrw/lrw_encrypt.c
@@ -0,0 +1,39 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file lrw_encrypt.c
+ LRW_MODE implementation, Encrypt blocks, Tom St Denis
+*/
+
+#ifdef LTC_LRW_MODE
+
+/**
+ LRW encrypt blocks
+ @param pt The plaintext
+ @param ct [out] The ciphertext
+ @param len The length in octets, must be a multiple of 16
+ @param lrw The LRW state
+*/
+int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw)
+{
+ int err;
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(lrw != NULL);
+
+ if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (cipher_descriptor[lrw->cipher].accel_lrw_encrypt != NULL) {
+ return cipher_descriptor[lrw->cipher].accel_lrw_encrypt(pt, ct, len, lrw->IV, lrw->tweak, &lrw->key);
+ }
+
+ return lrw_process(pt, ct, len, LRW_ENCRYPT, lrw);
+}
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/lrw/lrw_getiv.c b/Sources/libtomcrypt/modes/lrw/lrw_getiv.c
new file mode 100644
index 00000000..9da1aabc
--- /dev/null
+++ b/Sources/libtomcrypt/modes/lrw/lrw_getiv.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file lrw_getiv.c
+ LRW_MODE implementation, Retrieve the current IV, Tom St Denis
+*/
+
+#ifdef LTC_LRW_MODE
+
+/**
+ Get the IV for LRW
+ @param IV [out] The IV, must be 16 octets
+ @param len Length ... must be at least 16 :-)
+ @param lrw The LRW state to read
+ @return CRYPT_OK if successful
+*/
+int lrw_getiv(unsigned char *IV, unsigned long *len, const symmetric_LRW *lrw)
+{
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(len != NULL);
+ LTC_ARGCHK(lrw != NULL);
+ if (*len < 16) {
+ *len = 16;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ XMEMCPY(IV, lrw->IV, 16);
+ *len = 16;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/lrw/lrw_process.c b/Sources/libtomcrypt/modes/lrw/lrw_process.c
new file mode 100644
index 00000000..d9a3edd5
--- /dev/null
+++ b/Sources/libtomcrypt/modes/lrw/lrw_process.c
@@ -0,0 +1,109 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file lrw_process.c
+ LRW_MODE implementation, Encrypt/decrypt blocks, Tom St Denis
+*/
+
+#ifdef LTC_LRW_MODE
+
+/**
+ Process blocks with LRW, since decrypt/encrypt are largely the same they share this code.
+ @param pt The "input" data
+ @param ct [out] The "output" data
+ @param len The length of the input, must be a multiple of 128-bits (16 octets)
+ @param mode LRW_ENCRYPT or LRW_DECRYPT
+ @param lrw The LRW state
+ @return CRYPT_OK if successful
+*/
+int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw)
+{
+ unsigned char prod[16];
+ int x, err;
+#ifdef LTC_LRW_TABLES
+ int y;
+#endif
+
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(lrw != NULL);
+
+ if (len & 15) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ while (len) {
+ /* copy pad */
+ XMEMCPY(prod, lrw->pad, 16);
+
+ /* increment IV */
+ for (x = 15; x >= 0; x--) {
+ lrw->IV[x] = (lrw->IV[x] + 1) & 255;
+ if (lrw->IV[x]) {
+ break;
+ }
+ }
+
+ /* update pad */
+#ifdef LTC_LRW_TABLES
+ /* for each byte changed we undo it's affect on the pad then add the new product */
+ for (; x < 16; x++) {
+#ifdef LTC_FAST
+ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(lrw->pad + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][lrw->IV[x]][y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][(lrw->IV[x]-1)&255][y]));
+ }
+#else
+ for (y = 0; y < 16; y++) {
+ lrw->pad[y] ^= lrw->PC[x][lrw->IV[x]][y] ^ lrw->PC[x][(lrw->IV[x]-1)&255][y];
+ }
+#endif
+ }
+#else
+ gcm_gf_mult(lrw->tweak, lrw->IV, lrw->pad);
+#endif
+
+ /* xor prod */
+#ifdef LTC_FAST
+ for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(pt + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(prod + x));
+ }
+#else
+ for (x = 0; x < 16; x++) {
+ ct[x] = pt[x] ^ prod[x];
+ }
+#endif
+
+ /* send through cipher */
+ if (mode == LRW_ENCRYPT) {
+ if ((err = cipher_descriptor[lrw->cipher].ecb_encrypt(ct, ct, &lrw->key)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ if ((err = cipher_descriptor[lrw->cipher].ecb_decrypt(ct, ct, &lrw->key)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* xor prod */
+#ifdef LTC_FAST
+ for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(ct + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(prod + x));
+ }
+#else
+ for (x = 0; x < 16; x++) {
+ ct[x] = ct[x] ^ prod[x];
+ }
+#endif
+
+ /* move to next */
+ pt += 16;
+ ct += 16;
+ len -= 16;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/lrw/lrw_setiv.c b/Sources/libtomcrypt/modes/lrw/lrw_setiv.c
new file mode 100644
index 00000000..efb44125
--- /dev/null
+++ b/Sources/libtomcrypt/modes/lrw/lrw_setiv.c
@@ -0,0 +1,68 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file lrw_setiv.c
+ LRW_MODE implementation, Set the current IV, Tom St Denis
+*/
+
+#ifdef LTC_LRW_MODE
+
+/**
+ Set the IV for LRW
+ @param IV The IV, must be 16 octets
+ @param len Length ... must be 16 :-)
+ @param lrw The LRW state to update
+ @return CRYPT_OK if successful
+*/
+int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw)
+{
+ int err;
+#ifdef LTC_LRW_TABLES
+ unsigned char T[16];
+ int x, y;
+#endif
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(lrw != NULL);
+
+ if (len != 16) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* copy the IV */
+ XMEMCPY(lrw->IV, IV, 16);
+
+ /* check if we have to actually do work */
+ if (cipher_descriptor[lrw->cipher].accel_lrw_encrypt != NULL && cipher_descriptor[lrw->cipher].accel_lrw_decrypt != NULL) {
+ /* we have accelerators, let's bail since they don't use lrw->pad anyways */
+ return CRYPT_OK;
+ }
+
+#ifdef LTC_LRW_TABLES
+ XMEMCPY(T, &lrw->PC[0][IV[0]][0], 16);
+ for (x = 1; x < 16; x++) {
+#ifdef LTC_FAST
+ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][IV[x]][y]));
+ }
+#else
+ for (y = 0; y < 16; y++) {
+ T[y] ^= lrw->PC[x][IV[x]][y];
+ }
+#endif
+ }
+ XMEMCPY(lrw->pad, T, 16);
+#else
+ gcm_gf_mult(lrw->tweak, IV, lrw->pad);
+#endif
+
+ return CRYPT_OK;
+}
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/lrw/lrw_start.c b/Sources/libtomcrypt/modes/lrw/lrw_start.c
new file mode 100644
index 00000000..20956859
--- /dev/null
+++ b/Sources/libtomcrypt/modes/lrw/lrw_start.c
@@ -0,0 +1,92 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file lrw_start.c
+ LRW_MODE implementation, start mode, Tom St Denis
+*/
+
+#ifdef LTC_LRW_MODE
+
+/**
+ Initialize the LRW context
+ @param cipher The cipher desired, must be a 128-bit block cipher
+ @param IV The index value, must be 128-bits
+ @param key The cipher key
+ @param keylen The length of the cipher key in octets
+ @param tweak The tweak value (second key), must be 128-bits
+ @param num_rounds The number of rounds for the cipher (0 == default)
+ @param lrw [out] The LRW state
+ @return CRYPT_OK on success.
+*/
+int lrw_start( int cipher,
+ const unsigned char *IV,
+ const unsigned char *key, int keylen,
+ const unsigned char *tweak,
+ int num_rounds,
+ symmetric_LRW *lrw)
+{
+ int err;
+#ifdef LTC_LRW_TABLES
+ unsigned char B[16];
+ int x, y, z, t;
+#endif
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(tweak != NULL);
+ LTC_ARGCHK(lrw != NULL);
+
+#ifdef LTC_FAST
+ if (16 % sizeof(LTC_FAST_TYPE)) {
+ return CRYPT_INVALID_ARG;
+ }
+#endif
+
+ /* is cipher valid? */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+ if (cipher_descriptor[cipher].block_length != 16) {
+ return CRYPT_INVALID_CIPHER;
+ }
+
+ /* schedule key */
+ if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &lrw->key)) != CRYPT_OK) {
+ return err;
+ }
+ lrw->cipher = cipher;
+
+ /* copy the IV and tweak */
+ XMEMCPY(lrw->tweak, tweak, 16);
+
+#ifdef LTC_LRW_TABLES
+ /* setup tables */
+ /* generate the first table as it has no shifting (from which we make the other tables) */
+ zeromem(B, 16);
+ for (y = 0; y < 256; y++) {
+ B[0] = y;
+ gcm_gf_mult(tweak, B, &lrw->PC[0][y][0]);
+ }
+
+ /* now generate the rest of the tables based the previous table */
+ for (x = 1; x < 16; x++) {
+ for (y = 0; y < 256; y++) {
+ /* now shift it right by 8 bits */
+ t = lrw->PC[x-1][y][15];
+ for (z = 15; z > 0; z--) {
+ lrw->PC[x][y][z] = lrw->PC[x-1][y][z-1];
+ }
+ lrw->PC[x][y][0] = gcm_shift_table[t<<1];
+ lrw->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1];
+ }
+ }
+#endif
+
+ /* generate first pad */
+ return lrw_setiv(IV, 16, lrw);
+}
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/lrw/lrw_test.c b/Sources/libtomcrypt/modes/lrw/lrw_test.c
new file mode 100644
index 00000000..3d9015ba
--- /dev/null
+++ b/Sources/libtomcrypt/modes/lrw/lrw_test.c
@@ -0,0 +1,124 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file lrw_test.c
+ LRW_MODE implementation, test LRW, Tom St Denis
+*/
+
+#ifdef LTC_LRW_MODE
+
+/**
+ Test LRW against specs
+ @return CRYPT_OK if goodly
+*/
+int lrw_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ unsigned char key[16], tweak[16], IV[16], P[16], expected_tweak[16], C[16];
+ } tests[] = {
+
+{
+{ 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d, 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85 },
+{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
+{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
+{ 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f, 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 }
+},
+
+{
+{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 },
+{ 0x35, 0x23, 0xc2, 0xde, 0xc5, 0x69, 0x4f, 0xa8, 0x72, 0xa9, 0xac, 0xa7, 0x0b, 0x2b, 0xee, 0xbc },
+{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e },
+{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
+},
+
+{
+{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 },
+{ 0x67, 0x53, 0xc9, 0x0c, 0xb7, 0xd8, 0xcd, 0xe5, 0x06, 0xa0, 0x47, 0x78, 0x1a, 0xad, 0x85, 0x11 },
+{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e },
+{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
+},
+
+{
+
+{ 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50, 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47 },
+{ 0x4e, 0xb5, 0x5d, 0x31, 0x05, 0x97, 0x3a, 0x3f, 0x5e, 0x23, 0xda, 0xfb, 0x5a, 0x45, 0xd6, 0xc0 },
+{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+{ 0x18, 0xc9, 0x1f, 0x6d, 0x60, 0x1a, 0x1a, 0x37, 0x5d, 0x0b, 0x0e, 0xf7, 0x3a, 0xd5, 0x74, 0xc4 },
+{ 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82, 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },
+
+}
+};
+
+ int idx, err, x;
+ symmetric_LRW lrw;
+ unsigned char buf[2][16];
+
+ idx = find_cipher("aes");
+ if (idx == -1) {
+ idx = find_cipher("rijndael");
+ if (idx == -1) {
+ return CRYPT_NOP;
+ }
+ }
+
+ for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+ /* schedule it */
+ if ((err = lrw_start(idx, tests[x].IV, tests[x].key, 16, tests[x].tweak, 0, &lrw)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* check pad against expected tweak */
+ if (compare_testvector(tests[x].expected_tweak, 16, lrw.pad, 16, "LRW Tweak", x)) {
+ lrw_done(&lrw);
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* process block */
+ if ((err = lrw_encrypt(tests[x].P, buf[0], 16, &lrw)) != CRYPT_OK) {
+ lrw_done(&lrw);
+ return err;
+ }
+
+ if (compare_testvector(buf[0], 16, tests[x].C, 16, "LRW Encrypt", x)) {
+ lrw_done(&lrw);
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* process block */
+ if ((err = lrw_setiv(tests[x].IV, 16, &lrw)) != CRYPT_OK) {
+ lrw_done(&lrw);
+ return err;
+ }
+
+ if ((err = lrw_decrypt(buf[0], buf[1], 16, &lrw)) != CRYPT_OK) {
+ lrw_done(&lrw);
+ return err;
+ }
+
+ if (compare_testvector(buf[1], 16, tests[x].P, 16, "LRW Decrypt", x)) {
+ lrw_done(&lrw);
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ if ((err = lrw_done(&lrw)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
+
diff --git a/Sources/libtomcrypt/modes/ofb/ofb_decrypt.c b/Sources/libtomcrypt/modes/ofb/ofb_decrypt.c
new file mode 100644
index 00000000..cebcd7b1
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ofb/ofb_decrypt.c
@@ -0,0 +1,31 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ofb_decrypt.c
+ OFB implementation, decrypt data, Tom St Denis
+*/
+
+#ifdef LTC_OFB_MODE
+
+/**
+ OFB decrypt
+ @param ct Ciphertext
+ @param pt [out] Plaintext
+ @param len Length of ciphertext (octets)
+ @param ofb OFB state
+ @return CRYPT_OK if successful
+*/
+int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb)
+{
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(ofb != NULL);
+ return ofb_encrypt(ct, pt, len, ofb);
+}
+
+
+#endif
+
+
diff --git a/Sources/libtomcrypt/modes/ofb/ofb_done.c b/Sources/libtomcrypt/modes/ofb/ofb_done.c
new file mode 100644
index 00000000..c4a01840
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ofb/ofb_done.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ofb_done.c
+ OFB implementation, finish chain, Tom St Denis
+*/
+
+#ifdef LTC_OFB_MODE
+
+/** Terminate the chain
+ @param ofb The OFB chain to terminate
+ @return CRYPT_OK on success
+*/
+int ofb_done(symmetric_OFB *ofb)
+{
+ int err;
+ LTC_ARGCHK(ofb != NULL);
+
+ if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+ cipher_descriptor[ofb->cipher].done(&ofb->key);
+ return CRYPT_OK;
+}
+
+
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ofb/ofb_encrypt.c b/Sources/libtomcrypt/modes/ofb/ofb_encrypt.c
new file mode 100644
index 00000000..63f1e18e
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ofb/ofb_encrypt.c
@@ -0,0 +1,48 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ofb_encrypt.c
+ OFB implementation, encrypt data, Tom St Denis
+*/
+
+#ifdef LTC_OFB_MODE
+
+/**
+ OFB encrypt
+ @param pt Plaintext
+ @param ct [out] Ciphertext
+ @param len Length of plaintext (octets)
+ @param ofb OFB state
+ @return CRYPT_OK if successful
+*/
+int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb)
+{
+ int err;
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(ofb != NULL);
+ if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* is blocklen/padlen valid? */
+ if (ofb->blocklen < 0 || ofb->blocklen > (int)sizeof(ofb->IV) ||
+ ofb->padlen < 0 || ofb->padlen > (int)sizeof(ofb->IV)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ while (len-- > 0) {
+ if (ofb->padlen == ofb->blocklen) {
+ if ((err = cipher_descriptor[ofb->cipher].ecb_encrypt(ofb->IV, ofb->IV, &ofb->key)) != CRYPT_OK) {
+ return err;
+ }
+ ofb->padlen = 0;
+ }
+ *ct++ = *pt++ ^ ofb->IV[(ofb->padlen)++];
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ofb/ofb_getiv.c b/Sources/libtomcrypt/modes/ofb/ofb_getiv.c
new file mode 100644
index 00000000..0a799f0d
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ofb/ofb_getiv.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ofb_getiv.c
+ OFB implementation, get IV, Tom St Denis
+*/
+
+#ifdef LTC_OFB_MODE
+
+/**
+ Get the current initialization vector
+ @param IV [out] The destination of the initialization vector
+ @param len [in/out] The max size and resulting size of the initialization vector
+ @param ofb The OFB state
+ @return CRYPT_OK if successful
+*/
+int ofb_getiv(unsigned char *IV, unsigned long *len, const symmetric_OFB *ofb)
+{
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(len != NULL);
+ LTC_ARGCHK(ofb != NULL);
+ if ((unsigned long)ofb->blocklen > *len) {
+ *len = ofb->blocklen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ XMEMCPY(IV, ofb->IV, ofb->blocklen);
+ *len = ofb->blocklen;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/ofb/ofb_setiv.c b/Sources/libtomcrypt/modes/ofb/ofb_setiv.c
new file mode 100644
index 00000000..1fdec7fb
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ofb/ofb_setiv.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ofb_setiv.c
+ OFB implementation, set IV, Tom St Denis
+*/
+
+#ifdef LTC_OFB_MODE
+
+/**
+ Set an initialization vector
+ @param IV The initialization vector
+ @param len The length of the vector (in octets)
+ @param ofb The OFB state
+ @return CRYPT_OK if successful
+*/
+int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb)
+{
+ int err;
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(ofb != NULL);
+
+ if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len != (unsigned long)ofb->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* force next block */
+ ofb->padlen = 0;
+ return cipher_descriptor[ofb->cipher].ecb_encrypt(IV, ofb->IV, &ofb->key);
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/modes/ofb/ofb_start.c b/Sources/libtomcrypt/modes/ofb/ofb_start.c
new file mode 100644
index 00000000..179fe575
--- /dev/null
+++ b/Sources/libtomcrypt/modes/ofb/ofb_start.c
@@ -0,0 +1,48 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ofb_start.c
+ OFB implementation, start chain, Tom St Denis
+*/
+
+
+#ifdef LTC_OFB_MODE
+
+/**
+ Initialize a OFB context
+ @param cipher The index of the cipher desired
+ @param IV The initialization vector
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param num_rounds Number of rounds in the cipher desired (0 for default)
+ @param ofb The OFB state to initialize
+ @return CRYPT_OK if successful
+*/
+int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_OFB *ofb)
+{
+ int x, err;
+
+ LTC_ARGCHK(IV != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ofb != NULL);
+
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* copy details */
+ ofb->cipher = cipher;
+ ofb->blocklen = cipher_descriptor[cipher].block_length;
+ for (x = 0; x < ofb->blocklen; x++) {
+ ofb->IV[x] = IV[x];
+ }
+
+ /* init the cipher */
+ ofb->padlen = ofb->blocklen;
+ return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ofb->key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/xts/xts_decrypt.c b/Sources/libtomcrypt/modes/xts/xts_decrypt.c
new file mode 100644
index 00000000..f1747d53
--- /dev/null
+++ b/Sources/libtomcrypt/modes/xts/xts_decrypt.c
@@ -0,0 +1,146 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects
+ */
+
+#ifdef LTC_XTS_MODE
+
+static int s_tweak_uncrypt(const unsigned char *C, unsigned char *P, unsigned char *T, const symmetric_xts *xts)
+{
+ unsigned long x;
+ int err;
+
+ /* tweak encrypt block i */
+#ifdef LTC_FAST
+ for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&P[x])) = *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&T[x]));
+ }
+#else
+ for (x = 0; x < 16; x++) {
+ P[x] = C[x] ^ T[x];
+ }
+#endif
+
+ err = cipher_descriptor[xts->cipher].ecb_decrypt(P, P, &xts->key1);
+
+#ifdef LTC_FAST
+ for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&T[x]));
+ }
+#else
+ for (x = 0; x < 16; x++) {
+ P[x] = P[x] ^ T[x];
+ }
+#endif
+
+ /* LFSR the tweak */
+ xts_mult_x(T);
+
+ return err;
+}
+
+/** XTS Decryption
+ @param ct [in] Ciphertext
+ @param ptlen Length of plaintext (and ciphertext)
+ @param pt [out] Plaintext
+ @param tweak [in] The 128--bit encryption tweak (e.g. sector number)
+ @param xts The XTS structure
+ Returns CRYPT_OK upon success
+ */
+int xts_decrypt(const unsigned char *ct, unsigned long ptlen, unsigned char *pt, unsigned char *tweak,
+ const symmetric_xts *xts)
+{
+ unsigned char PP[16], CC[16], T[16];
+ unsigned long i, m, mo, lim;
+ int err;
+
+ /* check inputs */
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tweak != NULL);
+ LTC_ARGCHK(xts != NULL);
+
+ /* check if valid */
+ if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get number of blocks */
+ m = ptlen >> 4;
+ mo = ptlen & 15;
+
+ /* must have at least one full block */
+ if (m == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (mo == 0) {
+ lim = m;
+ } else {
+ lim = m - 1;
+ }
+
+ if (cipher_descriptor[xts->cipher].accel_xts_decrypt && lim > 0) {
+
+ /* use accelerated decryption for whole blocks */
+ if ((err = cipher_descriptor[xts->cipher].accel_xts_decrypt(ct, pt, lim, tweak, &xts->key1, &xts->key2)) !=
+ CRYPT_OK) {
+ return err;
+ }
+ ct += lim * 16;
+ pt += lim * 16;
+
+ /* tweak is encrypted on output */
+ XMEMCPY(T, tweak, sizeof(T));
+ } else {
+ /* encrypt the tweak */
+ if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) {
+ return err;
+ }
+
+ for (i = 0; i < lim; i++) {
+ if ((err = s_tweak_uncrypt(ct, pt, T, xts)) != CRYPT_OK) {
+ return err;
+ }
+ ct += 16;
+ pt += 16;
+ }
+ }
+
+ /* if ptlen not divide 16 then */
+ if (mo > 0) {
+ XMEMCPY(CC, T, 16);
+ xts_mult_x(CC);
+
+ /* PP = tweak decrypt block m-1 */
+ if ((err = s_tweak_uncrypt(ct, PP, CC, xts)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* Pm = first ptlen % 16 bytes of PP */
+ for (i = 0; i < mo; i++) {
+ CC[i] = ct[16 + i];
+ pt[16 + i] = PP[i];
+ }
+ for (; i < 16; i++) {
+ CC[i] = PP[i];
+ }
+
+ /* Pm-1 = Tweak uncrypt CC */
+ if ((err = s_tweak_uncrypt(CC, pt, T, xts)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* Decrypt the tweak back */
+ if ((err = cipher_descriptor[xts->cipher].ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) {
+ return err;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/xts/xts_done.c b/Sources/libtomcrypt/modes/xts/xts_done.c
new file mode 100644
index 00000000..4f775217
--- /dev/null
+++ b/Sources/libtomcrypt/modes/xts/xts_done.c
@@ -0,0 +1,21 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects
+*/
+
+#ifdef LTC_XTS_MODE
+
+/** Terminate XTS state
+ @param xts The state to terminate
+*/
+void xts_done(symmetric_xts *xts)
+{
+ LTC_ARGCHKVD(xts != NULL);
+ cipher_descriptor[xts->cipher].done(&xts->key1);
+ cipher_descriptor[xts->cipher].done(&xts->key2);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/xts/xts_encrypt.c b/Sources/libtomcrypt/modes/xts/xts_encrypt.c
new file mode 100644
index 00000000..c269b7c7
--- /dev/null
+++ b/Sources/libtomcrypt/modes/xts/xts_encrypt.c
@@ -0,0 +1,147 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects
+ */
+
+#ifdef LTC_XTS_MODE
+
+static int s_tweak_crypt(const unsigned char *P, unsigned char *C, unsigned char *T, const symmetric_xts *xts)
+{
+ unsigned long x;
+ int err;
+
+ /* tweak encrypt block i */
+#ifdef LTC_FAST
+ for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&C[x])) = *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&T[x]));
+ }
+#else
+ for (x = 0; x < 16; x++) {
+ C[x] = P[x] ^ T[x];
+ }
+#endif
+
+ if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(C, C, &xts->key1)) != CRYPT_OK) {
+ return err;
+ }
+
+#ifdef LTC_FAST
+ for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
+ *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&T[x]));
+ }
+#else
+ for (x = 0; x < 16; x++) {
+ C[x] = C[x] ^ T[x];
+ }
+#endif
+
+ /* LFSR the tweak */
+ xts_mult_x(T);
+
+ return CRYPT_OK;
+}
+
+/** XTS Encryption
+ @param pt [in] Plaintext
+ @param ptlen Length of plaintext (and ciphertext)
+ @param ct [out] Ciphertext
+ @param tweak [in] The 128--bit encryption tweak (e.g. sector number)
+ @param xts The XTS structure
+ Returns CRYPT_OK upon success
+ */
+int xts_encrypt(const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tweak,
+ const symmetric_xts *xts)
+{
+ unsigned char PP[16], CC[16], T[16];
+ unsigned long i, m, mo, lim;
+ int err;
+
+ /* check inputs */
+ LTC_ARGCHK(pt != NULL);
+ LTC_ARGCHK(ct != NULL);
+ LTC_ARGCHK(tweak != NULL);
+ LTC_ARGCHK(xts != NULL);
+
+ /* check if valid */
+ if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get number of blocks */
+ m = ptlen >> 4;
+ mo = ptlen & 15;
+
+ /* must have at least one full block */
+ if (m == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (mo == 0) {
+ lim = m;
+ } else {
+ lim = m - 1;
+ }
+
+ if (cipher_descriptor[xts->cipher].accel_xts_encrypt && lim > 0) {
+
+ /* use accelerated encryption for whole blocks */
+ if ((err = cipher_descriptor[xts->cipher].accel_xts_encrypt(pt, ct, lim, tweak, &xts->key1, &xts->key2)) !=
+ CRYPT_OK) {
+ return err;
+ }
+ ct += lim * 16;
+ pt += lim * 16;
+
+ /* tweak is encrypted on output */
+ XMEMCPY(T, tweak, sizeof(T));
+ } else {
+
+ /* encrypt the tweak */
+ if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) {
+ return err;
+ }
+
+ for (i = 0; i < lim; i++) {
+ if ((err = s_tweak_crypt(pt, ct, T, xts)) != CRYPT_OK) {
+ return err;
+ }
+ ct += 16;
+ pt += 16;
+ }
+ }
+
+ /* if ptlen not divide 16 then */
+ if (mo > 0) {
+ /* CC = tweak encrypt block m-1 */
+ if ((err = s_tweak_crypt(pt, CC, T, xts)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* Cm = first ptlen % 16 bytes of CC */
+ for (i = 0; i < mo; i++) {
+ PP[i] = pt[16 + i];
+ ct[16 + i] = CC[i];
+ }
+
+ for (; i < 16; i++) {
+ PP[i] = CC[i];
+ }
+
+ /* Cm-1 = Tweak encrypt PP */
+ if ((err = s_tweak_crypt(PP, ct, T, xts)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* Decrypt the tweak back */
+ if ((err = cipher_descriptor[xts->cipher].ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) {
+ return err;
+ }
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/xts/xts_init.c b/Sources/libtomcrypt/modes/xts/xts_init.c
new file mode 100644
index 00000000..cec3a329
--- /dev/null
+++ b/Sources/libtomcrypt/modes/xts/xts_init.c
@@ -0,0 +1,51 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects
+*/
+
+#ifdef LTC_XTS_MODE
+
+/** Start XTS mode
+ @param cipher The index of the cipher to use
+ @param key1 The encrypt key
+ @param key2 The tweak encrypt key
+ @param keylen The length of the keys (each) in octets
+ @param num_rounds The number of rounds for the cipher (0 == default)
+ @param xts [out] XTS structure
+ Returns CRYPT_OK upon success.
+*/
+int xts_start(int cipher, const unsigned char *key1, const unsigned char *key2, unsigned long keylen, int num_rounds,
+ symmetric_xts *xts)
+{
+ int err;
+
+ /* check inputs */
+ LTC_ARGCHK(key1 != NULL);
+ LTC_ARGCHK(key2 != NULL);
+ LTC_ARGCHK(xts != NULL);
+
+ /* check if valid */
+ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (cipher_descriptor[cipher].block_length != 16) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* schedule the two ciphers */
+ if ((err = cipher_descriptor[cipher].setup(key1, keylen, num_rounds, &xts->key1)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = cipher_descriptor[cipher].setup(key2, keylen, num_rounds, &xts->key2)) != CRYPT_OK) {
+ return err;
+ }
+ xts->cipher = cipher;
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/xts/xts_mult_x.c b/Sources/libtomcrypt/modes/xts/xts_mult_x.c
new file mode 100644
index 00000000..20947a54
--- /dev/null
+++ b/Sources/libtomcrypt/modes/xts/xts_mult_x.c
@@ -0,0 +1,29 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects
+*/
+
+#ifdef LTC_XTS_MODE
+
+/** multiply by x
+ @param I The value to multiply by x (LFSR shift)
+*/
+void xts_mult_x(unsigned char *I)
+{
+ int x;
+ unsigned char t, tt;
+
+ for (x = t = 0; x < 16; x++) {
+ tt = I[x] >> 7;
+ I[x] = ((I[x] << 1) | t) & 0xFF;
+ t = tt;
+ }
+ if (tt) {
+ I[0] ^= 0x87;
+ }
+}
+
+#endif
diff --git a/Sources/libtomcrypt/modes/xts/xts_test.c b/Sources/libtomcrypt/modes/xts/xts_test.c
new file mode 100644
index 00000000..ad927357
--- /dev/null
+++ b/Sources/libtomcrypt/modes/xts/xts_test.c
@@ -0,0 +1,296 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_XTS_MODE
+
+#ifndef LTC_NO_TEST
+static int s_xts_test_accel_xts_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long blocks,
+ unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2)
+{
+ int ret;
+ symmetric_xts xts;
+ int (*orig)(const unsigned char *, unsigned char *,
+ unsigned long , unsigned char *,
+ const symmetric_key *, const symmetric_key *);
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((xts.cipher = find_cipher("aes")) == -1) {
+ if ((xts.cipher = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+ orig = cipher_descriptor[xts.cipher].accel_xts_encrypt;
+ cipher_descriptor[xts.cipher].accel_xts_encrypt = NULL;
+
+ XMEMCPY(&xts.key1, skey1, sizeof(symmetric_key));
+ XMEMCPY(&xts.key2, skey2, sizeof(symmetric_key));
+
+ ret = xts_encrypt(pt, blocks << 4, ct, tweak, &xts);
+ cipher_descriptor[xts.cipher].accel_xts_encrypt = orig;
+
+ return ret;
+}
+
+static int s_xts_test_accel_xts_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long blocks,
+ unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2)
+{
+ int ret;
+ symmetric_xts xts;
+ int (*orig)(const unsigned char *, unsigned char *,
+ unsigned long , unsigned char *,
+ const symmetric_key *, const symmetric_key *);
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((xts.cipher = find_cipher("aes")) == -1) {
+ if ((xts.cipher = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+ orig = cipher_descriptor[xts.cipher].accel_xts_decrypt;
+ cipher_descriptor[xts.cipher].accel_xts_decrypt = NULL;
+
+ XMEMCPY(&xts.key1, skey1, sizeof(symmetric_key));
+ XMEMCPY(&xts.key2, skey2, sizeof(symmetric_key));
+
+ ret = xts_decrypt(ct, blocks << 4, pt, tweak, &xts);
+ cipher_descriptor[xts.cipher].accel_xts_decrypt = orig;
+
+ return ret;
+}
+#endif
+
+/**
+ Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects
+
+ Returns CRYPT_OK upon success.
+*/
+int xts_test(void)
+{
+#ifdef LTC_NO_TEST
+ return CRYPT_NOP;
+#else
+ static const struct
+ {
+ int keylen;
+ unsigned char key1[32];
+ unsigned char key2[32];
+ ulong64 seqnum;
+ unsigned long PTLEN;
+ unsigned char PTX[512], CTX[512];
+ } tests[] = {
+
+/* #1 32 byte key, 32 byte PTX */
+{
+ 32,
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ 0,
+ 32,
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ { 0x91,0x7c,0xf6,0x9e,0xbd,0x68,0xb2,0xec,0x9b,0x9f,0xe9,0xa3,0xea,0xdd,0xa6,0x92,0xcd,0x43,0xd2,0xf5,0x95,0x98,0xed,0x85,0x8c,0x02,0xc2,0x65,0x2f,0xbf,0x92,0x2e },
+},
+
+/* #2, 32 byte key, 32 byte PTX */
+{
+ 32,
+ { 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11 },
+ { 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22 },
+ CONST64(0x3333333333),
+ 32,
+ { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 },
+ { 0xc4,0x54,0x18,0x5e,0x6a,0x16,0x93,0x6e,0x39,0x33,0x40,0x38,0xac,0xef,0x83,0x8b,0xfb,0x18,0x6f,0xff,0x74,0x80,0xad,0xc4,0x28,0x93,0x82,0xec,0xd6,0xd3,0x94,0xf0 },
+},
+
+/* #5 from xts.7, 32 byte key, 32 byte PTX */
+{
+ 32,
+ { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 },
+ { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 },
+ CONST64(0x123456789a),
+ 32,
+ { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 },
+ { 0xb0,0x1f,0x86,0xf8,0xed,0xc1,0x86,0x37,0x06,0xfa,0x8a,0x42,0x53,0xe3,0x4f,0x28,0xaf,0x31,0x9d,0xe3,0x83,0x34,0x87,0x0f,0x4d,0xd1,0xf9,0x4c,0xbe,0x98,0x32,0xf1 },
+},
+
+/* #4, 32 byte key, 512 byte PTX */
+{
+ 32,
+ { 0x27,0x18,0x28,0x18,0x28,0x45,0x90,0x45,0x23,0x53,0x60,0x28,0x74,0x71,0x35,0x26 },
+ { 0x31,0x41,0x59,0x26,0x53,0x58,0x97,0x93,0x23,0x84,0x62,0x64,0x33,0x83,0x27,0x95 },
+ 0,
+ 512,
+ {
+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,
+0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
+0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
+0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
+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,
+0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
+0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
+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,
+0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
+0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
+0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
+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,
+0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
+0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
+ },
+ {
+0x27,0xa7,0x47,0x9b,0xef,0xa1,0xd4,0x76,0x48,0x9f,0x30,0x8c,0xd4,0xcf,0xa6,0xe2,0xa9,0x6e,0x4b,0xbe,0x32,0x08,0xff,0x25,0x28,0x7d,0xd3,0x81,0x96,0x16,0xe8,0x9c,
+0xc7,0x8c,0xf7,0xf5,0xe5,0x43,0x44,0x5f,0x83,0x33,0xd8,0xfa,0x7f,0x56,0x00,0x00,0x05,0x27,0x9f,0xa5,0xd8,0xb5,0xe4,0xad,0x40,0xe7,0x36,0xdd,0xb4,0xd3,0x54,0x12,
+0x32,0x80,0x63,0xfd,0x2a,0xab,0x53,0xe5,0xea,0x1e,0x0a,0x9f,0x33,0x25,0x00,0xa5,0xdf,0x94,0x87,0xd0,0x7a,0x5c,0x92,0xcc,0x51,0x2c,0x88,0x66,0xc7,0xe8,0x60,0xce,
+0x93,0xfd,0xf1,0x66,0xa2,0x49,0x12,0xb4,0x22,0x97,0x61,0x46,0xae,0x20,0xce,0x84,0x6b,0xb7,0xdc,0x9b,0xa9,0x4a,0x76,0x7a,0xae,0xf2,0x0c,0x0d,0x61,0xad,0x02,0x65,
+0x5e,0xa9,0x2d,0xc4,0xc4,0xe4,0x1a,0x89,0x52,0xc6,0x51,0xd3,0x31,0x74,0xbe,0x51,0xa1,0x0c,0x42,0x11,0x10,0xe6,0xd8,0x15,0x88,0xed,0xe8,0x21,0x03,0xa2,0x52,0xd8,
+0xa7,0x50,0xe8,0x76,0x8d,0xef,0xff,0xed,0x91,0x22,0x81,0x0a,0xae,0xb9,0x9f,0x91,0x72,0xaf,0x82,0xb6,0x04,0xdc,0x4b,0x8e,0x51,0xbc,0xb0,0x82,0x35,0xa6,0xf4,0x34,
+0x13,0x32,0xe4,0xca,0x60,0x48,0x2a,0x4b,0xa1,0xa0,0x3b,0x3e,0x65,0x00,0x8f,0xc5,0xda,0x76,0xb7,0x0b,0xf1,0x69,0x0d,0xb4,0xea,0xe2,0x9c,0x5f,0x1b,0xad,0xd0,0x3c,
+0x5c,0xcf,0x2a,0x55,0xd7,0x05,0xdd,0xcd,0x86,0xd4,0x49,0x51,0x1c,0xeb,0x7e,0xc3,0x0b,0xf1,0x2b,0x1f,0xa3,0x5b,0x91,0x3f,0x9f,0x74,0x7a,0x8a,0xfd,0x1b,0x13,0x0e,
+0x94,0xbf,0xf9,0x4e,0xff,0xd0,0x1a,0x91,0x73,0x5c,0xa1,0x72,0x6a,0xcd,0x0b,0x19,0x7c,0x4e,0x5b,0x03,0x39,0x36,0x97,0xe1,0x26,0x82,0x6f,0xb6,0xbb,0xde,0x8e,0xcc,
+0x1e,0x08,0x29,0x85,0x16,0xe2,0xc9,0xed,0x03,0xff,0x3c,0x1b,0x78,0x60,0xf6,0xde,0x76,0xd4,0xce,0xcd,0x94,0xc8,0x11,0x98,0x55,0xef,0x52,0x97,0xca,0x67,0xe9,0xf3,
+0xe7,0xff,0x72,0xb1,0xe9,0x97,0x85,0xca,0x0a,0x7e,0x77,0x20,0xc5,0xb3,0x6d,0xc6,0xd7,0x2c,0xac,0x95,0x74,0xc8,0xcb,0xbc,0x2f,0x80,0x1e,0x23,0xe5,0x6f,0xd3,0x44,
+0xb0,0x7f,0x22,0x15,0x4b,0xeb,0xa0,0xf0,0x8c,0xe8,0x89,0x1e,0x64,0x3e,0xd9,0x95,0xc9,0x4d,0x9a,0x69,0xc9,0xf1,0xb5,0xf4,0x99,0x02,0x7a,0x78,0x57,0x2a,0xee,0xbd,
+0x74,0xd2,0x0c,0xc3,0x98,0x81,0xc2,0x13,0xee,0x77,0x0b,0x10,0x10,0xe4,0xbe,0xa7,0x18,0x84,0x69,0x77,0xae,0x11,0x9f,0x7a,0x02,0x3a,0xb5,0x8c,0xca,0x0a,0xd7,0x52,
+0xaf,0xe6,0x56,0xbb,0x3c,0x17,0x25,0x6a,0x9f,0x6e,0x9b,0xf1,0x9f,0xdd,0x5a,0x38,0xfc,0x82,0xbb,0xe8,0x72,0xc5,0x53,0x9e,0xdb,0x60,0x9e,0xf4,0xf7,0x9c,0x20,0x3e,
+0xbb,0x14,0x0f,0x2e,0x58,0x3c,0xb2,0xad,0x15,0xb4,0xaa,0x5b,0x65,0x50,0x16,0xa8,0x44,0x92,0x77,0xdb,0xd4,0x77,0xef,0x2c,0x8d,0x6c,0x01,0x7d,0xb7,0x38,0xb1,0x8d,
+0xeb,0x4a,0x42,0x7d,0x19,0x23,0xce,0x3f,0xf2,0x62,0x73,0x57,0x79,0xa4,0x18,0xf2,0x0a,0x28,0x2d,0xf9,0x20,0x14,0x7b,0xea,0xbe,0x42,0x1e,0xe5,0x31,0x9d,0x05,0x68,
+ }
+},
+
+/* #7, 32 byte key, 17 byte PTX */
+{
+ 32,
+ { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 },
+ { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 },
+ CONST64(0x123456789a),
+ 17,
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10 },
+ { 0x6c,0x16,0x25,0xdb,0x46,0x71,0x52,0x2d,0x3d,0x75,0x99,0x60,0x1d,0xe7,0xca,0x09,0xed },
+},
+
+/* #15, 32 byte key, 25 byte PTX */
+{
+ 32,
+ { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 },
+ { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 },
+ CONST64(0x123456789a),
+ 25,
+ { 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 },
+ { 0x8f,0x4d,0xcb,0xad,0x55,0x55,0x8d,0x7b,0x4e,0x01,0xd9,0x37,0x9c,0xd4,0xea,0x22,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73 },
+},
+
+/* #21, 32 byte key, 31 byte PTX */
+{
+ 32,
+ { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 },
+ { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 },
+ CONST64(0x123456789a),
+ 31,
+ { 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 },
+ { 0xd0,0x5b,0xc0,0x90,0xa8,0xe0,0x4f,0x1b,0x3d,0x3e,0xcd,0xd5,0xba,0xec,0x0f,0xd4,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73,0x06,0xe6,0x4b,0xe5,0xdd,0x82 },
+},
+
+};
+ unsigned char OUT[512], Torg[16], T[16];
+ ulong64 seq;
+ symmetric_xts xts;
+ int i, j, k, err, idx;
+ unsigned long len;
+
+ /* AES can be under rijndael or aes... try to find it */
+ if ((idx = find_cipher("aes")) == -1) {
+ if ((idx = find_cipher("rijndael")) == -1) {
+ return CRYPT_NOP;
+ }
+ }
+ for (k = 0; k < 4; ++k) {
+ cipher_descriptor[idx].accel_xts_encrypt = NULL;
+ cipher_descriptor[idx].accel_xts_decrypt = NULL;
+ if (k & 0x1) {
+ cipher_descriptor[idx].accel_xts_encrypt = s_xts_test_accel_xts_encrypt;
+ }
+ if (k & 0x2) {
+ cipher_descriptor[idx].accel_xts_decrypt = s_xts_test_accel_xts_decrypt;
+ }
+ for (j = 0; j < 2; j++) {
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ /* skip the cases where
+ * the length is smaller than 2*blocklen
+ * or the length is not a multiple of 32
+ */
+ if ((j == 1) && ((tests[i].PTLEN < 32) || (tests[i].PTLEN % 32))) {
+ continue;
+ }
+ if ((k > 0) && (j == 1)) {
+ continue;
+ }
+ len = tests[i].PTLEN / 2;
+
+ err = xts_start(idx, tests[i].key1, tests[i].key2, tests[i].keylen / 2, 0, &xts);
+ if (err != CRYPT_OK) {
+ return err;
+ }
+
+ seq = tests[i].seqnum;
+ STORE64L(seq, Torg);
+ XMEMSET(Torg + 8, 0, 8);
+
+ XMEMCPY(T, Torg, sizeof(T));
+ if (j == 0) {
+ err = xts_encrypt(tests[i].PTX, tests[i].PTLEN, OUT, T, &xts);
+ if (err != CRYPT_OK) {
+ xts_done(&xts);
+ return err;
+ }
+ } else {
+ err = xts_encrypt(tests[i].PTX, len, OUT, T, &xts);
+ if (err != CRYPT_OK) {
+ xts_done(&xts);
+ return err;
+ }
+ err = xts_encrypt(&tests[i].PTX[len], len, &OUT[len], T, &xts);
+ if (err != CRYPT_OK) {
+ xts_done(&xts);
+ return err;
+ }
+ }
+
+ if (compare_testvector(OUT, tests[i].PTLEN, tests[i].CTX, tests[i].PTLEN, "XTS encrypt", i)) {
+ xts_done(&xts);
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ XMEMCPY(T, Torg, sizeof(T));
+ if (j == 0) {
+ err = xts_decrypt(tests[i].CTX, tests[i].PTLEN, OUT, T, &xts);
+ if (err != CRYPT_OK) {
+ xts_done(&xts);
+ return err;
+ }
+ } else {
+ err = xts_decrypt(tests[i].CTX, len, OUT, T, &xts);
+ if (err != CRYPT_OK) {
+ xts_done(&xts);
+ return err;
+ }
+ err = xts_decrypt(&tests[i].CTX[len], len, &OUT[len], T, &xts);
+ if (err != CRYPT_OK) {
+ xts_done(&xts);
+ return err;
+ }
+ }
+
+ if (compare_testvector(OUT, tests[i].PTLEN, tests[i].PTX, tests[i].PTLEN, "XTS decrypt", i)) {
+ xts_done(&xts);
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ xts_done(&xts);
+ }
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c b/Sources/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c
new file mode 100644
index 00000000..83c915dc
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c
@@ -0,0 +1,77 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a BIT STRING
+ @param in The DER encoded BIT STRING
+ @param inlen The size of the DER BIT STRING
+ @param out [out] The array of bits stored (one per char)
+ @param outlen [in/out] The number of bits stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long dlen, blen, x, y;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* packet must be at least 4 bytes */
+ if (inlen < 4) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* check for 0x03 */
+ if ((in[0]&0x1F) != 0x03) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* offset in the data */
+ x = 1;
+
+ /* get the length of the data */
+ y = inlen - 1;
+ if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+ /* is the data len too long or too short? */
+ if ((dlen == 0) || (dlen > (inlen - x))) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get padding count */
+ blen = ((dlen - 1) << 3) - (in[x++] & 7);
+
+ /* too many bits? */
+ if (blen > *outlen) {
+ *outlen = blen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode/store the bits */
+ for (y = 0; y < blen; y++) {
+ out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0;
+ if ((y & 7) == 7) {
+ ++x;
+ }
+ }
+
+ /* we done */
+ *outlen = blen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/bit/der_decode_raw_bit_string.c b/Sources/libtomcrypt/pk/asn1/der/bit/der_decode_raw_bit_string.c
new file mode 100644
index 00000000..1bc74f60
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/bit/der_decode_raw_bit_string.c
@@ -0,0 +1,84 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+#define SETBIT(v, n) (v=((unsigned char)(v) | (1U << (unsigned char)(n))))
+#define CLRBIT(v, n) (v=((unsigned char)(v) & ~(1U << (unsigned char)(n))))
+
+/**
+ Store a BIT STRING
+ @param in The DER encoded BIT STRING
+ @param inlen The size of the DER BIT STRING
+ @param out [out] The array of bits stored (8 per char)
+ @param outlen [in/out] The number of bits stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long dlen, blen, x, y;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* packet must be at least 4 bytes */
+ if (inlen < 4) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* check for 0x03 */
+ if ((in[0]&0x1F) != 0x03) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* offset in the data */
+ x = 1;
+
+ /* get the length of the data */
+ y = inlen - 1;
+ if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+ /* is the data len too long or too short? */
+ if ((dlen == 0) || (dlen > (inlen - x))) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get padding count */
+ blen = ((dlen - 1) << 3) - (in[x++] & 7);
+
+ /* too many bits? */
+ if (blen > *outlen) {
+ *outlen = blen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode/store the bits */
+ for (y = 0; y < blen; y++) {
+ if (in[x] & (1 << (7 - (y & 7)))) {
+ SETBIT(out[y/8], 7-(y%8));
+ } else {
+ CLRBIT(out[y/8], 7-(y%8));
+ }
+ if ((y & 7) == 7) {
+ ++x;
+ }
+ }
+
+ /* we done */
+ *outlen = blen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c b/Sources/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c
new file mode 100644
index 00000000..0c2cd168
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c
@@ -0,0 +1,72 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a BIT STRING
+ @param in The array of bits to store (one per char)
+ @param inlen The number of bits tostore
+ @param out [out] The destination for the DER encoded BIT STRING
+ @param outlen [in/out] The max size and resulting size of the DER BIT STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long len, x, y;
+ unsigned char buf;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* avoid overflows */
+ if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store header (include bit padding count in length) */
+ x = 0;
+ y = ((inlen + 7) >> 3) + 1;
+
+ out[x++] = 0x03;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += len;
+
+ /* store number of zero padding bits */
+ out[x++] = (unsigned char)((8 - inlen) & 7);
+
+ /* store the bits in big endian format */
+ for (y = buf = 0; y < inlen; y++) {
+ buf |= (in[y] ? 1 : 0) << (7 - (y & 7));
+ if ((y & 7) == 7) {
+ out[x++] = buf;
+ buf = 0;
+ }
+ }
+ /* store last byte */
+ if (inlen & 7) {
+ out[x++] = buf;
+ }
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/bit/der_encode_raw_bit_string.c b/Sources/libtomcrypt/pk/asn1/der/bit/der_encode_raw_bit_string.c
new file mode 100644
index 00000000..9cc23aec
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/bit/der_encode_raw_bit_string.c
@@ -0,0 +1,75 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+#define getbit(n, k) (((n) & ( 1 << (k) )) >> (k))
+
+/**
+ Store a BIT STRING
+ @param in The array of bits to store (8 per char)
+ @param inlen The number of bits to store
+ @param out [out] The destination for the DER encoded BIT STRING
+ @param outlen [in/out] The max size and resulting size of the DER BIT STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long len, x, y;
+ unsigned char buf;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* avoid overflows */
+ if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store header (include bit padding count in length) */
+ x = 0;
+ y = ((inlen + 7) >> 3) + 1;
+
+ out[x++] = 0x03;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += len;
+
+ /* store number of zero padding bits */
+ out[x++] = (unsigned char)((8 - inlen) & 7);
+
+ /* store the bits in big endian format */
+ for (y = buf = 0; y < inlen; y++) {
+ buf |= (getbit(in[y/8],7-y%8)?1:0) << (7 - (y & 7));
+ if ((y & 7) == 7) {
+ out[x++] = buf;
+ buf = 0;
+ }
+ }
+ /* store last byte */
+ if (inlen & 7) {
+ out[x++] = buf;
+ }
+
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c b/Sources/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c
new file mode 100644
index 00000000..4554a801
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_bit_string.c
+ ASN.1 DER, get length of BIT STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of BIT STRING
+ @param nbits The number of bits in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_bit_string(unsigned long nbits, unsigned long *outlen)
+{
+ unsigned long nbytes, x;
+ int err;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the number of the bytes */
+ nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1;
+
+ if ((err = der_length_asn1_length(nbytes, &x)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + x + nbytes;
+
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c b/Sources/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c
new file mode 100644
index 00000000..35ac7ece
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c
@@ -0,0 +1,35 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_boolean.c
+ ASN.1 DER, decode a BOOLEAN, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a BOOLEAN
+ @param in The destination for the DER encoded BOOLEAN
+ @param inlen The size of the DER BOOLEAN
+ @param out [out] The boolean to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_boolean(const unsigned char *in, unsigned long inlen,
+ int *out)
+{
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (inlen < 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ *out = (in[2]==0xFF) ? 1 : 0;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c b/Sources/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c
new file mode 100644
index 00000000..a77aefb7
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c
@@ -0,0 +1,39 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_boolean.c
+ ASN.1 DER, encode a BOOLEAN, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a BOOLEAN
+ @param in The boolean to encode
+ @param out [out] The destination for the DER encoded BOOLEAN
+ @param outlen [in/out] The max size and resulting size of the DER BOOLEAN
+ @return CRYPT_OK if successful
+*/
+int der_encode_boolean(int in,
+ unsigned char *out, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (*outlen < 3) {
+ *outlen = 3;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ *outlen = 3;
+ out[0] = 0x01;
+ out[1] = 0x01;
+ out[2] = in ? 0xFF : 0x00;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c b/Sources/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c
new file mode 100644
index 00000000..f1b9e576
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c
@@ -0,0 +1,23 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_boolean.c
+ ASN.1 DER, get length of a BOOLEAN, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of a BOOLEAN
+ @param outlen [out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_length_boolean(unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ *outlen = 3;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c b/Sources/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c
new file mode 100644
index 00000000..cf4422a5
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c
@@ -0,0 +1,221 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_choice.c
+ ASN.1 DER, decode a CHOICE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a CHOICE
+ @param in The DER encoded input
+ @param inlen [in/out] The size of the input and resulting size of read type
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @return CRYPT_OK on success
+*/
+int der_decode_choice(const unsigned char *in, unsigned long *inlen,
+ ltc_asn1_list *list, unsigned long outlen)
+{
+ unsigned long size, x, z;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(list != NULL);
+
+ /* get blk size */
+ if (*inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* set all of the "used" flags to zero */
+ for (x = 0; x < outlen; x++) {
+ list[x].used = 0;
+ }
+
+ /* now scan until we have a winner */
+ for (x = 0; x < outlen; x++) {
+ size = list[x].size;
+ data = list[x].data;
+
+ switch (list[x].type) {
+ case LTC_ASN1_BOOLEAN:
+ if (der_decode_boolean(in, *inlen, data) == CRYPT_OK) {
+ if (der_length_boolean(&z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
+ if (der_length_integer(data, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {
+ if (der_length_short_integer(*(unsigned long*)data, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_bit_string(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_RAW_BIT_STRING:
+ if (der_decode_raw_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_bit_string(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_octet_string(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) {
+ *inlen = 2;
+ list[x].used = 1;
+ return CRYPT_OK;
+ }
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_object_identifier(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_TELETEX_STRING:
+ if (der_decode_teletex_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_teletex_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_printable_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_utf8_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *inlen;
+ if (der_decode_utctime(in, &z, data) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ z = *inlen;
+ if (der_decode_generalizedtime(in, &z, data) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) {
+ if (der_length_sequence(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) {
+ if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_EOL:
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ return CRYPT_INVALID_PACKET;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/custom_type/der_decode_custom_type.c b/Sources/libtomcrypt/pk/asn1/der/custom_type/der_decode_custom_type.c
new file mode 100644
index 00000000..4c4d52d3
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/custom_type/der_decode_custom_type.c
@@ -0,0 +1,426 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+
+/**
+ @file der_decode_custom_type.c
+ ASN.1 DER, decode a Custom type, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a Custom type
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param root The item that defines the custom type to decode
+ @return CRYPT_OK on success
+*/
+int der_decode_custom_type(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root)
+{
+ LTC_ARGCHK(root != NULL);
+ return der_decode_custom_type_ex(in, inlen, root, NULL, 0, LTC_DER_SEQ_ORDERED | LTC_DER_SEQ_RELAXED);
+}
+
+/**
+ Extended-decode a Custom type
+
+ This function is used to decode custom types and sequences/sets
+ For custom types root is used
+ For sequences/sets list and outlen are used
+
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param root The item that defines the custom type to decode
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @param flags c.f. enum ltc_der_seq
+ @return CRYPT_OK on success
+*/
+int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root,
+ ltc_asn1_list *list, unsigned long outlen,
+ unsigned int flags)
+{
+ int err, seq_err, i, ordered;
+ ltc_asn1_type type;
+ ltc_asn1_list ident;
+ unsigned long size, x, y, z, blksize;
+ unsigned char* in_new = NULL;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+
+ /* get blk size */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 0;
+
+ if (root == NULL) {
+ LTC_ARGCHK(list != NULL);
+
+ /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
+ if (in[x] != 0x30 && in[x] != 0x31) {
+ return CRYPT_INVALID_PACKET;
+ }
+ ++x;
+ } else {
+ if (root->type != LTC_ASN1_CUSTOM_TYPE) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* Alloc a copy of the data for primitive handling. */
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ in_new = XMALLOC(inlen);
+ if (in_new == NULL) {
+ return CRYPT_MEM;
+ }
+ XMEMCPY(in_new, in, inlen);
+ in = in_new;
+ }
+
+ y = inlen;
+ if ((err = der_decode_asn1_identifier(in, &y, &ident)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((ident.type != root->type) ||
+ (ident.klass != root->klass) ||
+ (ident.pc != root->pc) ||
+ (ident.tag != root->tag)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ x += y;
+
+ list = root->data;
+ outlen = root->size;
+ }
+
+ if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) ||
+ (der_asn1_type_to_identifier_map[root->used] == -1)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ root->type = (ltc_asn1_type)root->used;
+ list = root;
+ outlen = 1;
+
+ x -= 1;
+ in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type];
+ blksize = inlen - x;
+ } else {
+
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += y;
+ }
+
+ /* would this blksize overflow? */
+ if (blksize > (inlen - x)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* mark all as unused */
+ for (i = 0; i < (int)outlen; i++) {
+ list[i].used = 0;
+ }
+ ordered = flags & LTC_DER_SEQ_ORDERED;
+
+ /* ok read data */
+ seq_err = CRYPT_OK;
+ blksize += x;
+ inlen -= x;
+ for (i = 0; i < (int)outlen; i++) {
+ z = 0;
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+ if (!ordered && list[i].used == 1) { continue; }
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE && i != 0) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto LBL_ERR;
+ }
+
+ switch (type) {
+ case LTC_ASN1_CUSTOM_TYPE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ break;
+ default:
+ /* Verify that all basic types are indeed UNIVERSAL&PRIMITIVE */
+ if (((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT) && (inlen > 0)) {
+ if (in[x] & 0xE0u) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto LBL_ERR;
+ }
+ }
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = inlen;
+ if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_boolean(&z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = inlen;
+ if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = inlen;
+ if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_RAW_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = inlen;
+ if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
+ if (!ordered || list[i].optional) { continue; }
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = inlen;
+ if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_TELETEX_STRING:
+ z = inlen;
+ if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = inlen;
+ if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = inlen;
+ if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = inlen;
+ if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = inlen;
+ if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ z = inlen;
+ if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = inlen;
+ if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ /* detect if we have the right type */
+ if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ z = inlen;
+ err = der_decode_sequence_ex(in + x, z, data, size, flags);
+ if (err == CRYPT_INPUT_TOO_LONG) {
+ seq_err = CRYPT_INPUT_TOO_LONG;
+ err = CRYPT_OK;
+ }
+ if (err != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ z = inlen;
+ err = der_decode_custom_type(in + x, z, &list[i]);
+ if (err == CRYPT_INPUT_TOO_LONG) {
+ seq_err = CRYPT_INPUT_TOO_LONG;
+ err = CRYPT_OK;
+ }
+ if (err != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CHOICE:
+ z = inlen;
+ if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_EOL:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ list[i].used = 1;
+ if (!ordered) {
+ /* restart the decoder */
+ i = -1;
+ }
+ }
+
+ for (i = 0; i < (int)outlen; i++) {
+ if (list[i].used == 0 && list[i].optional == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+
+ if (blksize == x && seq_err == CRYPT_OK && inlen == 0) {
+ /* everything decoded and no errors in nested sequences */
+ err = CRYPT_OK;
+ } else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) {
+ /* a sequence reported too-long input, but now we've decoded everything */
+ err = CRYPT_OK;
+ } else if (blksize != x && ((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT)) {
+ err = CRYPT_INVALID_PACKET;
+ } else {
+ err = CRYPT_INPUT_TOO_LONG;
+ }
+
+LBL_ERR:
+ if (in_new != NULL) {
+ XFREE(in_new);
+ }
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/custom_type/der_encode_custom_type.c b/Sources/libtomcrypt/pk/asn1/der/custom_type/der_encode_custom_type.c
new file mode 100644
index 00000000..586fb316
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/custom_type/der_encode_custom_type.c
@@ -0,0 +1,228 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+
+/**
+ @file der_encode_custom_type.c
+ ASN.1 DER, encode a Custom Type, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a Custom Type
+
+ This function is a bit special compared to the others, as it requires the
+ root-ltc_asn1_list where the type is defined.
+
+ @param root The root of the list of items to encode
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_custom_type(const ltc_asn1_list *root,
+ unsigned char *out, unsigned long *outlen)
+{
+ int err;
+ ltc_asn1_type type;
+ const ltc_asn1_list *list;
+ unsigned long size, x, y, z, i, inlen, id_len;
+ void *data;
+
+ LTC_ARGCHK(root != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0; z = 0;
+ if (der_length_custom_type(root, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG;
+
+ /* too big ? */
+ if (*outlen < y) {
+ *outlen = y;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* get length of the identifier, so we know the offset where to start writing */
+ if (der_length_asn1_identifier(root, &id_len) != CRYPT_OK) return CRYPT_INVALID_ARG;
+ x = id_len;
+
+
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ list = root;
+ inlen = 1;
+ /* In case it's a PRIMITIVE type we encode directly to the output
+ * but leave space for a potentially longer identifier as it will
+ * simply be replaced afterwards.
+ */
+ x -= 1;
+ } else {
+ list = root->data;
+ inlen = root->size;
+ /* store length, identifier will be added later */
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += y;
+ }
+
+ /* store data */
+ *outlen -= x;
+ for (i = 0; i < inlen; i++) {
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ type = (ltc_asn1_type)list[i].used;
+ } else {
+ type = list[i].type;
+ }
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = *outlen;
+ if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_RAW_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = *outlen;
+ if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ out[x] = 0x05;
+ out[x+1] = 0x00;
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = *outlen;
+ if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = *outlen;
+ if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = *outlen;
+ if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = *outlen;
+ if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *outlen;
+ if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ z = *outlen;
+ if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = *outlen;
+ if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ z = *outlen;
+ if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SEQUENCE:
+ z = *outlen;
+ if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ z = *outlen;
+ if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_EOL:
+ case LTC_ASN1_TELETEX_STRING:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+
+ x += z;
+ *outlen -= z;
+ }
+
+ if ((err = der_encode_asn1_identifier(root, out, &id_len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ *outlen = x;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/custom_type/der_length_custom_type.c b/Sources/libtomcrypt/pk/asn1/der/custom_type/der_length_custom_type.c
new file mode 100644
index 00000000..01e58ec8
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/custom_type/der_length_custom_type.c
@@ -0,0 +1,203 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_custom_type.c
+ ASN.1 DER, length of a custom type, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Get the length of a DER custom type
+
+ This function is a bit special compared to the others, as it requires the
+ root-ltc_asn1_list where the type is defined.
+
+ @param root The root of the struct to encode
+ @param outlen [out] The length required in octets to store it
+ @param payloadlen [out] The length of the payload in octets
+ @return CRYPT_OK on success
+*/
+int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen)
+{
+ int err;
+ const ltc_asn1_list *list;
+ ltc_asn1_type type;
+ unsigned long size, x, y, i, inlen, id_len;
+ void *data;
+
+ LTC_ARGCHK(root != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) {
+ return err;
+ }
+ y = id_len;
+
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ list = root;
+ inlen = 1;
+ } else {
+ list = root->data;
+ inlen = root->size;
+ }
+ for (i = 0; i < inlen; i++) {
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ type = (ltc_asn1_type)list[i].used;
+ } else {
+ type = list[i].type;
+ }
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ /* some items may be optional during import */
+ if (!list[i].used && list[i].optional) continue;
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ if ((err = der_length_boolean(&x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_RAW_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_TELETEX_STRING:
+ if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_EOL:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ /* In case it's a PRIMITIVE element we're going
+ * to only replace the identifier of the one element
+ * by the custom identifier.
+ */
+ y -= 1;
+ if (payloadlen != NULL) {
+ *payloadlen = y - id_len;
+ }
+ } else {
+ /* calc length of length */
+ if ((err = der_length_asn1_length(y - id_len, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if (payloadlen != NULL) {
+ *payloadlen = y - id_len;
+ }
+ y += x;
+ }
+
+ /* store size */
+ *outlen = y;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/general/der_asn1_maps.c b/Sources/libtomcrypt/pk/asn1/der/general/der_asn1_maps.c
new file mode 100644
index 00000000..8f54f091
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/general/der_asn1_maps.c
@@ -0,0 +1,157 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_asn1_maps.c
+ ASN.1 DER, a collection of maps to convert between different representations, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ A Map from ltc_asn1_type to the regularly used ASN.1 identifier
+*/
+const int der_asn1_type_to_identifier_map[] =
+{
+ /* 0 */
+ -1, /* LTC_ASN1_EOL, */
+ 1, /* LTC_ASN1_BOOLEAN, */
+ 2, /* LTC_ASN1_INTEGER, */
+ 2, /* LTC_ASN1_SHORT_INTEGER, */
+ 3, /* LTC_ASN1_BIT_STRING, */
+ /* 5 */
+ 4, /* LTC_ASN1_OCTET_STRING, */
+ 5, /* LTC_ASN1_NULL, */
+ 6, /* LTC_ASN1_OBJECT_IDENTIFIER, */
+ 22, /* LTC_ASN1_IA5_STRING, */
+ 19, /* LTC_ASN1_PRINTABLE_STRING, */
+ /* 10 */
+ 12, /* LTC_ASN1_UTF8_STRING, */
+ 23, /* LTC_ASN1_UTCTIME, */
+ -1, /* LTC_ASN1_CHOICE, */
+ 48, /* LTC_ASN1_SEQUENCE, */
+ 49, /* LTC_ASN1_SET, */
+ /* 15 */
+ 49, /* LTC_ASN1_SETOF, */
+ 3, /* LTC_ASN1_RAW_BIT_STRING, */
+ 20, /* LTC_ASN1_TELETEX_STRING, */
+ 24, /* LTC_ASN1_GENERALIZEDTIME, */
+ -1, /* LTC_ASN1_CUSTOM_TYPE, */
+};
+const unsigned long der_asn1_type_to_identifier_map_sz = sizeof(der_asn1_type_to_identifier_map)/sizeof(der_asn1_type_to_identifier_map[0]);
+
+/**
+ A Map from the ASN.1 Class to its string
+*/
+const char* der_asn1_class_to_string_map[] =
+{
+ "UNIVERSAL",
+ "APPLICATION",
+ "CONTEXT-SPECIFIC",
+ "PRIVATE",
+};
+const unsigned long der_asn1_class_to_string_map_sz = sizeof(der_asn1_class_to_string_map)/sizeof(der_asn1_class_to_string_map[0]);
+
+/**
+ A Map from the ASN.1 P/C-bit to its string
+*/
+const char* der_asn1_pc_to_string_map[] =
+{
+ "PRIMITIVE",
+ "CONSTRUCTED",
+};
+const unsigned long der_asn1_pc_to_string_map_sz = sizeof(der_asn1_pc_to_string_map)/sizeof(der_asn1_pc_to_string_map[0]);
+
+/**
+ A Map from the ASN.1 tag to its string
+*/
+const char* der_asn1_tag_to_string_map[] =
+{
+ "Reserved for use by the encoding rules",
+ "Boolean type",
+ "Integer type",
+ "Bitstring type",
+ "Octetstring type",
+ "Null type",
+ "Object identifier type",
+ "Object descriptor type",
+ "External type and Instance-of type",
+ "Real type",
+ "Enumerated type",
+ "Embedded-pdv type",
+ "UTF8String type",
+ "Relative object identifier type",
+ "The time type",
+ "Reserved for future editions of this Recommendation | International Standard",
+ "Sequence and Sequence-of types",
+ "Set and Set-of types",
+ "NumericString type",
+ "PrintableString type",
+ "TeletexString (T61String) type",
+ "VideotexString type",
+ "IA5String type",
+ "UTCTime type",
+ "GeneralizedTime type",
+ "GraphicString type",
+ "VisibleString (ISO646String) type",
+ "GeneralString type",
+ "UniversalString type",
+ "UnrestrictedCharacterString type",
+ "BMPString type",
+ "Date type",
+ "TimeOfDay type",
+ "DateTime type",
+ "Duration type",
+ "OID internationalized resource identifier type",
+ "Relative OID internationalized resource identifier type",
+};
+const unsigned long der_asn1_tag_to_string_map_sz = sizeof(der_asn1_tag_to_string_map)/sizeof(der_asn1_tag_to_string_map[0]);
+
+/**
+ A Map from ASN.1 Tags to ltc_asn1_type
+*/
+const ltc_asn1_type der_asn1_tag_to_type_map[] =
+{
+ /* 0 */
+ LTC_ASN1_EOL, /* Reserved for use by the encoding rules */
+ LTC_ASN1_BOOLEAN, /* Boolean type */
+ LTC_ASN1_INTEGER, /* Integer type */
+ LTC_ASN1_BIT_STRING, /* Bitstring type */
+ LTC_ASN1_OCTET_STRING, /* Octetstring type */
+ /* 5 */
+ LTC_ASN1_NULL, /* Null type */
+ LTC_ASN1_OBJECT_IDENTIFIER, /* Object identifier type */
+ LTC_ASN1_CUSTOM_TYPE, /* Object descriptor type */
+ LTC_ASN1_CUSTOM_TYPE, /* External type and Instance-of type */
+ LTC_ASN1_CUSTOM_TYPE, /* Real type */
+ /* 10 */
+ LTC_ASN1_CUSTOM_TYPE, /* Enumerated type */
+ LTC_ASN1_CUSTOM_TYPE, /* Embedded-pdv type */
+ LTC_ASN1_UTF8_STRING, /* UTF8String type */
+ LTC_ASN1_CUSTOM_TYPE, /* Relative object identifier type */
+ LTC_ASN1_CUSTOM_TYPE, /* The time type */
+ /* 15 */
+ LTC_ASN1_EOL, /* Reserved for future editions of this Recommendation | International Standard */
+ LTC_ASN1_SEQUENCE, /* Sequence and Sequence-of types */
+ LTC_ASN1_SET, /* Set and Set-of types */
+ LTC_ASN1_CUSTOM_TYPE, /* NumericString types */
+ LTC_ASN1_PRINTABLE_STRING, /* PrintableString types */
+ /* 20 */
+ LTC_ASN1_TELETEX_STRING, /* TeletexString (T61String) types */
+ LTC_ASN1_CUSTOM_TYPE, /* VideotexString types */
+ LTC_ASN1_IA5_STRING, /* IA5String types */
+ LTC_ASN1_UTCTIME, /* UTCTime types */
+ LTC_ASN1_GENERALIZEDTIME, /* GeneralizedTime types */
+ /* 25 */
+ LTC_ASN1_CUSTOM_TYPE, /* GraphicString types */
+ LTC_ASN1_CUSTOM_TYPE, /* VisibleString (ISO646String) types */
+ LTC_ASN1_CUSTOM_TYPE, /* GeneralString types */
+ LTC_ASN1_CUSTOM_TYPE, /* UniversalString types */
+ LTC_ASN1_CUSTOM_TYPE, /* UnrestrictedCharacterString types */
+ /* 30 */
+ LTC_ASN1_CUSTOM_TYPE, /* BMPString types */
+};
+const unsigned long der_asn1_tag_to_type_map_sz = sizeof(der_asn1_tag_to_type_map)/sizeof(der_asn1_tag_to_type_map[0]);
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/general/der_decode_asn1_identifier.c b/Sources/libtomcrypt/pk/asn1/der/general/der_decode_asn1_identifier.c
new file mode 100644
index 00000000..ad4dc7b4
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/general/der_decode_asn1_identifier.c
@@ -0,0 +1,123 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_asn1_identifier.c
+ ASN.1 DER, decode the ASN.1 Identifier, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/* c.f. X.680 & X.690, some decisions backed by X.690 ch. 10.2 */
+static const unsigned char tag_constructed_map[] =
+{
+ /* 0 */
+ 255,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 5 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 10 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 15 */
+ 255,
+ LTC_ASN1_PC_CONSTRUCTED,
+ LTC_ASN1_PC_CONSTRUCTED,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 20 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 25 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+};
+ static const unsigned long tag_constructed_map_sz = sizeof(tag_constructed_map)/sizeof(tag_constructed_map[0]);
+
+/**
+ Decode the ASN.1 Identifier
+ @param id Where to store the decoded Identifier
+ @param in Where to read the Identifier from
+ @param inlen [in/out] The size of in available/read
+ @return CRYPT_OK if successful
+*/
+int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id)
+{
+ ulong64 tmp;
+ unsigned long tag_len;
+ int err;
+
+ LTC_ARGCHK(id != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+
+ if (*inlen == 0) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ tag_len = 1;
+ id->klass = (in[0] >> 6) & 0x3;
+ id->pc = (in[0] >> 5) & 0x1;
+ id->tag = in[0] & 0x1f;
+
+ err = CRYPT_OK;
+ if (id->tag == 0x1f) {
+ id->tag = 0;
+ do {
+ if (*inlen < tag_len) {
+ /* break the loop and trigger the BOF error-code */
+ tmp = 0xff;
+ break;
+ }
+ id->tag <<= 7;
+ id->tag |= in[tag_len] & 0x7f;
+ tmp = in[tag_len] & 0x80;
+ tag_len++;
+ } while ((tmp != 0) && (tag_len < 10));
+
+ if (tmp != 0) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else if (id->tag < 0x1f) {
+ err = CRYPT_PK_ASN1_ERROR;
+ }
+ }
+
+ if (err != CRYPT_OK) {
+ id->pc = 0;
+ id->klass = 0;
+ id->tag = 0;
+ } else {
+ *inlen = tag_len;
+ if ((id->klass == LTC_ASN1_CL_UNIVERSAL) &&
+ (id->tag < der_asn1_tag_to_type_map_sz) &&
+ (id->tag < tag_constructed_map_sz) &&
+ (id->pc == tag_constructed_map[id->tag])) {
+ id->type = der_asn1_tag_to_type_map[id->tag];
+ } else {
+ if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && (id->tag == 0)) {
+ id->type = LTC_ASN1_EOL;
+ } else {
+ id->type = LTC_ASN1_CUSTOM_TYPE;
+ }
+ }
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/general/der_decode_asn1_length.c b/Sources/libtomcrypt/pk/asn1/der/general/der_decode_asn1_length.c
new file mode 100644
index 00000000..0e5a3939
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/general/der_decode_asn1_length.c
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_asn1_length.c
+ ASN.1 DER, decode the ASN.1 Length field, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Decode the ASN.1 Length field
+ @param in Where to read the length field from
+ @param inlen [in/out] The size of in available/read
+ @param outlen [out] The decoded ASN.1 length
+ @return CRYPT_OK if successful
+*/
+int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen)
+{
+ unsigned long real_len, decoded_len, offset, i;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+
+ if (*inlen < 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ real_len = in[0];
+
+ if (real_len < 128) {
+ decoded_len = real_len;
+ offset = 1;
+ } else {
+ real_len &= 0x7F;
+ if (real_len == 0) {
+ return CRYPT_PK_ASN1_ERROR;
+ }
+ if (real_len > sizeof(decoded_len)) {
+ return CRYPT_OVERFLOW;
+ }
+ if (real_len > (*inlen - 1)) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ decoded_len = 0;
+ offset = 1 + real_len;
+ for (i = 0; i < real_len; i++) {
+ decoded_len = (decoded_len << 8) | in[1 + i];
+ }
+ }
+
+ if (outlen != NULL) *outlen = decoded_len;
+ if (decoded_len > (*inlen - offset)) return CRYPT_OVERFLOW;
+ *inlen = offset;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/general/der_encode_asn1_identifier.c b/Sources/libtomcrypt/pk/asn1/der/general/der_encode_asn1_identifier.c
new file mode 100644
index 00000000..51d57ec1
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/general/der_encode_asn1_identifier.c
@@ -0,0 +1,86 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_asn1_identifier.c
+ ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Encode the ASN.1 Identifier
+ @param id The ASN.1 Identifer to encode
+ @param out Where to write the identifier to
+ @param outlen [in/out] The size of out available/written
+ @return CRYPT_OK if successful
+*/
+int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen)
+{
+ ulong64 tmp;
+ unsigned long tag_len;
+
+ LTC_ARGCHK(id != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (id->type != LTC_ASN1_CUSTOM_TYPE) {
+ if ((unsigned)id->type >= der_asn1_type_to_identifier_map_sz) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (der_asn1_type_to_identifier_map[id->type] == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (out != NULL) {
+ *out = der_asn1_type_to_identifier_map[id->type];
+ }
+ *outlen = 1;
+ return CRYPT_OK;
+ }
+ if (id->klass < LTC_ASN1_CL_UNIVERSAL || id->klass > LTC_ASN1_CL_PRIVATE) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (id->tag > (ULONG_MAX >> (8 + 7))) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (out != NULL) {
+ if (*outlen < 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ out[0] = id->klass << 6 | id->pc << 5;
+ }
+
+ if (id->tag < 0x1f) {
+ if (out != NULL) {
+ out[0] |= id->tag & 0x1f;
+ }
+ *outlen = 1;
+ } else {
+ tag_len = 0;
+ tmp = id->tag;
+ do {
+ tag_len++;
+ tmp >>= 7;
+ } while (tmp);
+
+ if (out != NULL) {
+ if (*outlen < tag_len + 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ out[0] |= 0x1f;
+ for (tmp = 1; tmp <= tag_len; ++tmp) {
+ out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80;
+ }
+ out[tag_len] &= ~0x80;
+ }
+ *outlen = tag_len + 1;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/general/der_encode_asn1_length.c b/Sources/libtomcrypt/pk/asn1/der/general/der_encode_asn1_length.c
new file mode 100644
index 00000000..7892eea2
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/general/der_encode_asn1_length.c
@@ -0,0 +1,117 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_asn1_length.c
+ ASN.1 DER, encode the ASN.1 length field, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Encode the ASN.1 length field
+ @param len The length to encode
+ @param out Where to write the length field to
+ @param outlen [in/out] The size of out available/written
+ @return CRYPT_OK if successful
+*/
+int der_encode_asn1_length(unsigned long len, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ x = len;
+ y = 0;
+
+ while(x != 0) {
+ y++;
+ x >>= 8;
+ }
+ if (y == 0) {
+ return CRYPT_PK_ASN1_ERROR;
+ }
+
+ if (out == NULL) {
+ if (len < 128) {
+ x = y;
+ } else {
+ x = y + 1;
+ }
+ } else {
+ if (*outlen < y) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ x = 0;
+ if (len < 128) {
+ out[x++] = (unsigned char)len;
+ } else if (len <= 0xffUL) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)len;
+ } else if (len <= 0xffffUL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffUL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((len>>16UL)&255);
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ #if ULONG_MAX != ULLONG_MAX
+ } else {
+ out[x++] = 0x84;
+ out[x++] = (unsigned char)((len>>24UL)&255);
+ out[x++] = (unsigned char)((len>>16UL)&255);
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ }
+ #else
+ } else if (len <= 0xffffffffUL) {
+ out[x++] = 0x84;
+ out[x++] = (unsigned char)((len>>24UL)&255);
+ out[x++] = (unsigned char)((len>>16UL)&255);
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffffffULL) {
+ out[x++] = 0x85;
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffffffffULL) {
+ out[x++] = 0x86;
+ out[x++] = (unsigned char)((len>>40ULL)&255);
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffffffffffULL) {
+ out[x++] = 0x87;
+ out[x++] = (unsigned char)((len>>48ULL)&255);
+ out[x++] = (unsigned char)((len>>40ULL)&255);
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else {
+ out[x++] = 0x88;
+ out[x++] = (unsigned char)((len>>56ULL)&255);
+ out[x++] = (unsigned char)((len>>48ULL)&255);
+ out[x++] = (unsigned char)((len>>40ULL)&255);
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ }
+ #endif
+ }
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/general/der_length_asn1_identifier.c b/Sources/libtomcrypt/pk/asn1/der/general/der_length_asn1_identifier.c
new file mode 100644
index 00000000..63e6bdd2
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/general/der_length_asn1_identifier.c
@@ -0,0 +1,23 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_asn1_identifier.c
+ ASN.1 DER, determine the length when encoding the ASN.1 Identifier, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Determine the length required when encoding the ASN.1 Identifier
+ @param id The ASN.1 identifier to encode
+ @param idlen [out] The required length to encode list
+ @return CRYPT_OK if successful
+*/
+
+int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen)
+{
+ return der_encode_asn1_identifier(id, NULL, idlen);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/general/der_length_asn1_length.c b/Sources/libtomcrypt/pk/asn1/der/general/der_length_asn1_length.c
new file mode 100644
index 00000000..1c81adb6
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/general/der_length_asn1_length.c
@@ -0,0 +1,22 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_asn1_length.c
+ ASN.1 DER, determine the length of the ASN.1 length field, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Determine the length required to encode len in the ASN.1 length field
+ @param len The length to encode
+ @param outlen [out] The length that's required to store len
+ @return CRYPT_OK if successful
+*/
+int der_length_asn1_length(unsigned long len, unsigned long *outlen)
+{
+ return der_encode_asn1_length(len, NULL, outlen);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c b/Sources/libtomcrypt/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c
new file mode 100644
index 00000000..7d2f2960
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c
@@ -0,0 +1,135 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_generalizedtime.c
+ ASN.1 DER, decode a GeneralizedTime, Steffen Jaeckel
+ Based on der_decode_utctime.c
+*/
+
+#ifdef LTC_DER
+
+static int s_char_to_int(unsigned char x)
+{
+ switch (x) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ default: return 100;
+ }
+}
+
+#define DECODE_V(y, max) do {\
+ y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \
+ if (y >= max) return CRYPT_INVALID_PACKET; \
+ x += 2; \
+} while(0)
+
+#define DECODE_V4(y, max) do {\
+ y = s_char_to_int(buf[x])*1000 + s_char_to_int(buf[x+1])*100 + s_char_to_int(buf[x+2])*10 + s_char_to_int(buf[x+3]); \
+ if (y >= max) return CRYPT_INVALID_PACKET; \
+ x += 4; \
+} while(0)
+
+/**
+ Decodes a Generalized time structure in DER format (reads all 6 valid encoding formats)
+ @param in Input buffer
+ @param inlen Length of input buffer in octets
+ @param out [out] Destination of Generalized time structure
+ @return CRYPT_OK if successful
+*/
+int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen,
+ ltc_generalizedtime *out)
+{
+ unsigned char buf[32];
+ unsigned long x;
+ int y;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* check header */
+ if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode the string */
+ for (x = 0; x < in[1]; x++) {
+ y = der_ia5_value_decode(in[x+2]);
+ if (y == -1) {
+ return CRYPT_INVALID_PACKET;
+ }
+ if (!((y >= '0' && y <= '9')
+ || y == 'Z' || y == '.'
+ || y == '+' || y == '-')) {
+ return CRYPT_INVALID_PACKET;
+ }
+ buf[x] = y;
+ }
+ *inlen = 2 + x;
+
+ if (x < 15) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* possible encodings are
+YYYYMMDDhhmmssZ
+YYYYMMDDhhmmss+hh'mm'
+YYYYMMDDhhmmss-hh'mm'
+YYYYMMDDhhmmss.fsZ
+YYYYMMDDhhmmss.fs+hh'mm'
+YYYYMMDDhhmmss.fs-hh'mm'
+
+ So let's do a trivial decode upto [including] ss
+ */
+
+ x = 0;
+ DECODE_V4(out->YYYY, 10000);
+ DECODE_V(out->MM, 13);
+ DECODE_V(out->DD, 32);
+ DECODE_V(out->hh, 24);
+ DECODE_V(out->mm, 60);
+ DECODE_V(out->ss, 60);
+
+ /* clear fractional seconds info */
+ out->fs = 0;
+
+ /* now is it Z or . */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ }
+ if (buf[x] == '.') {
+ x++;
+ while (buf[x] >= '0' && buf[x] <= '9') {
+ unsigned fs = out->fs;
+ if (x >= sizeof(buf)) return CRYPT_INVALID_PACKET;
+ out->fs *= 10;
+ out->fs += s_char_to_int(buf[x]);
+ if (fs > out->fs) return CRYPT_OVERFLOW;
+ x++;
+ }
+ }
+
+ /* now is it Z, +, - */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ }
+ if (buf[x] == '+' || buf[x] == '-') {
+ out->off_dir = (buf[x++] == '+') ? 0 : 1;
+ DECODE_V(out->off_hh, 24);
+ DECODE_V(out->off_mm, 60);
+ return CRYPT_OK;
+ }
+ return CRYPT_INVALID_PACKET;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c b/Sources/libtomcrypt/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c
new file mode 100644
index 00000000..2378eeba
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c
@@ -0,0 +1,98 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_utctime.c
+ ASN.1 DER, encode a GeneralizedTime, Steffen Jaeckel
+ Based on der_encode_utctime.c
+*/
+
+#ifdef LTC_DER
+
+static const char * const baseten = "0123456789";
+
+#define STORE_V(y) do {\
+ out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \
+ out[x++] = der_ia5_char_encode(baseten[y % 10]); \
+} while(0)
+
+#define STORE_V4(y) do {\
+ out[x++] = der_ia5_char_encode(baseten[(y/1000) % 10]); \
+ out[x++] = der_ia5_char_encode(baseten[(y/100) % 10]); \
+ out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \
+ out[x++] = der_ia5_char_encode(baseten[y % 10]); \
+} while(0)
+
+/**
+ Encodes a Generalized time structure in DER format
+ @param gtime The GeneralizedTime structure to encode
+ @param out The destination of the DER encoding of the GeneralizedTime structure
+ @param outlen [in/out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_encode_generalizedtime(const ltc_generalizedtime *gtime,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, tmplen;
+ int err;
+
+ LTC_ARGCHK(gtime != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = der_length_generalizedtime(gtime, &tmplen)) != CRYPT_OK) {
+ return err;
+ }
+ if (tmplen > *outlen) {
+ *outlen = tmplen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store header */
+ out[0] = 0x18;
+
+ /* store values */
+ x = 2;
+ STORE_V4(gtime->YYYY);
+ STORE_V(gtime->MM);
+ STORE_V(gtime->DD);
+ STORE_V(gtime->hh);
+ STORE_V(gtime->mm);
+ STORE_V(gtime->ss);
+
+ if (gtime->fs) {
+ unsigned long divisor;
+ unsigned fs = gtime->fs;
+ unsigned len = 0;
+ out[x++] = der_ia5_char_encode('.');
+ divisor = 1;
+ do {
+ fs /= 10;
+ divisor *= 10;
+ len++;
+ } while(fs != 0);
+ while (len-- > 1) {
+ divisor /= 10;
+ out[x++] = der_ia5_char_encode(baseten[(gtime->fs/divisor) % 10]);
+ }
+ out[x++] = der_ia5_char_encode(baseten[gtime->fs % 10]);
+ }
+
+ if (gtime->off_mm || gtime->off_hh) {
+ out[x++] = der_ia5_char_encode(gtime->off_dir ? '-' : '+');
+ STORE_V(gtime->off_hh);
+ STORE_V(gtime->off_mm);
+ } else {
+ out[x++] = der_ia5_char_encode('Z');
+ }
+
+ /* store length */
+ out[1] = (unsigned char)(x - 2);
+
+ /* all good let's return */
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/generalizedtime/der_length_generalizedtime.c b/Sources/libtomcrypt/pk/asn1/der/generalizedtime/der_length_generalizedtime.c
new file mode 100644
index 00000000..dc237d30
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/generalizedtime/der_length_generalizedtime.c
@@ -0,0 +1,48 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_utctime.c
+ ASN.1 DER, get length of GeneralizedTime, Steffen Jaeckel
+ Based on der_length_utctime.c
+*/
+
+#ifdef LTC_DER
+
+/**
+ Gets length of DER encoding of GeneralizedTime
+ @param gtime The GeneralizedTime structure to get the size of
+ @param outlen [out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(gtime != NULL);
+
+ if (gtime->fs == 0) {
+ /* we encode as YYYYMMDDhhmmssZ */
+ *outlen = 2 + 14 + 1;
+ } else {
+ unsigned long len = 2 + 14 + 1;
+ unsigned fs = gtime->fs;
+ do {
+ fs /= 10;
+ len++;
+ } while(fs != 0);
+ if (gtime->off_hh == 0 && gtime->off_mm == 0) {
+ /* we encode as YYYYMMDDhhmmss.fsZ */
+ len += 1;
+ }
+ else {
+ /* we encode as YYYYMMDDhhmmss.fs{+|-}hh'mm' */
+ len += 5;
+ }
+ *outlen = len;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c b/Sources/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c
new file mode 100644
index 00000000..8fd80cf1
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c
@@ -0,0 +1,73 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_ia5_string.c
+ ASN.1 DER, encode a IA5 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a IA5 STRING
+ @param in The DER encoded IA5 STRING
+ @param inlen The size of the DER IA5 STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t, err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x16 */
+ if ((in[0] & 0x1F) != 0x16) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len > (inlen - x)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_ia5_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c b/Sources/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c
new file mode 100644
index 00000000..8b8bd36b
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_ia5_string.c
+ ASN.1 DER, encode a IA5 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Store an IA5 STRING
+ @param in The array of IA5 to store (one per char)
+ @param inlen The number of IA5 to store
+ @param out [out] The destination for the DER encoded IA5 STRING
+ @param outlen [in/out] The max size and resulting size of the DER IA5 STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x16;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += len;
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = der_ia5_char_encode(in[y]);
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c b/Sources/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c
new file mode 100644
index 00000000..e397b1c8
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c
@@ -0,0 +1,172 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_ia5_string.c
+ ASN.1 DER, get length of IA5 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} ia5_table[] = {
+{ '\0', 0 },
+{ '\a', 7 },
+{ '\b', 8 },
+{ '\t', 9 },
+{ '\n', 10 },
+{ '\f', 12 },
+{ '\r', 13 },
+{ ' ', 32 },
+{ '!', 33 },
+{ '"', 34 },
+{ '#', 35 },
+{ '$', 36 },
+{ '%', 37 },
+{ '&', 38 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '*', 42 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ ';', 59 },
+{ '<', 60 },
+{ '=', 61 },
+{ '>', 62 },
+{ '?', 63 },
+{ '@', 64 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ '[', 91 },
+{ '\\', 92 },
+{ ']', 93 },
+{ '^', 94 },
+{ '_', 95 },
+{ '`', 96 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+{ '{', 123 },
+{ '|', 124 },
+{ '}', 125 },
+{ '~', 126 }
+};
+
+int der_ia5_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].code == c) {
+ return ia5_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_ia5_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].value == v) {
+ return ia5_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of IA5 STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_ia5_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + x + noctets;
+
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c b/Sources/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c
new file mode 100644
index 00000000..2c9bf7b7
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c
@@ -0,0 +1,68 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a mp_int integer
+ @param in The DER encoded data
+ @param inlen Size of DER encoded data
+ @param num The first mp_int to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
+{
+ unsigned long x, y;
+ int err;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* min DER INTEGER is 0x02 01 00 == 0 */
+ if (inlen < (1 + 1 + 1)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* ok expect 0x02 when we AND with 0001 1111 [1F] */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the length of the data */
+ inlen -= x;
+ if ((err = der_decode_asn1_length(in + x, &inlen, &y)) != CRYPT_OK) {
+ return err;
+ }
+ x += inlen;
+
+ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* see if it's negative */
+ if (in[x] & 0x80) {
+ void *tmp;
+ if (mp_init(&tmp) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) {
+ mp_clear(tmp);
+ return CRYPT_MEM;
+ }
+ mp_clear(tmp);
+ }
+
+ return CRYPT_OK;
+
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c b/Sources/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c
new file mode 100644
index 00000000..72611496
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c
@@ -0,0 +1,105 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_integer.c
+ ASN.1 DER, encode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */
+/**
+ Store a mp_int integer
+ @param num The first mp_int to encode
+ @param out [out] The destination for the DER encoded integers
+ @param outlen [in/out] The max size and resulting size of the DER encoded integers
+ @return CRYPT_OK if successful
+*/
+int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long tmplen, y, len;
+ int err, leading_zero;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* find out how big this will be */
+ if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < tmplen) {
+ *outlen = tmplen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (mp_cmp_d(num, 0) != LTC_MP_LT) {
+ /* we only need a leading zero if the msb of the first byte is one */
+ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
+ leading_zero = 1;
+ } else {
+ leading_zero = 0;
+ }
+
+ /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
+ y = mp_unsigned_bin_size(num) + leading_zero;
+ } else {
+ leading_zero = 0;
+ y = mp_count_bits(num);
+ y = y + (8 - (y & 7));
+ y = y >> 3;
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --y;
+ }
+
+ /* now store initial data */
+ *out++ = 0x02;
+ len = *outlen - 1;
+ if ((err = der_encode_asn1_length(y, out, &len)) != CRYPT_OK) {
+ return err;
+ }
+ out += len;
+
+ /* now store msbyte of zero if num is non-zero */
+ if (leading_zero) {
+ *out++ = 0x00;
+ }
+
+ /* if it's not zero store it as big endian */
+ if (mp_cmp_d(num, 0) == LTC_MP_GT) {
+ /* now store the mpint */
+ if ((err = mp_to_unsigned_bin(num, out)) != CRYPT_OK) {
+ return err;
+ }
+ } else if (mp_iszero(num) != LTC_MP_YES) {
+ void *tmp;
+
+ /* negative */
+ if (mp_init(&tmp) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* 2^roundup and subtract */
+ y = mp_count_bits(num);
+ y = y + (8 - (y & 7));
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) y -= 8;
+ if (mp_2expt(tmp, y) != CRYPT_OK || mp_add(tmp, num, tmp) != CRYPT_OK) {
+ mp_clear(tmp);
+ return CRYPT_MEM;
+ }
+ if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) {
+ mp_clear(tmp);
+ return err;
+ }
+ mp_clear(tmp);
+ }
+
+ /* we good */
+ *outlen = tmplen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/integer/der_length_integer.c b/Sources/libtomcrypt/pk/asn1/der/integer/der_length_integer.c
new file mode 100644
index 00000000..90e2de37
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/integer/der_length_integer.c
@@ -0,0 +1,55 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The int to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_integer(void *num, unsigned long *outlen)
+{
+ unsigned long z, len;
+ int leading_zero, err;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (mp_cmp_d(num, 0) != LTC_MP_LT) {
+ /* positive */
+
+ /* we only need a leading zero if the msb of the first byte is one */
+ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
+ leading_zero = 1;
+ } else {
+ leading_zero = 0;
+ }
+
+ /* size for bignum */
+ len = leading_zero + mp_unsigned_bin_size(num);
+ } else {
+ /* it's negative */
+ /* find power of 2 that is a multiple of eight and greater than count bits */
+ z = mp_count_bits(num);
+ z = z + (8 - (z & 7));
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z;
+ len = z >> 3;
+ }
+
+ if ((err = der_length_asn1_length(len, &z)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + z + len;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/Sources/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c
new file mode 100644
index 00000000..72512477
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c
@@ -0,0 +1,94 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_object_identifier.c
+ ASN.1 DER, Decode Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Decode OID data and store the array of integers in words
+ @param in The OID DER encoded data
+ @param inlen The length of the OID data
+ @param words [out] The destination of the OID words
+ @param outlen [in/out] The number of OID words
+ @return CRYPT_OK if successful
+*/
+int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
+ unsigned long *words, unsigned long *outlen)
+{
+ unsigned long x, y, t, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* header is at least 3 bytes */
+ if (inlen < 3) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* must be room for at least two words */
+ if (*outlen < 2) {
+ *outlen = 2;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode the packet header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x06) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+
+ if ((len == 0) || (len > (inlen - x))) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode words */
+ y = 0;
+ t = 0;
+ while (len--) {
+ t = (t << 7) | (in[x] & 0x7F);
+ if (!(in[x++] & 0x80)) {
+ /* store t */
+ if (y >= *outlen) {
+ y++;
+ } else {
+ if (y == 0) {
+ if (t <= 79) {
+ words[0] = t / 40;
+ words[1] = t % 40;
+ } else {
+ words[0] = 2;
+ words[1] = t - 80;
+ }
+ y = 2;
+ } else {
+ words[y++] = t;
+ }
+ }
+ t = 0;
+ }
+ }
+
+ if (y > *outlen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else {
+ err = CRYPT_OK;
+ }
+
+ *outlen = y;
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/Sources/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c
new file mode 100644
index 00000000..9a9c62d9
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c
@@ -0,0 +1,92 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_object_identifier.c
+ ASN.1 DER, Encode Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Encode an OID
+ @param words The words to encode (upto 32-bits each)
+ @param nwords The number of words in the OID
+ @param out [out] Destination of OID data
+ @param outlen [in/out] The max and resulting size of the OID
+ @return CRYPT_OK if successful
+*/
+int der_encode_object_identifier(const unsigned long *words, unsigned long nwords,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long i, x, y, z, t, mask, wordbuf;
+ int err;
+
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* check length */
+ if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) {
+ return err;
+ }
+ if (x > *outlen) {
+ *outlen = x;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* compute length to store OID data */
+ z = 0;
+ wordbuf = words[0] * 40 + words[1];
+ for (y = 1; y < nwords; y++) {
+ t = der_object_identifier_bits(wordbuf);
+ z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
+ if (y < nwords - 1) {
+ wordbuf = words[y + 1];
+ }
+ }
+
+ /* store header + length */
+ x = 0;
+ out[x++] = 0x06;
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(z, out + x, &y)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+
+ /* store first byte */
+ wordbuf = words[0] * 40 + words[1];
+ for (i = 1; i < nwords; i++) {
+ /* store 7 bit words in little endian */
+ t = wordbuf & 0xFFFFFFFF;
+ if (t) {
+ y = x;
+ mask = 0;
+ while (t) {
+ out[x++] = (unsigned char)((t & 0x7F) | mask);
+ t >>= 7;
+ mask |= 0x80; /* upper bit is set on all but the last byte */
+ }
+ /* now swap bytes y...x-1 */
+ z = x - 1;
+ while (y < z) {
+ t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t;
+ ++y;
+ --z;
+ }
+ } else {
+ /* zero word */
+ out[x++] = 0x00;
+ }
+
+ if (i < nwords - 1) {
+ wordbuf = words[i + 1];
+ }
+ }
+
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c b/Sources/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c
new file mode 100644
index 00000000..d9ded029
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c
@@ -0,0 +1,77 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_object_identifier.c
+ ASN.1 DER, get length of Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+unsigned long der_object_identifier_bits(unsigned long x)
+{
+ unsigned long c;
+ x &= 0xFFFFFFFF;
+ c = 0;
+ while (x) {
+ ++c;
+ x >>= 1;
+ }
+ return c;
+}
+
+
+/**
+ Gets length of DER encoding of Object Identifier
+ @param nwords The number of OID words
+ @param words The actual OID words to get the size of
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen)
+{
+ unsigned long y, z, t, wordbuf;
+
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+
+ /* must be >= 2 words */
+ if (nwords < 2) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* word1 = 0,1,2 and word2 0..39 */
+ if (words[0] > 2 || (words[0] < 2 && words[1] > 39)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* leading word is the first two */
+ z = 0;
+ wordbuf = words[0] * 40 + words[1];
+ for (y = 1; y < nwords; y++) {
+ t = der_object_identifier_bits(wordbuf);
+ z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
+ if (y < nwords - 1) {
+ /* grab next word */
+ wordbuf = words[y+1];
+ }
+ }
+
+ /* now depending on the length our length encoding changes */
+ if (z < 128) {
+ z += 2;
+ } else if (z < 256) {
+ z += 3;
+ } else if (z < 65536UL) {
+ z += 4;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ *outlen = z;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c b/Sources/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c
new file mode 100644
index 00000000..df847214
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c
@@ -0,0 +1,69 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_octet_string.c
+ ASN.1 DER, encode a OCTET STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a OCTET STRING
+ @param in The DER encoded OCTET STRING
+ @param inlen The size of the DER OCTET STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x04 */
+ if ((in[0] & 0x1F) != 0x04) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len > (inlen - x)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ out[y] = in[x++];
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c b/Sources/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c
new file mode 100644
index 00000000..73f1ee76
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c
@@ -0,0 +1,62 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_octet_string.c
+ ASN.1 DER, encode a OCTET STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store an OCTET STRING
+ @param in The array of OCTETS to store (one per char)
+ @param inlen The number of OCTETS to store
+ @param out [out] The destination for the DER encoded OCTET STRING
+ @param outlen [in/out] The max size and resulting size of the DER OCTET STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x04;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += len;
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = in[y];
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c b/Sources/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c
new file mode 100644
index 00000000..67b071e6
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c
@@ -0,0 +1,33 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_octet_string.c
+ ASN.1 DER, get length of OCTET STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of OCTET STRING
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_octet_string(unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + x + noctets;
+
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c b/Sources/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c
new file mode 100644
index 00000000..3f9b533e
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c
@@ -0,0 +1,73 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_printable_string.c
+ ASN.1 DER, encode a printable STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a printable STRING
+ @param in The DER encoded printable STRING
+ @param inlen The size of the DER printable STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t, err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x13 */
+ if ((in[0] & 0x1F) != 0x13) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len > (inlen - x)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_printable_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c b/Sources/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c
new file mode 100644
index 00000000..7b3aefd1
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_printable_string.c
+ ASN.1 DER, encode a printable STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Store an printable STRING
+ @param in The array of printable to store (one per char)
+ @param inlen The number of printable to store
+ @param out [out] The destination for the DER encoded printable STRING
+ @param outlen [in/out] The max size and resulting size of the DER printable STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x13;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += len;
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = der_printable_char_encode(in[y]);
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c b/Sources/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c
new file mode 100644
index 00000000..c52e36df
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c
@@ -0,0 +1,144 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_printable_string.c
+ ASN.1 DER, get length of Printable STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} printable_table[] = {
+{ ' ', 32 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ '=', 61 },
+{ '?', 63 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+};
+
+int der_printable_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].code == c) {
+ return printable_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_printable_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].value == v) {
+ return printable_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of Printable STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_printable_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + x + noctets;
+
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c b/Sources/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c
new file mode 100644
index 00000000..6d7f8467
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+
+/**
+ @file der_decode_sequence_ex.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a SEQUENCE
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @param flags c.f. enum ltc_der_seq
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *list, unsigned long outlen, unsigned int flags)
+{
+ return der_decode_custom_type_ex(in, inlen, NULL, list, outlen, flags);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/Sources/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c
new file mode 100644
index 00000000..35886cf8
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c
@@ -0,0 +1,541 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_sequence_flexi.c
+ ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static int s_new_element(ltc_asn1_list **l)
+{
+ /* alloc new link */
+ if (*l == NULL) {
+ *l = XCALLOC(1, sizeof(ltc_asn1_list));
+ if (*l == NULL) {
+ return CRYPT_MEM;
+ }
+ } else {
+ (*l)->next = XCALLOC(1, sizeof(ltc_asn1_list));
+ if ((*l)->next == NULL) {
+ return CRYPT_MEM;
+ }
+ (*l)->next->prev = *l;
+ *l = (*l)->next;
+ }
+ return CRYPT_OK;
+}
+
+/**
+ ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
+ @param in The input buffer
+ @param inlen [in/out] The length of the input buffer and on output the amount of decoded data
+ @param out [out] A pointer to the linked list
+ @param depth The depth/level of decoding recursion we've already reached
+ @return CRYPT_OK on success.
+*/
+static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out, unsigned long depth)
+{
+ ltc_asn1_list *l;
+ unsigned long err, identifier, len, totlen, data_offset, id_len, len_len;
+ void *realloc_tmp;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ l = NULL;
+ totlen = 0;
+
+ if (*inlen == 0) {
+ /* alloc new link */
+ if ((err = s_new_element(&l)) != CRYPT_OK) {
+ goto error;
+ }
+ }
+
+ /* scan the input and and get lengths and what not */
+ while (*inlen) {
+ /* alloc new link */
+ if ((err = s_new_element(&l)) != CRYPT_OK) {
+ goto error;
+ }
+
+ id_len = *inlen;
+ if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) {
+ goto error;
+ }
+ /* read the type byte */
+ identifier = *in;
+
+ if (l->type != LTC_ASN1_EOL) {
+ /* fetch length */
+ len_len = *inlen - id_len;
+#if defined(LTC_TEST_DBG)
+ data_offset = 666;
+ len = 0;
+#endif
+ if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) {
+#if defined(LTC_TEST_DBG)
+ fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
+#endif
+ goto error;
+ } else if (len > (*inlen - id_len - len_len)) {
+ err = CRYPT_INVALID_PACKET;
+#if defined(LTC_TEST_DBG)
+ fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
+#endif
+ goto error;
+ }
+ data_offset = id_len + len_len;
+#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
+ if (l->type == LTC_ASN1_CUSTOM_TYPE && l->klass == LTC_ASN1_CL_CONTEXT_SPECIFIC) {
+ fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag);
+ } else {
+ fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]);
+ }
+#endif
+ len += data_offset;
+
+ if (l->type == LTC_ASN1_CUSTOM_TYPE) {
+ /* Custom type, use the 'used' field to store the original identifier */
+ l->used = identifier;
+ if (l->pc == LTC_ASN1_PC_CONSTRUCTED) {
+ /* treat constructed elements like SEQUENCEs */
+ identifier = 0x20;
+ } else {
+ /* primitive elements are treated as opaque data */
+ identifier = 0x80;
+ }
+ }
+ } else {
+ /* Init this so gcc won't complain,
+ * as this case will only be hit when we
+ * can't decode the identifier so the
+ * switch-case should go to default anyway...
+ */
+ data_offset = 0;
+ len = 0;
+ }
+
+ /* now switch on type */
+ switch (identifier) {
+ case 0x01: /* BOOLEAN */
+ if (l->type != LTC_ASN1_BOOLEAN) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = 1;
+ l->data = XCALLOC(1, sizeof(int));
+
+ if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_boolean(&len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x02: /* INTEGER */
+ if (l->type != LTC_ASN1_INTEGER) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = 1;
+ if ((err = mp_init(&l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* decode field */
+ if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* calc length of object */
+ if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x03: /* BIT */
+ if (l->type != LTC_ASN1_BIT_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x04: /* OCTET */
+ if (l->type != LTC_ASN1_OCTET_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x05: /* NULL */
+ if (l->type != LTC_ASN1_NULL) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* valid NULL is 0x05 0x00 */
+ if (in[0] != 0x05 || in[1] != 0x00) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* simple to store ;-) */
+ l->data = NULL;
+ l->size = 0;
+ len = 2;
+
+ break;
+
+ case 0x06: /* OID */
+ if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = len;
+
+ if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* resize it to save a bunch of mem */
+ if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) {
+ /* out of heap but this is not an error */
+ break;
+ }
+ l->data = realloc_tmp;
+ break;
+
+ case 0x0C: /* UTF8 */
+
+ /* init field */
+ if (l->type != LTC_ASN1_UTF8_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+ l->size = len;
+
+ if ((l->data = XCALLOC(l->size, sizeof(wchar_t))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x13: /* PRINTABLE */
+ if (l->type != LTC_ASN1_PRINTABLE_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x14: /* TELETEXT */
+ if (l->type != LTC_ASN1_TELETEX_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x16: /* IA5 */
+ if (l->type != LTC_ASN1_IA5_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x17: /* UTC TIME */
+ if (l->type != LTC_ASN1_UTCTIME) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = 1;
+
+ if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ len = *inlen;
+ if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x18:
+ if (l->type != LTC_ASN1_GENERALIZEDTIME) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) {
+ goto error;
+ }
+
+ break;
+
+ case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */
+ case 0x30: /* SEQUENCE */
+ case 0x31: /* SET */
+
+ /* init field */
+ if (identifier == 0x20) {
+ if (l->type != LTC_ASN1_CUSTOM_TYPE) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+ }
+ else if (identifier == 0x30) {
+ if (l->type != LTC_ASN1_SEQUENCE) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+ }
+ else {
+ if (l->type != LTC_ASN1_SET) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+ }
+
+ /* check that we don't go over the recursion limit */
+ if (depth > LTC_DER_MAX_RECURSION) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ if ((l->data = XMALLOC(len)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ XMEMCPY(l->data, in, len);
+ l->size = len;
+
+
+ /* jump to the start of the data */
+ in += data_offset;
+ *inlen -= data_offset;
+ len -= data_offset;
+
+ /* save the decoded ASN.1 len */
+ len_len = len;
+
+ /* Sequence elements go as child */
+ if ((err = s_der_decode_sequence_flexi(in, &len, &(l->child), depth+1)) != CRYPT_OK) {
+ goto error;
+ }
+ if (len_len != len) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* len update */
+ totlen += data_offset;
+
+ /* the flexi decoder can also do nothing, so make sure a child has been allocated */
+ if (l->child) {
+ /* link them up y0 */
+ l->child->parent = l;
+ }
+
+ break;
+
+ case 0x80: /* Context-specific */
+ if (l->type != LTC_ASN1_CUSTOM_TYPE) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ if ((l->data = XCALLOC(1, len - data_offset)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ XMEMCPY(l->data, in + data_offset, len - data_offset);
+ l->size = len - data_offset;
+
+ break;
+
+ default:
+ /* invalid byte ... this is a soft error */
+ /* remove link */
+ if (l->prev) {
+ l = l->prev;
+ XFREE(l->next);
+ l->next = NULL;
+ }
+ goto outside;
+ }
+
+ /* advance pointers */
+ totlen += len;
+ in += len;
+ *inlen -= len;
+ }
+
+outside:
+
+ /* in case we processed anything */
+ if (totlen) {
+ /* rewind l please */
+ while (l->prev != NULL || l->parent != NULL) {
+ if (l->parent != NULL) {
+ l = l->parent;
+ } else {
+ l = l->prev;
+ }
+ }
+ }
+
+ /* return */
+ *out = l;
+ *inlen = totlen;
+ return CRYPT_OK;
+
+error:
+ /* free list */
+ der_sequence_free(l);
+
+ return err;
+}
+
+/**
+ ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
+ @param in The input buffer
+ @param inlen [in/out] The length of the input buffer and on output the amount of decoded data
+ @param out [out] A pointer to the linked list
+ @return CRYPT_OK on success.
+*/
+int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
+{
+ return s_der_decode_sequence_flexi(in, inlen, out, 0);
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c b/Sources/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c
new file mode 100644
index 00000000..5d1c9474
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c
@@ -0,0 +1,181 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+
+/**
+ @file der_decode_sequence_multi.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @param a1 Initialized argument list #1
+ @param a2 Initialized argument list #2 (copy of #1)
+ @param flags c.f. enum ltc_der_seq
+ @return CRYPT_OK on success
+*/
+static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags)
+{
+ int err;
+ ltc_asn1_type type;
+ unsigned long size, x;
+ void *data;
+ ltc_asn1_list *list;
+
+ LTC_ARGCHK(in != NULL);
+
+ /* get size of output that will be required */
+ x = 0;
+ for (;;) {
+ type = (ltc_asn1_type)va_arg(a1, int);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ size = va_arg(a1, unsigned long);
+ data = va_arg(a1, void*);
+ LTC_UNUSED_PARAM(size);
+ LTC_UNUSED_PARAM(data);
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_RAW_BIT_STRING:
+ case LTC_ASN1_TELETEX_STRING:
+ case LTC_ASN1_GENERALIZEDTIME:
+ ++x;
+ break;
+
+ case LTC_ASN1_EOL:
+ case LTC_ASN1_CUSTOM_TYPE:
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ /* allocate structure for x elements */
+ if (x == 0) {
+ return CRYPT_NOP;
+ }
+
+ list = XCALLOC(x, sizeof(*list));
+ if (list == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in the structure */
+ x = 0;
+ for (;;) {
+ type = (ltc_asn1_type)va_arg(a2, int);
+ size = va_arg(a2, unsigned long);
+ data = va_arg(a2, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_RAW_BIT_STRING:
+ case LTC_ASN1_TELETEX_STRING:
+ case LTC_ASN1_GENERALIZEDTIME:
+ LTC_SET_ASN1(list, x++, type, data, size);
+ break;
+ /* coverity[dead_error_line] */
+ case LTC_ASN1_EOL:
+ case LTC_ASN1_CUSTOM_TYPE:
+ break;
+ }
+ }
+
+ err = der_decode_sequence_ex(in, inlen, list, x, flags);
+ XFREE(list);
+ return err;
+}
+
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @remark <...> is of the form (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
+{
+ va_list a1, a2;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+
+ va_start(a1, inlen);
+ va_start(a2, inlen);
+
+ err = s_der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED);
+
+ va_end(a2);
+ va_end(a1);
+
+ return err;
+}
+
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @param flags c.f. enum ltc_der_seq
+ @remark <...> is of the form (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...)
+{
+ va_list a1, a2;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+
+ va_start(a1, flags);
+ va_start(a2, flags);
+
+ err = s_der_decode_sequence_va(in, inlen, a1, a2, flags);
+
+ va_end(a2);
+ va_end(a1);
+
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c b/Sources/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c
new file mode 100644
index 00000000..2ea33a6d
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c
@@ -0,0 +1,202 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+
+/**
+ @file der_encode_sequence_ex.c
+ ASN.1 DER, encode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a SEQUENCE
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF
+ @return CRYPT_OK on success
+*/
+int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int type_of)
+{
+ int err;
+ ltc_asn1_type type;
+ unsigned long size, x, y, z, i;
+ void *data;
+
+ LTC_ARGCHK(list != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0; z = 0;
+ if (der_length_sequence_ex(list, inlen, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG;
+
+ /* too big ? */
+ if (*outlen < y) {
+ *outlen = y;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* store header */
+ x = 0;
+ out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
+
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += y;
+
+ /* store data */
+ *outlen -= x;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = *outlen;
+ if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_RAW_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = *outlen;
+ if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ out[x] = 0x05;
+ out[x+1] = 0x00;
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = *outlen;
+ if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = *outlen;
+ if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = *outlen;
+ if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = *outlen;
+ if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *outlen;
+ if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ z = *outlen;
+ if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = *outlen;
+ if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ z = *outlen;
+ if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SEQUENCE:
+ z = *outlen;
+ if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ z = *outlen;
+ if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_EOL:
+ case LTC_ASN1_TELETEX_STRING:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+ x += z;
+ *outlen -= z;
+ }
+ *outlen = x;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c b/Sources/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c
new file mode 100644
index 00000000..7758585e
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c
@@ -0,0 +1,139 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+#include
+
+
+/**
+ @file der_encode_sequence_multi.c
+ ASN.1 DER, encode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a SEQUENCE type using a VA list
+ @param out [out] Destination for data
+ @param outlen [in/out] Length of buffer and resulting length of output
+ @remark <...> is of the form (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
+{
+ int err;
+ ltc_asn1_type type;
+ unsigned long size, x;
+ void *data;
+ va_list args;
+ ltc_asn1_list *list;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ va_start(args, outlen);
+ x = 0;
+ for (;;) {
+ type = (ltc_asn1_type)va_arg(args, int);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+ LTC_UNUSED_PARAM(size);
+ LTC_UNUSED_PARAM(data);
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_RAW_BIT_STRING:
+ case LTC_ASN1_GENERALIZEDTIME:
+ ++x;
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_CUSTOM_TYPE:
+ case LTC_ASN1_EOL:
+ case LTC_ASN1_TELETEX_STRING:
+ va_end(args);
+ return CRYPT_INVALID_ARG;
+ }
+ }
+ va_end(args);
+
+ /* allocate structure for x elements */
+ if (x == 0) {
+ return CRYPT_NOP;
+ }
+
+ list = XCALLOC(x, sizeof(*list));
+ if (list == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in the structure */
+ va_start(args, outlen);
+ x = 0;
+ for (;;) {
+ type = (ltc_asn1_type)va_arg(args, int);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_RAW_BIT_STRING:
+ case LTC_ASN1_GENERALIZEDTIME:
+ LTC_SET_ASN1(list, x++, type, data, size);
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_CUSTOM_TYPE:
+ case LTC_ASN1_EOL:
+ case LTC_ASN1_TELETEX_STRING:
+ va_end(args);
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ va_end(args);
+
+ err = der_encode_sequence(list, x, out, outlen);
+LBL_ERR:
+ XFREE(list);
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/asn1/der/sequence/der_flexi_sequence_cmp.c b/Sources/libtomcrypt/pk/asn1/der/sequence/der_flexi_sequence_cmp.c
new file mode 100644
index 00000000..026eb504
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/sequence/der_flexi_sequence_cmp.c
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_sequence.c
+ ASN.1 DER, length a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Get the length of a DER sequence
+ @param list The sequences of items in the SEQUENCE
+ @param inlen The number of items
+ @param outlen [out] The length required in octets to store it
+ @return CRYPT_OK on success
+*/
+
+int der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check)
+{
+ ltc_asn1_list *cur;
+ if (flexi->type != LTC_ASN1_SEQUENCE) {
+ return CRYPT_INVALID_PACKET;
+ }
+ cur = flexi->child;
+ while(check->t != LTC_ASN1_EOL) {
+ if (!LTC_ASN1_IS_TYPE(cur, check->t)) {
+ return CRYPT_INVALID_PACKET;
+ }
+ if (check->pp != NULL) *check->pp = cur;
+ cur = cur->next;
+ check++;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c b/Sources/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c
new file mode 100644
index 00000000..6d25391d
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c
@@ -0,0 +1,179 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_sequence.c
+ ASN.1 DER, length a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Get the length of a DER sequence
+ @param list The sequences of items in the SEQUENCE
+ @param inlen The number of items
+ @param outlen [out] The length required in octets to store it
+ @return CRYPT_OK on success
+*/
+int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen)
+{
+ return der_length_sequence_ex(list, inlen, outlen, NULL);
+}
+
+int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen, unsigned long *payloadlen)
+{
+ int err;
+ ltc_asn1_type type;
+ unsigned long size, x, y, i;
+ void *data;
+
+ LTC_ARGCHK(list != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ /* some items may be optional during import */
+ if (!list[i].used && list[i].optional) continue;
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ if ((err = der_length_boolean(&x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_RAW_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_TELETEX_STRING:
+ if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_EOL:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if (payloadlen != NULL) {
+ *payloadlen = y;
+ }
+
+ /* store size */
+ *outlen = y + x + 1;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c b/Sources/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c
new file mode 100644
index 00000000..b7cbd070
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c
@@ -0,0 +1,53 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_sequence_free.c
+ ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Free memory allocated by der_decode_sequence_flexi()
+ @param in The list to free
+*/
+void der_sequence_free(ltc_asn1_list *in)
+{
+ ltc_asn1_list *l;
+
+ if (!in) return;
+
+ /* walk to the start of the chain */
+ while (in->prev != NULL || in->parent != NULL) {
+ if (in->parent != NULL) {
+ in = in->parent;
+ } else {
+ in = in->prev;
+ }
+ }
+
+ /* now walk the list and free stuff */
+ while (in != NULL) {
+ /* is there a child? */
+ if (in->child) {
+ /* disconnect */
+ in->child->parent = NULL;
+ der_sequence_free(in->child);
+ }
+
+ switch (in->type) {
+ case LTC_ASN1_SETOF: break;
+ case LTC_ASN1_INTEGER : if (in->data != NULL) { mp_clear(in->data); } break;
+ default : if (in->data != NULL) { XFREE(in->data); }
+ }
+
+ /* move to next and free current */
+ l = in->next;
+ XFREE(in);
+ in = l;
+ }
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/sequence/der_sequence_shrink.c b/Sources/libtomcrypt/pk/asn1/der/sequence/der_sequence_shrink.c
new file mode 100644
index 00000000..22634a32
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/sequence/der_sequence_shrink.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_sequence_shrink.c
+ Free memory allocated for CONSTRUCTED, SET or SEQUENCE elements by der_decode_sequence_flexi(), Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Free memory allocated for CONSTRUCTED,
+ SET or SEQUENCE elements by der_decode_sequence_flexi()
+ @param in The list to shrink
+*/
+void der_sequence_shrink(ltc_asn1_list *in)
+{
+ if (!in) return;
+
+ /* now walk the list and free stuff */
+ while (in != NULL) {
+ /* is there a child? */
+ if (in->child) {
+ der_sequence_shrink(in->child);
+ }
+
+ switch (in->type) {
+ case LTC_ASN1_CUSTOM_TYPE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break;
+ default: break;
+ }
+
+ /* move to next and free current */
+ in = in->next;
+ }
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/set/der_encode_set.c b/Sources/libtomcrypt/pk/asn1/der/set/der_encode_set.c
new file mode 100644
index 00000000..1e90a1f2
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/set/der_encode_set.c
@@ -0,0 +1,74 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_set.c
+ ASN.1 DER, Encode a SET, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/* LTC define to ASN.1 TAG */
+static int s_ltc_to_asn1(ltc_asn1_type v)
+{
+ return der_asn1_type_to_identifier_map[v];
+}
+
+
+static int s_qsort_helper(const void *a, const void *b)
+{
+ ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b;
+ int r;
+
+ r = s_ltc_to_asn1(A->type) - s_ltc_to_asn1(B->type);
+
+ /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC. So we force it to be :-) */
+ if (r == 0) {
+ /* their order in the original list now determines the position */
+ return A->used - B->used;
+ }
+ return r;
+}
+
+/*
+ Encode a SET type
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_set(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ ltc_asn1_list *copy;
+ unsigned long x;
+ int err;
+
+ /* make copy of list */
+ copy = XCALLOC(inlen, sizeof(*copy));
+ if (copy == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in used member with index so we can fully sort it */
+ for (x = 0; x < inlen; x++) {
+ copy[x] = list[x];
+ copy[x].used = x;
+ }
+
+ /* sort it by the "type" field */
+ XQSORT(copy, inlen, sizeof(*copy), &s_qsort_helper);
+
+ /* call der_encode_sequence_ex() */
+ err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET);
+
+ /* free list */
+ XFREE(copy);
+
+ return err;
+}
+
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/set/der_encode_setof.c b/Sources/libtomcrypt/pk/asn1/der/set/der_encode_setof.c
new file mode 100644
index 00000000..184b6ec3
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/set/der_encode_setof.c
@@ -0,0 +1,151 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_setof.c
+ ASN.1 DER, Encode SET OF, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+struct edge {
+ unsigned char *start;
+ unsigned long size;
+};
+
+static int s_qsort_helper(const void *a, const void *b)
+{
+ struct edge *A = (struct edge *)a, *B = (struct edge *)b;
+ int r;
+ unsigned long x;
+
+ /* compare min length */
+ r = XMEMCMP(A->start, B->start, MIN(A->size, B->size));
+
+ if (r == 0 && A->size != B->size) {
+ if (A->size > B->size) {
+ for (x = B->size; x < A->size; x++) {
+ if (A->start[x]) {
+ return 1;
+ }
+ }
+ } else {
+ for (x = A->size; x < B->size; x++) {
+ if (B->start[x]) {
+ return -1;
+ }
+ }
+ }
+ }
+
+ return r;
+}
+
+/**
+ Encode a SETOF stucture
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_setof(const ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, z;
+ ptrdiff_t hdrlen;
+ int err;
+ struct edge *edges;
+ unsigned char *ptr, *buf;
+
+ /* check that they're all the same type */
+ for (x = 1; x < inlen; x++) {
+ if (list[x].type != list[x-1].type) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ /* alloc buffer to store copy of output */
+ buf = XCALLOC(1, *outlen);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* encode list */
+ if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+
+ /* allocate edges */
+ edges = XCALLOC(inlen, sizeof(*edges));
+ if (edges == NULL) {
+ XFREE(buf);
+ return CRYPT_MEM;
+ }
+
+ /* skip header */
+ ptr = buf + 1;
+
+ /* now skip length data */
+ x = *ptr++;
+ if (x >= 0x80) {
+ ptr += (x & 0x7F);
+ }
+
+ /* get the size of the static header */
+ hdrlen = ptr - buf;
+
+
+ /* scan for edges */
+ x = 0;
+ while (ptr < (buf + *outlen)) {
+ /* store start */
+ edges[x].start = ptr;
+
+ /* skip type */
+ z = 1;
+
+ /* parse length */
+ y = ptr[z++];
+ if (y < 128) {
+ edges[x].size = y;
+ } else {
+ y &= 0x7F;
+ edges[x].size = 0;
+ while (y--) {
+ edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]);
+ }
+ }
+
+ /* skip content */
+ edges[x].size += z;
+ ptr += edges[x].size;
+ ++x;
+ }
+
+ /* sort based on contents (using edges) */
+ XQSORT(edges, inlen, sizeof(*edges), &s_qsort_helper);
+
+ /* copy static header */
+ XMEMCPY(out, buf, hdrlen);
+
+ /* copy+sort using edges+indecies to output from buffer */
+ for (y = (unsigned long)hdrlen, x = 0; x < inlen; x++) {
+ XMEMCPY(out+y, edges[x].start, edges[x].size);
+ y += edges[x].size;
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, *outlen);
+#endif
+
+ /* free buffers */
+ XFREE(edges);
+ XFREE(buf);
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c b/Sources/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c
new file mode 100644
index 00000000..e00702d1
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c
@@ -0,0 +1,60 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_short_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a short integer
+ @param in The DER encoded data
+ @param inlen Size of data
+ @param num [out] The integer to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num)
+{
+ unsigned long len, x, y;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* check length */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the packet len */
+ len = in[x++];
+
+ if (x + len > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ if (len > sizeof(unsigned long)) {
+ return CRYPT_OVERFLOW;
+ }
+
+ /* read number */
+ y = 0;
+ while (len--) {
+ y = (y<<8) | (unsigned long)in[x++];
+ }
+ *num = y;
+
+ return CRYPT_OK;
+
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c b/Sources/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c
new file mode 100644
index 00000000..3af47c5f
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c
@@ -0,0 +1,85 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_short_integer.c
+ ASN.1 DER, encode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a short integer in the range (0,2^32-1)
+ @param num The integer to encode
+ @param out [out] The destination for the DER encoded integers
+ @param outlen [in/out] The max size and resulting size of the DER encoded integers
+ @return CRYPT_OK if successful
+*/
+int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long len, x, y, z;
+ int err;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* force to 32 bits */
+ num &= 0xFFFFFFFFUL;
+
+ /* find out how big this will be */
+ if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < len) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* get len of output */
+ z = 0;
+ y = num;
+ while (y) {
+ ++z;
+ y >>= 8;
+ }
+
+ /* handle zero */
+ if (z == 0) {
+ z = 1;
+ }
+
+ /* see if msb is set */
+ z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
+
+ /* adjust the number so the msB is non-zero */
+ for (x = 0; (z <= 4) && (x < (4 - z)); x++) {
+ num <<= 8;
+ }
+
+ /* store header */
+ x = 0;
+ out[x++] = 0x02;
+ out[x++] = (unsigned char)z;
+
+ /* if 31st bit is set output a leading zero and decrement count */
+ if (z == 5) {
+ out[x++] = 0;
+ --z;
+ }
+
+ /* store values */
+ for (y = 0; y < z; y++) {
+ out[x++] = (unsigned char)((num >> 24) & 0xFF);
+ num <<= 8;
+ }
+
+ /* we good */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c b/Sources/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c
new file mode 100644
index 00000000..aeee9481
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c
@@ -0,0 +1,52 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_short_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The integer to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_short_integer(unsigned long num, unsigned long *outlen)
+{
+ unsigned long z, y;
+ int err;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ /* force to 32 bits */
+ num &= 0xFFFFFFFFUL;
+
+ /* get the number of bytes */
+ z = 0;
+ y = num;
+ while (y) {
+ ++z;
+ y >>= 8;
+ }
+
+ /* handle zero */
+ if (z == 0) {
+ z = 1;
+ } else if ((num&(1UL<<((z<<3) - 1))) != 0) {
+ /* in case msb is set */
+ ++z;
+ }
+
+ if ((err = der_length_asn1_length(z, &y)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + y + z;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/teletex_string/der_decode_teletex_string.c b/Sources/libtomcrypt/pk/asn1/der/teletex_string/der_decode_teletex_string.c
new file mode 100644
index 00000000..6779cd56
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/teletex_string/der_decode_teletex_string.c
@@ -0,0 +1,72 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_teletex_string.c
+ ASN.1 DER, encode a teletex STRING
+*/
+
+#ifdef LTC_DER
+
+/**
+ Store a teletex STRING
+ @param in The DER encoded teletex STRING
+ @param inlen The size of the DER teletex STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t, err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x14 */
+ if ((in[0] & 0x1F) != 0x14) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len > (inlen - x)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_teletex_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/teletex_string/der_length_teletex_string.c b/Sources/libtomcrypt/pk/asn1/der/teletex_string/der_length_teletex_string.c
new file mode 100644
index 00000000..05dc4b02
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/teletex_string/der_length_teletex_string.c
@@ -0,0 +1,188 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_teletex_string.c
+ ASN.1 DER, get length of teletex STRING
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} teletex_table[] = {
+{ '\0', 0 },
+{ '\a', 7 },
+{ '\b', 8 },
+{ '\t', 9 },
+{ '\n', 10 },
+{ '\v', 11 },
+{ '\f', 12 },
+{ '\r', 13 },
+{ ' ', 32 },
+{ '!', 33 },
+{ '"', 34 },
+{ '%', 37 },
+{ '&', 38 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ ';', 59 },
+{ '<', 60 },
+{ '=', 61 },
+{ '>', 62 },
+{ '?', 63 },
+{ '@', 64 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ '[', 91 },
+{ ']', 93 },
+{ '_', 95 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+{ '|', 124 },
+{ ' ', 160 },
+{ 0xa1, 161 },
+{ 0xa2, 162 },
+{ 0xa3, 163 },
+{ '$', 164 },
+{ 0xa5, 165 },
+{ '#', 166 },
+{ 0xa7, 167 },
+{ 0xa4, 168 },
+{ 0xab, 171 },
+{ 0xb0, 176 },
+{ 0xb1, 177 },
+{ 0xb2, 178 },
+{ 0xb3, 179 },
+{ 0xd7, 180 },
+{ 0xb5, 181 },
+{ 0xb6, 182 },
+{ 0xb7, 183 },
+{ 0xf7, 184 },
+{ 0xbb, 187 },
+{ 0xbc, 188 },
+{ 0xbd, 189 },
+{ 0xbe, 190 },
+{ 0xbf, 191 },
+};
+
+int der_teletex_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) {
+ if (teletex_table[x].code == c) {
+ return teletex_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_teletex_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) {
+ if (teletex_table[x].value == v) {
+ return teletex_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of teletex STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_teletex_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + x + noctets;
+
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c b/Sources/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c
new file mode 100644
index 00000000..6149bfed
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c
@@ -0,0 +1,116 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_utctime.c
+ ASN.1 DER, decode a UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static int s_char_to_int(unsigned char x)
+{
+ switch (x) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ default: return 100;
+ }
+}
+
+#define DECODE_V(y, max) \
+ y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \
+ if (y >= max) return CRYPT_INVALID_PACKET; \
+ x += 2;
+
+/**
+ Decodes a UTC time structure in DER format (reads all 6 valid encoding formats)
+ @param in Input buffer
+ @param inlen Length of input buffer in octets
+ @param out [out] Destination of UTC time structure
+ @return CRYPT_OK if successful
+*/
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+ ltc_utctime *out)
+{
+ unsigned char buf[32] = { 0 }; /* initialize as all zeroes */
+ unsigned long x;
+ int y;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* check header */
+ if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode the string */
+ for (x = 0; x < in[1]; x++) {
+ y = der_ia5_value_decode(in[x+2]);
+ if (y == -1) {
+ return CRYPT_INVALID_PACKET;
+ }
+ buf[x] = y;
+ }
+ *inlen = 2 + x;
+
+
+ /* possible encodings are
+YYMMDDhhmmZ
+YYMMDDhhmm+hh'mm'
+YYMMDDhhmm-hh'mm'
+YYMMDDhhmmssZ
+YYMMDDhhmmss+hh'mm'
+YYMMDDhhmmss-hh'mm'
+
+ So let's do a trivial decode upto [including] mm
+ */
+
+ x = 0;
+ DECODE_V(out->YY, 100);
+ DECODE_V(out->MM, 13);
+ DECODE_V(out->DD, 32);
+ DECODE_V(out->hh, 24);
+ DECODE_V(out->mm, 60);
+
+ /* clear timezone and seconds info */
+ out->off_dir = out->off_hh = out->off_mm = out->ss = 0;
+
+ /* now is it Z, +, - or 0-9 */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ }
+ if (buf[x] == '+' || buf[x] == '-') {
+ out->off_dir = (buf[x++] == '+') ? 0 : 1;
+ DECODE_V(out->off_hh, 24);
+ DECODE_V(out->off_mm, 60);
+ return CRYPT_OK;
+ }
+
+ /* decode seconds */
+ DECODE_V(out->ss, 60);
+
+ /* now is it Z, +, - */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ }
+ if (buf[x] == '+' || buf[x] == '-') {
+ out->off_dir = (buf[x++] == '+') ? 0 : 1;
+ DECODE_V(out->off_hh, 24);
+ DECODE_V(out->off_mm, 60);
+ return CRYPT_OK;
+ }
+ return CRYPT_INVALID_PACKET;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c b/Sources/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c
new file mode 100644
index 00000000..b1c6fbe6
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c
@@ -0,0 +1,71 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_utctime.c
+ ASN.1 DER, encode a UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const char * const baseten = "0123456789";
+
+#define STORE_V(y) \
+ out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \
+ out[x++] = der_ia5_char_encode(baseten[y % 10]);
+
+/**
+ Encodes a UTC time structure in DER format
+ @param utctime The UTC time structure to encode
+ @param out The destination of the DER encoding of the UTC time structure
+ @param outlen [in/out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_encode_utctime(const ltc_utctime *utctime,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, tmplen;
+ int err;
+
+ LTC_ARGCHK(utctime != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = der_length_utctime(utctime, &tmplen)) != CRYPT_OK) {
+ return err;
+ }
+ if (tmplen > *outlen) {
+ *outlen = tmplen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store header */
+ out[0] = 0x17;
+
+ /* store values */
+ x = 2;
+ STORE_V(utctime->YY);
+ STORE_V(utctime->MM);
+ STORE_V(utctime->DD);
+ STORE_V(utctime->hh);
+ STORE_V(utctime->mm);
+ STORE_V(utctime->ss);
+
+ if (utctime->off_mm || utctime->off_hh) {
+ out[x++] = der_ia5_char_encode(utctime->off_dir ? '-' : '+');
+ STORE_V(utctime->off_hh);
+ STORE_V(utctime->off_mm);
+ } else {
+ out[x++] = der_ia5_char_encode('Z');
+ }
+
+ /* store length */
+ out[1] = (unsigned char)(x - 2);
+
+ /* all good let's return */
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c b/Sources/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c
new file mode 100644
index 00000000..b93c25f8
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_utctime.c
+ ASN.1 DER, get length of UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Gets length of DER encoding of UTCTIME
+ @param utctime The UTC time structure to get the size of
+ @param outlen [out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_length_utctime(const ltc_utctime *utctime, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(utctime != NULL);
+
+ if (utctime->off_hh == 0 && utctime->off_mm == 0) {
+ /* we encode as YYMMDDhhmmssZ */
+ *outlen = 2 + 13;
+ } else {
+ /* we encode as YYMMDDhhmmss{+|-}hh'mm' */
+ *outlen = 2 + 17;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c b/Sources/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c
new file mode 100644
index 00000000..ee543ddb
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c
@@ -0,0 +1,118 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_decode_utf8_string.c
+ ASN.1 DER, encode a UTF8 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Decode a UTF8 STRING and recover an array of unicode characters.
+ @param in The DER encoded UTF8 STRING
+ @param inlen The size of the DER UTF8 STRING
+ @param out [out] The array of unicode characters (wchar_t*)
+ @param outlen [in/out] The number of unicode characters in the array
+ @return CRYPT_OK if successful
+*/
+int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
+ wchar_t *out, unsigned long *outlen)
+{
+ wchar_t tmp;
+ unsigned long x, y, z, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x0C */
+ if ((in[0] & 0x1F) != 0x0C) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+
+ if (len > (inlen - x)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* proceed to recover unicode characters from utf8 data.
+ for reference see Section 3 of RFC 3629:
+
+ https://tools.ietf.org/html/rfc3629#section-3
+ */
+ len += x;
+ for (y = 0; x < len; ) {
+ /* read first byte */
+ tmp = in[x++];
+
+ /* a unicode character is recovered from a sequence of 1 to 4 utf8 bytes.
+ the form of those bytes must match a row in the following table:
+
+ 0xxxxxxx
+ 110xxxxx 10xxxxxx
+ 1110xxxx 10xxxxxx 10xxxxxx
+ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+ the number of leading ones in the first byte (0,2,3,4) determines the
+ number of remaining bytes to read (0,1,2,3)
+ */
+
+ /* determine z, the number of leading ones.
+ this is done by left-shifting tmp, which clears the ms-bits */
+ for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF);
+
+ /* z should be in {0,2,3,4} */
+ if (z == 1 || z > 4) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* right-shift tmp to restore least-sig bits */
+ tmp >>= z;
+
+ /* now update z so it equals the number of additional bytes to read */
+ if (z > 0) { --z; }
+
+ if (x + z > len) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read remaining bytes */
+ while (z-- != 0) {
+ if ((in[x] & 0xC0) != 0x80) {
+ return CRYPT_INVALID_PACKET;
+ }
+ tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F);
+ }
+
+ if (y < *outlen) {
+ out[y] = tmp;
+ }
+ y++;
+ }
+ if (y > *outlen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else {
+ err = CRYPT_OK;
+ }
+ *outlen = y;
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c b/Sources/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c
new file mode 100644
index 00000000..f2c07c2a
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c
@@ -0,0 +1,75 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_encode_utf8_string.c
+ ASN.1 DER, encode a UTF8 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store an UTF8 STRING
+ @param in The array of UTF8 to store (one per wchar_t)
+ @param inlen The number of UTF8 to store
+ @param out [out] The destination for the DER encoded UTF8 STRING
+ @param outlen [in/out] The max size and resulting size of the DER UTF8 STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ for (x = len = 0; x < inlen; x++) {
+ if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG;
+ len += der_utf8_charsize(in[x]);
+ }
+ if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
+ return err;
+ }
+ x += len + 1;
+
+ /* too big? */
+ if (x > *outlen) {
+ *outlen = x;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x0C;
+
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(len, out + x, &y)) != CRYPT_OK) {
+ return err;
+ }
+ x += y;
+
+ /* store UTF8 */
+ for (y = 0; y < inlen; y++) {
+ switch (der_utf8_charsize(in[y])) {
+ case 1: out[x++] = (unsigned char)in[y]; break;
+ case 2: out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F); out[x++] = 0x80 | (in[y] & 0x3F); break;
+ case 3: out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break;
+#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF
+ case 4: out[x++] = 0xF0 | ((in[y] >> 18) & 0x07); out[x++] = 0x80 | ((in[y] >> 12) & 0x3F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break;
+#endif
+ }
+ }
+
+ /* return length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c b/Sources/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c
new file mode 100644
index 00000000..424002b2
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c
@@ -0,0 +1,81 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file der_length_utf8_string.c
+ ASN.1 DER, get length of UTF8 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/** Return the size in bytes of a UTF-8 character
+ @param c The UTF-8 character to measure
+ @return The size in bytes
+*/
+unsigned long der_utf8_charsize(const wchar_t c)
+{
+ if (c <= 0x7F) {
+ return 1;
+ }
+ if (c <= 0x7FF) {
+ return 2;
+ }
+#if LTC_WCHAR_MAX == 0xFFFF
+ return 3;
+#else
+ if (c <= 0xFFFF) {
+ return 3;
+ }
+ return 4;
+#endif
+}
+
+/**
+ Test whether the given code point is valid character
+ @param c The UTF-8 character to test
+ @return 1 - valid, 0 - invalid
+*/
+int der_utf8_valid_char(const wchar_t c)
+{
+ LTC_UNUSED_PARAM(c);
+#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF
+ if (c > 0x10FFFF) return 0;
+#endif
+#if LTC_WCHAR_MAX != 0xFFFF && LTC_WCHAR_MAX != 0xFFFFFFFF
+ if (c < 0) return 0;
+#endif
+ return 1;
+}
+
+/**
+ Gets length of DER encoding of UTF8 STRING
+ @param in The characters to measure the length of
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ len = 0;
+ for (x = 0; x < noctets; x++) {
+ if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG;
+ len += der_utf8_charsize(in[x]);
+ }
+
+ if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + x + len;
+
+ return CRYPT_OK;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/asn1/oid/pk_get.c b/Sources/libtomcrypt/pk/asn1/oid/pk_get.c
new file mode 100644
index 00000000..48a8a984
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/oid/pk_get.c
@@ -0,0 +1,106 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_DER
+
+typedef struct {
+ enum ltc_oid_id id;
+ enum ltc_pka_id pka;
+ const char* oid;
+} oid_table_entry;
+
+static const oid_table_entry pka_oids[] = {
+ { LTC_OID_UNDEF, LTC_PKA_UNDEF, NULL },
+ { LTC_OID_RSA, LTC_PKA_RSA, "1.2.840.113549.1.1.1" },
+ { LTC_OID_DSA, LTC_PKA_DSA, "1.2.840.10040.4.1" },
+ { LTC_OID_EC, LTC_PKA_EC, "1.2.840.10045.2.1" },
+ { LTC_OID_EC_PRIMEF, LTC_PKA_EC, "1.2.840.10045.1.1" },
+ { LTC_OID_X25519, LTC_PKA_X25519, "1.3.101.110" },
+ { LTC_OID_ED25519, LTC_PKA_ED25519, "1.3.101.112" },
+ { LTC_OID_DH, LTC_PKA_DH, "1.2.840.113549.1.3.1" },
+};
+
+static LTC_INLINE const oid_table_entry* s_get_entry(enum ltc_oid_id id)
+{
+ if (id < LTC_OID_NUM)
+ return &pka_oids[id];
+ return NULL;
+}
+
+/*
+ Returns the OID requested.
+ @return CRYPT_OK if valid
+*/
+int pk_get_oid(enum ltc_oid_id id, const char **st)
+{
+ const oid_table_entry* e = s_get_entry(id);
+ LTC_ARGCHK(st != NULL);
+ if (e != NULL) {
+ *st = e->oid;
+ return CRYPT_OK;
+ }
+ return CRYPT_INVALID_ARG;
+}
+
+/*
+ Returns the PKA ID requested.
+ @return CRYPT_OK if valid
+*/
+int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka)
+{
+ const oid_table_entry* e = s_get_entry(id);
+ LTC_ARGCHK(pka != NULL);
+ if (e != NULL) {
+ *pka = e->pka;
+ return CRYPT_OK;
+ }
+ return CRYPT_INVALID_ARG;
+}
+
+/*
+ Returns the OID ID requested.
+ @return CRYPT_OK if valid
+*/
+int pk_get_oid_id(enum ltc_pka_id pka, enum ltc_oid_id *oid)
+{
+ unsigned int i;
+ LTC_ARGCHK(oid != NULL);
+ for (i = 1; i < sizeof(pka_oids)/sizeof(pka_oids[0]); ++i) {
+ if (pka_oids[i].pka == pka) {
+ *oid = pka_oids[i].id;
+ return CRYPT_OK;
+ }
+ }
+ return CRYPT_INVALID_ARG;
+}
+
+/*
+ Returns the PKA ID of an OID.
+ @return CRYPT_OK if valid
+*/
+int pk_get_oid_from_asn1(const ltc_asn1_list *oid, enum ltc_oid_id *id)
+{
+ unsigned long i;
+ char tmp[LTC_OID_MAX_STRLEN] = { 0 };
+ int err;
+
+ LTC_ARGCHK(oid != NULL);
+ LTC_ARGCHK(id != NULL);
+
+ if (oid->type != LTC_ASN1_OBJECT_IDENTIFIER) return CRYPT_INVALID_ARG;
+
+ i = sizeof(tmp);
+ if ((err = pk_oid_num_to_str(oid->data, oid->size, tmp, &i)) != CRYPT_OK) {
+ return err;
+ }
+
+ for (i = 1; i < sizeof(pka_oids)/sizeof(pka_oids[0]); ++i) {
+ if (XSTRCMP(pka_oids[i].oid, tmp) == 0) {
+ *id = pka_oids[i].id;
+ return CRYPT_OK;
+ }
+ }
+ return CRYPT_INVALID_ARG;
+}
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/oid/pk_oid_cmp.c b/Sources/libtomcrypt/pk/asn1/oid/pk_oid_cmp.c
new file mode 100644
index 00000000..04a379bf
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/oid/pk_oid_cmp.c
@@ -0,0 +1,44 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_DER
+
+/*
+ Compare an OID string to an array of `unsigned long`.
+ @return CRYPT_OK if equal
+*/
+int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size)
+{
+ unsigned long i;
+ char tmp[LTC_OID_MAX_STRLEN] = { 0 };
+ int err;
+
+ if (o1 == NULL || o2 == NULL) return CRYPT_ERROR;
+
+ i = sizeof(tmp);
+ if ((err = pk_oid_num_to_str(o2, o2size, tmp, &i)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (XSTRCMP(o1, tmp) != 0) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ return CRYPT_OK;
+}
+
+/*
+ Compare an OID string to an OID element decoded from ASN.1.
+ @return CRYPT_OK if equal
+*/
+int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2)
+{
+ if (o1 == NULL || o2 == NULL) return CRYPT_ERROR;
+
+ if (o2->type != LTC_ASN1_OBJECT_IDENTIFIER) return CRYPT_INVALID_ARG;
+
+ return pk_oid_cmp_with_ulong(o1, o2->data, o2->size);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/oid/pk_oid_str.c b/Sources/libtomcrypt/pk/asn1/oid/pk_oid_str.c
new file mode 100644
index 00000000..f670cd06
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/oid/pk_oid_str.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen)
+{
+ unsigned long i, j, limit, oid_j;
+ size_t OID_len;
+
+ LTC_ARGCHK(oidlen != NULL);
+
+ limit = *oidlen;
+ *oidlen = 0; /* make sure that we return zero oidlen on error */
+ for (i = 0; i < limit; i++) oid[i] = 0;
+
+ if (OID == NULL) return CRYPT_OK;
+
+ OID_len = XSTRLEN(OID);
+ if (OID_len == 0) return CRYPT_OK;
+
+ for (i = 0, j = 0; i < OID_len; i++) {
+ if (OID[i] == '.') {
+ if (++j >= limit) continue;
+ }
+ else if ((OID[i] >= '0') && (OID[i] <= '9')) {
+ if ((j >= limit) || (oid == NULL)) continue;
+ oid_j = oid[j];
+ oid[j] = oid[j] * 10 + (OID[i] - '0');
+ if (oid[j] < oid_j) return CRYPT_OVERFLOW;
+ }
+ else {
+ return CRYPT_ERROR;
+ }
+ }
+ if (j == 0) return CRYPT_ERROR;
+ if (j >= limit) {
+ *oidlen = j;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ *oidlen = j + 1;
+ return CRYPT_OK;
+}
+
+int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen)
+{
+ int i;
+ unsigned long j, k;
+ char tmp[LTC_OID_MAX_STRLEN] = { 0 };
+
+ LTC_ARGCHK(oid != NULL);
+ LTC_ARGCHK(oidlen < INT_MAX);
+ LTC_ARGCHK(outlen != NULL);
+
+ for (i = oidlen - 1, k = 0; i >= 0; i--) {
+ j = oid[i];
+ if (j == 0) {
+ tmp[k] = '0';
+ if (++k >= sizeof(tmp)) return CRYPT_ERROR;
+ }
+ else {
+ while (j > 0) {
+ tmp[k] = '0' + (j % 10);
+ if (++k >= sizeof(tmp)) return CRYPT_ERROR;
+ j /= 10;
+ }
+ }
+ if (i > 0) {
+ tmp[k] = '.';
+ if (++k >= sizeof(tmp)) return CRYPT_ERROR;
+ }
+ }
+ if (*outlen < k + 1) {
+ *outlen = k + 1;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ LTC_ARGCHK(OID != NULL);
+ for (j = 0; j < k; j++) OID[j] = tmp[k - j - 1];
+ OID[k] = '\0';
+ *outlen = k; /* the length without terminating NUL byte */
+ return CRYPT_OK;
+}
diff --git a/Sources/libtomcrypt/pk/asn1/pkcs8/pkcs8_decode_flexi.c b/Sources/libtomcrypt/pk/asn1/pkcs8/pkcs8_decode_flexi.c
new file mode 100644
index 00000000..42eac451
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/pkcs8/pkcs8_decode_flexi.c
@@ -0,0 +1,106 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_PKCS_8
+
+/**
+ PKCS#8 decrypt if necessary & flexi-decode
+
+ @param in Pointer to the ASN.1 encoded input data
+ @param inlen Length of the input data
+ @param pwd Pointer to the password that was used when encrypting
+ @param pwdlen Length of the password
+ @param decoded_list Pointer to a pointer for the flexi-decoded list
+ @return CRYPT_OK on success
+*/
+int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ ltc_asn1_list **decoded_list)
+{
+ unsigned long len = inlen;
+ unsigned long dec_size;
+ unsigned char *dec_data = NULL;
+ ltc_asn1_list *l = NULL;
+ int err;
+ pbes_arg pbes;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(decoded_list != NULL);
+
+ XMEMSET(&pbes, 0, sizeof(pbes));
+
+ *decoded_list = NULL;
+ if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) {
+ /* the following "if" detects whether it is encrypted or not */
+ /* PKCS8 Setup
+ * 0:d=0 hl=4 l= 380 cons: SEQUENCE
+ * 4:d=1 hl=2 l= 78 cons: SEQUENCE
+ * 6:d=2 hl=2 l= 9 prim: OBJECT :OID indicating PBES1 or PBES2 (== *lalgoid)
+ * 17:d=2 hl=2 l= 65 cons: SEQUENCE
+ * Stuff in between is dependent on whether it's PBES1 or PBES2
+ * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
+ */
+ if (l->type == LTC_ASN1_SEQUENCE &&
+ LTC_ASN1_IS_TYPE(l->child, LTC_ASN1_SEQUENCE) &&
+ LTC_ASN1_IS_TYPE(l->child->child, LTC_ASN1_OBJECT_IDENTIFIER) &&
+ LTC_ASN1_IS_TYPE(l->child->child->next, LTC_ASN1_SEQUENCE) &&
+ LTC_ASN1_IS_TYPE(l->child->next, LTC_ASN1_OCTET_STRING)) {
+ ltc_asn1_list *lalgoid = l->child->child;
+
+ if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) {
+ err = CRYPT_PW_CTX_MISSING;
+ goto LBL_DONE;
+ }
+
+ if (pbes1_extract(lalgoid, &pbes) == CRYPT_OK) {
+ /* Successfully extracted PBES1 parameters */
+ } else if (pbes2_extract(lalgoid, &pbes) == CRYPT_OK) {
+ /* Successfully extracted PBES2 parameters */
+ } else {
+ /* unsupported encryption */
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+ }
+
+ if (pw_ctx->callback(&pbes.pw.pw, &pbes.pw.l, pw_ctx->userdata)) {
+ err = CRYPT_ERROR;
+ goto LBL_DONE;
+ }
+
+ pbes.enc_data = l->child->next;
+
+ dec_size = pbes.enc_data->size;
+ if ((dec_data = XMALLOC(dec_size)) == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_DONE;
+ }
+
+ if ((err = pbes_decrypt(&pbes, dec_data, &dec_size)) != CRYPT_OK) goto LBL_DONE;
+
+ der_free_sequence_flexi(l);
+ l = NULL;
+ err = der_decode_sequence_flexi(dec_data, &dec_size, &l);
+ if (err != CRYPT_OK) goto LBL_DONE;
+ *decoded_list = l;
+ }
+ else {
+ /* not encrypted */
+ err = CRYPT_OK;
+ *decoded_list = l;
+ }
+ /* Set l to NULL so it won't be free'd */
+ l = NULL;
+ }
+
+LBL_DONE:
+ if (dec_data) {
+ zeromem(dec_data, dec_size);
+ XFREE(dec_data);
+ }
+ password_free(&pbes.pw, pw_ctx);
+ if (l) der_free_sequence_flexi(l);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/pkcs8/pkcs8_get.c b/Sources/libtomcrypt/pk/asn1/pkcs8/pkcs8_get.c
new file mode 100644
index 00000000..3ff74e2d
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/pkcs8/pkcs8_get.c
@@ -0,0 +1,48 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs8_get.c
+ PKCS#8 utility functions
+*/
+
+#ifdef LTC_PKCS_8
+
+int pkcs8_get_children(const ltc_asn1_list *decoded_list, enum ltc_oid_id *pka, ltc_asn1_list **alg_id, ltc_asn1_list **priv_key)
+{
+ int err;
+ unsigned long n;
+ der_flexi_check flexi_should[4];
+ ltc_asn1_list *seq_l, *version;
+
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ if (alg_id == NULL) alg_id = &seq_l;
+
+ /* Setup for basic structure */
+ n=0;
+ LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &version);
+ LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, alg_id);
+ LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, priv_key);
+ LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
+
+ err = der_flexi_sequence_cmp(decoded_list, flexi_should);
+ switch (err) {
+ case CRYPT_OK:
+ case CRYPT_INPUT_TOO_LONG:
+ /* If there are attributes added after the private_key it is tagged with version 1 and
+ * we get an 'input too long' error but the rest is already decoded and can be
+ * handled the same as for version 0
+ */
+ if (mp_cmp_d(version->data, 0) != LTC_MP_EQ && mp_cmp_d(version->data, 1) != LTC_MP_EQ) {
+ return CRYPT_INVALID_PACKET;
+ }
+ break;
+ default:
+ return err;
+ }
+ return pk_get_oid_from_asn1((*alg_id)->child, pka);
+}
+
+#endif /* LTC_PKCS_8 */
diff --git a/Sources/libtomcrypt/pk/asn1/x509/x509_decode_public_key_from_certificate.c b/Sources/libtomcrypt/pk/asn1/x509/x509_decode_public_key_from_certificate.c
new file mode 100644
index 00000000..45a1c6f6
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/x509/x509_decode_public_key_from_certificate.c
@@ -0,0 +1,71 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x509_decode_public_key_from_certificate.c
+ ASN.1 DER/X.509, decode a certificate
+*/
+
+#ifdef LTC_DER
+
+/**
+ Try to decode the public key from a X.509 certificate
+ @param in The input buffer
+ @param inlen The length of the input buffer
+ @param algorithm One out of the enum #public_key_algorithms
+ @param param_type The parameters' type out of the enum ltc_asn1_type
+ @param parameters The parameters to include
+ @param parameters_len [in/out] The number of parameters to include
+ @param callback The callback
+ @param ctx The context passed to the callback
+ @return CRYPT_OK on success,
+ CRYPT_NOP if no SubjectPublicKeyInfo was found,
+ another error if decoding or memory allocation failed
+*/
+int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen,
+ enum ltc_oid_id algorithm, ltc_asn1_type param_type,
+ ltc_asn1_list* parameters, unsigned long *parameters_len,
+ public_key_decode_cb callback, void *ctx)
+{
+ int err;
+ unsigned char *tmpbuf = NULL;
+ unsigned long tmpbuf_len;
+ ltc_asn1_list *decoded_list = NULL, *spki;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != 0);
+ LTC_ARGCHK(callback != NULL);
+
+ if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (algorithm == LTC_OID_EC) {
+ err = callback(spki->data, spki->size, ctx);
+ } else {
+
+ tmpbuf_len = inlen;
+ tmpbuf = XCALLOC(1, tmpbuf_len);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_OUT;
+ }
+
+ err = x509_decode_subject_public_key_info(spki->data, spki->size,
+ algorithm, tmpbuf, &tmpbuf_len,
+ param_type, parameters, parameters_len);
+ if (err == CRYPT_OK) {
+ err = callback(tmpbuf, tmpbuf_len, ctx);
+ goto LBL_OUT;
+ }
+ }
+
+LBL_OUT:
+ if (decoded_list) der_free_sequence_flexi(decoded_list);
+ if (tmpbuf != NULL) XFREE(tmpbuf);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/x509/x509_decode_spki.c b/Sources/libtomcrypt/pk/asn1/x509/x509_decode_spki.c
new file mode 100644
index 00000000..147aaf1c
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/x509/x509_decode_spki.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x509_decode_public_key_from_certificate.c
+ ASN.1 DER/X.509, decode a SubjectPublicKeyInfo
+*/
+
+#ifdef LTC_DER
+
+/* Check if it looks like a SubjectPublicKeyInfo */
+#define LOOKS_LIKE_SPKI(l) ((l) != NULL) \
+&& ((l)->type == LTC_ASN1_SEQUENCE) \
+&& ((l)->child != NULL) \
+&& ((l)->child->type == LTC_ASN1_OBJECT_IDENTIFIER) \
+&& ((l)->next != NULL) \
+&& ((l)->next->type == LTC_ASN1_BIT_STRING)
+
+/**
+ DER decode a X.509 certificate and return the SubjectPublicKeyInfo
+ @param in The input buffer
+ @param inlen The length of the input buffer
+ @param out [out] A pointer to the decoded linked list (you take ownership of this one and
+ `der_free_sequence_flexi()` it when you're done)
+ @param spki [out] A pointer to the SubjectPublicKeyInfo
+ @return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found, another error if decoding failed
+*/
+int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki)
+{
+ int err;
+ unsigned long tmp_inlen;
+ ltc_asn1_list *decoded_list = NULL, *l;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != 0);
+
+ tmp_inlen = inlen;
+ if ((err = der_decode_sequence_flexi(in, &tmp_inlen, &decoded_list)) == CRYPT_OK) {
+ l = decoded_list;
+
+ err = CRYPT_NOP;
+
+ /* Move 2 levels up in the tree
+ SEQUENCE
+ SEQUENCE
+ ...
+ */
+ if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
+ l = l->child;
+ if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
+ l = l->child;
+
+ /* Move forward in the tree until we find this combination
+ ...
+ SEQUENCE
+ SEQUENCE
+ OBJECT IDENTIFIER
+ NULL
+ BIT STRING
+ */
+ do {
+ /* The additional check for l->data is there to make sure
+ * we won't try to decode a list that has been 'shrunk'
+ */
+ if ((l->type == LTC_ASN1_SEQUENCE)
+ && (l->data != NULL)
+ && LOOKS_LIKE_SPKI(l->child)) {
+ *out = decoded_list;
+ *spki = l;
+ return CRYPT_OK;
+ }
+ l = l->next;
+ } while(l);
+ }
+ }
+ }
+ if (decoded_list) der_free_sequence_flexi(decoded_list);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/x509/x509_decode_subject_public_key_info.c b/Sources/libtomcrypt/pk/asn1/x509/x509_decode_subject_public_key_info.c
new file mode 100644
index 00000000..f958825d
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/x509/x509_decode_subject_public_key_info.c
@@ -0,0 +1,119 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x509_decode_subject_public_key_info.c
+ ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav
+*/
+
+#ifdef LTC_DER
+
+/* AlgorithmIdentifier := SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm
+ * }
+ *
+ * SubjectPublicKeyInfo := SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ */
+/**
+ Decode a SubjectPublicKeyInfo
+ @param in The input buffer
+ @param inlen The length of the input buffer
+ @param algorithm One out of the enum #public_key_algorithms
+ @param public_key The buffer for the public key
+ @param public_key_len [in/out] The length of the public key buffer and the written length
+ @param parameters_type The parameters' type out of the enum ltc_asn1_type
+ @param parameters The parameters to include
+ @param parameters_len [in/out] The number of parameters to include
+ @return CRYPT_OK on success
+*/
+int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
+ enum ltc_oid_id algorithm, void *public_key, unsigned long *public_key_len,
+ ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len)
+{
+ int err;
+ unsigned long len, alg_id_num, tmplen;
+ const char* oid;
+ unsigned char *tmpbuf;
+ unsigned long tmpoid[16];
+ unsigned long *_parameters_len;
+ ltc_asn1_list alg_id[2];
+ ltc_asn1_list subject_pubkey[2];
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != 0);
+ LTC_ARGCHK(public_key_len != NULL);
+
+ if (parameters_type != LTC_ASN1_EOL) {
+ if ((parameters == NULL) || (parameters_len == NULL)) {
+ tmplen = 0;
+ _parameters_len = &tmplen;
+ } else {
+ _parameters_len = parameters_len;
+ }
+ }
+
+ err = pk_get_oid(algorithm, &oid);
+ if (err != CRYPT_OK) {
+ return err;
+ }
+
+ /* see if the OpenSSL DER format RSA public key will work */
+ tmpbuf = XCALLOC(1, inlen);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ /* this includes the internal hash ID and optional params (NULL in this case) */
+ LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
+ if (parameters_type == LTC_ASN1_EOL) {
+ alg_id_num = 1;
+ } else {
+ LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, *_parameters_len);
+ alg_id_num = 2;
+ }
+
+ /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey
+ * in a **BIT** string ... so we have to extract it then proceed to convert bit to octet
+ */
+ LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, alg_id_num);
+ LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, inlen*8U);
+
+ err=der_decode_sequence(in, inlen, subject_pubkey, 2UL);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if (parameters_type != LTC_ASN1_EOL) {
+ *_parameters_len = alg_id[1].size;
+ }
+
+ if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) {
+ /* OID mismatch */
+ goto LBL_ERR;
+ }
+
+ len = subject_pubkey[1].size/8;
+ if (*public_key_len >= len) {
+ XMEMCPY(public_key, subject_pubkey[1].data, len);
+ *public_key_len = len;
+ } else {
+ *public_key_len = len;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ err = CRYPT_OK;
+
+LBL_ERR:
+
+ XFREE(tmpbuf);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/asn1/x509/x509_encode_subject_public_key_info.c b/Sources/libtomcrypt/pk/asn1/x509/x509_encode_subject_public_key_info.c
new file mode 100644
index 00000000..874574d0
--- /dev/null
+++ b/Sources/libtomcrypt/pk/asn1/x509/x509_encode_subject_public_key_info.c
@@ -0,0 +1,66 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x509_encode_subject_public_key_info.c
+ ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav
+*/
+
+#ifdef LTC_DER
+
+/* AlgorithmIdentifier := SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm
+ * }
+ *
+ * SubjectPublicKeyInfo := SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ */
+/**
+ Encode a SubjectPublicKeyInfo
+ @param out The output buffer
+ @param outlen [in/out] Length of buffer and resulting length of output
+ @param algorithm One out of the enum #public_key_algorithms
+ @param public_key The buffer for the public key
+ @param public_key_len The length of the public key buffer
+ @param parameters_type The parameters' type out of the enum ltc_asn1_type
+ @param parameters The parameters to include
+ @param parameters_len The number of parameters to include
+ @return CRYPT_OK on success
+*/
+int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
+ enum ltc_oid_id algorithm, const void* public_key, unsigned long public_key_len,
+ ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len)
+{
+ int err;
+ ltc_asn1_list alg_id[2];
+ const char *OID;
+ unsigned long oid[16], oidlen;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = pk_get_oid(algorithm, &OID)) != CRYPT_OK) {
+ return err;
+ }
+
+ oidlen = sizeof(oid)/sizeof(oid[0]);
+ if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) {
+ return err;
+ }
+
+ LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen);
+ LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len);
+
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id,
+ LTC_ASN1_RAW_BIT_STRING, public_key_len*8U, public_key,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/dh/dh.c b/Sources/libtomcrypt/pk/dh/dh.c
new file mode 100644
index 00000000..471d215c
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh.c
@@ -0,0 +1,242 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
+const ltc_dh_set_type ltc_dh_sets[] = {
+#ifdef LTC_DH768
+{ /* 768-bit MODP Group 1 - https://tools.ietf.org/html/rfc7296#appendix-B.1 */
+ 96,
+ "DH-768",
+ "2",
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
+},
+#endif
+#ifdef LTC_DH1024
+{ /* 1024-bit MODP Group 2 - https://tools.ietf.org/html/rfc7296#appendix-B.2 */
+ 128,
+ "DH-1024",
+ "2",
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
+ "FFFFFFFFFFFFFFFF"
+},
+#endif
+#ifdef LTC_DH1536
+{ /* 1536-bit MODP Group 5 - https://tools.ietf.org/html/rfc3526#section-2 */
+ 192,
+ "DH-1536",
+ "2",
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
+},
+#endif
+#ifdef LTC_DH2048
+{ /* 2048-bit MODP Group 14 - https://tools.ietf.org/html/rfc3526#section-3 */
+ 256,
+ "DH-2048",
+ "2",
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+ "15728E5A8AACAA68FFFFFFFFFFFFFFFF"
+},
+#endif
+#ifdef LTC_DH3072
+{ /* 3072-bit MODP Group 15 - https://tools.ietf.org/html/rfc3526#section-4 */
+ 384,
+ "DH-3072",
+ "2",
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+ "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
+ "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+ "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
+},
+#endif
+#ifdef LTC_DH4096
+{ /* 4096-bit MODP Group 16 - https://tools.ietf.org/html/rfc3526#section-5 */
+ 512,
+ "DH-4096",
+ "2",
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+ "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
+ "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+ "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
+ "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
+ "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
+ "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
+ "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
+ "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
+ "FFFFFFFFFFFFFFFF"
+},
+#endif
+#ifdef LTC_DH6144
+{ /* 6144-bit MODP Group 17 - https://tools.ietf.org/html/rfc3526#section-6 */
+ 768,
+ "DH-6144",
+ "2",
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+ "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
+ "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+ "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
+ "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
+ "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
+ "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
+ "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
+ "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
+ "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
+ "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
+ "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
+ "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
+ "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
+ "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
+ "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
+ "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
+ "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
+ "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF"
+},
+#endif
+#ifdef LTC_DH8192
+{ /* 8192-bit MODP Group 18 - https://tools.ietf.org/html/rfc3526#section-7 */
+ 1024,
+ "DH-8192",
+ "2",
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+ "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
+ "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+ "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
+ "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
+ "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
+ "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
+ "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
+ "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
+ "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
+ "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
+ "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
+ "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
+ "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
+ "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
+ "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
+ "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
+ "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
+ "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
+ "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
+ "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"
+ "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
+ "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
+ "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
+ "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"
+ "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
+ "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
+ "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
+ "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
+ "60C980DD98EDD3DFFFFFFFFFFFFFFFFF"
+},
+#endif
+{
+ 0,
+ NULL,
+ NULL,
+ NULL
+}
+};
+
+/**
+ Returns the DH group size (octets) for given key
+ @param key The DH key to get the size of
+ @return The group size in octets (0 on error)
+ */
+int dh_get_groupsize(const dh_key *key)
+{
+ if (key == NULL) return 0;
+ return mp_unsigned_bin_size(key->prime);
+}
+
+/**
+ Init a DH key
+ @param key The DH key to initialize
+ @return CRYPT_OK if successful
+*/
+int dh_init(dh_key *key)
+{
+ int err;
+ LTC_ARGCHK(key != NULL);
+ if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+ return CRYPT_OK;
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_check_pubkey.c b/Sources/libtomcrypt/pk/dh/dh_check_pubkey.c
new file mode 100644
index 00000000..7dd128ed
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_check_pubkey.c
@@ -0,0 +1,55 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+/**
+ Check DH public key (INTERNAL ONLY, not part of public API)
+ @param key The key you wish to test
+ @return CRYPT_OK if successful
+*/
+int dh_check_pubkey(const dh_key *key)
+{
+ void *p_minus1;
+ ltc_mp_digit digit;
+ int i, digit_count, bits_set = 0, err;
+
+ LTC_ARGCHK(key != NULL);
+
+ if ((err = mp_init(&p_minus1)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* avoid: y <= 1 OR y >= p-1 */
+ if ((err = mp_sub_d(key->prime, 1, p_minus1)) != CRYPT_OK) {
+ goto error;
+ }
+ if (mp_cmp(key->y, p_minus1) != LTC_MP_LT || mp_cmp_d(key->y, 1) != LTC_MP_GT) {
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+
+ /* public key must have more than one bit set */
+ digit_count = mp_get_digit_count(key->y);
+ for (i = 0; i < digit_count && bits_set < 2; i++) {
+ digit = mp_get_digit(key->y, i);
+ while (digit > 0) {
+ if (digit & 1) bits_set++;
+ digit >>= 1;
+ }
+ }
+ if (bits_set > 1) {
+ err = CRYPT_OK;
+ }
+ else {
+ err = CRYPT_INVALID_ARG;
+ }
+
+error:
+ mp_clear(p_minus1);
+ return err;
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_export.c b/Sources/libtomcrypt/pk/dh/dh_export.c
new file mode 100644
index 00000000..19112c44
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_export.c
@@ -0,0 +1,52 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+/**
+ Export a DH key to a binary packet
+ @param out [out] The destination for the key
+ @param outlen [in/out] The max size and resulting size of the DH key
+ @param type Which type of key (PK_PRIVATE or PK_PUBLIC)
+ @param key The key you wish to export
+ @return CRYPT_OK if successful
+*/
+int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key)
+{
+ unsigned char flags[1];
+ int err;
+ unsigned long version = 0;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (type == PK_PRIVATE) {
+ /* export x - private key */
+ flags[0] = 1;
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, key->prime,
+ LTC_ASN1_INTEGER, 1UL, key->base,
+ LTC_ASN1_INTEGER, 1UL, key->x,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+ else {
+ /* export y - public key */
+ flags[0] = 0;
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, key->prime,
+ LTC_ASN1_INTEGER, 1UL, key->base,
+ LTC_ASN1_INTEGER, 1UL, key->y,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+
+ return err;
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_export_key.c b/Sources/libtomcrypt/pk/dh/dh_export_key.c
new file mode 100644
index 00000000..374635c7
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_export_key.c
@@ -0,0 +1,37 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+/**
+ Binary export a DH key to a buffer
+ @param out [out] The destination for the key
+ @param outlen [in/out] The max size and resulting size of the DH key
+ @param type Which type of key (PK_PRIVATE or PK_PUBLIC)
+ @param key The key you wish to export
+ @return CRYPT_OK if successful
+*/
+int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key)
+{
+ unsigned long len;
+ void *k;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ k = (type == PK_PRIVATE) ? key->x : key->y;
+ len = mp_unsigned_bin_size(k);
+
+ if (*outlen < len) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ *outlen = len;
+
+ return mp_to_unsigned_bin(k, out);
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_free.c b/Sources/libtomcrypt/pk/dh/dh_free.c
new file mode 100644
index 00000000..ff56b006
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_free.c
@@ -0,0 +1,18 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+/**
+ Free the allocated ram for a DH key
+ @param key The key which you wish to free
+*/
+void dh_free(dh_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_cleanup_multi(&key->prime, &key->base, &key->y, &key->x, LTC_NULL);
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_generate_key.c b/Sources/libtomcrypt/pk/dh/dh_generate_key.c
new file mode 100644
index 00000000..39ef8e14
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_generate_key.c
@@ -0,0 +1,90 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+static int s_dh_groupsize_to_keysize(int groupsize)
+{
+ /* The strength estimates from https://tools.ietf.org/html/rfc3526#section-8
+ * We use "Estimate 2" to get an appropriate private key (exponent) size.
+ */
+ if (groupsize <= 0) {
+ return 0;
+ }
+ if (groupsize <= 192) {
+ return 30; /* 1536-bit => key size 240-bit */
+ }
+ if (groupsize <= 256) {
+ return 40; /* 2048-bit => key size 320-bit */
+ }
+ if (groupsize <= 384) {
+ return 52; /* 3072-bit => key size 416-bit */
+ }
+ if (groupsize <= 512) {
+ return 60; /* 4096-bit => key size 480-bit */
+ }
+ if (groupsize <= 768) {
+ return 67; /* 6144-bit => key size 536-bit */
+ }
+ if (groupsize <= 1024) {
+ return 77; /* 8192-bit => key size 616-bit */
+ }
+ return 0;
+}
+
+int dh_generate_key(prng_state *prng, int wprng, dh_key *key)
+{
+ unsigned char *buf;
+ unsigned long keysize;
+ int err, max_iterations = LTC_PK_MAX_RETRIES;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* good prng? */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ keysize = s_dh_groupsize_to_keysize(mp_unsigned_bin_size(key->prime));
+ if (keysize == 0) {
+ err = CRYPT_INVALID_KEYSIZE;
+ goto freemp;
+ }
+
+ /* allocate buffer */
+ buf = XMALLOC(keysize);
+ if (buf == NULL) {
+ err = CRYPT_MEM;
+ goto freemp;
+ }
+
+ key->type = PK_PRIVATE;
+ do {
+ /* make up random buf */
+ if (prng_descriptor[wprng].read(buf, keysize, prng) != keysize) {
+ err = CRYPT_ERROR_READPRNG;
+ goto freebuf;
+ }
+ /* load the x value - private key */
+ if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) {
+ goto freebuf;
+ }
+ /* compute the y value - public key */
+ if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) {
+ goto freebuf;
+ }
+ err = dh_check_pubkey(key);
+ } while (err != CRYPT_OK && max_iterations-- > 0);
+
+freebuf:
+ zeromem(buf, keysize);
+ XFREE(buf);
+freemp:
+ if (err != CRYPT_OK) dh_free(key);
+ return err;
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_import.c b/Sources/libtomcrypt/pk/dh/dh_import.c
new file mode 100644
index 00000000..8be75e25
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_import.c
@@ -0,0 +1,89 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+/**
+ Import a DH key from a binary packet
+ @param in The packet to read
+ @param inlen The length of the input packet
+ @param key [out] Where to import the key to
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
+{
+ unsigned char flags[1];
+ int err;
+ unsigned long version;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* init */
+ if ((err = dh_init(key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* find out what type of key it is */
+ err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+ LTC_ASN1_BIT_STRING, 1UL, &flags,
+ LTC_ASN1_EOL, 0UL, NULL);
+ if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
+ goto error;
+ }
+
+ if (version == 0) {
+ if (flags[0] == 1) {
+ key->type = PK_PRIVATE;
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, key->prime,
+ LTC_ASN1_INTEGER, 1UL, key->base,
+ LTC_ASN1_INTEGER, 1UL, key->x,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+ /* compute public key: y = (base ^ x) mod prime */
+ if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) {
+ goto error;
+ }
+ }
+ else if (flags[0] == 0) {
+ key->type = PK_PUBLIC;
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, key->prime,
+ LTC_ASN1_INTEGER, 1UL, key->base,
+ LTC_ASN1_INTEGER, 1UL, key->y,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* check public key */
+ if ((err = dh_check_pubkey(key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ return CRYPT_OK;
+
+error:
+ dh_free(key);
+ return err;
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_import_pkcs8.c b/Sources/libtomcrypt/pk/dh/dh_import_pkcs8.c
new file mode 100644
index 00000000..431b05ee
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_import_pkcs8.c
@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+int dh_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dh_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+
+ if (!alg_id->child ||
+ !LTC_ASN1_IS_TYPE(alg_id->child->next, LTC_ASN1_SEQUENCE) ||
+ !LTC_ASN1_IS_TYPE(alg_id->child->next->child, LTC_ASN1_INTEGER) ||
+ !LTC_ASN1_IS_TYPE(alg_id->child->next->child->next, LTC_ASN1_INTEGER)) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ if ((err = dh_init(key)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_copy(alg_id->child->next->child->data, key->prime)) != CRYPT_OK) {
+ goto error;
+ }
+ if ((err = mp_copy(alg_id->child->next->child->next->data, key->base)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_decode_integer(priv_key->data, priv_key->size, key->x)) != CRYPT_OK) {
+ goto error;
+ }
+ /* compute public key: y = (base ^ x) mod prime */
+ if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) {
+ goto error;
+ }
+ /* check public key */
+ if ((err = dh_check_pubkey(key)) != CRYPT_OK) {
+ goto error;
+ }
+ key->type = PK_PRIVATE;
+
+ return CRYPT_OK;
+error:
+ dh_free(key);
+ return err;
+}
+
+/**
+ Import a DH key in PKCS#8 format
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param pw_ctx The password context when decrypting the private key
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int dh_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx, dh_key *key)
+{
+ int err;
+ ltc_asn1_list *l = NULL;
+ ltc_asn1_list *alg_id, *priv_key;
+ enum ltc_oid_id pka;
+
+ LTC_ARGCHK(in != NULL);
+
+ if ((err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) {
+ goto LBL_DER_FREE;
+ }
+ if (pka != LTC_OID_DH) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DER_FREE;
+ }
+
+ err = dh_import_pkcs8_asn1(alg_id, priv_key, key);
+
+LBL_DER_FREE:
+ der_free_sequence_flexi(l);
+ return err;
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_set.c b/Sources/libtomcrypt/pk/dh/dh_set.c
new file mode 100644
index 00000000..f81bf381
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_set.c
@@ -0,0 +1,115 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+/**
+ Import DH key parts p and g from raw numbers
+
+ @param p DH's p (prime)
+ @param plen DH's p's length
+ @param g DH's g (group)
+ @param glen DH's g's length
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful
+*/
+int dh_set_pg(const unsigned char *p, unsigned long plen,
+ const unsigned char *g, unsigned long glen,
+ dh_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(p != NULL);
+ LTC_ARGCHK(g != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ if ((err = dh_init(key)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_read_unsigned_bin(key->base, (unsigned char*)g, glen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->prime, (unsigned char*)p, plen)) != CRYPT_OK) { goto LBL_ERR; }
+
+ return CRYPT_OK;
+
+LBL_ERR:
+ dh_free(key);
+ return err;
+}
+
+/**
+ Import DH key parts p and g from built-in DH groups
+
+ @param groupsize The size of the DH group to use
+ @param key [out] Where the newly created DH key will be stored
+ @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically.
+*/
+int dh_set_pg_groupsize(int groupsize, dh_key *key)
+{
+ int err, i;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+ LTC_ARGCHK(groupsize > 0);
+
+ for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++);
+ if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE;
+
+ if ((err = dh_init(key)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_radix(key->prime, ltc_dh_sets[i].prime, 16)) != CRYPT_OK) { goto LBL_ERR; }
+
+ return CRYPT_OK;
+
+LBL_ERR:
+ dh_free(key);
+ return err;
+}
+
+/**
+ Import DH public or private key part from raw numbers
+
+ NB: The p & g parts must be set beforehand
+
+ @param in The key-part to import, either public or private.
+ @param inlen The key-part's length
+ @param type Which type of key (PK_PRIVATE or PK_PUBLIC)
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful
+*/
+int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ if (type == PK_PRIVATE) {
+ key->type = PK_PRIVATE;
+ if ((err = mp_read_unsigned_bin(key->x, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto LBL_ERR; }
+ }
+ else {
+ key->type = PK_PUBLIC;
+ if ((err = mp_read_unsigned_bin(key->y, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
+ }
+
+ /* check public key */
+ if ((err = dh_check_pubkey(key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ return CRYPT_OK;
+
+LBL_ERR:
+ dh_free(key);
+ return err;
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_set_pg_dhparam.c b/Sources/libtomcrypt/pk/dh/dh_set_pg_dhparam.c
new file mode 100644
index 00000000..4d254fd2
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_set_pg_dhparam.c
@@ -0,0 +1,44 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+/**
+ Import DH key parts p and g from dhparam
+
+ dhparam data: openssl dhparam -outform DER -out dhparam.der 2048
+
+ @param dhparam The DH param DER encoded data
+ @param dhparamlen The length of dhparam data
+ @param key [out] Where the newly created DH key will be stored
+ @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically.
+*/
+int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+ LTC_ARGCHK(dhparam != NULL);
+ LTC_ARGCHK(dhparamlen > 0);
+
+ if ((err = dh_init(key)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = der_decode_sequence_multi(dhparam, dhparamlen,
+ LTC_ASN1_INTEGER, 1UL, key->prime,
+ LTC_ASN1_INTEGER, 1UL, key->base,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ return CRYPT_OK;
+
+LBL_ERR:
+ dh_free(key);
+ return err;
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dh/dh_shared_secret.c b/Sources/libtomcrypt/pk/dh/dh_shared_secret.c
new file mode 100644
index 00000000..0c4dfc9a
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dh/dh_shared_secret.c
@@ -0,0 +1,70 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+/**
+ Create a DH shared secret.
+ @param private_key The private DH key in the pair
+ @param public_key The public DH key in the pair
+ @param out [out] The destination of the shared data
+ @param outlen [in/out] The max size and resulting size of the shared data.
+ @return CRYPT_OK if successful
+*/
+int dh_shared_secret(const dh_key *private_key, const dh_key *public_key,
+ unsigned char *out, unsigned long *outlen)
+{
+ void *tmp;
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(private_key != NULL);
+ LTC_ARGCHK(public_key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* types valid? */
+ if (private_key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* same DH group? */
+ if (mp_cmp(private_key->prime, public_key->prime) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; }
+ if (mp_cmp(private_key->base, public_key->base) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; }
+
+ /* init big numbers */
+ if ((err = mp_init(&tmp)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* check public key */
+ if ((err = dh_check_pubkey(public_key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* compute tmp = y^x mod p */
+ if ((err = mp_exptmod(public_key->y, private_key->x, private_key->prime, tmp)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* enough space for output? */
+ x = (unsigned long)mp_unsigned_bin_size(tmp);
+ if (*outlen < x) {
+ *outlen = x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto error;
+ }
+ if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) {
+ goto error;
+ }
+ *outlen = x;
+ err = CRYPT_OK;
+
+error:
+ mp_clear(tmp);
+ return err;
+}
+
+#endif /* LTC_MDH */
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_decrypt_key.c b/Sources/libtomcrypt/pk/dsa/dsa_decrypt_key.c
new file mode 100644
index 00000000..c8970239
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_decrypt_key.c
@@ -0,0 +1,129 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_decrypt_key.c
+ DSA Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Decrypt an DSA encrypted key
+ @param in The ciphertext
+ @param inlen The length of the ciphertext (octets)
+ @param out [out] The plaintext
+ @param outlen [in/out] The max size and resulting size of the plaintext
+ @param key The corresponding private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const dsa_key *key)
+{
+ unsigned char *skey, *expt;
+ void *g_pub;
+ unsigned long x, y;
+ unsigned long hashOID[32] = { 0 };
+ int hash, err;
+ ltc_asn1_list decode[3];
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* right key type? */
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* decode to find out hash */
+ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
+ err = der_decode_sequence(in, inlen, decode, 1);
+ if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
+ return err;
+ }
+
+ hash = find_hash_oid(hashOID, decode[0].size);
+ if (hash_is_valid(hash) != CRYPT_OK) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* we now have the hash! */
+
+ if ((err = mp_init(&g_pub)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* allocate memory */
+ expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (expt == NULL || skey == NULL) {
+ if (expt != NULL) {
+ XFREE(expt);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ mp_clear(g_pub);
+ return CRYPT_MEM;
+ }
+
+ LTC_SET_ASN1(decode, 1, LTC_ASN1_INTEGER, g_pub, 1UL);
+ LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE);
+
+ /* read the structure in now */
+ if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* make shared key */
+ x = mp_unsigned_bin_size(key->p) + 1;
+ if ((err = dsa_shared_secret(key->x, g_pub, key, expt, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ y = mp_unsigned_bin_size(key->p) + 1;
+ y = MIN(y, MAXBLOCKSIZE);
+ if ((err = hash_memory(hash, expt, x, expt, &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* ensure the hash of the shared secret is at least as big as the encrypt itself */
+ if (decode[2].size > y) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* avoid buffer overflow */
+ if (*outlen < decode[2].size) {
+ *outlen = decode[2].size;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* Decrypt the key */
+ for (x = 0; x < decode[2].size; x++) {
+ out[x] = expt[x] ^ skey[x];
+ }
+ *outlen = x;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(expt, mp_unsigned_bin_size(key->p) + 1);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+
+ XFREE(expt);
+ XFREE(skey);
+
+ mp_clear(g_pub);
+
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_encrypt_key.c b/Sources/libtomcrypt/pk/dsa/dsa_encrypt_key.c
new file mode 100644
index 00000000..2f460921
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_encrypt_key.c
@@ -0,0 +1,118 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_encrypt_key.c
+ DSA Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Encrypt a symmetric key with DSA
+ @param in The symmetric key you want to encrypt
+ @param inlen The length of the key to encrypt (octets)
+ @param out [out] The destination for the ciphertext
+ @param outlen [in/out] The max size and resulting size of the ciphertext
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param hash The index of the hash you want to use
+ @param key The DSA key you want to encrypt to
+ @return CRYPT_OK if successful
+*/
+int dsa_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, int hash,
+ const dsa_key *key)
+{
+ unsigned char *expt, *skey;
+ void *g_pub, *g_priv;
+ unsigned long x, y;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* check that wprng/cipher/hash are not invalid */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (inlen > hash_descriptor[hash].hashsize) {
+ return CRYPT_INVALID_HASH;
+ }
+
+ /* make a random key and export the public copy */
+ if ((err = mp_init_multi(&g_pub, &g_priv, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (expt == NULL || skey == NULL) {
+ if (expt != NULL) {
+ XFREE(expt);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ mp_clear_multi(g_pub, g_priv, LTC_NULL);
+ return CRYPT_MEM;
+ }
+
+ /* make a random g_priv, g_pub = g^x pair
+ private key x should be in range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2)
+ */
+ if ((err = rand_bn_upto(g_priv, key->q, prng, wprng)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* compute y */
+ if ((err = mp_exptmod(key->g, g_priv, key->p, g_pub)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* make random key */
+ x = mp_unsigned_bin_size(key->p) + 1;
+ if ((err = dsa_shared_secret(g_priv, key->y, key, expt, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ y = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash, expt, x, skey, &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* Encrypt key */
+ for (x = 0; x < inlen; x++) {
+ skey[x] ^= in[x];
+ }
+
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID,
+ LTC_ASN1_INTEGER, 1UL, g_pub,
+ LTC_ASN1_OCTET_STRING, inlen, skey,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ /* clean up */
+ zeromem(expt, mp_unsigned_bin_size(key->p) + 1);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+
+ XFREE(skey);
+ XFREE(expt);
+
+ mp_clear_multi(g_pub, g_priv, LTC_NULL);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_export.c b/Sources/libtomcrypt/pk/dsa/dsa_export.c
new file mode 100644
index 00000000..3550cbec
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_export.c
@@ -0,0 +1,100 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_export.c
+ DSA implementation, export key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Export a DSA key to a binary packet
+ @param out [out] Where to store the packet
+ @param outlen [in/out] The max size and resulting size of the packet
+ @param type The type of key to export (PK_PRIVATE or PK_PUBLIC)
+ @param key The key to export
+ @return CRYPT_OK if successful
+*/
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_key *key)
+{
+ unsigned long zero=0;
+ unsigned char flags[1];
+ int err, std;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ std = type & PK_STD;
+ type &= ~PK_STD;
+
+ if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ if (type == PK_PRIVATE) {
+ if (std) {
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->g,
+ LTC_ASN1_INTEGER, 1UL, key->y,
+ LTC_ASN1_INTEGER, 1UL, key->x,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+ flags[0] = 1;
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, key->g,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->y,
+ LTC_ASN1_INTEGER, 1UL, key->x,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+
+ if (type == PK_PUBLIC) {
+ if (std) {
+ unsigned long tmplen = (unsigned long)(mp_count_bits(key->y) / 8) + 8;
+ unsigned char* tmp = XMALLOC(tmplen);
+ ltc_asn1_list int_list[3];
+
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+ err = der_encode_integer(key->y, tmp, &tmplen);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ LTC_SET_ASN1(int_list, 0, LTC_ASN1_INTEGER, key->p, 1UL);
+ LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL);
+ LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL);
+
+ err = x509_encode_subject_public_key_info(out, outlen, LTC_OID_DSA, tmp,
+ tmplen, LTC_ASN1_SEQUENCE, int_list,
+ sizeof(int_list) / sizeof(int_list[0]));
+
+error:
+ XFREE(tmp);
+ return err;
+ }
+ flags[0] = 0;
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, key->g,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->y,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+
+ return CRYPT_INVALID_ARG;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_free.c b/Sources/libtomcrypt/pk/dsa/dsa_free.c
new file mode 100644
index 00000000..dbe86253
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_free.c
@@ -0,0 +1,23 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_free.c
+ DSA implementation, free a DSA key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Free a DSA key
+ @param key The key to free from memory
+*/
+void dsa_free(dsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, LTC_NULL);
+ key->type = key->qord = 0;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_generate_key.c b/Sources/libtomcrypt/pk/dsa/dsa_generate_key.c
new file mode 100644
index 00000000..bc83c0ed
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_generate_key.c
@@ -0,0 +1,37 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_make_key.c
+ DSA implementation, generate a DSA key
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Create a DSA key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key [in/out] Where to store the created key
+ @return CRYPT_OK if successful.
+*/
+int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* so now we have our DH structure, generator g, order q, modulus p
+ Now we need a random exponent [mod q] and it's power g^x mod p
+ */
+ /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */
+ if ((err = rand_bn_upto(key->x, key->q, prng, wprng)) != CRYPT_OK) { return err; }
+ if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { return err; }
+ key->type = PK_PRIVATE;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_generate_pqg.c b/Sources/libtomcrypt/pk/dsa/dsa_generate_pqg.c
new file mode 100644
index 00000000..d607782f
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_generate_pqg.c
@@ -0,0 +1,229 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_generate_pqg.c
+ DSA implementation - generate DSA parameters p, q & g
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Create DSA parameters (INTERNAL ONLY, not part of public API)
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param group_size Size of the multiplicative group (octets)
+ @param modulus_size Size of the modulus (octets)
+ @param p [out] bignum where generated 'p' is stored (must be initialized by caller)
+ @param q [out] bignum where generated 'q' is stored (must be initialized by caller)
+ @param g [out] bignum where generated 'g' is stored (must be initialized by caller)
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+static int s_dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g)
+{
+ unsigned long L, N, n, outbytes, seedbytes, counter, j, i;
+ int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash;
+ unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE];
+ void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc;
+ const char *accepted_hashes[] = { "sha3-512", "sha512", "sha3-384", "sha384", "sha3-256", "sha256" };
+
+ /* check size */
+ if (group_size > LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size || modulus_size > LTC_MDSA_MAX_MODULUS) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
+ *
+ * L = The desired length of the prime p (in bits e.g. L = 1024)
+ * N = The desired length of the prime q (in bits e.g. N = 160)
+ * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N
+ * outlen = The bit length of Hash function
+ *
+ * 1. Check that the (L, N)
+ * 2. If (seedlen = 2^(L-1)) {
+ * Test whether or not p is prime as specified in Appendix C.3.
+ * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter
+ * }
+ * offset = offset + n + 1 Comment: Increment offset
+ * }
+ */
+
+ seedbytes = group_size;
+ L = (unsigned long)modulus_size * 8;
+ N = (unsigned long)group_size * 8;
+
+ /* XXX-TODO no Lucas test */
+#ifdef LTC_MPI_HAS_LUCAS_TEST
+ /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */
+ mr_tests_p = (L <= 2048) ? 3 : 2;
+ if (N <= 160) { mr_tests_q = 19; }
+ else if (N <= 224) { mr_tests_q = 24; }
+ else { mr_tests_q = 27; }
+#else
+ /* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */
+ if (L <= 1024) { mr_tests_p = 40; }
+ else if (L <= 2048) { mr_tests_p = 56; }
+ else { mr_tests_p = 64; }
+
+ if (N <= 160) { mr_tests_q = 40; }
+ else if (N <= 224) { mr_tests_q = 56; }
+ else { mr_tests_q = 64; }
+#endif
+
+ hash = -1;
+ for (i = 0; i < sizeof(accepted_hashes)/sizeof(accepted_hashes[0]); ++i) {
+ hash = find_hash(accepted_hashes[i]);
+ if (hash != -1) break;
+ }
+ if (hash == -1) {
+ return CRYPT_INVALID_ARG; /* no appropriate hash function found */
+ }
+ if (N > hash_descriptor[hash].hashsize * 8) {
+ return CRYPT_INVALID_ARG; /* group_size too big */
+ }
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; }
+ outbytes = hash_descriptor[hash].hashsize;
+
+ n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1;
+
+ if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; }
+ if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; }
+
+ err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, LTC_NULL);
+ if (err != CRYPT_OK) { goto cleanup1; }
+
+ if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; }
+ /* t2L1 = 2^(L-1) */
+ if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; }
+ /* t2N1 = 2^(N-1) */
+ if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; }
+ /* t2seedlen = 2^seedlen */
+
+ for(found_p=0; !found_p;) {
+ /* q */
+ for(found_q=0; !found_q;) {
+ if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; }
+ i = outbytes;
+ if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; }
+ if (!mp_isodd(q)) mp_add_d(q, 1, q);
+ if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; }
+ if (res == LTC_MP_YES) found_q = 1;
+ }
+
+ /* p */
+ if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; }
+ for(counter=0; counter < 4*L && !found_p; counter++) {
+ for(j=0; j<=n; j++) {
+ if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; }
+ /* seedinc = (seedinc+1) % 2^seed_bitlen */
+ if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; }
+ zeromem(sbuf, seedbytes);
+ if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; }
+ i = outbytes;
+ err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i);
+ if (err != CRYPT_OK) { goto cleanup; }
+ }
+ if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; }
+ if (mp_cmp(p, t2L1) != LTC_MP_LT) {
+ /* p >= 2^(L-1) */
+ if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; }
+ if (res == LTC_MP_YES) {
+ found_p = 1;
+ }
+ }
+ }
+ }
+
+ /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g
+ * 1. e = (p - 1)/q
+ * 2. h = any integer satisfying: 1 < h < (p - 1)
+ * h could be obtained from a random number generator or from a counter that changes after each use
+ * 3. g = h^e mod p
+ * 4. if (g == 1), then go to step 2.
+ *
+ */
+
+ if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; }
+ /* e = (p - 1)/q */
+ i = mp_count_bits(p);
+ do {
+ do {
+ if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; }
+ } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT);
+ if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; }
+ /* h is randon and 1 < h < (p-1) */
+ if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; }
+ } while (mp_cmp_d(g, 1) == LTC_MP_EQ);
+
+ err = CRYPT_OK;
+cleanup:
+ mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, LTC_NULL);
+cleanup1:
+ XFREE(sbuf);
+cleanup2:
+ XFREE(wbuf);
+cleanup3:
+ return err;
+}
+
+/**
+ Generate DSA parameters p, q & g
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param group_size Size of the multiplicative group (octets)
+ @param modulus_size Size of the modulus (octets)
+ @param key [out] Where to store the created key
+ @return CRYPT_OK if successful.
+*/
+int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
+{
+ int err;
+
+ /* init key */
+ if ((err = dsa_int_init(key)) != CRYPT_OK) return err;
+ /* generate params */
+ err = s_dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g);
+ if (err != CRYPT_OK) {
+ goto cleanup;
+ }
+
+ key->qord = group_size;
+
+ return CRYPT_OK;
+
+cleanup:
+ dsa_free(key);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_import.c b/Sources/libtomcrypt/pk/dsa/dsa_import.c
new file mode 100644
index 00000000..71619a55
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_import.c
@@ -0,0 +1,139 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_import.c
+ DSA implementation, import a DSA key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key)
+{
+ int err;
+ unsigned long zero = 0;
+ /* get key type */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->g,
+ LTC_ASN1_INTEGER, 1UL, key->y,
+ LTC_ASN1_INTEGER, 1UL, key->x,
+ LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) {
+
+ key->type = PK_PRIVATE;
+ }
+ return err;
+}
+
+/**
+ Import a DSA key
+ @param in The binary packet to import from
+ @param inlen The length of the binary packet
+ @param key [out] Where to store the imported key
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
+{
+ int err, stat;
+ unsigned char* tmpbuf = NULL;
+ unsigned char flags[1];
+
+ LTC_ARGCHK(in != NULL);
+
+ /* init key */
+ if ((err = dsa_int_init(key)) != CRYPT_OK) return err;
+
+ /* try to match the old libtomcrypt format */
+ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+ if (err == CRYPT_OK || err == CRYPT_INPUT_TOO_LONG) {
+ /* private key */
+ if (flags[0] == 1) {
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, key->g,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->y,
+ LTC_ASN1_INTEGER, 1UL, key->x,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ key->type = PK_PRIVATE;
+ goto LBL_OK;
+ }
+ /* public key */
+ else if (flags[0] == 0) {
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, key->g,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->y,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ key->type = PK_PUBLIC;
+ goto LBL_OK;
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+
+ if (dsa_import_pkcs1(in, inlen, key) != CRYPT_OK) {
+ ltc_asn1_list params[3];
+ unsigned long tmpbuf_len = inlen, len;
+
+ LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL);
+ LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL);
+ LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL);
+ len = 3;
+
+ tmpbuf = XCALLOC(1, tmpbuf_len);
+ if (tmpbuf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ err = x509_decode_subject_public_key_info(in, inlen,
+ LTC_OID_DSA, tmpbuf, &tmpbuf_len,
+ LTC_ASN1_SEQUENCE, params, &len);
+ if (err != CRYPT_OK) {
+ XFREE(tmpbuf);
+ goto LBL_ERR;
+ }
+
+ if ((err = der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) {
+ XFREE(tmpbuf);
+ goto LBL_ERR;
+ }
+
+ key->type = PK_PUBLIC;
+ XFREE(tmpbuf);
+ }
+
+LBL_OK:
+ key->qord = mp_unsigned_bin_size(key->q);
+
+ /* quick p, q, g validation, without primality testing
+ * + x, y validation */
+ if ((err = dsa_int_validate(key, &stat)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if (stat == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ return CRYPT_OK;
+LBL_ERR:
+ dsa_free(key);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_import_pkcs8.c b/Sources/libtomcrypt/pk/dsa/dsa_import_pkcs8.c
new file mode 100644
index 00000000..f8a592a6
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_import_pkcs8.c
@@ -0,0 +1,88 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_import_pkcs8.c
+ Import a PKCS DSA key
+*/
+
+#ifdef LTC_MDSA
+
+int dsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dsa_key *key)
+{
+ int err, stat;
+
+ LTC_UNUSED_PARAM(alg_id);
+
+ if (!alg_id->child
+ || !LTC_ASN1_IS_TYPE(alg_id->child->next, LTC_ASN1_SEQUENCE)
+ || !LTC_ASN1_IS_TYPE(priv_key, LTC_ASN1_OCTET_STRING)) {
+ return CRYPT_INVALID_PACKET;
+ }
+ if ((err = dsa_set_pqg_dsaparam(alg_id->child->next->data, alg_id->child->next->size, key)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = der_decode_integer(priv_key->data, priv_key->size, key->x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* quick p, q, g validation, without primality testing
+ * + x, y validation */
+ if ((err = dsa_int_validate(key, &stat)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if (stat == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ key->qord = mp_unsigned_bin_size(key->q);
+ key->type = PK_PRIVATE;
+
+ return err;
+LBL_ERR:
+ dsa_free(key);
+ return err;
+}
+/**
+ Import an RSAPrivateKey in PKCS#8 format
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param pw_ctx The password context when decrypting the private key
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int dsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ dsa_key *key)
+{
+ int err;
+ ltc_asn1_list *l = NULL;
+ ltc_asn1_list *alg_id, *priv_key;
+ enum ltc_oid_id pka;
+
+ LTC_ARGCHK(in != NULL);
+
+ if ((err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) {
+ goto LBL_DER_FREE;
+ }
+ if (pka != LTC_OID_DSA) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DER_FREE;
+ }
+
+ err = dsa_import_pkcs8_asn1(alg_id, priv_key, key);
+
+LBL_DER_FREE:
+ der_free_sequence_flexi(l);
+ return err;
+}
+
+#endif /* LTC_MRSA */
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_init.c b/Sources/libtomcrypt/pk/dsa/dsa_init.c
new file mode 100644
index 00000000..e7952845
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_init.c
@@ -0,0 +1,22 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+
+#ifdef LTC_MDSA
+
+/**
+ Init DSA key
+ @param key [out] the key to init
+ @return CRYPT_OK if successful.
+*/
+int dsa_int_init(dsa_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* init key */
+ return mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_make_key.c b/Sources/libtomcrypt/pk/dsa/dsa_make_key.c
new file mode 100644
index 00000000..5a205b27
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_make_key.c
@@ -0,0 +1,31 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_make_key.c
+ DSA implementation, generate a DSA key
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Old-style creation of a DSA key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param group_size Size of the multiplicative group (octets)
+ @param modulus_size Size of the modulus (octets)
+ @param key [out] Where to store the created key
+ @return CRYPT_OK if successful.
+*/
+int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
+{
+ int err;
+
+ if ((err = dsa_generate_pqg(prng, wprng, group_size, modulus_size, key)) != CRYPT_OK) { return err; }
+ if ((err = dsa_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_set.c b/Sources/libtomcrypt/pk/dsa/dsa_set.c
new file mode 100644
index 00000000..af7fcaa7
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_set.c
@@ -0,0 +1,99 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+
+#ifdef LTC_MDSA
+
+/**
+ Import DSA's p, q & g from raw numbers
+ @param p DSA's p in binary representation
+ @param plen The length of p
+ @param q DSA's q in binary representation
+ @param qlen The length of q
+ @param g DSA's g in binary representation
+ @param glen The length of g
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful.
+*/
+int dsa_set_pqg(const unsigned char *p, unsigned long plen,
+ const unsigned char *q, unsigned long qlen,
+ const unsigned char *g, unsigned long glen,
+ dsa_key *key)
+{
+ int err, stat;
+
+ LTC_ARGCHK(p != NULL);
+ LTC_ARGCHK(q != NULL);
+ LTC_ARGCHK(g != NULL);
+
+ /* init key */
+ if ((err = dsa_int_init(key)) != CRYPT_OK) return err;
+
+ if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->g, (unsigned char *)g , glen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->q, (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; }
+
+ key->qord = mp_unsigned_bin_size(key->q);
+
+ /* do only a quick validation, without primality testing */
+ if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { goto LBL_ERR; }
+ if (stat == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ return CRYPT_OK;
+
+LBL_ERR:
+ dsa_free(key);
+ return err;
+}
+
+/**
+ Import DSA public or private key-part from raw numbers
+
+ NB: The p, q & g parts must be set beforehand
+
+ @param in The key-part to import, either public or private.
+ @param inlen The key-part's length
+ @param type Which type of key (PK_PRIVATE or PK_PUBLIC)
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful.
+*/
+int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key)
+{
+ int err, stat = 0;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(key->x != NULL);
+ LTC_ARGCHK(key->y != NULL);
+ LTC_ARGCHK(key->p != NULL);
+ LTC_ARGCHK(key->g != NULL);
+ LTC_ARGCHK(key->q != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ if (type == PK_PRIVATE) {
+ key->type = PK_PRIVATE;
+ if ((err = mp_read_unsigned_bin(key->x, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto LBL_ERR; }
+ }
+ else {
+ key->type = PK_PUBLIC;
+ if ((err = mp_read_unsigned_bin(key->y, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
+ }
+
+ if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { goto LBL_ERR; }
+ if (stat == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ return CRYPT_OK;
+
+LBL_ERR:
+ dsa_free(key);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_set_pqg_dsaparam.c b/Sources/libtomcrypt/pk/dsa/dsa_set_pqg_dsaparam.c
new file mode 100644
index 00000000..f269c4bb
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_set_pqg_dsaparam.c
@@ -0,0 +1,56 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+
+#ifdef LTC_MDSA
+
+/**
+ Import DSA's p, q & g from dsaparam
+
+ dsaparam data: openssl dsaparam -outform DER -out dsaparam.der 2048
+
+ @param dsaparam The DSA param DER encoded data
+ @param dsaparamlen The length of dhparam data
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful.
+*/
+int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen,
+ dsa_key *key)
+{
+ int err, stat;
+
+ LTC_ARGCHK(dsaparam != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* init key */
+ if ((err = dsa_int_init(key)) != CRYPT_OK) return err;
+
+ if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->g,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ key->qord = mp_unsigned_bin_size(key->q);
+
+ /* quick p, q, g validation, without primality testing */
+ if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if (stat == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ return CRYPT_OK;
+
+LBL_ERR:
+ dsa_free(key);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_shared_secret.c b/Sources/libtomcrypt/pk/dsa/dsa_shared_secret.c
new file mode 100644
index 00000000..df11c178
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_shared_secret.c
@@ -0,0 +1,60 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_shared_secret.c
+ DSA Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Create a DSA shared secret between two keys
+ @param private_key The private DSA key (the exponent)
+ @param base The base of the exponentiation (allows this to be used for both encrypt and decrypt)
+ @param public_key The public key
+ @param out [out] Destination of the shared secret
+ @param outlen [in/out] The max size and resulting size of the shared secret
+ @return CRYPT_OK if successful
+*/
+int dsa_shared_secret(void *private_key, void *base,
+ const dsa_key *public_key,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x;
+ void *res;
+ int err;
+
+ LTC_ARGCHK(private_key != NULL);
+ LTC_ARGCHK(public_key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* make new point */
+ if ((err = mp_init(&res)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_exptmod(base, private_key, public_key->p, res)) != CRYPT_OK) {
+ mp_clear(res);
+ return err;
+ }
+
+ x = (unsigned long)mp_unsigned_bin_size(res);
+ if (*outlen < x) {
+ *outlen = x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto done;
+ }
+ zeromem(out, x);
+ if ((err = mp_to_unsigned_bin(res, out + (x - mp_unsigned_bin_size(res)))) != CRYPT_OK) { goto done; }
+
+ err = CRYPT_OK;
+ *outlen = x;
+done:
+ mp_clear(res);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_sign_hash.c b/Sources/libtomcrypt/pk/dsa/dsa_sign_hash.c
new file mode 100644
index 00000000..56baa803
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_sign_hash.c
@@ -0,0 +1,142 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_sign_hash.c
+ DSA implementation, sign a hash, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param r The "r" integer of the signature (caller must initialize with mp_init() first)
+ @param s The "s" integer of the signature (caller must initialize with mp_init() first)
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ void *r, void *s,
+ prng_state *prng, int wprng, const dsa_key *key)
+{
+ void *k, *kinv, *tmp;
+ unsigned char *buf;
+ int err, qbits;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* check group order size */
+ if (key->qord >= LTC_MDSA_MAX_GROUP) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ buf = XMALLOC(LTC_MDSA_MAX_GROUP);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* Init our temps */
+ if ((err = mp_init_multi(&k, &kinv, &tmp, LTC_NULL)) != CRYPT_OK) { goto ERRBUF; }
+
+ qbits = mp_count_bits(key->q);
+retry:
+
+ do {
+ /* gen random k */
+ if ((err = rand_bn_bits(k, qbits, prng, wprng)) != CRYPT_OK) { goto error; }
+
+ /* k should be from range: 1 <= k <= q-1 (see FIPS 186-4 B.2.2) */
+ if (mp_cmp_d(k, 0) != LTC_MP_GT || mp_cmp(k, key->q) != LTC_MP_LT) { goto retry; }
+
+ /* test gcd */
+ if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK) { goto error; }
+ } while (mp_cmp_d(tmp, 1) != LTC_MP_EQ);
+
+ /* now find 1/k mod q */
+ if ((err = mp_invmod(k, key->q, kinv)) != CRYPT_OK) { goto error; }
+
+ /* now find r = g^k mod p mod q */
+ if ((err = mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(r, key->q, r)) != CRYPT_OK) { goto error; }
+
+ if (mp_iszero(r) == LTC_MP_YES) { goto retry; }
+
+ /* FIPS 186-4 4.6: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash'*/
+ inlen = MIN(inlen, (unsigned long)(key->qord));
+
+ /* now find s = (in + xr)/k mod q */
+ if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mul(key->x, r, s)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(s, tmp, s)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK) { goto error; }
+
+ if (mp_iszero(s) == LTC_MP_YES) { goto retry; }
+
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(k, kinv, tmp, LTC_NULL);
+ERRBUF:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, LTC_MDSA_MAX_GROUP);
+#endif
+ XFREE(buf);
+ return err;
+}
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param out [out] Where to store the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, const dsa_key *key)
+{
+ void *r, *s;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (mp_init_multi(&r, &s, LTC_NULL) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = dsa_sign_hash_raw(in, inlen, r, s, prng, wprng, key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_INTEGER, 1UL, r,
+ LTC_ASN1_INTEGER, 1UL, s,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+error:
+ mp_clear_multi(r, s, LTC_NULL);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_verify_hash.c b/Sources/libtomcrypt/pk/dsa/dsa_verify_hash.c
new file mode 100644
index 00000000..500feda9
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_verify_hash.c
@@ -0,0 +1,127 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_verify_hash.c
+ DSA implementation, verify a signature, Tom St Denis
+*/
+
+
+#ifdef LTC_MDSA
+
+/**
+ Verify a DSA signature
+ @param r DSA "r" parameter
+ @param s DSA "s" parameter
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DSA key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash_raw( void *r, void *s,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, const dsa_key *key)
+{
+ void *w, *v, *u1, *u2;
+ int err;
+
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+
+ /* init our variables */
+ if ((err = mp_init_multi(&w, &v, &u1, &u2, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* neither r or s can be null or >q*/
+ if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || mp_cmp(r, key->q) != LTC_MP_LT || mp_cmp(s, key->q) != LTC_MP_LT) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* FIPS 186-4 4.7: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash' */
+ hashlen = MIN(hashlen, (unsigned long)(key->qord));
+
+ /* w = 1/s mod q */
+ if ((err = mp_invmod(s, key->q, w)) != CRYPT_OK) { goto error; }
+
+ /* u1 = m * w mod q */
+ if ((err = mp_read_unsigned_bin(u1, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(u1, w, key->q, u1)) != CRYPT_OK) { goto error; }
+
+ /* u2 = r*w mod q */
+ if ((err = mp_mulmod(r, w, key->q, u2)) != CRYPT_OK) { goto error; }
+
+ /* v = g^u1 * y^u2 mod p mod q */
+ if ((err = mp_exptmod(key->g, u1, key->p, u1)) != CRYPT_OK) { goto error; }
+ if ((err = mp_exptmod(key->y, u2, key->p, u2)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(u1, u2, key->p, v)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(v, key->q, v)) != CRYPT_OK) { goto error; }
+
+ /* if r = v then we're set */
+ if (mp_cmp(r, v) == LTC_MP_EQ) {
+ *stat = 1;
+ }
+
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(w, v, u1, u2, LTC_NULL);
+ return err;
+}
+
+/**
+ Verify a DSA signature
+ @param sig The signature
+ @param siglen The length of the signature (octets)
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DSA key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, const dsa_key *key)
+{
+ int err;
+ void *r, *s;
+ ltc_asn1_list sig_seq[2];
+ unsigned long reallen = 0;
+
+ LTC_ARGCHK(stat != NULL);
+ *stat = 0; /* must be set before the first return */
+
+ if ((err = mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL);
+ LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL);
+
+ err = der_decode_sequence_strict(sig, siglen, sig_seq, 2);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ err = der_length_sequence(sig_seq, 2, &reallen);
+ if (err != CRYPT_OK || reallen != siglen) {
+ goto LBL_ERR;
+ }
+
+ /* do the op */
+ err = dsa_verify_hash_raw(r, s, hash, hashlen, stat, key);
+
+LBL_ERR:
+ mp_clear_multi(r, s, LTC_NULL);
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/dsa/dsa_verify_key.c b/Sources/libtomcrypt/pk/dsa/dsa_verify_key.c
new file mode 100644
index 00000000..ccf7c6a3
--- /dev/null
+++ b/Sources/libtomcrypt/pk/dsa/dsa_verify_key.c
@@ -0,0 +1,204 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file dsa_verify_key.c
+ DSA implementation, verify a key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Validate a DSA key
+
+ Yeah, this function should've been called dsa_validate_key()
+ in the first place and for compat-reasons we keep it
+ as it was (for now).
+
+ @param key The key to validate
+ @param stat [out] Result of test, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int dsa_verify_key(const dsa_key *key, int *stat)
+{
+ int err;
+
+ err = dsa_int_validate_primes(key, stat);
+ if (err != CRYPT_OK || *stat == 0) return err;
+
+ return dsa_int_validate(key, stat);
+}
+
+/**
+ Non-complex part (no primality testing) of the validation
+ of DSA params (p, q, g)
+
+ @param key The key to validate
+ @param stat [out] Result of test, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int dsa_int_validate_pqg(const dsa_key *key, int *stat)
+{
+ void *tmp1, *tmp2;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+ *stat = 0;
+
+ /* check q-order */
+ if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 ||
+ (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) ||
+ (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) {
+ return CRYPT_OK;
+ }
+
+ /* FIPS 186-4 chapter 4.1: 1 < g < p */
+ if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) {
+ return CRYPT_OK;
+ }
+
+ if ((err = mp_init_multi(&tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { return err; }
+
+ /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */
+ if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; }
+ if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; }
+ if (mp_iszero(tmp2) != LTC_MP_YES) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ /* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in
+ * the multiplicative group of GF(p) - so we make sure that g^q mod p = 1
+ */
+ if ((err = mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; }
+ if (mp_cmp_d(tmp1, 1) != LTC_MP_EQ) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ err = CRYPT_OK;
+ *stat = 1;
+error:
+ mp_clear_multi(tmp2, tmp1, LTC_NULL);
+ return err;
+}
+
+/**
+ Primality testing of DSA params p and q
+
+ @param key The key to validate
+ @param stat [out] Result of test, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int dsa_int_validate_primes(const dsa_key *key, int *stat)
+{
+ int err, res;
+
+ *stat = 0;
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* key->q prime? */
+ if ((err = mp_prime_is_prime(key->q, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == LTC_MP_NO) {
+ return CRYPT_OK;
+ }
+
+ /* key->p prime? */
+ if ((err = mp_prime_is_prime(key->p, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == LTC_MP_NO) {
+ return CRYPT_OK;
+ }
+
+ *stat = 1;
+ return CRYPT_OK;
+}
+
+/**
+ Validation of a DSA key (x and y values)
+
+ @param key The key to validate
+ @param stat [out] Result of test, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int dsa_int_validate_xy(const dsa_key *key, int *stat)
+{
+ void *tmp;
+ int err;
+
+ *stat = 0;
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* 1 < y < p-1 */
+ if ((err = mp_init(&tmp)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) {
+ goto error;
+ }
+ if (mp_cmp_d(key->y, 1) != LTC_MP_GT || mp_cmp(key->y, tmp) != LTC_MP_LT) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ if (key->type == PK_PRIVATE) {
+ /* FIPS 186-4 chapter 4.1: 0 < x < q */
+ if (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT) {
+ err = CRYPT_OK;
+ goto error;
+ }
+ /* FIPS 186-4 chapter 4.1: y = g^x mod p */
+ if ((err = mp_exptmod(key->g, key->x, key->p, tmp)) != CRYPT_OK) {
+ goto error;
+ }
+ if (mp_cmp(tmp, key->y) != LTC_MP_EQ) {
+ err = CRYPT_OK;
+ goto error;
+ }
+ }
+ else {
+ /* with just a public key we cannot test y = g^x mod p therefore we
+ * only test that y^q mod p = 1, which makes sure y is in g^x mod p
+ */
+ if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) {
+ goto error;
+ }
+ if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) {
+ err = CRYPT_OK;
+ goto error;
+ }
+ }
+
+ err = CRYPT_OK;
+ *stat = 1;
+error:
+ mp_clear(tmp);
+ return err;
+}
+
+/**
+ Validation of DSA params (p, q, g) and DSA key (x and y)
+
+ @param key The key to validate
+ @param stat [out] Result of test, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int dsa_int_validate(const dsa_key *key, int *stat)
+{
+ int err;
+
+ err = dsa_int_validate_pqg(key, stat);
+ if (err != CRYPT_OK || *stat == 0) return err;
+
+ return dsa_int_validate_xy(key, stat);
+
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ec25519/ec25519_crypto_ctx.c b/Sources/libtomcrypt/pk/ec25519/ec25519_crypto_ctx.c
new file mode 100644
index 00000000..e1efb301
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ec25519/ec25519_crypto_ctx.c
@@ -0,0 +1,41 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ec25519_crypto_ctx.c
+ curve25519 crypto context helper
+*/
+
+#ifdef LTC_CURVE25519
+
+int ec25519_crypto_ctx(unsigned char *out, unsigned long *outlen, unsigned char flag, const unsigned char *ctx, unsigned long ctxlen)
+{
+ unsigned char *buf = out;
+
+ const char *prefix = "SigEd25519 no Ed25519 collisions";
+ const unsigned long prefix_len = XSTRLEN(prefix);
+ const unsigned char ctxlen8 = (unsigned char)ctxlen;
+
+ if (ctxlen > 255u) return CRYPT_INPUT_TOO_LONG;
+ if (*outlen < prefix_len + 2u + ctxlen) return CRYPT_BUFFER_OVERFLOW;
+
+ XMEMCPY(buf, prefix, prefix_len);
+ buf += prefix_len;
+ XMEMCPY(buf, &flag, 1);
+ buf++;
+ XMEMCPY(buf, &ctxlen8, 1);
+ buf++;
+
+ if (ctxlen > 0u) {
+ LTC_ARGCHK(ctx != NULL);
+ XMEMCPY(buf, ctx, ctxlen);
+ buf += ctxlen;
+ }
+
+ *outlen = buf-out;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ec25519/ec25519_export.c b/Sources/libtomcrypt/pk/ec25519/ec25519_export.c
new file mode 100644
index 00000000..a6dba677
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ec25519/ec25519_export.c
@@ -0,0 +1,94 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ec25519_export.c
+ Generic export of a Curve/Ed25519 key to a binary packet, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Generic export of a Curve/Ed25519 key to a binary packet
+ @param out [out] The destination for the key
+ @param outlen [in/out] The max size and resulting size of the Ed25519 key
+ @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC)
+ @param key The key you wish to export
+ @return CRYPT_OK if successful
+*/
+int ec25519_export( unsigned char *out, unsigned long *outlen,
+ int which,
+ const curve25519_key *key)
+{
+ int err, std;
+ const char* OID;
+ unsigned long oid[16], oidlen;
+ ltc_asn1_list alg_id[1];
+ enum ltc_oid_id oid_id;
+ unsigned char private_key[34];
+ unsigned long version, private_key_len = sizeof(private_key);
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ std = which & PK_STD;
+ which &= ~PK_STD;
+ if ((err = pk_get_oid_id(key->pka, &oid_id)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (which == PK_PRIVATE) {
+ if(key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE;
+
+ if (std == PK_STD) {
+ if ((err = pk_get_oid(oid_id, &OID)) != CRYPT_OK) {
+ return err;
+ }
+ oidlen = sizeof(oid)/sizeof(oid[0]);
+ if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) {
+ return err;
+ }
+
+ LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen);
+
+ /* encode private key as PKCS#8 */
+ if ((err = der_encode_octet_string(key->priv, 32uL, private_key, &private_key_len)) != CRYPT_OK) {
+ return err;
+ }
+
+ version = 0;
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1uL, &version,
+ LTC_ASN1_SEQUENCE, 1uL, alg_id,
+ LTC_ASN1_OCTET_STRING, private_key_len, private_key,
+ LTC_ASN1_EOL, 0uL, NULL);
+ } else {
+ if (*outlen < sizeof(key->priv)) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else {
+ XMEMCPY(out, key->priv, sizeof(key->priv));
+ err = CRYPT_OK;
+ }
+ *outlen = sizeof(key->priv);
+ }
+ } else {
+ if (std == PK_STD) {
+ /* encode public key as SubjectPublicKeyInfo */
+ err = x509_encode_subject_public_key_info(out, outlen, oid_id, key->pub, 32uL, LTC_ASN1_EOL, NULL, 0);
+ } else {
+ if (*outlen < sizeof(key->pub)) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else {
+ XMEMCPY(out, key->pub, sizeof(key->pub));
+ err = CRYPT_OK;
+ }
+ *outlen = sizeof(key->pub);
+ }
+ }
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ec25519/ec25519_import_pkcs8.c b/Sources/libtomcrypt/pk/ec25519/ec25519_import_pkcs8.c
new file mode 100644
index 00000000..4a7f9fb9
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ec25519/ec25519_import_pkcs8.c
@@ -0,0 +1,86 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ec25519_import_pkcs8.c
+ Generic import of a Curve/Ed25519 private key in PKCS#8 format, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+typedef int (*sk_to_pk)(unsigned char *pk , const unsigned char *sk);
+
+int ec25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
+ enum ltc_oid_id id,
+ curve25519_key *key)
+{
+ int err;
+ unsigned long key_len;
+ sk_to_pk fp;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ LTC_UNUSED_PARAM(alg_id);
+
+ switch (id) {
+ case LTC_OID_ED25519:
+ fp = tweetnacl_crypto_sk_to_pk;
+ break;
+ case LTC_OID_X25519:
+ fp = tweetnacl_crypto_scalarmult_base;
+ break;
+ default:
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ key_len = sizeof(key->priv);
+ if ((err = der_decode_octet_string(priv_key->data, priv_key->size, key->priv, &key_len)) == CRYPT_OK) {
+ fp(key->pub, key->priv);
+ key->type = PK_PRIVATE;
+ err = pk_get_pka_id(id, &key->pka);
+ }
+ return err;
+}
+
+/**
+ Generic import of a Curve/Ed25519 private key in PKCS#8 format
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param pw_ctx The password context when decrypting the private key
+ @param id The type of the private key
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ enum ltc_oid_id id,
+ curve25519_key *key)
+{
+ int err;
+ ltc_asn1_list *l = NULL;
+ ltc_asn1_list *alg_id, *priv_key;
+ enum ltc_oid_id pka;
+
+ LTC_ARGCHK(in != NULL);
+
+ err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l);
+ if (err != CRYPT_OK) return err;
+
+ if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) {
+ goto LBL_DER_FREE;
+ }
+ if (pka != id) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DER_FREE;
+ }
+
+ err = ec25519_import_pkcs8_asn1(alg_id, priv_key, id, key);
+
+LBL_DER_FREE:
+ der_free_sequence_flexi(l);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ec25519/tweetnacl.c b/Sources/libtomcrypt/pk/ec25519/tweetnacl.c
new file mode 100644
index 00000000..9db0dcd8
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ec25519/tweetnacl.c
@@ -0,0 +1,491 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/* automatically generated file, do not edit */
+
+#define FOR(i,n) for (i = 0;i < n;++i)
+#define sv static void
+
+typedef unsigned char u8;
+typedef ulong32 u32;
+typedef ulong64 u64;
+typedef long64 i64;
+typedef i64 gf[16];
+
+static const u8
+ nine[32] = {9};
+static const gf
+ gf0,
+ gf1 = {1},
+ gf121665 = {0xDB41,1},
+ D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
+ D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
+ X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
+ Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666},
+ I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
+
+static int vn(const u8 *x,const u8 *y,int n)
+{
+ int i;
+ u32 d = 0;
+ FOR(i,n) d |= x[i]^y[i];
+ return (1 & ((d - 1) >> 8)) - 1;
+}
+
+static int tweetnacl_crypto_verify_32(const u8 *x,const u8 *y)
+{
+ return vn(x,y,32);
+}
+
+sv set25519(gf r, const gf a)
+{
+ int i;
+ FOR(i,16) r[i]=a[i];
+}
+
+sv car25519(gf o)
+{
+ int i;
+ i64 c;
+ FOR(i,16) {
+ o[i]+=(1LL<<16);
+ c=o[i]>>16;
+ o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
+ o[i]-=c<<16;
+ }
+}
+
+sv sel25519(gf p,gf q,int b)
+{
+ i64 t,i,c=~(b-1);
+ FOR(i,16) {
+ t= c&(p[i]^q[i]);
+ p[i]^=t;
+ q[i]^=t;
+ }
+}
+
+sv pack25519(u8 *o,const gf n)
+{
+ int i,j,b;
+ gf m,t;
+ FOR(i,16) t[i]=n[i];
+ car25519(t);
+ car25519(t);
+ car25519(t);
+ FOR(j,2) {
+ m[0]=t[0]-0xffed;
+ for(i=1;i<15;i++) {
+ m[i]=t[i]-0xffff-((m[i-1]>>16)&1);
+ m[i-1]&=0xffff;
+ }
+ m[15]=t[15]-0x7fff-((m[14]>>16)&1);
+ b=(m[15]>>16)&1;
+ m[14]&=0xffff;
+ sel25519(t,m,1-b);
+ }
+ FOR(i,16) {
+ o[2*i]=t[i]&0xff;
+ o[2*i+1]=t[i]>>8;
+ }
+}
+
+static int neq25519(const gf a, const gf b)
+{
+ u8 c[32],d[32];
+ pack25519(c,a);
+ pack25519(d,b);
+ return tweetnacl_crypto_verify_32(c,d);
+}
+
+static u8 par25519(const gf a)
+{
+ u8 d[32];
+ pack25519(d,a);
+ return d[0]&1;
+}
+
+sv unpack25519(gf o, const u8 *n)
+{
+ int i;
+ FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
+ o[15]&=0x7fff;
+}
+
+sv A(gf o,const gf a,const gf b)
+{
+ int i;
+ FOR(i,16) o[i]=a[i]+b[i];
+}
+
+sv Z(gf o,const gf a,const gf b)
+{
+ int i;
+ FOR(i,16) o[i]=a[i]-b[i];
+}
+
+sv M(gf o,const gf a,const gf b)
+{
+ i64 i,j,t[31];
+ FOR(i,31) t[i]=0;
+ FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
+ FOR(i,15) t[i]+=38*t[i+16];
+ FOR(i,16) o[i]=t[i];
+ car25519(o);
+ car25519(o);
+}
+
+sv S(gf o,const gf a)
+{
+ M(o,a,a);
+}
+
+sv inv25519(gf o,const gf i)
+{
+ gf c;
+ int a;
+ FOR(a,16) c[a]=i[a];
+ for(a=253;a>=0;a--) {
+ S(c,c);
+ if(a!=2&&a!=4) M(c,c,i);
+ }
+ FOR(a,16) o[a]=c[a];
+}
+
+sv pow2523(gf o,const gf i)
+{
+ gf c;
+ int a;
+ FOR(a,16) c[a]=i[a];
+ for(a=250;a>=0;a--) {
+ S(c,c);
+ if(a!=1) M(c,c,i);
+ }
+ FOR(a,16) o[a]=c[a];
+}
+
+int tweetnacl_crypto_scalarmult(u8 *q,const u8 *n,const u8 *p)
+{
+ u8 z[32];
+ i64 x[80],r,i;
+ gf a,b,c,d,e,f;
+ FOR(i,31) z[i]=n[i];
+ z[31]=(n[31]&127)|64;
+ z[0]&=248;
+ unpack25519(x,p);
+ FOR(i,16) {
+ b[i]=x[i];
+ d[i]=a[i]=c[i]=0;
+ }
+ a[0]=d[0]=1;
+ for(i=254;i>=0;--i) {
+ r=(z[i>>3]>>(i&7))&1;
+ sel25519(a,b,r);
+ sel25519(c,d,r);
+ A(e,a,c);
+ Z(a,a,c);
+ A(c,b,d);
+ Z(b,b,d);
+ S(d,e);
+ S(f,a);
+ M(a,c,a);
+ M(c,b,e);
+ A(e,a,c);
+ Z(a,a,c);
+ S(b,a);
+ Z(c,d,f);
+ M(a,c,gf121665);
+ A(a,a,d);
+ M(c,c,a);
+ M(a,d,f);
+ M(d,b,x);
+ S(b,e);
+ sel25519(a,b,r);
+ sel25519(c,d,r);
+ }
+ FOR(i,16) {
+ x[i+16]=a[i];
+ x[i+32]=c[i];
+ x[i+48]=b[i];
+ x[i+64]=d[i];
+ }
+ inv25519(x+32,x+32);
+ M(x+16,x+16,x+32);
+ pack25519(q,x+16);
+ return 0;
+}
+
+int tweetnacl_crypto_scalarmult_base(u8 *q,const u8 *n)
+{
+ return tweetnacl_crypto_scalarmult(q,n,nine);
+}
+
+static LTC_INLINE int tweetnacl_crypto_hash_ctx(u8 *out,const u8 *m,u64 n,const u8 *ctx,u32 cs)
+{
+ unsigned long len = 64;
+ int hash_idx = find_hash("sha512");
+
+ if (n > ULONG_MAX) return CRYPT_OVERFLOW;
+
+ if(cs == 0)
+ return hash_memory(hash_idx, m, n, out, &len);
+
+ return hash_memory_multi(hash_idx, out, &len, ctx, cs, m, n, LTC_NULL);
+}
+
+static LTC_INLINE int tweetnacl_crypto_hash(u8 *out,const u8 *m,u64 n)
+{
+ return tweetnacl_crypto_hash_ctx(out, m, n, NULL, 0);
+}
+
+sv add(gf p[4],gf q[4])
+{
+ gf a,b,c,d,t,e,f,g,h;
+
+ Z(a, p[1], p[0]);
+ Z(t, q[1], q[0]);
+ M(a, a, t);
+ A(b, p[0], p[1]);
+ A(t, q[0], q[1]);
+ M(b, b, t);
+ M(c, p[3], q[3]);
+ M(c, c, D2);
+ M(d, p[2], q[2]);
+ A(d, d, d);
+ Z(e, b, a);
+ Z(f, d, c);
+ A(g, d, c);
+ A(h, b, a);
+
+ M(p[0], e, f);
+ M(p[1], h, g);
+ M(p[2], g, f);
+ M(p[3], e, h);
+}
+
+sv cswap(gf p[4],gf q[4],u8 b)
+{
+ int i;
+ FOR(i,4)
+ sel25519(p[i],q[i],b);
+}
+
+sv pack(u8 *r,gf p[4])
+{
+ gf tx, ty, zi;
+ inv25519(zi, p[2]);
+ M(tx, p[0], zi);
+ M(ty, p[1], zi);
+ pack25519(r, ty);
+ r[31] ^= par25519(tx) << 7;
+}
+
+sv scalarmult(gf p[4],gf q[4],const u8 *s)
+{
+ int i;
+ set25519(p[0],gf0);
+ set25519(p[1],gf1);
+ set25519(p[2],gf1);
+ set25519(p[3],gf0);
+ for (i = 255;i >= 0;--i) {
+ u8 b = (s[i/8]>>(i&7))&1;
+ cswap(p,q,b);
+ add(q,p);
+ add(p,p);
+ cswap(p,q,b);
+ }
+}
+
+sv scalarbase(gf p[4],const u8 *s)
+{
+ gf q[4];
+ set25519(q[0],X);
+ set25519(q[1],Y);
+ set25519(q[2],gf1);
+ M(q[3],X,Y);
+ scalarmult(p,q,s);
+}
+
+int tweetnacl_crypto_sk_to_pk(u8 *pk, const u8 *sk)
+{
+ u8 d[64];
+ gf p[4];
+ tweetnacl_crypto_hash(d, sk, 32);
+ d[0] &= 248;
+ d[31] &= 127;
+ d[31] |= 64;
+
+ scalarbase(p,d);
+ pack(pk,p);
+
+ return 0;
+}
+
+int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, u8 *pk, u8 *sk)
+{
+ int err;
+
+ /* randombytes(sk,32); */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (prng_descriptor[wprng].read(sk,32, prng) != 32) {
+ return CRYPT_ERROR_READPRNG;
+ }
+
+ if ((err = tweetnacl_crypto_sk_to_pk(pk, sk)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* FOR(i,32) sk[32 + i] = pk[i];
+ * we don't copy the pk in the sk */
+ return CRYPT_OK;
+}
+
+static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
+
+sv modL(u8 *r,i64 x[64])
+{
+ i64 carry,i,j;
+ for (i = 63;i >= 32;--i) {
+ carry = 0;
+ for (j = i - 32;j < i - 12;++j) {
+ x[j] += carry - 16 * x[i] * L[j - (i - 32)];
+ carry = (x[j] + 128) >> 8;
+ x[j] -= carry << 8;
+ }
+ x[j] += carry;
+ x[i] = 0;
+ }
+ carry = 0;
+ FOR(j,32) {
+ x[j] += carry - (x[31] >> 4) * L[j];
+ carry = x[j] >> 8;
+ x[j] &= 255;
+ }
+ FOR(j,32) x[j] -= carry * L[j];
+ FOR(i,32) {
+ x[i+1] += x[i] >> 8;
+ r[i] = x[i] & 255;
+ }
+}
+
+sv reduce(u8 *r)
+{
+ i64 x[64],i;
+ FOR(i,64) x[i] = (u64) r[i];
+ FOR(i,64) r[i] = 0;
+ modL(r,x);
+}
+
+int tweetnacl_crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 mlen,const u8 *sk,const u8 *pk, const u8 *ctx, u64 cs)
+{
+ u8 d[64],h[64],r[64];
+ i64 i,j,x[64];
+ gf p[4];
+
+ tweetnacl_crypto_hash(d, sk, 32);
+ d[0] &= 248;
+ d[31] &= 127;
+ d[31] |= 64;
+
+ *smlen = mlen+64;
+ FOR(i,(i64)mlen) sm[64 + i] = m[i];
+ FOR(i,32) sm[32 + i] = d[32 + i];
+
+ tweetnacl_crypto_hash_ctx(r, sm+32, mlen+32,ctx,cs);
+ reduce(r);
+ scalarbase(p,r);
+ pack(sm,p);
+
+ FOR(i,32) sm[i+32] = pk[i];
+ tweetnacl_crypto_hash_ctx(h,sm,mlen + 64,ctx,cs);
+ reduce(h);
+
+ FOR(i,64) x[i] = 0;
+ FOR(i,32) x[i] = (u64) r[i];
+ FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j];
+ modL(sm + 32,x);
+
+ return 0;
+}
+
+static int unpackneg(gf r[4],const u8 p[32])
+{
+ gf t, chk, num, den, den2, den4, den6;
+ set25519(r[2],gf1);
+ unpack25519(r[1],p);
+ S(num,r[1]);
+ M(den,num,D);
+ Z(num,num,r[2]);
+ A(den,r[2],den);
+
+ S(den2,den);
+ S(den4,den2);
+ M(den6,den4,den2);
+ M(t,den6,num);
+ M(t,t,den);
+
+ pow2523(t,t);
+ M(t,t,num);
+ M(t,t,den);
+ M(t,t,den);
+ M(r[0],t,den);
+
+ S(chk,r[0]);
+ M(chk,chk,den);
+ if (neq25519(chk, num)) M(r[0],r[0],I);
+
+ S(chk,r[0]);
+ M(chk,chk,den);
+ if (neq25519(chk, num)) return -1;
+
+ if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]);
+
+ M(r[3],r[0],r[1]);
+ return 0;
+}
+
+int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen,const u8 *ctx,u64 cs,const u8 *pk)
+{
+ u64 i;
+ u8 s[32],t[32],h[64];
+ gf p[4],q[4];
+
+ *stat = 0;
+ if (*mlen < smlen) return CRYPT_BUFFER_OVERFLOW;
+ *mlen = -1;
+ if (smlen < 64) return CRYPT_INVALID_ARG;
+
+ if (unpackneg(q,pk)) return CRYPT_ERROR;
+
+ XMEMMOVE(m,sm,smlen);
+ XMEMMOVE(s,m + 32,32);
+ XMEMMOVE(m + 32,pk,32);
+ tweetnacl_crypto_hash_ctx(h,m,smlen,ctx,cs);
+ reduce(h);
+ scalarmult(p,q,h);
+
+ scalarbase(q,s);
+ add(p,q);
+ pack(t,p);
+
+ smlen -= 64;
+ if (tweetnacl_crypto_verify_32(sm, t)) {
+ FOR(i,smlen) m[i] = 0;
+ zeromem(m, smlen);
+ return CRYPT_OK;
+ }
+
+ *stat = 1;
+ XMEMMOVE(m,m + 64,smlen);
+ *mlen = smlen;
+ return CRYPT_OK;
+}
+
+int tweetnacl_crypto_ph(u8 *out,const u8 *msg,u64 msglen)
+{
+ return tweetnacl_crypto_hash(out, msg, msglen);
+}
diff --git a/Sources/libtomcrypt/pk/ecc/ecc.c b/Sources/libtomcrypt/pk/ecc/ecc.c
new file mode 100644
index 00000000..84068a97
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc.c
@@ -0,0 +1,435 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/* This array holds the curve parameters.
+ * Curves (prime field only) are taken from:
+ * - http://www.secg.org/collateral/sec2_final.pdf (named: SECP*)
+ * - http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (named: NISTP*)
+ * - ANS X9.62 (named: PRIMEP*)
+ * - http://www.ecc-brainpool.org/download/Domain-parameters.pdf (named: BRAINPOOLP*)
+ */
+const ltc_ecc_curve ltc_ecc_curves[] = {
+#ifdef LTC_ECC_SECP112R1
+{
+ /* prime */ "DB7C2ABF62E35E668076BEAD208B",
+ /* A */ "DB7C2ABF62E35E668076BEAD2088",
+ /* B */ "659EF8BA043916EEDE8911702B22",
+ /* order */ "DB7C2ABF62E35E7628DFAC6561C5",
+ /* Gx */ "09487239995A5EE76B55F9C2F098",
+ /* Gy */ "A89CE5AF8724C0A23E0E0FF77500",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.6"
+},
+#endif
+#ifdef LTC_ECC_SECP112R2
+{
+ /* prime */ "DB7C2ABF62E35E668076BEAD208B",
+ /* A */ "6127C24C05F38A0AAAF65C0EF02C",
+ /* B */ "51DEF1815DB5ED74FCC34C85D709",
+ /* order */ "36DF0AAFD8B8D7597CA10520D04B",
+ /* Gx */ "4BA30AB5E892B4E1649DD0928643",
+ /* Gy */ "ADCD46F5882E3747DEF36E956E97",
+ /* cofactor */ 4,
+ /* OID */ "1.3.132.0.7"
+},
+#endif
+#ifdef LTC_ECC_SECP128R1
+{
+ /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
+ /* A */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
+ /* B */ "E87579C11079F43DD824993C2CEE5ED3",
+ /* order */ "FFFFFFFE0000000075A30D1B9038A115",
+ /* Gx */ "161FF7528B899B2D0C28607CA52C5B86",
+ /* Gy */ "CF5AC8395BAFEB13C02DA292DDED7A83",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.28"
+},
+#endif
+#ifdef LTC_ECC_SECP128R2
+{
+ /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
+ /* A */ "D6031998D1B3BBFEBF59CC9BBFF9AEE1",
+ /* B */ "5EEEFCA380D02919DC2C6558BB6D8A5D",
+ /* order */ "3FFFFFFF7FFFFFFFBE0024720613B5A3",
+ /* Gx */ "7B6AA5D85E572983E6FB32A7CDEBC140",
+ /* Gy */ "27B6916A894D3AEE7106FE805FC34B44",
+ /* cofactor */ 4,
+ /* OID */ "1.3.132.0.29"
+},
+#endif
+#ifdef LTC_ECC_SECP160R1
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
+ /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
+ /* B */ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
+ /* order */ "0100000000000000000001F4C8F927AED3CA752257",
+ /* Gx */ "4A96B5688EF573284664698968C38BB913CBFC82",
+ /* Gy */ "23A628553168947D59DCC912042351377AC5FB32",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.8"
+},
+#endif
+#ifdef LTC_ECC_SECP160R2
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
+ /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
+ /* B */ "B4E134D3FB59EB8BAB57274904664D5AF50388BA",
+ /* order */ "0100000000000000000000351EE786A818F3A1A16B",
+ /* Gx */ "52DCB034293A117E1F4FF11B30F7199D3144CE6D",
+ /* Gy */ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.30"
+},
+#endif
+#ifdef LTC_ECC_SECP160K1
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
+ /* A */ "0000000000000000000000000000000000000000",
+ /* B */ "0000000000000000000000000000000000000007",
+ /* order */ "0100000000000000000001B8FA16DFAB9ACA16B6B3",
+ /* Gx */ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
+ /* Gy */ "938CF935318FDCED6BC28286531733C3F03C4FEE",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.9"
+},
+#endif
+#ifdef LTC_ECC_SECP192R1
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+ /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
+ /* B */ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
+ /* Gx */ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
+ /* Gy */ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
+ /* cofactor */ 1,
+ /* OID */ "1.2.840.10045.3.1.1"
+},
+#endif
+#ifdef LTC_ECC_PRIME192V2
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+ /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
+ /* B */ "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31",
+ /* Gx */ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A",
+ /* Gy */ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15",
+ /* cofactor */ 1,
+ /* OID */ "1.2.840.10045.3.1.2"
+},
+#endif
+#ifdef LTC_ECC_PRIME192V3
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+ /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
+ /* B */ "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13",
+ /* Gx */ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896",
+ /* Gy */ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0",
+ /* cofactor */ 1,
+ /* OID */ "1.2.840.10045.3.1.3"
+},
+#endif
+#ifdef LTC_ECC_SECP192K1
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
+ /* A */ "000000000000000000000000000000000000000000000000",
+ /* B */ "000000000000000000000000000000000000000000000003",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D",
+ /* Gx */ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
+ /* Gy */ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.31"
+},
+#endif
+#ifdef LTC_ECC_SECP224R1
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
+ /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
+ /* B */ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
+ /* Gx */ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
+ /* Gy */ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.33"
+},
+#endif
+#ifdef LTC_ECC_SECP224K1
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
+ /* A */ "00000000000000000000000000000000000000000000000000000000",
+ /* B */ "00000000000000000000000000000000000000000000000000000005",
+ /* order */ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",
+ /* Gx */ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
+ /* Gy */ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.32"
+},
+#endif
+#ifdef LTC_ECC_SECP256R1
+{
+ /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+ /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
+ /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+ /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+ /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+ /* cofactor */ 1,
+ /* OID */ "1.2.840.10045.3.1.7"
+},
+#endif
+#ifdef LTC_ECC_SECP256K1
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
+ /* A */ "0000000000000000000000000000000000000000000000000000000000000000",
+ /* B */ "0000000000000000000000000000000000000000000000000000000000000007",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
+ /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
+ /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.10"
+},
+#endif
+#ifdef LTC_ECC_SECP384R1
+{
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+ /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+ /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.34"
+},
+#endif
+#ifdef LTC_ECC_SECP521R1
+{
+ /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+ /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+ /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+ /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+ /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+ /* cofactor */ 1,
+ /* OID */ "1.3.132.0.35"
+},
+#endif
+#ifdef LTC_ECC_PRIME239V1
+{
+ /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
+ /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
+ /* B */ "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A",
+ /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B",
+ /* Gx */ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF",
+ /* Gy */ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE",
+ /* cofactor */ 1,
+ /* OID */ "1.2.840.10045.3.1.4"
+},
+#endif
+#ifdef LTC_ECC_PRIME239V2
+{
+ /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
+ /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
+ /* B */ "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C",
+ /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063",
+ /* Gx */ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7",
+ /* Gy */ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA",
+ /* cofactor */ 1,
+ /* OID */ "1.2.840.10045.3.1.5"
+},
+#endif
+#ifdef LTC_ECC_PRIME239V3
+{
+ /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
+ /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
+ /* B */ "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E",
+ /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551",
+ /* Gx */ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A",
+ /* Gy */ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3",
+ /* cofactor */ 1,
+ /* OID */ "1.2.840.10045.3.1.6"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP160R1
+{
+ /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
+ /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
+ /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58",
+ /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
+ /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3",
+ /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.1"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP192R1
+{
+ /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
+ /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
+ /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
+ /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
+ /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6",
+ /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.3"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP224R1
+{
+ /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
+ /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
+ /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
+ /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
+ /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
+ /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.5"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP256R1
+{
+ /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
+ /* A */ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
+ /* B */ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
+ /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
+ /* Gx */ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
+ /* Gy */ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.7"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP320R1
+{
+ /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
+ /* A */ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
+ /* B */ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
+ /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
+ /* Gx */ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
+ /* Gy */ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.9"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP384R1
+{
+ /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
+ /* A */ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
+ /* B */ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
+ /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
+ /* Gx */ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
+ /* Gy */ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.11"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP512R1
+{
+ /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
+ /* A */ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
+ /* B */ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
+ /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
+ /* Gx */ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
+ /* Gy */ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.13"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP160T1
+{
+ /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
+ /* A */ "E95E4A5F737059DC60DFC7AD95B3D8139515620C",
+ /* B */ "7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380",
+ /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
+ /* Gx */ "B199B13B9B34EFC1397E64BAEB05ACC265FF2378",
+ /* Gy */ "ADD6718B7C7C1961F0991B842443772152C9E0AD",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.2"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP192T1
+{
+ /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
+ /* A */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294",
+ /* B */ "13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79",
+ /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
+ /* Gx */ "3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129",
+ /* Gy */ "097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.4"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP224T1
+{
+ /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
+ /* A */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC",
+ /* B */ "4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D",
+ /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
+ /* Gx */ "6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580",
+ /* Gy */ "0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.6"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP256T1
+{
+ /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
+ /* A */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374",
+ /* B */ "662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04",
+ /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
+ /* Gx */ "A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4",
+ /* Gy */ "2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.8"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP320T1
+{
+ /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
+ /* A */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24",
+ /* B */ "A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353",
+ /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
+ /* Gx */ "925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52",
+ /* Gy */ "63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.10"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP384T1
+{
+ /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
+ /* A */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50",
+ /* B */ "7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE",
+ /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
+ /* Gx */ "18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC",
+ /* Gy */ "25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.12"
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP512T1
+{
+ /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
+ /* A */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0",
+ /* B */ "7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E",
+ /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
+ /* Gx */ "640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA",
+ /* Gy */ "5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332",
+ /* cofactor */ 1,
+ /* OID */ "1.3.36.3.3.2.8.1.1.14"
+},
+#endif
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL
+}
+};
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_ansi_x963_export.c b/Sources/libtomcrypt/pk/ecc/ecc_ansi_x963_export.c
new file mode 100644
index 00000000..472e1b56
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_ansi_x963_export.c
@@ -0,0 +1,24 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_ansi_x963_export.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/** ECC X9.63 (Sec. 4.3.6) uncompressed export
+ @param key Key to export
+ @param out [out] destination of export
+ @param outlen [in/out] Length of destination and final output size
+ Return CRYPT_OK on success
+*/
+int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen)
+{
+ return ecc_get_key(out, outlen, PK_PUBLIC, key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_ansi_x963_import.c b/Sources/libtomcrypt/pk/ecc/ecc_ansi_x963_import.c
new file mode 100644
index 00000000..58eb27d9
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_ansi_x963_import.c
@@ -0,0 +1,52 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_ansi_x963_import.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/** Import an ANSI X9.63 format public key
+ @param in The input data to read
+ @param inlen The length of the input data
+ @param key [out] destination to store imported key \
+*/
+int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ return ecc_ansi_x963_import_ex(in, inlen, key, NULL);
+}
+
+int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu)
+{
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* must be odd */
+ if ((inlen & 1) == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* initialize key->dp */
+ if (cu == NULL) {
+ /* this case works only for uncompressed public keys */
+ if ((err = ecc_set_curve_by_size((inlen-1)>>1, key)) != CRYPT_OK) { return err; }
+ }
+ else {
+ /* this one works for both compressed / uncompressed pubkeys */
+ if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; }
+ }
+
+ /* load public key */
+ if ((err = ecc_set_key((unsigned char *)in, inlen, PK_PUBLIC, key)) != CRYPT_OK) { return err; }
+
+ /* we're done */
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_decrypt_key.c b/Sources/libtomcrypt/pk/ecc/ecc_decrypt_key.c
new file mode 100644
index 00000000..ad2d9b13
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_decrypt_key.c
@@ -0,0 +1,133 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_decrypt_key.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Decrypt an ECC encrypted key
+ @param in The ciphertext
+ @param inlen The length of the ciphertext (octets)
+ @param out [out] The plaintext
+ @param outlen [in/out] The max size and resulting size of the plaintext
+ @param key The corresponding private ECC key
+ @return CRYPT_OK if successful
+*/
+int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const ecc_key *key)
+{
+ unsigned char *ecc_shared, *skey, *pub_expt;
+ unsigned long x, y;
+ unsigned long hashOID[32] = { 0 };
+ int hash, err;
+ ecc_key pubkey;
+ ltc_asn1_list decode[3];
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* right key type? */
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* decode to find out hash */
+ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
+ err = der_decode_sequence(in, inlen, decode, 1);
+ if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
+ return err;
+ }
+
+ hash = find_hash_oid(hashOID, decode[0].size);
+ if (hash_is_valid(hash) != CRYPT_OK) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* we now have the hash! */
+
+ /* allocate memory */
+ pub_expt = XMALLOC(ECC_BUF_SIZE);
+ ecc_shared = XMALLOC(ECC_BUF_SIZE);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
+ if (pub_expt != NULL) {
+ XFREE(pub_expt);
+ }
+ if (ecc_shared != NULL) {
+ XFREE(ecc_shared);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ return CRYPT_MEM;
+ }
+ LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE);
+ LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE);
+
+ /* read the structure in now */
+ if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* import ECC key from packet */
+ if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = ecc_set_key(decode[1].data, decode[1].size, PK_PUBLIC, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
+
+ /* make shared key */
+ x = ECC_BUF_SIZE;
+ if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) {
+ ecc_free(&pubkey);
+ goto LBL_ERR;
+ }
+ ecc_free(&pubkey);
+
+ y = MIN(ECC_BUF_SIZE, MAXBLOCKSIZE);
+ if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* ensure the hash of the shared secret is at least as big as the encrypt itself */
+ if (decode[2].size > y) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* avoid buffer overflow */
+ if (*outlen < decode[2].size) {
+ *outlen = decode[2].size;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* Decrypt the key */
+ for (x = 0; x < decode[2].size; x++) {
+ out[x] = skey[x] ^ ecc_shared[x];
+ }
+ *outlen = x;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(pub_expt, ECC_BUF_SIZE);
+ zeromem(ecc_shared, ECC_BUF_SIZE);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+
+ XFREE(pub_expt);
+ XFREE(ecc_shared);
+ XFREE(skey);
+
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_encrypt_key.c b/Sources/libtomcrypt/pk/ecc/ecc_encrypt_key.c
new file mode 100644
index 00000000..9929ff5a
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_encrypt_key.c
@@ -0,0 +1,120 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_encrypt_key.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Encrypt a symmetric key with ECC
+ @param in The symmetric key you want to encrypt
+ @param inlen The length of the key to encrypt (octets)
+ @param out [out] The destination for the ciphertext
+ @param outlen [in/out] The max size and resulting size of the ciphertext
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param hash The index of the hash you want to use
+ @param key The ECC key you want to encrypt to
+ @return CRYPT_OK if successful
+*/
+int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, int hash,
+ const ecc_key *key)
+{
+ unsigned char *pub_expt, *ecc_shared, *skey;
+ ecc_key pubkey;
+ unsigned long x, y, pubkeysize;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (inlen > hash_descriptor[hash].hashsize) {
+ return CRYPT_INVALID_HASH;
+ }
+
+ /* make a random key and export the public copy */
+ if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { return err; }
+ if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { return err; }
+
+ pub_expt = XMALLOC(ECC_BUF_SIZE);
+ ecc_shared = XMALLOC(ECC_BUF_SIZE);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
+ if (pub_expt != NULL) {
+ XFREE(pub_expt);
+ }
+ if (ecc_shared != NULL) {
+ XFREE(ecc_shared);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ ecc_free(&pubkey);
+ return CRYPT_MEM;
+ }
+
+ pubkeysize = ECC_BUF_SIZE;
+ if (ltc_mp.sqrtmod_prime != NULL) {
+ /* PK_COMPRESSED requires sqrtmod_prime */
+ err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey);
+ }
+ else {
+ err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey);
+ }
+ if (err != CRYPT_OK) {
+ ecc_free(&pubkey);
+ goto LBL_ERR;
+ }
+
+ /* make random key */
+ x = ECC_BUF_SIZE;
+ if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
+ ecc_free(&pubkey);
+ goto LBL_ERR;
+ }
+ ecc_free(&pubkey);
+ y = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* Encrypt key */
+ for (x = 0; x < inlen; x++) {
+ skey[x] ^= in[x];
+ }
+
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID,
+ LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt,
+ LTC_ASN1_OCTET_STRING, inlen, skey,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ /* clean up */
+ zeromem(pub_expt, ECC_BUF_SIZE);
+ zeromem(ecc_shared, ECC_BUF_SIZE);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+
+ XFREE(skey);
+ XFREE(ecc_shared);
+ XFREE(pub_expt);
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_export.c b/Sources/libtomcrypt/pk/ecc/ecc_export.c
new file mode 100644
index 00000000..edbe4c39
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_export.c
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_export.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Export an ECC key as a binary packet
+ @param out [out] Destination for the key
+ @param outlen [in/out] Max size and resulting size of the exported key
+ @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC)
+ @param key The key to export
+ @return CRYPT_OK if successful
+*/
+int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key)
+{
+ int err;
+ unsigned char flags[1];
+ unsigned long key_size;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* type valid? */
+ if (key->type != PK_PRIVATE && type == PK_PRIVATE) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ /* we store the NIST byte size */
+ key_size = key->dp.size;
+
+ if (type == PK_PRIVATE) {
+ flags[0] = 1;
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
+ LTC_ASN1_INTEGER, 1UL, key->k,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ flags[0] = 0;
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_export_openssl.c b/Sources/libtomcrypt/pk/ecc/ecc_export_openssl.c
new file mode 100644
index 00000000..2e899968
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_export_openssl.c
@@ -0,0 +1,167 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+/**
+ Export an ECC key as a binary packet
+ @param out [out] Destination for the key
+ @param outlen [in/out] Max size and resulting size of the exported key
+ @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC)
+ @param key The key to export
+ @return CRYPT_OK if successful
+*/
+
+int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key)
+{
+ int err;
+ void *prime, *order, *a, *b, *gx, *gy;
+ unsigned char bin_a[256], bin_b[256], bin_k[256], bin_g[512], bin_xy[512];
+ unsigned long len_a, len_b, len_k, len_g, len_xy;
+ unsigned long cofactor, one = 1;
+ const char *OID;
+ unsigned long oid[16], oidlen;
+ ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], pub_xy, ecparams;
+ int flag_oid = type & PK_CURVEOID ? 1 : 0;
+ int flag_com = type & PK_COMPRESSED ? 1 : 0;
+ int flag_pri = type & PK_PRIVATE ? 1 : 0;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (key->type != PK_PRIVATE && flag_pri) return CRYPT_PK_TYPE_MISMATCH;
+
+ if (flag_oid) {
+ /* http://tools.ietf.org/html/rfc5912
+ ECParameters ::= CHOICE {
+ namedCurve CURVE.&id({NamedCurve}) # OBJECT
+ }
+ */
+ if (key->dp.oidlen == 0) { err = CRYPT_INVALID_ARG; goto error; }
+ LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp.oid, key->dp.oidlen);
+ }
+ else {
+ prime = key->dp.prime;
+ order = key->dp.order;
+ a = key->dp.A;
+ b = key->dp.B;
+ gx = key->dp.base.x;
+ gy = key->dp.base.y;
+ cofactor = key->dp.cofactor;
+
+ /* curve param a */
+ len_a = mp_unsigned_bin_size(a);
+ if (len_a > sizeof(bin_a)) { err = CRYPT_BUFFER_OVERFLOW; goto error; }
+ if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK) { goto error; }
+ if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* handle case a == 0 */
+
+ /* curve param b */
+ len_b = mp_unsigned_bin_size(b);
+ if (len_b > sizeof(bin_b)) { err = CRYPT_BUFFER_OVERFLOW; goto error; }
+ if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) { goto error; }
+ if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* handle case b == 0 */
+
+ /* base point - (un)compressed based on flag_com */
+ len_g = sizeof(bin_g);
+ err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com);
+ if (err != CRYPT_OK) { goto error; }
+
+ /* we support only prime-field EC */
+ if ((err = pk_get_oid(LTC_OID_EC_PRIMEF, &OID)) != CRYPT_OK) { goto error; }
+
+ /* http://tools.ietf.org/html/rfc3279
+ ECParameters ::= SEQUENCE { # SEQUENCE
+ version INTEGER { ecpVer1(1) } (ecpVer1) # INTEGER :01
+ FieldID ::= SEQUENCE { # SEQUENCE
+ fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field
+ parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER
+ }
+ Curve ::= SEQUENCE { # SEQUENCE
+ a FieldElement ::= OCTET STRING # OCTET STRING
+ b FieldElement ::= OCTET STRING # OCTET STRING
+ seed BIT STRING OPTIONAL
+ }
+ base ECPoint ::= OCTET STRING # OCTET STRING
+ order INTEGER, # INTEGER
+ cofactor INTEGER OPTIONAL # INTEGER
+ }
+ */
+
+ oidlen = sizeof(oid)/sizeof(oid[0]);
+ if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* FieldID SEQUENCE */
+ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen);
+ LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
+
+ /* Curve SEQUENCE */
+ LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, len_a);
+ LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, len_b);
+
+ /* ECParameters SEQUENCE */
+ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
+ LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 2UL);
+ LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, len_g);
+ LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
+
+ /* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */
+ LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
+ }
+
+ /* public key - (un)compressed based on flag_com */
+ len_xy = sizeof(bin_xy);
+ err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ if (flag_pri) {
+
+ /* http://tools.ietf.org/html/rfc5915
+ ECPrivateKey ::= SEQUENCE { # SEQUENCE
+ version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1) # INTEGER :01
+ privateKey OCTET STRING, # OCTET STRING
+ [0] ECParameters # see above
+ [1] publicKey # BIT STRING
+ }
+ */
+
+ /* private key */
+ len_k = mp_unsigned_bin_size(key->k);
+ if (len_k > sizeof(bin_k)) { err = CRYPT_BUFFER_OVERFLOW; goto error; }
+ if ((err = mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK) { goto error; }
+
+ LTC_SET_ASN1(&pub_xy, 0, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy);
+ LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1);
+ LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k);
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, &ecparams); /* context specific 0 */
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, &pub_xy); /* context specific 1 */
+
+ err = der_encode_sequence(seq_priv, 4, out, outlen);
+ }
+ else {
+ /* http://tools.ietf.org/html/rfc5480
+ SubjectPublicKeyInfo ::= SEQUENCE { # SEQUENCE
+ AlgorithmIdentifier ::= SEQUENCE { # SEQUENCE
+ algorithm OBJECT IDENTIFIER # OBJECT :id-ecPublicKey
+ ECParameters # see above
+ }
+ subjectPublicKey BIT STRING # BIT STRING
+ }
+ */
+ err = x509_encode_subject_public_key_info( out, outlen, LTC_OID_EC, bin_xy, len_xy,
+ ecparams.type, ecparams.data, ecparams.size );
+ }
+
+error:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_find_curve.c b/Sources/libtomcrypt/pk/ecc/ecc_find_curve.c
new file mode 100644
index 00000000..87d63443
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_find_curve.c
@@ -0,0 +1,241 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+static const struct {
+ const char *OID;
+ const char *names[6];
+} s_curve_names[] = {
+#ifdef LTC_ECC_SECP112R1
+ {
+ "1.3.132.0.6", { "SECP112R1", "ECC-112", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP112R2
+ {
+ "1.3.132.0.7", { "SECP112R2", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP128R1
+ {
+ "1.3.132.0.28", { "SECP128R1", "ECC-128", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP128R2
+ {
+ "1.3.132.0.29", { "SECP128R2", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP160R1
+ {
+ "1.3.132.0.8", { "SECP160R1", "ECC-160", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP160R2
+ {
+ "1.3.132.0.30", { "SECP160R2", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP160K1
+ {
+ "1.3.132.0.9", { "SECP160K1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP192R1
+ {
+ "1.2.840.10045.3.1.1", { "SECP192R1", "NISTP192", "PRIME192V1", "ECC-192", "P-192", NULL }
+ },
+#endif
+#ifdef LTC_ECC_PRIME192V2
+ {
+ "1.2.840.10045.3.1.2", { "PRIME192V2", NULL }
+ },
+#endif
+#ifdef LTC_ECC_PRIME192V3
+ {
+ "1.2.840.10045.3.1.3", { "PRIME192V3", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP192K1
+ {
+ "1.3.132.0.31", { "SECP192K1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP224R1
+ {
+ "1.3.132.0.33", { "SECP224R1", "NISTP224", "ECC-224", "P-224", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP224K1
+ {
+ "1.3.132.0.32", { "SECP224K1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP256R1
+ {
+ "1.2.840.10045.3.1.7", { "SECP256R1", "NISTP256", "PRIME256V1", "ECC-256", "P-256", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP256K1
+ {
+ "1.3.132.0.10", { "SECP256K1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP384R1
+ {
+ "1.3.132.0.34", { "SECP384R1", "NISTP384", "ECC-384", "P-384", NULL }
+ },
+#endif
+#ifdef LTC_ECC_SECP521R1
+ {
+ "1.3.132.0.35", { "SECP521R1", "NISTP521", "ECC-521", "P-521", NULL }
+ },
+#endif
+#ifdef LTC_ECC_PRIME239V1
+ {
+ "1.2.840.10045.3.1.4", { "PRIME239V1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_PRIME239V2
+ {
+ "1.2.840.10045.3.1.5", { "PRIME239V2", NULL }
+ },
+#endif
+#ifdef LTC_ECC_PRIME239V3
+ {
+ "1.2.840.10045.3.1.6", { "PRIME239V3", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP160R1
+ {
+ "1.3.36.3.3.2.8.1.1.1", { "BRAINPOOLP160R1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP192R1
+ {
+ "1.3.36.3.3.2.8.1.1.3", { "BRAINPOOLP192R1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP224R1
+ {
+ "1.3.36.3.3.2.8.1.1.5", { "BRAINPOOLP224R1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP256R1
+ {
+ "1.3.36.3.3.2.8.1.1.7", { "BRAINPOOLP256R1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP320R1
+ {
+ "1.3.36.3.3.2.8.1.1.9", { "BRAINPOOLP320R1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP384R1
+ {
+ "1.3.36.3.3.2.8.1.1.11", { "BRAINPOOLP384R1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP512R1
+ {
+ "1.3.36.3.3.2.8.1.1.13", { "BRAINPOOLP512R1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP160T1
+ {
+ "1.3.36.3.3.2.8.1.1.2", { "BRAINPOOLP160T1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP192T1
+ {
+ "1.3.36.3.3.2.8.1.1.4", { "BRAINPOOLP192T1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP224T1
+ {
+ "1.3.36.3.3.2.8.1.1.6", { "BRAINPOOLP224T1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP256T1
+ {
+ "1.3.36.3.3.2.8.1.1.8", { "BRAINPOOLP256T1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP320T1
+ {
+ "1.3.36.3.3.2.8.1.1.10", { "BRAINPOOLP320T1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP384T1
+ {
+ "1.3.36.3.3.2.8.1.1.12", { "BRAINPOOLP384T1", NULL }
+ },
+#endif
+#ifdef LTC_ECC_BRAINPOOLP512T1
+ {
+ "1.3.36.3.3.2.8.1.1.14", { "BRAINPOOLP512T1", NULL }
+ },
+#endif
+ {
+ NULL, { NULL }
+ }
+};
+
+/* case-insensitive match + ignore '-', '_', ' ' */
+static int s_name_match(const char *left, const char *right)
+{
+ char lc_r, lc_l;
+
+ while ((*left != '\0') && (*right != '\0')) {
+ while ((*left == ' ') || (*left == '-') || (*left == '_')) left++;
+ while ((*right == ' ') || (*right == '-') || (*right == '_')) right++;
+ if (*left == '\0' || *right == '\0') break;
+ lc_r = *right;
+ lc_l = *left;
+ if ((lc_r >= 'A') && (lc_r <= 'Z')) lc_r += 32;
+ if ((lc_l >= 'A') && (lc_l <= 'Z')) lc_l += 32;
+ if (lc_l != lc_r) return 0;
+ left++;
+ right++;
+ }
+
+ if ((*left == '\0') && (*right == '\0')) return 1;
+ return 0;
+}
+
+int ecc_find_curve(const char *name_or_oid, const ltc_ecc_curve **cu)
+{
+ int i, j;
+ const char *OID = NULL;
+
+ LTC_ARGCHK(name_or_oid != NULL);
+
+ if (cu) *cu = NULL;
+
+ for (i = 0; s_curve_names[i].OID != NULL && !OID; i++) {
+ if (XSTRCMP(s_curve_names[i].OID, name_or_oid) == 0) {
+ OID = s_curve_names[i].OID;
+ }
+ for (j = 0; s_curve_names[i].names[j] != NULL && !OID; j++) {
+ if (s_name_match(s_curve_names[i].names[j], name_or_oid)) {
+ OID = s_curve_names[i].OID;
+ }
+ }
+ }
+
+ if (OID != NULL) {
+ for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) {
+ if (XSTRCMP(ltc_ecc_curves[i].OID, OID) == 0) {
+ if (cu) *cu = <c_ecc_curves[i];
+ return CRYPT_OK;
+ }
+ }
+ }
+
+ return CRYPT_INVALID_ARG; /* not found */
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_free.c b/Sources/libtomcrypt/pk/ecc/ecc_free.c
new file mode 100644
index 00000000..61331090
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_free.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_free.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Free an ECC key from memory
+ @param key The key you wish to free
+*/
+void ecc_free(ecc_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+
+ mp_cleanup_multi(&key->dp.prime, &key->dp.order,
+ &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z,
+ &key->k, NULL);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_get_key.c b/Sources/libtomcrypt/pk/ecc/ecc_get_key.c
new file mode 100644
index 00000000..891a7413
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_get_key.c
@@ -0,0 +1,53 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+/** Export raw public or private key (public keys = ANS X9.63 compressed or uncompressed; private keys = raw bytes)
+ @param out [out] destination of export
+ @param outlen [in/out] Length of destination and final output size
+ @param type PK_PRIVATE, PK_PUBLIC or PK_PUBLIC|PK_COMPRESSED
+ @param key Key to export
+ Return CRYPT_OK on success
+*/
+
+int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key)
+{
+ unsigned long size, ksize;
+ int err, compressed;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ size = key->dp.size;
+ compressed = type & PK_COMPRESSED ? 1 : 0;
+ type &= ~PK_COMPRESSED;
+
+ if (type == PK_PUBLIC) {
+ if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, compressed)) != CRYPT_OK) {
+ return err;
+ }
+ }
+ else if (type == PK_PRIVATE) {
+ if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
+ if (size > *outlen) {
+ *outlen = size;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ *outlen = size;
+ if ((ksize = mp_unsigned_bin_size(key->k)) > size) return CRYPT_BUFFER_OVERFLOW;
+ /* pad and store k */
+ if ((err = mp_to_unsigned_bin(key->k, out + (size - ksize))) != CRYPT_OK) return err;
+ zeromem(out, size - ksize);
+ }
+ else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_get_oid_str.c b/Sources/libtomcrypt/pk/ecc/ecc_get_oid_str.c
new file mode 100644
index 00000000..756f641a
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_get_oid_str.c
@@ -0,0 +1,22 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+/** Extract OID as a string from ECC key
+ @param out [out] destination buffer
+ @param outlen [in/out] Length of destination buffer and final output size (without terminating NUL byte)
+ @param key The ECC key
+ Return CRYPT_OK on success
+*/
+
+int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+
+ return pk_oid_num_to_str(key->dp.oid, key->dp.oidlen, out, outlen);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_get_size.c b/Sources/libtomcrypt/pk/ecc/ecc_get_size.c
new file mode 100644
index 00000000..e5633396
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_get_size.c
@@ -0,0 +1,26 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_get_size.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Get the size of an ECC key
+ @param key The key to get the size of
+ @return The size (octets) of the key or INT_MAX on error
+*/
+int ecc_get_size(const ecc_key *key)
+{
+ if (key == NULL) {
+ return INT_MAX;
+ }
+ return key->dp.size;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_import.c b/Sources/libtomcrypt/pk/ecc/ecc_import.c
new file mode 100644
index 00000000..64bed21c
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_import.c
@@ -0,0 +1,100 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_import.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Import an ECC key from a binary packet
+ @param in The packet to import
+ @param inlen The length of the packet
+ @param key [out] The destination of the import
+ @return CRYPT_OK if successful, upon error all allocated memory will be freed
+*/
+int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ return ecc_import_ex(in, inlen, key, NULL);
+}
+
+/**
+ Import an ECC key from a binary packet, using user supplied domain params rather than one of the NIST ones
+ @param in The packet to import
+ @param inlen The length of the packet
+ @param key [out] The destination of the import
+ @param cu pointer to user supplied params; must be the same as the params used when exporting
+ @return CRYPT_OK if successful, upon error all allocated memory will be freed
+*/
+int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu)
+{
+ unsigned long key_size;
+ unsigned char flags[1];
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* find out what type of key it is */
+ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_EOL, 0UL, NULL);
+ if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
+ return err;
+ }
+
+ /* allocate & initialize the key */
+ if (cu == NULL) {
+ if ((err = ecc_set_curve_by_size(key_size, key)) != CRYPT_OK) { goto done; }
+ } else {
+ if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { goto done; }
+ }
+
+ if (flags[0] == 1) {
+ /* private key */
+ key->type = PK_PRIVATE;
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
+ LTC_ASN1_INTEGER, 1UL, key->k,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto done;
+ }
+ } else if (flags[0] == 0) {
+ /* public key */
+ key->type = PK_PUBLIC;
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto done;
+ }
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto done;
+ }
+
+ /* set z */
+ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; }
+
+ /* point on the curve + other checks */
+ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto done; }
+
+ /* we're good */
+ return CRYPT_OK;
+
+done:
+ ecc_free(key);
+ return err;
+}
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_import_openssl.c b/Sources/libtomcrypt/pk/ecc/ecc_import_openssl.c
new file mode 100644
index 00000000..9008c73a
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_import_openssl.c
@@ -0,0 +1,142 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+static int s_ecc_import_private_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ ltc_asn1_list seq_priv[4], custom[2];
+ unsigned char bin_xy[2*ECC_MAXSIZE+2], bin_k[ECC_MAXSIZE];
+ unsigned long pkver = 0, curveoid[16];
+ int err;
+
+ /* ### try to load private key - no curve parameters just curve OID */
+
+ /* ECPrivateKey SEQUENCE */
+ LTC_SET_ASN1(custom, 0, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL);
+ LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy));
+ LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
+ LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k));
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
+
+ /* try to load private key */
+ err = der_decode_sequence(in, inlen, seq_priv, 4);
+ if (err != CRYPT_OK) { goto error; }
+ err = ecc_import_with_oid(bin_k, seq_priv[1].size, curveoid, custom[0].size, PK_PRIVATE, key);
+error:
+ return err;
+}
+
+int ecc_import_with_oid(const unsigned char *in, unsigned long inlen, unsigned long *oid, unsigned long oid_len, int type, ecc_key *key)
+{
+ char OID[256];
+ unsigned long len;
+ const ltc_ecc_curve *curve;
+ int err;
+
+ /* load curve parameters for given curve OID */
+ len = sizeof(OID);
+ if ((err = pk_oid_num_to_str(oid, oid_len, OID, &len)) != CRYPT_OK) { goto error; }
+ if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; }
+ if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; }
+ /* load public key */
+ err = ecc_set_key(in, inlen, type, key);
+error:
+ return err;
+}
+
+int ecc_import_with_curve(const unsigned char *in, unsigned long inlen, int type, ecc_key *key)
+{
+ void *prime, *order, *a, *b, *gx, *gy;
+ ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2];
+ unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE];
+ unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
+ unsigned long len_a, len_b, len_k, len_g, len_xy, len;
+ unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16];
+ int err;
+
+ if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* FieldID SEQUENCE */
+ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
+ LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
+ /* Curve SEQUENCE */
+ LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a));
+ LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b));
+ LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8UL*sizeof(bin_seed));
+ seq_curve[2].optional = 1;
+ /* ECParameters SEQUENCE */
+ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
+ LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
+ LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g));
+ LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
+ seq_ecparams[5].optional = 1;
+ if (type == PK_PRIVATE) {
+ /* ECPrivateKey SEQUENCE */
+ LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
+ LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy));
+ LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
+ LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k));
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
+ /* try to load private key */
+ err = der_decode_sequence(in, inlen, seq_priv, 4);
+ } else if (type == PK_PUBLIC) {
+ /* try to load public key */
+ len_xy = sizeof(bin_xy);
+ len = 6;
+ err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len);
+ } else {
+ err = CRYPT_PK_INVALID_TYPE;
+ }
+ if (err == CRYPT_OK) {
+ len_a = seq_curve[0].size;
+ len_b = seq_curve[1].size;
+ len_g = seq_ecparams[3].size;
+ /* create bignums */
+ if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
+ /* load curve parameters */
+ if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; }
+
+ if (type == PK_PRIVATE) {
+ len_k = seq_priv[1].size;
+ /* load private+public key */
+ err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key);
+ } else {
+ /* load public key */
+ err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key);
+ }
+ }
+error:
+ mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL);
+ return err;
+}
+
+int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ int err;
+
+ if ((err = ecc_import_subject_public_key_info(in, inlen, key)) == CRYPT_OK) {
+ goto success;
+ }
+
+ if ((err = s_ecc_import_private_with_oid(in, inlen, key)) == CRYPT_OK) {
+ goto success;
+ }
+
+ err = ecc_import_with_curve(in, inlen, PK_PRIVATE, key);
+
+success:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_import_pkcs8.c b/Sources/libtomcrypt/pk/ecc/ecc_import_pkcs8.c
new file mode 100644
index 00000000..f073d984
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_import_pkcs8.c
@@ -0,0 +1,167 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+int ecc_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, ecc_key *key)
+{
+ void *a, *b, *gx, *gy;
+ unsigned long len, cofactor, n;
+ int err;
+ char OID[256];
+ const ltc_ecc_curve *curve;
+ ltc_asn1_list *p = NULL;
+ der_flexi_check case2_should[7];
+ ltc_asn1_list *version, *field, *point, *point_g, *order, *p_cofactor;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* init key */
+ err = mp_init_multi(&a, &b, &gx, &gy, LTC_NULL);
+ if (err != CRYPT_OK) goto LBL_DER_FREE;
+
+ /* Setup for CASE 2 */
+ n=0;
+ LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_INTEGER, &version);
+ LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_SEQUENCE, &field);
+ LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_SEQUENCE, &point);
+ LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_OCTET_STRING, &point_g);
+ LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_INTEGER, &order);
+ LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_INTEGER, &p_cofactor);
+ LTC_SET_DER_FLEXI_CHECK(case2_should, n, LTC_ASN1_EOL, NULL);
+
+ if (LTC_ASN1_IS_TYPE(alg_id->child->next, LTC_ASN1_OBJECT_IDENTIFIER)) {
+ /* CASE 1: curve by OID (AKA short variant):
+ * 0:d=0 hl=2 l= 100 cons: SEQUENCE
+ * 2:d=1 hl=2 l= 1 prim: INTEGER :00
+ * 5:d=1 hl=2 l= 16 cons: SEQUENCE (== *seq)
+ * 7:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
+ * 16:d=2 hl=2 l= 5 prim: OBJECT :(== *curve_oid (e.g. secp256k1 (== 1.3.132.0.10)))
+ * 23:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key)
+ */
+ ltc_asn1_list *curve_oid = alg_id->child->next;
+ len = sizeof(OID);
+ if ((err = pk_oid_num_to_str(curve_oid->data, curve_oid->size, OID, &len)) != CRYPT_OK) { goto LBL_DONE; }
+ if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto LBL_DONE; }
+ if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto LBL_DONE; }
+ } else if (der_flexi_sequence_cmp(alg_id->child->next, case2_should) == CRYPT_OK) {
+
+ /* CASE 2: explicit curve parameters (AKA long variant):
+ * 0:d=0 hl=3 l= 227 cons: SEQUENCE
+ * 3:d=1 hl=2 l= 1 prim: INTEGER :00
+ * 6:d=1 hl=3 l= 142 cons: SEQUENCE (== *seq)
+ * 9:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
+ * 18:d=2 hl=3 l= 130 cons: SEQUENCE
+ * 21:d=3 hl=2 l= 1 prim: INTEGER :01
+ * 24:d=3 hl=2 l= 44 cons: SEQUENCE (== *field)
+ * 26:d=4 hl=2 l= 7 prim: OBJECT :prime-field
+ * 35:d=4 hl=2 l= 33 prim: INTEGER :(== *prime / curve.prime)
+ * 70:d=3 hl=2 l= 6 cons: SEQUENCE (== *point)
+ * 72:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.A)
+ * 75:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.B)
+ * 78:d=3 hl=2 l= 33 prim: OCTET STRING :bytes (== *g_point / curve.G-point)
+ * 113:d=3 hl=2 l= 33 prim: INTEGER :(== *order / curve.order)
+ * 148:d=3 hl=2 l= 1 prim: INTEGER :(== curve.cofactor)
+ * 151:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key)
+ */
+
+ if (mp_cmp_d(version->data, 1) != LTC_MP_EQ) {
+ goto LBL_DONE;
+ }
+ cofactor = mp_get_int(p_cofactor->data);
+
+ if (LTC_ASN1_IS_TYPE(field->child, LTC_ASN1_OBJECT_IDENTIFIER) &&
+ LTC_ASN1_IS_TYPE(field->child->next, LTC_ASN1_INTEGER) &&
+ LTC_ASN1_IS_TYPE(point->child, LTC_ASN1_OCTET_STRING) &&
+ LTC_ASN1_IS_TYPE(point->child->next, LTC_ASN1_OCTET_STRING)) {
+
+ ltc_asn1_list *prime = field->child->next;
+ if ((err = mp_read_unsigned_bin(a, point->child->data, point->child->size)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ if ((err = mp_read_unsigned_bin(b, point->child->next->data, point->child->next->size)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ if ((err = ltc_ecc_import_point(point_g->data, point_g->size, prime->data, a, b, gx, gy)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ if ((err = ecc_set_curve_from_mpis(a, b, prime->data, order->data, gx, gy, cofactor, key)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ }
+ } else {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+ }
+
+ /* load private key value 'k' */
+ len = priv_key->size;
+ if (der_decode_sequence_flexi(priv_key->data, &len, &p) == CRYPT_OK) {
+ if (p->type == LTC_ASN1_SEQUENCE &&
+ LTC_ASN1_IS_TYPE(p->child, LTC_ASN1_INTEGER) &&
+ LTC_ASN1_IS_TYPE(p->child->next, LTC_ASN1_OCTET_STRING)) {
+ ltc_asn1_list *lk = p->child->next;
+ if (mp_cmp_d(p->child->data, 1) != LTC_MP_EQ) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ECCFREE;
+ }
+ if ((err = ecc_set_key(lk->data, lk->size, PK_PRIVATE, key)) != CRYPT_OK) {
+ goto LBL_ECCFREE;
+ }
+ goto LBL_DONE; /* success */
+ }
+ }
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+
+LBL_ECCFREE:
+ ecc_free(key);
+LBL_DONE:
+ mp_clear_multi(a, b, gx, gy, LTC_NULL);
+LBL_DER_FREE:
+ if (p) der_free_sequence_flexi(p);
+ return err;
+}
+
+/**
+ Import an ECC private from in PKCS#8 format
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param pw_ctx The password context when decrypting the private key
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ ecc_key *key)
+{
+ int err;
+ ltc_asn1_list *l = NULL;
+ ltc_asn1_list *alg_id, *priv_key;
+ enum ltc_oid_id pka;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l);
+ if (err != CRYPT_OK) return err;
+
+ if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) {
+ goto LBL_DER_FREE;
+ }
+ if (pka != LTC_OID_EC) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DER_FREE;
+ }
+
+ err = ecc_import_pkcs8_asn1(alg_id, priv_key, key);
+
+LBL_DER_FREE:
+ der_free_sequence_flexi(l);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_import_x509.c b/Sources/libtomcrypt/pk/ecc/ecc_import_x509.c
new file mode 100644
index 00000000..5217c850
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_import_x509.c
@@ -0,0 +1,54 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+static int s_ecc_import_x509_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ unsigned char bin_xy[2*ECC_MAXSIZE+2];
+ unsigned long curveoid[16];
+ unsigned long len_xy, len_oid;
+ int err;
+
+ len_xy = sizeof(bin_xy);
+ len_oid = 16;
+ err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy,
+ LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid);
+ if (err != CRYPT_OK) { goto error; }
+ err = ecc_import_with_oid(bin_xy, len_xy, curveoid, len_oid, PK_PUBLIC, key);
+error:
+ return err;
+}
+
+int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ int err;
+
+ if ((err = s_ecc_import_x509_with_oid(in, inlen, key)) == CRYPT_OK) {
+ goto success;
+ }
+
+ err = ecc_import_with_curve(in, inlen, PK_PUBLIC, key);
+
+success:
+ return err;
+}
+
+/**
+ Import an ECC key from a X.509 certificate
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ return x509_decode_public_key_from_certificate(in, inlen,
+ LTC_OID_EC,
+ LTC_ASN1_EOL, NULL, NULL,
+ (public_key_decode_cb)ecc_import_subject_public_key_info, key);
+}
+
+#endif /* LTC_MECC */
+
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_make_key.c b/Sources/libtomcrypt/pk/ecc/ecc_make_key.c
new file mode 100644
index 00000000..1b047417
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_make_key.c
@@ -0,0 +1,73 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_make_key.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Make a new ECC key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param keysize The keysize for the new key (in octets from 20 to 65 bytes)
+ @param key [out] Destination of the newly created key
+ @return CRYPT_OK if successful, upon error all allocated memory will be freed
+*/
+int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
+{
+ int err;
+
+ if ((err = ecc_set_curve_by_size(keysize, key)) != CRYPT_OK) { return err; }
+ if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
+ return CRYPT_OK;
+}
+
+int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu)
+{
+ int err;
+ if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; }
+ if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
+ return CRYPT_OK;
+}
+
+int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(ltc_mp.name != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(key->dp.size > 0);
+
+ /* ECC key pair generation according to FIPS-186-4 (B.4.2 Key Pair Generation by Testing Candidates):
+ * the generated private key k should be the range [1, order-1]
+ * a/ N = bitlen(order)
+ * b/ generate N random bits and convert them into big integer k
+ * c/ if k not in [1, order-1] go to b/
+ * e/ Q = k*G
+ */
+ if ((err = rand_bn_upto(key->k, key->dp.order, prng, wprng)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* make the public key */
+ if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) {
+ goto error;
+ }
+ key->type = PK_PRIVATE;
+
+ /* success */
+ err = CRYPT_OK;
+ goto cleanup;
+
+error:
+ ecc_free(key);
+cleanup:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_recover_key.c b/Sources/libtomcrypt/pk/ecc/ecc_recover_key.c
new file mode 100644
index 00000000..b6ae644b
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_recover_key.c
@@ -0,0 +1,260 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+#ifdef LTC_ECC_SHAMIR
+
+/**
+ @file ecc_recover_key.c
+ ECC Crypto, Russ Williams
+*/
+
+/**
+ Recover ECC public key from signature and hash
+ @param sig The signature to verify
+ @param siglen The length of the signature (octets)
+ @param hash The hash (message digest) that was signed
+ @param hashlen The length of the hash (octets)
+ @param recid The recovery ID ("v"), can be -1 if signature contains it
+ @param sigformat The format of the signature (ecc_signature_type)
+ @param key The recovered public ECC key
+ @return CRYPT_OK if successful (even if the signature is not valid)
+*/
+int ecc_recover_key(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int recid, ecc_signature_type sigformat, ecc_key *key)
+{
+ ecc_point *mG = NULL, *mQ = NULL, *mR = NULL;
+ void *p, *m, *a, *b;
+ void *r, *s, *v, *w, *t1, *t2, *u1, *u2, *v1, *v2, *e, *x, *y, *a_plus3;
+ void *mu = NULL, *ma = NULL;
+ void *mp = NULL;
+ int err;
+ unsigned long pbits, pbytes, i, shift_right;
+ unsigned char ch, buf[MAXBLOCKSIZE];
+
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* BEWARE: requires sqrtmod_prime */
+ if (ltc_mp.sqrtmod_prime == NULL) {
+ return CRYPT_ERROR;
+ }
+
+ /* allocate ints */
+ if ((err = mp_init_multi(&r, &s, &v, &w, &t1, &t2, &u1, &u2, &v1, &v2, &e, &x, &y, &a_plus3, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ p = key->dp.order;
+ m = key->dp.prime;
+ a = key->dp.A;
+ b = key->dp.B;
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* allocate points */
+ mG = ltc_ecc_new_point();
+ mQ = ltc_ecc_new_point();
+ mR = ltc_ecc_new_point();
+ if (mR == NULL || mQ == NULL || mG == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if (sigformat == LTC_ECCSIG_ANSIX962) {
+ /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */
+ if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT,
+ LTC_ASN1_INTEGER, 1UL, r,
+ LTC_ASN1_INTEGER, 1UL, s,
+ LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; }
+ }
+ else if (sigformat == LTC_ECCSIG_RFC7518) {
+ /* RFC7518 format - raw (r,s) */
+ i = mp_unsigned_bin_size(key->dp.order);
+ if (siglen != (2*i)) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; }
+ }
+ else if (sigformat == LTC_ECCSIG_ETH27) {
+ /* Ethereum (v,r,s) format */
+ if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) {
+ /* Only valid for secp256k1 - OID 1.3.132.0.10 */
+ err = CRYPT_ERROR; goto error;
+ }
+ if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ i = (unsigned long)sig[64];
+ if ((i>=27) && (i<31)) i -= 27; /* Ethereum adds 27 to recovery ID */
+ if (recid >= 0 && ((unsigned long)recid != i)) {
+ /* Recovery ID specified, but doesn't match signature */
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ recid = i;
+ if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+32, 32)) != CRYPT_OK) { goto error; }
+ }
+#ifdef LTC_SSH
+ else if (sigformat == LTC_ECCSIG_RFC5656) {
+ char name[64], name2[64];
+ unsigned long namelen = sizeof(name);
+ unsigned long name2len = sizeof(name2);
+
+ /* Decode as SSH data sequence, per RFC4251 */
+ if ((err = ssh_decode_sequence_multi(sig, &siglen,
+ LTC_SSHDATA_STRING, name, &namelen,
+ LTC_SSHDATA_MPINT, r,
+ LTC_SSHDATA_MPINT, s,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; }
+
+
+ /* Check curve matches identifier string */
+ if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; }
+ if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) {
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+ }
+#endif
+ else {
+ /* Unknown signature format */
+ err = CRYPT_ERROR;
+ goto error;
+ }
+
+ if (recid < 0 || (unsigned long)recid >= 2*(key->dp.cofactor+1)) {
+ /* Recovery ID is out of range, reject it */
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+
+ /* check for zero */
+ if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT ||
+ mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* read hash - truncate if needed */
+ pbits = mp_count_bits(p);
+ pbytes = (pbits+7) >> 3;
+ if (pbits > hashlen*8) {
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; }
+ }
+ else if (pbits % 8 == 0) {
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; }
+ }
+ else {
+ shift_right = 8 - pbits % 8;
+ for (i=0, ch=0; i> shift_right);
+ }
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; }
+ }
+
+ /* decompress point from r=(x mod p) - BEWARE: requires sqrtmod_prime */
+ /* x = r + p*(recid/2) */
+ if ((err = mp_set(x, recid/2)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(p, x, m, x)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(x, r, x)) != CRYPT_OK) { goto error; }
+ /* compute x^3 */
+ if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(t1, x, m, t1)) != CRYPT_OK) { goto error; }
+ /* compute x^3 + a*x */
+ if ((err = mp_mulmod(a, x, m, t2)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto error; }
+ /* compute x^3 + a*x + b */
+ if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto error; }
+ /* compute sqrt(x^3 + a*x + b) */
+ if ((err = mp_sqrtmod_prime(t1, m, t2)) != CRYPT_OK) { goto error; }
+
+ /* fill in mR */
+ if ((err = mp_copy(x, mR->x)) != CRYPT_OK) { goto error; }
+ if ((mp_isodd(t2) && (recid%2)) || (!mp_isodd(t2) && !(recid%2))) {
+ if ((err = mp_mod(t2, m, mR->y)) != CRYPT_OK) { goto error; }
+ }
+ else {
+ if ((err = mp_submod(m, t2, m, mR->y)) != CRYPT_OK) { goto error; }
+ }
+ if ((err = mp_set(mR->z, 1)) != CRYPT_OK) { goto error; }
+
+ /* w = r^-1 mod n */
+ if ((err = mp_invmod(r, p, w)) != CRYPT_OK) { goto error; }
+ /* v1 = sw */
+ if ((err = mp_mulmod(s, w, p, v1)) != CRYPT_OK) { goto error; }
+ /* v2 = -ew */
+ if ((err = mp_mulmod(e, w, p, v2)) != CRYPT_OK) { goto error; }
+ if ((err = mp_submod(p, v2, p, v2)) != CRYPT_OK) { goto error; }
+
+ /* w = s^-1 mod n */
+ if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; }
+ /* u1 = ew */
+ if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; }
+ /* u2 = rw */
+ if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
+
+ /* find mG */
+ if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; }
+
+ /* find the montgomery mp */
+ if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if (mp_cmp(a_plus3, m) != LTC_MP_EQ) {
+ if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; }
+ }
+
+ /* recover mQ from mR */
+ /* compute v1*mR + v2*mG = mQ using Shamir's trick */
+ if ((err = ltc_mp.ecc_mul2add(mR, v1, mG, v2, mQ, ma, m)) != CRYPT_OK) { goto error; }
+
+ /* compute u1*mG + u2*mQ = mG using Shamir's trick */
+ if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; }
+
+ /* v = X_x1 mod n */
+ if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; }
+
+ /* does v == r */
+ if (mp_cmp(v, r) == LTC_MP_EQ) {
+ /* found public key which verifies signature */
+ if ((err = ltc_ecc_copy_point(mQ, &key->pubkey)) != CRYPT_OK) { goto error; }
+ /* point on the curve + other checks */
+ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto error; }
+
+ key->type = PK_PUBLIC;
+
+ err = CRYPT_OK;
+ }
+ else {
+ /* not found - recid is wrong or we're unable to calculate public key for some other reason */
+ err = CRYPT_INVALID_ARG;
+ }
+
+error:
+ if (ma != NULL) mp_clear(ma);
+ if (mu != NULL) mp_clear(mu);
+ if (mp != NULL) mp_montgomery_free(mp);
+ if (mR != NULL) ltc_ecc_del_point(mR);
+ if (mQ != NULL) ltc_ecc_del_point(mQ);
+ if (mG != NULL) ltc_ecc_del_point(mG);
+ mp_clear_multi(a_plus3, y, x, e, v2, v1, u2, u1, t2, t1, w, v, s, r, LTC_NULL);
+ return err;
+}
+
+#endif
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_set_curve.c b/Sources/libtomcrypt/pk/ecc/ecc_set_curve.c
new file mode 100644
index 00000000..427a5937
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_set_curve.c
@@ -0,0 +1,80 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(cu != NULL);
+
+ if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
+ NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* A, B, order, prime, Gx, Gy */
+ if ((err = mp_read_radix(key->dp.prime, cu->prime, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.order, cu->order, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.A, cu->A, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.B, cu->B, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.base.x, cu->Gx, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.base.y, cu->Gy, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; }
+ /* cofactor & size */
+ key->dp.cofactor = cu->cofactor;
+ key->dp.size = mp_unsigned_bin_size(key->dp.prime);
+ /* OID string >> unsigned long oid[16] + oidlen */
+ key->dp.oidlen = 16;
+ if ((err = pk_oid_str_to_num(cu->OID, key->dp.oid, &key->dp.oidlen)) != CRYPT_OK) { goto error; }
+ /* success */
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+int ecc_set_curve_by_size(int size, ecc_key *key)
+{
+ const ltc_ecc_curve *cu = NULL;
+ int err = CRYPT_ERROR;
+
+ /* for compatibility with libtomcrypt-1.17 the sizes below must match the specific curves */
+ if (size <= 14) {
+ err = ecc_find_curve("SECP112R1", &cu);
+ }
+ else if (size <= 16) {
+ err = ecc_find_curve("SECP128R1", &cu);
+ }
+ else if (size <= 20) {
+ err = ecc_find_curve("SECP160R1", &cu);
+ }
+ else if (size <= 24) {
+ err = ecc_find_curve("SECP192R1", &cu);
+ }
+ else if (size <= 28) {
+ err = ecc_find_curve("SECP224R1", &cu);
+ }
+ else if (size <= 32) {
+ err = ecc_find_curve("SECP256R1", &cu);
+ }
+ else if (size <= 48) {
+ err = ecc_find_curve("SECP384R1", &cu);
+ }
+ else if (size <= 66) {
+ err = ecc_find_curve("SECP521R1", &cu);
+ }
+
+ if (err == CRYPT_OK && cu != NULL) return ecc_set_curve(cu, key);
+
+ return CRYPT_INVALID_ARG;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_set_curve_internal.c b/Sources/libtomcrypt/pk/ecc/ecc_set_curve_internal.c
new file mode 100644
index 00000000..4f43914e
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_set_curve_internal.c
@@ -0,0 +1,119 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+static int s_ecc_cmp_hex_bn(const char *left_hex, void *right_bn, void *tmp_bn)
+{
+ if (mp_read_radix(tmp_bn, left_hex, 16) != CRYPT_OK) return 0;
+ if (mp_cmp(tmp_bn, right_bn) != LTC_MP_EQ) return 0;
+ return 1;
+}
+
+static void s_ecc_oid_lookup(ecc_key *key)
+{
+ void *bn;
+ const ltc_ecc_curve *curve;
+
+ key->dp.oidlen = 0;
+ if (mp_init(&bn) != CRYPT_OK) return;
+ for (curve = ltc_ecc_curves; curve->prime != NULL; curve++) {
+ if (s_ecc_cmp_hex_bn(curve->prime, key->dp.prime, bn) != 1) continue;
+ if (s_ecc_cmp_hex_bn(curve->order, key->dp.order, bn) != 1) continue;
+ if (s_ecc_cmp_hex_bn(curve->A, key->dp.A, bn) != 1) continue;
+ if (s_ecc_cmp_hex_bn(curve->B, key->dp.B, bn) != 1) continue;
+ if (s_ecc_cmp_hex_bn(curve->Gx, key->dp.base.x, bn) != 1) continue;
+ if (s_ecc_cmp_hex_bn(curve->Gy, key->dp.base.y, bn) != 1) continue;
+ if (key->dp.cofactor != curve->cofactor) continue;
+ break; /* found */
+ }
+ mp_clear(bn);
+ if (curve->prime && curve->OID) {
+ key->dp.oidlen = 16; /* size of key->dp.oid */
+ pk_oid_str_to_num(curve->OID, key->dp.oid, &key->dp.oidlen);
+ }
+}
+
+int ecc_copy_curve(const ecc_key *srckey, ecc_key *key)
+{
+ unsigned long i;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(srckey != NULL);
+
+ if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
+ NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* A, B, order, prime, Gx, Gy */
+ if ((err = mp_copy(srckey->dp.prime, key->dp.prime )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.order, key->dp.order )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.A, key->dp.A )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.B, key->dp.B )) != CRYPT_OK) { goto error; }
+ if ((err = ltc_ecc_copy_point(&srckey->dp.base, &key->dp.base)) != CRYPT_OK) { goto error; }
+ /* cofactor & size */
+ key->dp.cofactor = srckey->dp.cofactor;
+ key->dp.size = srckey->dp.size;
+ /* OID */
+ if (srckey->dp.oidlen > 0) {
+ key->dp.oidlen = srckey->dp.oidlen;
+ for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = srckey->dp.oid[i];
+ }
+ else {
+ s_ecc_oid_lookup(key); /* try to find OID in ltc_ecc_curves */
+ }
+ /* success */
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(prime != NULL);
+ LTC_ARGCHK(order != NULL);
+ LTC_ARGCHK(gx != NULL);
+ LTC_ARGCHK(gy != NULL);
+
+ if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
+ NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* A, B, order, prime, Gx, Gy */
+ if ((err = mp_copy(prime, key->dp.prime )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(order, key->dp.order )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(a, key->dp.A )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(b, key->dp.B )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(gx, key->dp.base.x)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(gy, key->dp.base.y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; }
+ /* cofactor & size */
+ key->dp.cofactor = cofactor;
+ key->dp.size = mp_unsigned_bin_size(prime);
+ /* try to find OID in ltc_ecc_curves */
+ s_ecc_oid_lookup(key);
+ /* success */
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_set_key.c b/Sources/libtomcrypt/pk/ecc/ecc_set_key.c
new file mode 100644
index 00000000..3cf5488b
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_set_key.c
@@ -0,0 +1,56 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key)
+{
+ int err;
+ void *prime, *a, *b;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen > 0);
+
+ prime = key->dp.prime;
+ a = key->dp.A;
+ b = key->dp.B;
+
+ if (type == PK_PRIVATE) {
+ /* load private key */
+ if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, inlen)) != CRYPT_OK) {
+ goto error;
+ }
+ if (mp_iszero(key->k) || (mp_cmp(key->k, key->dp.order) != LTC_MP_LT)) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ /* compute public key */
+ if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto error; }
+ }
+ else if (type == PK_PUBLIC) {
+ /* load public key */
+ if ((err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* point on the curve + other checks */
+ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ key->type = type;
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_shared_secret.c b/Sources/libtomcrypt/pk/ecc/ecc_shared_secret.c
new file mode 100644
index 00000000..21ac9134
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_shared_secret.c
@@ -0,0 +1,66 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_shared_secret.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Create an ECC shared secret between two keys
+ @param private_key The private ECC key
+ @param public_key The public key
+ @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63)
+ @param outlen [in/out] The max size and resulting size of the shared secret
+ @return CRYPT_OK if successful
+*/
+int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x;
+ ecc_point *result;
+ void *prime, *a;
+ int err;
+
+ LTC_ARGCHK(private_key != NULL);
+ LTC_ARGCHK(public_key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* type valid? */
+ if (private_key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* make new point */
+ result = ltc_ecc_new_point();
+ if (result == NULL) {
+ return CRYPT_MEM;
+ }
+
+ prime = private_key->dp.prime;
+ a = private_key->dp.A;
+
+ if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; }
+
+ x = (unsigned long)mp_unsigned_bin_size(prime);
+ if (*outlen < x) {
+ *outlen = x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto done;
+ }
+ zeromem(out, x);
+ if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; }
+
+ err = CRYPT_OK;
+ *outlen = x;
+done:
+ ltc_ecc_del_point(result);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_sign_hash.c b/Sources/libtomcrypt/pk/ecc/ecc_sign_hash.c
new file mode 100644
index 00000000..229ced19
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_sign_hash.c
@@ -0,0 +1,181 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+/**
+ @file ecc_sign_hash.c
+ ECC Crypto, Tom St Denis
+*/
+
+/**
+ Sign a message digest
+ @param in The message digest to sign
+ @param inlen The length of the digest
+ @param out [out] The destination for the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param sigformat The format of the signature to generate (ecc_signature_type)
+ @param recid [out] The recovery ID for this signature (optional)
+ @param key A private ECC key
+ @return CRYPT_OK if successful
+*/
+int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, ecc_signature_type sigformat,
+ int *recid, const ecc_key *key)
+{
+ ecc_key pubkey;
+ void *r, *s, *e, *p, *b;
+ int v = 0;
+ int err, max_iterations = LTC_PK_MAX_RETRIES;
+ unsigned long pbits, pbytes, i, shift_right;
+ unsigned char ch, buf[MAXBLOCKSIZE];
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* is this a private key? */
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* init the bignums */
+ if ((err = mp_init_multi(&r, &s, &e, &b, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get the hash and load it as a bignum into 'e' */
+ p = key->dp.order;
+ pbits = mp_count_bits(p);
+ pbytes = (pbits+7) >> 3;
+ if (pbits > inlen*8) {
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, inlen)) != CRYPT_OK) { goto errnokey; }
+ }
+ else if (pbits % 8 == 0) {
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, pbytes)) != CRYPT_OK) { goto errnokey; }
+ }
+ else {
+ shift_right = 8 - pbits % 8;
+ for (i=0, ch=0; i> shift_right);
+ }
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto errnokey; }
+ }
+
+ /* make up a key and export the public copy */
+ do {
+ if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto errnokey; }
+ if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; }
+
+ /* find r = x1 mod n */
+ if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
+
+ if (recid || sigformat==LTC_ECCSIG_ETH27) {
+ /* find recovery ID (if needed) */
+ v = 0;
+ if (mp_copy(pubkey.pubkey.x, s) != CRYPT_OK) { goto error; }
+ while (mp_cmp_d(s, 0) == LTC_MP_GT && mp_cmp(s, p) != LTC_MP_LT) {
+ /* Compute x1 div n... this will almost never be reached for curves with order 1 */
+ v += 2;
+ if ((err = mp_sub(s, p, s)) != CRYPT_OK) { goto error; }
+ }
+ if (mp_isodd(pubkey.pubkey.y)) v += 1;
+ }
+
+ if (mp_iszero(r) == LTC_MP_YES) {
+ ecc_free(&pubkey);
+ } else {
+ if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */
+ /* find s = (e + xr)/k */
+ if ((err = mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = kb */
+ if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/kb */
+ if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */
+ if ((err = mp_mulmod(pubkey.k, s, p, s)) != CRYPT_OK) { goto error; } /* s = xr/kb */
+ if ((err = mp_mulmod(pubkey.k, e, p, e)) != CRYPT_OK) { goto error; } /* e = e/kb */
+ if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e/kb + xr/kb */
+ if ((err = mp_mulmod(s, b, p, s)) != CRYPT_OK) { goto error; } /* s = b(e/kb + xr/kb) = (e + xr)/k */
+ ecc_free(&pubkey);
+ if (mp_iszero(s) == LTC_MP_NO) {
+ break;
+ }
+ }
+ } while (--max_iterations > 0);
+
+ if (max_iterations == 0) {
+ goto errnokey;
+ }
+
+ if (recid) *recid = v;
+
+ if (sigformat == LTC_ECCSIG_ANSIX962) {
+ /* store as ASN.1 SEQUENCE { r, s -- integer } */
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_INTEGER, 1UL, r,
+ LTC_ASN1_INTEGER, 1UL, s,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+ else if (sigformat == LTC_ECCSIG_RFC7518) {
+ /* RFC7518 format - raw (r,s) */
+ if (*outlen < 2*pbytes) { err = CRYPT_MEM; goto errnokey; }
+ zeromem(out, 2*pbytes);
+ i = mp_unsigned_bin_size(r);
+ if ((err = mp_to_unsigned_bin(r, out + (pbytes - i))) != CRYPT_OK) { goto errnokey; }
+ i = mp_unsigned_bin_size(s);
+ if ((err = mp_to_unsigned_bin(s, out + (2*pbytes - i))) != CRYPT_OK) { goto errnokey; }
+ *outlen = 2*pbytes;
+ err = CRYPT_OK;
+ }
+ else if (sigformat == LTC_ECCSIG_ETH27) {
+ /* Ethereum (v,r,s) format */
+ if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) {
+ /* Only valid for secp256k1 - OID 1.3.132.0.10 */
+ err = CRYPT_ERROR; goto errnokey;
+ }
+ if (*outlen < 65) { err = CRYPT_MEM; goto errnokey; }
+ zeromem(out, 65);
+ i = mp_unsigned_bin_size(r);
+ if ((err = mp_to_unsigned_bin(r, out + 32 - i)) != CRYPT_OK) { goto errnokey; }
+ i = mp_unsigned_bin_size(s);
+ if ((err = mp_to_unsigned_bin(s, out + 64 - i)) != CRYPT_OK) { goto errnokey; }
+ out[64] = (unsigned char)(v + 27); /* Recovery ID is 27/28 for Ethereum */
+ *outlen = 65;
+ err = CRYPT_OK;
+ }
+#ifdef LTC_SSH
+ else if (sigformat == LTC_ECCSIG_RFC5656) {
+ /* Get identifier string */
+ char name[64];
+ unsigned long namelen = sizeof(name);
+ if ((err = ecc_ssh_ecdsa_encode_name(name, &namelen, key)) != CRYPT_OK) { goto errnokey; }
+
+ /* Store as SSH data sequence, per RFC4251 */
+ err = ssh_encode_sequence_multi(out, outlen,
+ LTC_SSHDATA_STRING, name, namelen,
+ LTC_SSHDATA_MPINT, r,
+ LTC_SSHDATA_MPINT, s,
+ LTC_SSHDATA_EOL, NULL);
+ }
+#endif
+ else {
+ /* Unknown signature format */
+ err = CRYPT_ERROR;
+ goto error;
+ }
+
+ goto errnokey;
+error:
+ ecc_free(&pubkey);
+errnokey:
+ mp_clear_multi(r, s, e, b, LTC_NULL);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_sizes.c b/Sources/libtomcrypt/pk/ecc/ecc_sizes.c
new file mode 100644
index 00000000..07379b69
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_sizes.c
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_sizes.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+void ecc_sizes(int *low, int *high)
+{
+ int i, size;
+ void *prime;
+
+ LTC_ARGCHKVD(low != NULL);
+ LTC_ARGCHKVD(high != NULL);
+
+ *low = INT_MAX;
+ *high = 0;
+
+ if (mp_init(&prime) == CRYPT_OK) {
+ for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) {
+ if (mp_read_radix(prime, ltc_ecc_curves[i].prime, 16) == CRYPT_OK) {
+ size = mp_unsigned_bin_size(prime);
+ if (size < *low) *low = size;
+ if (size > *high) *high = size;
+ }
+ }
+ mp_clear(prime);
+ }
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_ssh_ecdsa_encode_name.c b/Sources/libtomcrypt/pk/ecc/ecc_ssh_ecdsa_encode_name.c
new file mode 100644
index 00000000..4b8d5542
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_ssh_ecdsa_encode_name.c
@@ -0,0 +1,65 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ecc_ssh_ecdsa_encode_name.c
+ Curve/OID to SSH+ECDSA name string mapping per RFC5656
+ Russ Williams
+*/
+
+#ifdef LTC_SSH
+
+/**
+ Curve/OID to SSH+ECDSA name string mapping
+ @param buffer [out] The destination for the name
+ @param buflen [in/out] The max size and resulting size (including terminator) of the name
+ @param key A public or private ECC key
+ @return CRYPT_OK if successful
+*/
+int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key)
+{
+ char oidstr[64] = {0};
+ unsigned long oidlen = sizeof(oidstr);
+ int err, size = 0;
+
+ LTC_ARGCHK(buffer != NULL);
+ LTC_ARGCHK(buflen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* Get the OID of the curve */
+ if ((err = ecc_get_oid_str(oidstr, &oidlen, key)) != CRYPT_OK) goto error;
+
+ /* Check for three named curves: nistp256, nistp384, nistp521 */
+ if (XSTRCMP("1.2.840.10045.3.1.7", oidstr) == 0) {
+ /* nistp256 - secp256r1 - OID 1.2.840.10045.3.1.7 */
+ size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp256");
+ }
+ else if (XSTRCMP("1.3.132.0.34", oidstr) == 0) {
+ /* nistp384 - secp384r1 - OID 1.3.132.0.34 */
+ size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp384");
+ }
+ else if (XSTRCMP("1.3.132.0.35", oidstr) == 0) {
+ /* nistp521 - secp521r1 - OID 1.3.132.0.35 */
+ size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp521");
+ } else {
+ /* Otherwise we use the OID... */
+ size = snprintf(buffer, *buflen, "ecdsa-sha2-%s", oidstr);
+ }
+
+ /* snprintf returns a negative value on error
+ * or the size that would have been written, but limits to buflen-1 chars plus terminator */
+ if (size < 0) {
+ err = CRYPT_ERROR;
+ } else if ((unsigned)size >= *buflen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else {
+ err = CRYPT_OK;
+ }
+ *buflen = size + 1; /* the string length + NUL byte */
+
+error:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ecc_verify_hash.c b/Sources/libtomcrypt/pk/ecc/ecc_verify_hash.c
new file mode 100644
index 00000000..4480ff45
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ecc_verify_hash.c
@@ -0,0 +1,206 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+/**
+ @file ecc_verify_hash.c
+ ECC Crypto, Tom St Denis
+*/
+
+/**
+ Verify an ECC signature in RFC7518 format
+ @param sig The signature to verify
+ @param siglen The length of the signature (octets)
+ @param hash The hash (message digest) that was signed
+ @param hashlen The length of the hash (octets)
+ @param sigformat The format of the signature (ecc_signature_type)
+ @param stat Result of signature, 1==valid, 0==invalid
+ @param key The corresponding public ECC key
+ @return CRYPT_OK if successful (even if the signature is not valid)
+*/
+int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ ecc_signature_type sigformat, int *stat, const ecc_key *key)
+{
+ ecc_point *mG = NULL, *mQ = NULL;
+ void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3;
+ void *mu = NULL, *ma = NULL;
+ void *mp = NULL;
+ int err;
+ unsigned long pbits, pbytes, i, shift_right;
+ unsigned char ch, buf[MAXBLOCKSIZE];
+
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+
+ /* allocate ints */
+ if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ p = key->dp.order;
+ m = key->dp.prime;
+ a = key->dp.A;
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* allocate points */
+ mG = ltc_ecc_new_point();
+ mQ = ltc_ecc_new_point();
+ if (mQ == NULL || mG == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if (sigformat == LTC_ECCSIG_ANSIX962) {
+ /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */
+ if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT,
+ LTC_ASN1_INTEGER, 1UL, r,
+ LTC_ASN1_INTEGER, 1UL, s,
+ LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; }
+ }
+ else if (sigformat == LTC_ECCSIG_RFC7518) {
+ /* RFC7518 format - raw (r,s) */
+ i = mp_unsigned_bin_size(key->dp.order);
+ if (siglen != (2 * i)) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; }
+ }
+ else if (sigformat == LTC_ECCSIG_ETH27) {
+ /* Ethereum (v,r,s) format */
+ if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) {
+ /* Only valid for secp256k1 - OID 1.3.132.0.10 */
+ err = CRYPT_ERROR; goto error;
+ }
+ if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+32, 32)) != CRYPT_OK) { goto error; }
+ }
+#ifdef LTC_SSH
+ else if (sigformat == LTC_ECCSIG_RFC5656) {
+ char name[64], name2[64];
+ unsigned long namelen = sizeof(name);
+ unsigned long name2len = sizeof(name2);
+
+ /* Decode as SSH data sequence, per RFC4251 */
+ if ((err = ssh_decode_sequence_multi(sig, &siglen,
+ LTC_SSHDATA_STRING, name, &namelen,
+ LTC_SSHDATA_MPINT, r,
+ LTC_SSHDATA_MPINT, s,
+ LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; }
+
+
+ /* Check curve matches identifier string */
+ if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; }
+ if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) {
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+ }
+#endif
+ else {
+ /* Unknown signature format */
+ err = CRYPT_ERROR;
+ goto error;
+ }
+
+ /* check for zero */
+ if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT ||
+ mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* read hash - truncate if needed */
+ pbits = mp_count_bits(p);
+ pbytes = (pbits+7) >> 3;
+ if (pbits > hashlen*8) {
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; }
+ }
+ else if (pbits % 8 == 0) {
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; }
+ }
+ else {
+ shift_right = 8 - pbits % 8;
+ for (i=0, ch=0; i> shift_right);
+ }
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; }
+ }
+
+ /* w = s^-1 mod n */
+ if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; }
+
+ /* u1 = ew */
+ if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; }
+
+ /* u2 = rw */
+ if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
+
+ /* find mG and mQ */
+ if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) { goto error; }
+
+ /* find the montgomery mp */
+ if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if (mp_cmp(a_plus3, m) != LTC_MP_EQ) {
+ if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; }
+ }
+
+ /* compute u1*mG + u2*mQ = mG */
+ if (ltc_mp.ecc_mul2add == NULL) {
+ if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; }
+
+ /* add them */
+ if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; }
+
+ /* reduce */
+ if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; }
+ } else {
+ /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
+ if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; }
+ }
+
+ /* v = X_x1 mod n */
+ if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; }
+
+ /* does v == r */
+ if (mp_cmp(v, r) == LTC_MP_EQ) {
+ *stat = 1;
+ }
+
+ /* clear up and return */
+ err = CRYPT_OK;
+error:
+ if (mG != NULL) ltc_ecc_del_point(mG);
+ if (mQ != NULL) ltc_ecc_del_point(mQ);
+ if (mu != NULL) mp_clear(mu);
+ if (ma != NULL) mp_clear(ma);
+ mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, LTC_NULL);
+ if (mp != NULL) mp_montgomery_free(mp);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_export_point.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_export_point.c
new file mode 100644
index 00000000..022c6bc9
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_export_point.c
@@ -0,0 +1,53 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed)
+{
+ int err;
+ unsigned char buf[ECC_BUF_SIZE];
+ unsigned long xsize, ysize;
+
+ if (size > sizeof(buf)) return CRYPT_BUFFER_OVERFLOW;
+ if ((xsize = mp_unsigned_bin_size(x)) > size) return CRYPT_BUFFER_OVERFLOW;
+ if ((ysize = mp_unsigned_bin_size(y)) > size) return CRYPT_BUFFER_OVERFLOW;
+
+ if(compressed) {
+ if (*outlen < (1 + size)) {
+ *outlen = 1 + size;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ /* store first byte */
+ out[0] = mp_isodd(y) ? 0x03 : 0x02;
+ /* pad and store x */
+ zeromem(buf, sizeof(buf));
+ if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err;
+ XMEMCPY(out+1, buf, size);
+ /* adjust outlen */
+ *outlen = 1 + size;
+ }
+ else {
+ if (*outlen < (1 + 2*size)) {
+ *outlen = 1 + 2*size;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ /* store byte 0x04 */
+ out[0] = 0x04;
+ /* pad and store x */
+ zeromem(buf, sizeof(buf));
+ if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err;
+ XMEMCPY(out+1, buf, size);
+ /* pad and store y */
+ zeromem(buf, sizeof(buf));
+ if ((err = mp_to_unsigned_bin(y, buf + (size - ysize))) != CRYPT_OK) return err;
+ XMEMCPY(out+1+size, buf, size);
+ /* adjust outlen */
+ *outlen = 1 + 2*size;
+ }
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_import_point.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_import_point.c
new file mode 100644
index 00000000..6250fca2
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_import_point.c
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y)
+{
+ int err;
+ unsigned long size;
+ void *t1, *t2;
+
+ /* init key + temporary numbers */
+ if (mp_init_multi(&t1, &t2, LTC_NULL) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ size = mp_unsigned_bin_size(prime);
+
+ if (in[0] == 0x04 && (inlen&1) && ((inlen-1)>>1) == size) {
+ /* read uncompressed point */
+ /* load x */
+ if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; }
+ /* load y */
+ if ((err = mp_read_unsigned_bin(y, (unsigned char *)in+1+size, size)) != CRYPT_OK) { goto cleanup; }
+ }
+ else if ((in[0] == 0x02 || in[0] == 0x03) && (inlen-1) == size && ltc_mp.sqrtmod_prime != NULL) {
+ /* read compressed point - BEWARE: requires sqrtmod_prime */
+ /* load x */
+ if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; }
+ /* compute x^3 */
+ if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_mulmod(t1, x, prime, t1)) != CRYPT_OK) { goto cleanup; }
+ /* compute x^3 + a*x */
+ if ((err = mp_mulmod(a, x, prime, t2)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto cleanup; }
+ /* compute x^3 + a*x + b */
+ if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto cleanup; }
+ /* compute sqrt(x^3 + a*x + b) */
+ if ((err = mp_sqrtmod_prime(t1, prime, t2)) != CRYPT_OK) { goto cleanup; }
+ /* adjust y */
+ if ((mp_isodd(t2) && in[0] == 0x03) || (!mp_isodd(t2) && in[0] == 0x02)) {
+ if ((err = mp_mod(t2, prime, y)) != CRYPT_OK) { goto cleanup; }
+ }
+ else {
+ if ((err = mp_submod(prime, t2, prime, y)) != CRYPT_OK) { goto cleanup; }
+ }
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto cleanup;
+ }
+
+ err = CRYPT_OK;
+cleanup:
+ mp_clear_multi(t1, t2, LTC_NULL);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_is_point.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_is_point.c
new file mode 100644
index 00000000..56a9537d
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_is_point.c
@@ -0,0 +1,62 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+/** Returns whether [x,y] is a point on curve defined by dp
+ @param dp curve parameters
+ @param x x point coordinate
+ @param y y point coordinate
+ @return CRYPT_OK if valid
+*/
+
+int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y)
+{
+ void *prime, *a, *b, *t1, *t2;
+ int err;
+
+ prime = dp->prime;
+ b = dp->B;
+ a = dp->A;
+
+ if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) return err;
+
+ /* compute y^2 */
+ if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup;
+
+ /* compute x^3 */
+ if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup;
+
+ /* compute y^2 - x^3 */
+ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup;
+
+ /* compute y^2 - x^3 - a*x */
+ if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup;
+
+ /* adjust range (0, prime) */
+ while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup;
+ }
+ while (mp_cmp(t1, prime) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup;
+ }
+
+ /* compare to b */
+ if (mp_cmp(t1, b) != LTC_MP_EQ) {
+ err = CRYPT_INVALID_PACKET;
+ } else {
+ err = CRYPT_OK;
+ }
+
+cleanup:
+ mp_clear_multi(t1, t2, LTC_NULL);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_is_point_at_infinity.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_is_point_at_infinity.c
new file mode 100644
index 00000000..2afc4d49
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_is_point_at_infinity.c
@@ -0,0 +1,53 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MECC
+
+/* http://crypto.stackexchange.com/questions/41468/point-at-infinity-for-jacobian-coordinates
+ * a point at infinity is any point (x,y,0) such that y^2 == x^3, except (0,0,0)
+ */
+
+int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval)
+{
+ int err;
+ void *x3, *y2;
+
+ /* trivial case */
+ if (!mp_iszero(P->z)) {
+ *retval = 0;
+ return CRYPT_OK;
+ }
+
+ /* point (0,0,0) is not at infinity */
+ if (mp_iszero(P->x) && mp_iszero(P->y)) {
+ *retval = 0;
+ return CRYPT_OK;
+ }
+
+ /* initialize */
+ if ((err = mp_init_multi(&x3, &y2, LTC_NULL)) != CRYPT_OK) goto done;
+
+ /* compute y^2 */
+ if ((err = mp_mulmod(P->y, P->y, modulus, y2)) != CRYPT_OK) goto cleanup;
+
+ /* compute x^3 */
+ if ((err = mp_mulmod(P->x, P->x, modulus, x3)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mulmod(P->x, x3, modulus, x3)) != CRYPT_OK) goto cleanup;
+
+ /* test y^2 == x^3 */
+ err = CRYPT_OK;
+ if ((mp_cmp(x3, y2) == LTC_MP_EQ) && !mp_iszero(y2)) {
+ *retval = 1;
+ } else {
+ *retval = 0;
+ }
+
+cleanup:
+ mp_clear_multi(x3, y2, LTC_NULL);
+done:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_map.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_map.c
new file mode 100644
index 00000000..163fb412
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_map.c
@@ -0,0 +1,63 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ltc_ecc_map.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Map a projective jacbobian point back to affine space
+ @param P [in/out] The point to map
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_map(ecc_point *P, void *modulus, void *mp)
+{
+ void *t1, *t2;
+ int err;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(mp != NULL);
+
+ if (mp_iszero(P->z)) {
+ return ltc_ecc_set_point_xyz(0, 0, 1, P);
+ }
+
+ if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* first map z back to normal */
+ if ((err = mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* get 1/z */
+ if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK) { goto done; }
+
+ /* get 1/z^2 and 1/z^3 */
+ if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mul(t1, t2, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mod(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+
+ /* multiply against x/y */
+ if ((err = mp_mul(P->x, t2, P->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mul(P->y, t1, P->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = mp_set(P->z, 1)) != CRYPT_OK) { goto done; }
+
+ err = CRYPT_OK;
+done:
+ mp_clear_multi(t1, t2, LTC_NULL);
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_mul2add.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_mul2add.c
new file mode 100644
index 00000000..a0188e32
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_mul2add.c
@@ -0,0 +1,192 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ltc_ecc_mul2add.c
+ ECC Crypto, Shamir's Trick, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+#ifdef LTC_ECC_SHAMIR
+
+/** Computes kA*A + kB*B = C using Shamir's Trick
+ @param A First point to multiply
+ @param kA What to multiple A by
+ @param B Second point to multiply
+ @param kB What to multiple B by
+ @param C [out] Destination point (can overlap with A or B)
+ @param ma ECC curve parameter a in montgomery form
+ @param modulus Modulus for curve
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_mul2add(const ecc_point *A, void *kA,
+ const ecc_point *B, void *kB,
+ ecc_point *C,
+ void *ma,
+ void *modulus)
+{
+ ecc_point *precomp[16];
+ unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble;
+ unsigned x, y;
+ unsigned char *tA, *tB;
+ int err, first;
+ void *mp, *mu;
+
+ /* argchks */
+ LTC_ARGCHK(A != NULL);
+ LTC_ARGCHK(B != NULL);
+ LTC_ARGCHK(C != NULL);
+ LTC_ARGCHK(kA != NULL);
+ LTC_ARGCHK(kB != NULL);
+ LTC_ARGCHK(modulus != NULL);
+
+ /* allocate memory */
+ tA = XCALLOC(1, ECC_BUF_SIZE);
+ if (tA == NULL) {
+ return CRYPT_MEM;
+ }
+ tB = XCALLOC(1, ECC_BUF_SIZE);
+ if (tB == NULL) {
+ XFREE(tA);
+ return CRYPT_MEM;
+ }
+
+ /* get sizes */
+ lenA = mp_unsigned_bin_size(kA);
+ lenB = mp_unsigned_bin_size(kB);
+ len = MAX(lenA, lenB);
+
+ /* sanity check */
+ if ((lenA > ECC_BUF_SIZE) || (lenB > ECC_BUF_SIZE)) {
+ err = CRYPT_INVALID_ARG;
+ goto ERR_T;
+ }
+
+ /* extract and justify kA */
+ mp_to_unsigned_bin(kA, (len - lenA) + tA);
+
+ /* extract and justify kB */
+ mp_to_unsigned_bin(kB, (len - lenB) + tB);
+
+ /* allocate the table */
+ for (x = 0; x < 16; x++) {
+ precomp[x] = ltc_ecc_new_point();
+ if (precomp[x] == NULL) {
+ for (y = 0; y < x; ++y) {
+ ltc_ecc_del_point(precomp[y]);
+ }
+ err = CRYPT_MEM;
+ goto ERR_T;
+ }
+ }
+
+ /* init montgomery reduction */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
+ goto ERR_P;
+ }
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ goto ERR_MP;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ goto ERR_MU;
+ }
+
+ /* copy ones ... */
+ if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(A->y, mu, modulus, precomp[1]->y)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(A->z, mu, modulus, precomp[1]->z)) != CRYPT_OK) { goto ERR_MU; }
+
+ if ((err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; }
+
+ /* precomp [i,0](A + B) table */
+ if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+
+ /* precomp [0,i](A + B) table */
+ if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+
+ /* precomp [i,j](A + B) table (i != 0, j != 0) */
+ for (x = 1; x < 4; x++) {
+ for (y = 1; y < 4; y++) {
+ if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ }
+ }
+
+ nibble = 3;
+ first = 1;
+ bitbufA = tA[0];
+ bitbufB = tB[0];
+
+ /* for every byte of the multiplicands */
+ for (x = 0;; ) {
+ /* grab a nibble */
+ if (++nibble == 4) {
+ if (x == len) break;
+ bitbufA = tA[x];
+ bitbufB = tB[x];
+ nibble = 0;
+ ++x;
+ }
+
+ /* extract two bits from both, shift/update */
+ nA = (bitbufA >> 6) & 0x03;
+ nB = (bitbufB >> 6) & 0x03;
+ bitbufA = (bitbufA << 2) & 0xFF;
+ bitbufB = (bitbufB << 2) & 0xFF;
+
+ /* if both zero, if first, continue */
+ if ((nA == 0) && (nB == 0) && (first == 1)) {
+ continue;
+ }
+
+ /* double twice, only if this isn't the first */
+ if (first == 0) {
+ /* double twice */
+ if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ }
+
+ /* if not both zero */
+ if ((nA != 0) || (nB != 0)) {
+ if (first == 1) {
+ /* if first, copy from table */
+ first = 0;
+ if ((err = ltc_ecc_copy_point(precomp[nA + (nB<<2)], C)) != CRYPT_OK) { goto ERR_MU; }
+ } else {
+ /* if not first, add from table */
+ if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ }
+ }
+ }
+
+ /* reduce to affine */
+ err = ltc_ecc_map(C, modulus, mp);
+
+ /* clean up */
+ERR_MU:
+ mp_clear(mu);
+ERR_MP:
+ mp_montgomery_free(mp);
+ERR_P:
+ for (x = 0; x < 16; x++) {
+ ltc_ecc_del_point(precomp[x]);
+ }
+ERR_T:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tA, ECC_BUF_SIZE);
+ zeromem(tB, ECC_BUF_SIZE);
+#endif
+ XFREE(tA);
+ XFREE(tB);
+
+ return err;
+}
+
+#endif
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_mulmod.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_mulmod.c
new file mode 100644
index 00000000..cabe266a
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_mulmod.c
@@ -0,0 +1,204 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ltc_ecc_mulmod.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+#ifndef LTC_ECC_TIMING_RESISTANT
+
+/* size of sliding window, don't change this! */
+#define WINSIZE 4
+
+/**
+ Perform a point multiplication
+ @param k The scalar to multiply by
+ @param G The base point
+ @param R [out] Destination for kG
+ @param modulus The modulus of the field the ECC curve is in
+ @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
+{
+ ecc_point *tG, *M[8];
+ int i, j, err, inf;
+ void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL;
+ ltc_mp_digit buf;
+ int first, bitbuf, bitcpy, bitcnt, mode, digidx;
+
+ LTC_ARGCHK(k != NULL);
+ LTC_ARGCHK(G != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+
+ if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err;
+ if (inf) {
+ /* return the point at infinity */
+ return ltc_ecc_set_point_xyz(1, 1, 0, R);
+ }
+
+ /* init montgomery reduction */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) {
+ if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; }
+ }
+
+ /* alloc ram for window temps */
+ for (i = 0; i < 8; i++) {
+ M[i] = ltc_ecc_new_point();
+ if (M[i] == NULL) {
+ for (j = 0; j < i; j++) {
+ ltc_ecc_del_point(M[j]);
+ }
+ err = CRYPT_MEM;
+ goto error;
+ }
+ }
+
+ /* make a copy of G incase R==G */
+ tG = ltc_ecc_new_point();
+ if (tG == NULL) { err = CRYPT_MEM; goto done; }
+
+ /* tG = G and convert to montgomery */
+ if (mp_cmp_d(mu, 1) == LTC_MP_EQ) {
+ if ((err = ltc_ecc_copy_point(G, tG)) != CRYPT_OK) { goto done; }
+ } else {
+ if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; }
+ }
+ mp_clear(mu);
+ mu = NULL;
+
+ /* calc the M tab, which holds kG for k==8..15 */
+ /* M[0] == 8G */
+ if ((err = ltc_mp.ecc_ptdbl(tG, M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* now find (8+k)G for k=1..7 */
+ for (j = 9; j < 16; j++) {
+ if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* setup sliding window */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = mp_get_digit_count(k) - 1;
+ bitcpy = bitbuf = 0;
+ first = 1;
+
+ /* perform ops */
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ if (digidx == -1) {
+ break;
+ }
+ buf = mp_get_digit(k, digidx);
+ bitcnt = (int) ltc_mp.bits_per_digit;
+ --digidx;
+ }
+
+ /* grab the next msb from the ltiplicand */
+ i = (buf >> (ltc_mp.bits_per_digit - 1)) & 1;
+ buf <<= 1;
+
+ /* skip leading zero bits */
+ if (mode == 0 && i == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we double */
+ if (mode == 1 && i == 0) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (i << (WINSIZE - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == WINSIZE) {
+ /* if this is the first window we do a simple copy */
+ if (first == 1) {
+ /* R = kG [k = first window] */
+ if ((err = ltc_ecc_copy_point(M[bitbuf-8], R)) != CRYPT_OK) { goto done; }
+ first = 0;
+ } else {
+ /* normal window */
+ /* ok window is filled so double as required and add */
+ /* double first */
+ for (j = 0; j < WINSIZE; j++) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
+ if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+ /* empty window and reset */
+ bitcpy = bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then double/add */
+ if (mode == 2 && bitcpy > 0) {
+ /* double then add */
+ for (j = 0; j < bitcpy; j++) {
+ /* only double if we have had at least one add first */
+ if (first == 0) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << WINSIZE)) != 0) {
+ if (first == 1){
+ /* first add, so copy */
+ if ((err = ltc_ecc_copy_point(tG, R)) != CRYPT_OK) { goto done; }
+ first = 0;
+ } else {
+ /* then add */
+ if ((err = ltc_mp.ecc_ptadd(R, tG, R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+ }
+ }
+ }
+
+ /* map R back from projective space */
+ if (map) {
+ err = ltc_ecc_map(R, modulus, mp);
+ } else {
+ err = CRYPT_OK;
+ }
+done:
+ ltc_ecc_del_point(tG);
+ for (i = 0; i < 8; i++) {
+ ltc_ecc_del_point(M[i]);
+ }
+error:
+ if (ma != NULL) mp_clear(ma);
+ if (a_plus3 != NULL) mp_clear(a_plus3);
+ if (mu != NULL) mp_clear(mu);
+ if (mp != NULL) mp_montgomery_free(mp);
+ return err;
+}
+
+#endif
+
+#undef WINSIZE
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_mulmod_timing.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_mulmod_timing.c
new file mode 100644
index 00000000..96f50f9e
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_mulmod_timing.c
@@ -0,0 +1,151 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ltc_ecc_mulmod_timing.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+#ifdef LTC_ECC_TIMING_RESISTANT
+
+/**
+ Perform a point multiplication (timing resistant)
+ @param k The scalar to multiply by
+ @param G The base point
+ @param R [out] Destination for kG
+ @param a ECC curve parameter a
+ @param modulus The modulus of the field the ECC curve is in
+ @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
+{
+ ecc_point *tG, *M[3];
+ int i, j, err, inf;
+ void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL;
+ ltc_mp_digit buf;
+ int bitcnt, mode, digidx;
+
+ LTC_ARGCHK(k != NULL);
+ LTC_ARGCHK(G != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+
+ if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err;
+ if (inf) {
+ /* return the point at infinity */
+ return ltc_ecc_set_point_xyz(1, 1, 0, R);
+ }
+
+ /* init montgomery reduction */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) {
+ if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; }
+ }
+
+ /* alloc ram for window temps */
+ for (i = 0; i < 3; i++) {
+ M[i] = ltc_ecc_new_point();
+ if (M[i] == NULL) {
+ for (j = 0; j < i; j++) {
+ ltc_ecc_del_point(M[j]);
+ }
+ mp_clear(mu);
+ mp_montgomery_free(mp);
+ return CRYPT_MEM;
+ }
+ }
+
+ /* make a copy of G incase R==G */
+ tG = ltc_ecc_new_point();
+ if (tG == NULL) { err = CRYPT_MEM; goto done; }
+
+ /* tG = G and convert to montgomery */
+ if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; }
+ mp_clear(mu);
+ mu = NULL;
+
+ /* calc the M tab */
+ /* M[0] == G */
+ if ((err = ltc_ecc_copy_point(tG, M[0])) != CRYPT_OK) { goto done; }
+ /* M[1] == 2G */
+ if ((err = ltc_mp.ecc_ptdbl(tG, M[1], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* setup sliding window */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = mp_get_digit_count(k) - 1;
+
+ /* perform ops */
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ if (digidx == -1) {
+ break;
+ }
+ buf = mp_get_digit(k, digidx);
+ bitcnt = (int) MP_DIGIT_BIT;
+ --digidx;
+ }
+
+ /* grab the next msb from the ltiplicand */
+ i = (int)((buf >> (MP_DIGIT_BIT - 1)) & 1);
+ buf <<= 1;
+
+ if (mode == 0 && i == 0) {
+ /* dummy operations */
+ if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ continue;
+ }
+
+ if (mode == 0 && i == 1) {
+ mode = 1;
+ /* dummy operations */
+ if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ continue;
+ }
+
+ if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], ma, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* copy result out */
+ if ((err = ltc_ecc_copy_point(M[0], R)) != CRYPT_OK) { goto done; }
+
+ /* map R back from projective space */
+ if (map) {
+ err = ltc_ecc_map(R, modulus, mp);
+ } else {
+ err = CRYPT_OK;
+ }
+done:
+ ltc_ecc_del_point(tG);
+ for (i = 0; i < 3; i++) {
+ ltc_ecc_del_point(M[i]);
+ }
+error:
+ if (ma != NULL) mp_clear(ma);
+ if (a_plus3 != NULL) mp_clear(a_plus3);
+ if (mu != NULL) mp_clear(mu);
+ if (mp != NULL) mp_montgomery_free(mp);
+ return err;
+}
+
+#endif
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_points.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_points.c
new file mode 100644
index 00000000..b762db50
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_points.c
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ltc_ecc_points.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Allocate a new ECC point
+ @return A newly allocated point or NULL on error
+*/
+ecc_point *ltc_ecc_new_point(void)
+{
+ ecc_point *p;
+ p = XCALLOC(1, sizeof(*p));
+ if (p == NULL) {
+ return NULL;
+ }
+ if (mp_init_multi(&p->x, &p->y, &p->z, LTC_NULL) != CRYPT_OK) {
+ XFREE(p);
+ return NULL;
+ }
+ return p;
+}
+
+/** Free an ECC point from memory
+ @param p The point to free
+*/
+void ltc_ecc_del_point(ecc_point *p)
+{
+ /* prevents free'ing null arguments */
+ if (p != NULL) {
+ mp_clear_multi(p->x, p->y, p->z, LTC_NULL); /* note: p->z may be NULL but that's ok with this function anyways */
+ XFREE(p);
+ }
+}
+
+int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p)
+{
+ int err;
+ if ((err = ltc_mp.set_int(p->x, x)) != CRYPT_OK) return err;
+ if ((err = ltc_mp.set_int(p->y, y)) != CRYPT_OK) return err;
+ if ((err = ltc_mp.set_int(p->z, z)) != CRYPT_OK) return err;
+ return CRYPT_OK;
+}
+
+int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst)
+{
+ int err;
+ if ((err = ltc_mp.copy(src->x, dst->x)) != CRYPT_OK) return err;
+ if ((err = ltc_mp.copy(src->y, dst->y)) != CRYPT_OK) return err;
+ if ((err = ltc_mp.copy(src->z, dst->z)) != CRYPT_OK) return err;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_projective_add_point.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_projective_add_point.c
new file mode 100644
index 00000000..448c2bb6
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_projective_add_point.c
@@ -0,0 +1,198 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file ltc_ecc_projective_add_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC))
+
+/**
+ Add two ECC points
+ @param P The point to add
+ @param Q The point to add
+ @param R [out] The destination of the double
+ @param ma ECC curve parameter a in montgomery form
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp)
+{
+ void *t1, *t2, *x, *y, *z;
+ int err, inf;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(Q != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(mp != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
+ if (inf) {
+ /* P is point at infinity >> Result = Q */
+ err = ltc_ecc_copy_point(Q, R);
+ goto done;
+ }
+
+ if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err;
+ if (inf) {
+ /* Q is point at infinity >> Result = P */
+ err = ltc_ecc_copy_point(P, R);
+ goto done;
+ }
+
+ if ((mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (mp_cmp(P->z, Q->z) == LTC_MP_EQ)) {
+ if (mp_cmp(P->y, Q->y) == LTC_MP_EQ) {
+ /* here P = Q >> Result = 2 * P (use doubling) */
+ mp_clear_multi(t1, t2, x, y, z, LTC_NULL);
+ return ltc_ecc_projective_dbl_point(P, R, ma, modulus, mp);
+ }
+ if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(P->y, t1) == LTC_MP_EQ) {
+ /* here Q = -P >>> Result = the point at infinity */
+ err = ltc_ecc_set_point_xyz(1, 1, 0, R);
+ goto done;
+ }
+ }
+
+ if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->y, y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->z, z)) != CRYPT_OK) { goto done; }
+
+ /* if Z is one then these are no-operations */
+ if (Q->z != NULL) {
+ /* T1 = Z' * Z' */
+ if ((err = mp_sqr(Q->z, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X * T1 */
+ if ((err = mp_mul(t1, x, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = Z' * T1 */
+ if ((err = mp_mul(Q->z, t1, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Y = Y * T1 */
+ if ((err = mp_mul(t1, y, y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* T1 = Z*Z */
+ if ((err = mp_sqr(z, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = X' * T1 */
+ if ((err = mp_mul(Q->x, t1, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = Z * T1 */
+ if ((err = mp_mul(z, t1, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = Y' * T1 */
+ if ((err = mp_mul(Q->y, t1, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* Y = Y - T1 */
+ if ((err = mp_sub(y, t1, y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = 2T1 */
+ if ((err = mp_add(t1, t1, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = Y + T1 */
+ if ((err = mp_add(t1, y, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* X = X - T2 */
+ if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = 2T2 */
+ if ((err = mp_add(t2, t2, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t2, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = X + T2 */
+ if ((err = mp_add(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t2, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+
+ /* if Z' != 1 */
+ if (Q->z != NULL) {
+ /* Z = Z * Z' */
+ if ((err = mp_mul(z, Q->z, z)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* Z = Z * X */
+ if ((err = mp_mul(z, x, z)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* T1 = T1 * X */
+ if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X * X */
+ if ((err = mp_sqr(x, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = T2 * x */
+ if ((err = mp_mul(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = T1 * X */
+ if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* X = Y*Y */
+ if ((err = mp_sqr(y, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X - T2 */
+ if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; }
+ }
+
+ /* T2 = T2 - X */
+ if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = T2 - X */
+ if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = T2 * Y */
+ if ((err = mp_mul(t2, y, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Y = T2 - T1 */
+ if ((err = mp_sub(t2, t1, y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
+ }
+ /* Y = Y/2 */
+ if (mp_isodd(y)) {
+ if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
+ }
+ if ((err = mp_div_2(y, y)) != CRYPT_OK) { goto done; }
+
+ if ((err = mp_copy(x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(z, R->z)) != CRYPT_OK) { goto done; }
+
+ err = CRYPT_OK;
+done:
+ mp_clear_multi(t1, t2, x, y, z, LTC_NULL);
+ return err;
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_projective_dbl_point.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_projective_dbl_point.c
new file mode 100644
index 00000000..c99a2674
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_projective_dbl_point.c
@@ -0,0 +1,182 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/* ### Point doubling in Jacobian coordinate system ###
+ *
+ * let us have a curve: y^2 = x^3 + a*x + b
+ * in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6
+ *
+ * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where:
+ * Xr = M^2 - 2*S
+ * Yr = M * (S - Xr) - 8*T
+ * Zr = 2 * Yp * Zp
+ *
+ * M = 3 * Xp^2 + a*Zp^4
+ * T = Yp^4
+ * S = 4 * Xp * Yp^2
+ *
+ * SPECIAL CASE: when a == -3 we can compute M as
+ * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2)
+ */
+
+/**
+ @file ltc_ecc_projective_dbl_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC))
+
+/**
+ Double an ECC point
+ @param P The point to double
+ @param R [out] The destination of the double
+ @param ma ECC curve parameter a in montgomery form
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp)
+{
+ void *t1, *t2;
+ int err, inf;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(mp != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (P != R) {
+ if ((err = ltc_ecc_copy_point(P, R)) != CRYPT_OK) { goto done; }
+ }
+
+ if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
+ if (inf) {
+ /* if P is point at infinity >> Result = point at infinity */
+ err = ltc_ecc_set_point_xyz(1, 1, 0, R);
+ goto done;
+ }
+
+ /* t1 = Z * Z */
+ if ((err = mp_sqr(R->z, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Z = Y * Z */
+ if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Z = 2Z */
+ if ((err = mp_add(R->z, R->z, R->z)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(R->z, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; }
+ }
+
+ if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */
+ /* T2 = X - T1 */
+ if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = X + T1 */
+ if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = T1 * T2 */
+ if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = 2T2 */
+ if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = T1 + T2 */
+ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ }
+ else {
+ /* T2 = T1 * T1 */
+ if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = T2 * a */
+ if ((err = mp_mul(t2, ma, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = X * X */
+ if ((err = mp_sqr(R->x, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = T2 + T1 */
+ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = T2 + T1 */
+ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = T2 + T1 */
+ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ }
+
+ /* Y = 2Y */
+ if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(R->y, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(R->y, modulus, R->y)) != CRYPT_OK) { goto done; }
+ }
+ /* Y = Y * Y */
+ if ((err = mp_sqr(R->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = Y * Y */
+ if ((err = mp_sqr(R->y, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = T2/2 */
+ if (mp_isodd(t2)) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ if ((err = mp_div_2(t2, t2)) != CRYPT_OK) { goto done; }
+ /* Y = Y * X */
+ if ((err = mp_mul(R->y, R->x, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* X = T1 * T1 */
+ if ((err = mp_sqr(t1, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X - Y */
+ if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; }
+ }
+ /* X = X - Y */
+ if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; }
+ }
+
+ /* Y = Y - X */
+ if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; }
+ }
+ /* Y = Y * T1 */
+ if ((err = mp_mul(R->y, t1, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Y = Y - T2 */
+ if ((err = mp_sub(R->y, t2, R->y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; }
+ }
+
+ err = CRYPT_OK;
+done:
+ mp_clear_multi(t2, t1, LTC_NULL);
+ return err;
+}
+#endif
diff --git a/Sources/libtomcrypt/pk/ecc/ltc_ecc_verify_key.c b/Sources/libtomcrypt/pk/ecc/ltc_ecc_verify_key.c
new file mode 100644
index 00000000..26c8383f
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ecc/ltc_ecc_verify_key.c
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/* origin of this code - OLPC */
+
+#ifdef LTC_MECC
+
+/**
+ Verify a key according to ANSI spec
+ @param key The key to validate
+ @return CRYPT_OK if successful
+*/
+
+int ltc_ecc_verify_key(const ecc_key *key)
+{
+ int err, inf;
+ ecc_point *point;
+ void *prime = key->dp.prime;
+ void *order = key->dp.order;
+ void *a = key->dp.A;
+
+ /* Test 1: Are the x and y points of the public key in the field? */
+ if (ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) {
+ if ((ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT) ||
+ (ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT) ||
+ (ltc_mp.compare_d(key->pubkey.x, 0) == LTC_MP_LT) ||
+ (ltc_mp.compare_d(key->pubkey.y, 0) == LTC_MP_LT) ||
+ (mp_iszero(key->pubkey.x) && mp_iszero(key->pubkey.y))
+ )
+ {
+ err = CRYPT_INVALID_PACKET;
+ goto done2;
+ }
+ }
+
+ /* Test 2: is the public key on the curve? */
+ if ((err = ltc_ecc_is_point(&key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; }
+
+ /* Test 3: does nG = O? (n = order, O = point at infinity, G = public key) */
+ point = ltc_ecc_new_point();
+ if ((err = ltc_ecc_mulmod(order, &(key->pubkey), point, a, prime, 1)) != CRYPT_OK) { goto done1; }
+
+ err = ltc_ecc_is_point_at_infinity(point, prime, &inf);
+ if (err != CRYPT_OK || inf) {
+ err = CRYPT_ERROR;
+ }
+ else {
+ err = CRYPT_OK;
+ }
+
+done1:
+ ltc_ecc_del_point(point);
+done2:
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ed25519/ed25519_export.c b/Sources/libtomcrypt/pk/ed25519/ed25519_export.c
new file mode 100644
index 00000000..5ec68eb2
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ed25519/ed25519_export.c
@@ -0,0 +1,31 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ed25519_export.c
+ Export an Ed25519 key to a binary packet, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Export an Ed25519 key to a binary packet
+ @param out [out] The destination for the key
+ @param outlen [in/out] The max size and resulting size of the Ed25519 key
+ @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC)
+ @param key The key you wish to export
+ @return CRYPT_OK if successful
+*/
+int ed25519_export( unsigned char *out, unsigned long *outlen,
+ int which,
+ const curve25519_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+
+ if (key->pka != LTC_PKA_ED25519) return CRYPT_PK_INVALID_TYPE;
+
+ return ec25519_export(out, outlen, which, key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ed25519/ed25519_import.c b/Sources/libtomcrypt/pk/ed25519/ed25519_import.c
new file mode 100644
index 00000000..634780c4
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ed25519/ed25519_import.c
@@ -0,0 +1,35 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ed25519_import.c
+ Import a Ed25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Import an Ed25519 public key
+ @param in The packet to read
+ @param inlen The length of the input packet
+ @param key [out] Where to import the key to
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key)
+{
+ int err;
+ unsigned long key_len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ key_len = sizeof(key->pub);
+ if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_ED25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) {
+ key->type = PK_PUBLIC;
+ key->pka = LTC_PKA_ED25519;
+ }
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ed25519/ed25519_import_pkcs8.c b/Sources/libtomcrypt/pk/ed25519/ed25519_import_pkcs8.c
new file mode 100644
index 00000000..b1e68332
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ed25519/ed25519_import_pkcs8.c
@@ -0,0 +1,33 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ed25519_import_pkcs8.c
+ Import an Ed25519 key in PKCS#8 format, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+int ed25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
+ curve25519_key *key)
+{
+ return ec25519_import_pkcs8_asn1(alg_id, priv_key, LTC_OID_ED25519, key);
+}
+
+/**
+ Import an Ed25519 private key in PKCS#8 format
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param pw_ctx The password context when decrypting the private key
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ curve25519_key *key)
+{
+ return ec25519_import_pkcs8(in, inlen, pw_ctx, LTC_OID_ED25519, key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ed25519/ed25519_import_raw.c b/Sources/libtomcrypt/pk/ed25519/ed25519_import_raw.c
new file mode 100644
index 00000000..6d470739
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ed25519/ed25519_import_raw.c
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ed25519_import_raw.c
+ Set the parameters of an Ed25519 key, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Set the parameters of an Ed25519 key
+
+ @param in The key
+ @param inlen The length of the key
+ @param which Which type of key (PK_PRIVATE or PK_PUBLIC)
+ @param key [out] Destination of the key
+ @return CRYPT_OK if successful
+*/
+int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key)
+{
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (which == PK_PRIVATE) {
+ LTC_ARGCHK(inlen == 32uL || inlen == 64uL);
+ XMEMCPY(key->priv, in, sizeof(key->priv));
+ if (inlen == 32) {
+ tweetnacl_crypto_sk_to_pk(key->pub, key->priv);
+ } else {
+ XMEMCPY(key->pub, in + 32, sizeof(key->pub));
+ }
+ } else if (which == PK_PUBLIC) {
+ LTC_ARGCHK(inlen == 32uL);
+ XMEMCPY(key->pub, in, sizeof(key->pub));
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+ key->pka = LTC_PKA_ED25519;
+ key->type = which;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ed25519/ed25519_import_x509.c b/Sources/libtomcrypt/pk/ed25519/ed25519_import_x509.c
new file mode 100644
index 00000000..306a0e1e
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ed25519/ed25519_import_x509.c
@@ -0,0 +1,45 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ed25519_import_x509.c
+ Import an Ed25519 key from a X.509 certificate, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+static int s_ed25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key)
+{
+ if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE;
+ XMEMCPY(key->pub, in, sizeof(key->pub));
+ return CRYPT_OK;
+}
+
+/**
+ Import an Ed25519 public key from a X.509 certificate
+ @param in The DER encoded X.509 certificate
+ @param inlen The length of the certificate
+ @param key [out] Where to import the key to
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((err = x509_decode_public_key_from_certificate(in, inlen,
+ LTC_OID_ED25519,
+ LTC_ASN1_EOL, NULL, NULL,
+ (public_key_decode_cb)s_ed25519_decode, key)) != CRYPT_OK) {
+ return err;
+ }
+ key->type = PK_PUBLIC;
+ key->pka = LTC_PKA_ED25519;
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ed25519/ed25519_make_key.c b/Sources/libtomcrypt/pk/ed25519/ed25519_make_key.c
new file mode 100644
index 00000000..289313b5
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ed25519/ed25519_make_key.c
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ed25519_make_key.c
+ Create an Ed25519 key, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Create an Ed25519 key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful
+*/
+int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((err = tweetnacl_crypto_sign_keypair(prng, wprng, key->pub, key->priv)) != CRYPT_OK) {
+ return err;
+ }
+
+ key->type = PK_PRIVATE;
+ key->pka = LTC_PKA_ED25519;
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ed25519/ed25519_sign.c b/Sources/libtomcrypt/pk/ed25519/ed25519_sign.c
new file mode 100644
index 00000000..33c24056
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ed25519/ed25519_sign.c
@@ -0,0 +1,126 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ed25519_shared_secret.c
+ Create an Ed25519 signature, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+static int s_ed25519_sign(const unsigned char *msg, unsigned long msglen,
+ unsigned char *sig, unsigned long *siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ const curve25519_key *private_key)
+{
+ unsigned char *s;
+ unsigned long long smlen;
+ int err;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(siglen != NULL);
+ LTC_ARGCHK(private_key != NULL);
+
+ if (private_key->pka != LTC_PKA_ED25519) return CRYPT_PK_INVALID_TYPE;
+ if (private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE;
+
+ if (*siglen < 64uL) {
+ *siglen = 64uL;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ smlen = msglen + 64;
+ s = XMALLOC(smlen);
+ if (s == NULL) return CRYPT_MEM;
+
+ err = tweetnacl_crypto_sign(s, &smlen,
+ msg, msglen,
+ private_key->priv, private_key->pub,
+ ctx, ctxlen);
+
+ XMEMCPY(sig, s, 64uL);
+ *siglen = 64uL;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(s, smlen);
+#endif
+ XFREE(s);
+
+ return err;
+}
+
+/**
+ Create an Ed25519ctx signature.
+ @param msg The data to be signed
+ @param msglen [in] The size of the date to be signed
+ @param sig [out] The destination of the shared data
+ @param siglen [in/out] The max size and resulting size of the shared data.
+ @param ctx [in] The context is a constant null terminated string
+ @param private_key The private Ed25519 key in the pair
+ @return CRYPT_OK if successful
+*/
+int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
+ unsigned char *sig, unsigned long *siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ const curve25519_key *private_key)
+{
+ int err;
+ unsigned char ctx_prefix[292];
+ unsigned long ctx_prefix_size = sizeof(ctx_prefix);
+
+ LTC_ARGCHK(ctx != NULL);
+
+ if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen)) != CRYPT_OK)
+ return err;
+
+ return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key);
+}
+
+/**
+ Create an Ed25519ph signature.
+ @param msg The data to be signed
+ @param msglen [in] The size of the date to be signed
+ @param sig [out] The destination of the shared data
+ @param siglen [in/out] The max size and resulting size of the shared data.
+ @param ctx [in] The context is a constant null terminated string
+ @param private_key The private Ed25519 key in the pair
+ @return CRYPT_OK if successful
+*/
+int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
+ unsigned char *sig, unsigned long *siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ const curve25519_key *private_key)
+{
+ int err;
+ unsigned char msg_hash[64];
+ unsigned char ctx_prefix[292];
+ unsigned long ctx_prefix_size = sizeof(ctx_prefix);
+
+ if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK)
+ return err;
+
+ if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK)
+ return err;
+
+ return s_ed25519_sign(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, private_key);
+}
+
+/**
+ Create an Ed25519 signature.
+ @param msg The data to be signed
+ @param msglen [in] The size of the date to be signed
+ @param sig [out] The destination of the shared data
+ @param siglen [in/out] The max size and resulting size of the shared data.
+ @param private_key The private Ed25519 key in the pair
+ @return CRYPT_OK if successful
+*/
+int ed25519_sign(const unsigned char *msg, unsigned long msglen,
+ unsigned char *sig, unsigned long *siglen,
+ const curve25519_key *private_key)
+{
+ return s_ed25519_sign(msg, msglen, sig, siglen, NULL, 0, private_key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/ed25519/ed25519_verify.c b/Sources/libtomcrypt/pk/ed25519/ed25519_verify.c
new file mode 100644
index 00000000..7afab7ca
--- /dev/null
+++ b/Sources/libtomcrypt/pk/ed25519/ed25519_verify.c
@@ -0,0 +1,134 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file ed25519_verify.c
+ Verify an Ed25519 signature, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+static int s_ed25519_verify(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *sig, unsigned long siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ int *stat,
+ const curve25519_key *public_key)
+{
+ unsigned char* m;
+ unsigned long long mlen;
+ int err;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(public_key != NULL);
+
+ *stat = 0;
+
+ if (siglen != 64uL) return CRYPT_INVALID_ARG;
+ if (public_key->pka != LTC_PKA_ED25519) return CRYPT_PK_INVALID_TYPE;
+
+ mlen = msglen + siglen;
+ if ((mlen < msglen) || (mlen < siglen)) return CRYPT_OVERFLOW;
+
+ m = XMALLOC(mlen);
+ if (m == NULL) return CRYPT_MEM;
+
+ XMEMCPY(m, sig, siglen);
+ XMEMCPY(m + siglen, msg, msglen);
+
+ err = tweetnacl_crypto_sign_open(stat,
+ m, &mlen,
+ m, mlen,
+ ctx, ctxlen,
+ public_key->pub);
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(m, msglen + siglen);
+#endif
+ XFREE(m);
+
+ return err;
+}
+
+/**
+ Verify an Ed25519ctx signature.
+ @param msg [in] The data to be verified
+ @param msglen [in] The size of the data to be verified
+ @param sig [in] The signature to be verified
+ @param siglen [in] The size of the signature to be verified
+ @param ctx [in] The context
+ @param ctxlen [in] The size of the context
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param public_key [in] The public Ed25519 key in the pair
+ @return CRYPT_OK if successful
+*/
+int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *sig, unsigned long siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ int *stat,
+ const curve25519_key *public_key)
+{
+ unsigned char ctx_prefix[292];
+ unsigned long ctx_prefix_size = sizeof(ctx_prefix);
+
+ LTC_ARGCHK(ctx != NULL);
+
+ if (ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen) != CRYPT_OK)
+ return CRYPT_INVALID_ARG;
+
+ return s_ed25519_verify(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key);
+}
+
+/**
+ Verify an Ed25519ph signature.
+ @param msg [in] The data to be verified
+ @param msglen [in] The size of the data to be verified
+ @param sig [in] The signature to be verified
+ @param siglen [in] The size of the signature to be verified
+ @param ctx [in] The context
+ @param ctxlen [in] The size of the context
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param public_key [in] The public Ed25519 key in the pair
+ @return CRYPT_OK if successful
+*/
+int ed25519ph_verify(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *sig, unsigned long siglen,
+ const unsigned char *ctx, unsigned long ctxlen,
+ int *stat,
+ const curve25519_key *public_key)
+{
+ int err;
+ unsigned char msg_hash[64];
+ unsigned char ctx_prefix[292];
+ unsigned long ctx_prefix_size = sizeof(ctx_prefix);
+
+ if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK)
+ return err;
+
+ if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK)
+ return err;
+
+ return s_ed25519_verify(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key);
+}
+
+/**
+ Verify an Ed25519 signature.
+ @param msg [in] The data to be verified
+ @param msglen [in] The size of the data to be verified
+ @param sig [in] The signature to be verified
+ @param siglen [in] The size of the signature to be verified
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param public_key [in] The public Ed25519 key in the pair
+ @return CRYPT_OK if successful
+*/
+int ed25519_verify(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *sig, unsigned long siglen,
+ int *stat,
+ const curve25519_key *public_key)
+{
+ return s_ed25519_verify(msg, msglen, sig, siglen, NULL, 0, stat, public_key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/pka_key.c b/Sources/libtomcrypt/pk/pka_key.c
new file mode 100644
index 00000000..d88ee3d3
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pka_key.c
@@ -0,0 +1,45 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+void pka_key_destroy(ltc_pka_key **key)
+{
+ LTC_ARGCHKVD(key != NULL);
+
+ if (!*key)
+ return;
+
+ pka_key_free(*key);
+ zeromem(*key, sizeof(**key));
+ XFREE(*key);
+ *key = NULL;
+}
+
+void pka_key_free(ltc_pka_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ switch (key->id) {
+ case LTC_PKA_DH:
+#if defined(LTC_MDH)
+ dh_free(&key->u.dh);
+#endif
+ break;
+ case LTC_PKA_DSA:
+#if defined(LTC_MDSA)
+ dsa_free(&key->u.dsa);
+#endif
+ break;
+ case LTC_PKA_RSA:
+#if defined(LTC_MRSA)
+ rsa_free(&key->u.rsa);
+#endif
+ break;
+ case LTC_PKA_EC:
+#if defined(LTC_MECC)
+ ecc_free(&key->u.ecc);
+#endif
+ break;
+ default:
+ break;
+ }
+}
diff --git a/Sources/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c
new file mode 100644
index 00000000..a62dd860
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c
@@ -0,0 +1,39 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs_1_i2osp.c
+ Integer to Octet I2OSP, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/* always stores the same # of bytes, pads with leading zero bytes
+ as required
+ */
+
+/**
+ PKCS #1 Integer to binary
+ @param n The integer to store
+ @param modulus_len The length of the RSA modulus
+ @param out [out] The destination for the integer
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out)
+{
+ unsigned long size;
+
+ size = mp_unsigned_bin_size(n);
+
+ if (size > modulus_len) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store it */
+ zeromem(out, modulus_len);
+ return mp_to_unsigned_bin(n, out+(modulus_len-size));
+}
+
+#endif /* LTC_PKCS_1 */
+
diff --git a/Sources/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c
new file mode 100644
index 00000000..7a68e72c
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs_1_mgf1.c
+ The Mask Generation Function (MGF1) for PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ Perform PKCS #1 MGF1 (internal)
+ @param hash_idx The index of the hash desired
+ @param seed The seed for MGF1
+ @param seedlen The length of the seed
+ @param mask [out] The destination
+ @param masklen The length of the mask desired
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_mgf1(int hash_idx,
+ const unsigned char *seed, unsigned long seedlen,
+ unsigned char *mask, unsigned long masklen)
+{
+ unsigned long hLen, x;
+ ulong32 counter;
+ int err;
+ hash_state *md;
+ unsigned char *buf;
+
+ LTC_ARGCHK(seed != NULL);
+ LTC_ARGCHK(mask != NULL);
+
+ /* ensure valid hash */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get hash output size */
+ hLen = hash_descriptor[hash_idx].hashsize;
+
+ /* allocate memory */
+ md = XMALLOC(sizeof(hash_state));
+ buf = XMALLOC(hLen);
+ if (md == NULL || buf == NULL) {
+ if (md != NULL) {
+ XFREE(md);
+ }
+ if (buf != NULL) {
+ XFREE(buf);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* start counter */
+ counter = 0;
+
+ while (masklen > 0) {
+ /* handle counter */
+ STORE32H(counter, buf);
+ ++counter;
+
+ /* get hash of seed || counter */
+ if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* store it */
+ for (x = 0; x < hLen && masklen > 0; x++, masklen--) {
+ *mask++ = buf[x];
+ }
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, hLen);
+ zeromem(md, sizeof(hash_state));
+#endif
+
+ XFREE(buf);
+ XFREE(md);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
diff --git a/Sources/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c
new file mode 100644
index 00000000..14519c1e
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c
@@ -0,0 +1,185 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs_1_oaep_decode.c
+ OAEP Padding for PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ PKCS #1 v2.00 OAEP decode
+ @param msg The encoded data to decode
+ @param msglen The length of the encoded data (octets)
+ @param lparam The session or system data (can be NULL)
+ @param lparamlen The length of the lparam
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param mgf_hash The hash algorithm used for the MGF
+ @param lparam_hash The hash algorithm used when hashing the lparam (can be -1)
+ @param out [out] Destination of decoding
+ @param outlen [in/out] The max size and resulting size of the decoding
+ @param res [out] Result of decoding, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen,
+ int mgf_hash, int lparam_hash,
+ unsigned char *out, unsigned long *outlen,
+ int *res)
+{
+ unsigned char *DB, *seed, *mask;
+ unsigned long hLen, x, y, modulus_len;
+ int err, ret, lparam_hash_used;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid packet */
+ *res = 0;
+
+ /* test valid hash */
+ if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
+ return err;
+ }
+ if (lparam_hash != -1) {
+ if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) {
+ return err;
+ }
+ lparam_hash_used = lparam_hash;
+ } else {
+ lparam_hash_used = mgf_hash;
+ }
+ hLen = hash_descriptor[lparam_hash_used].hashsize;
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test hash/message size */
+ if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ seed = XMALLOC(hLen);
+ if (DB == NULL || mask == NULL || seed == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (seed != NULL) {
+ XFREE(seed);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ok so it's now in the form
+
+ 0x00 || maskedseed || maskedDB
+
+ 1 || hLen || modulus_len - hLen - 1
+
+ */
+
+ ret = CRYPT_OK;
+
+ /* must have leading 0x00 byte */
+ if (msg[0] != 0x00) {
+ ret = CRYPT_INVALID_PACKET;
+ }
+
+ /* now read the masked seed */
+ x = 1;
+ XMEMCPY(seed, msg + x, hLen);
+ x += hLen;
+
+ /* now read the masked DB */
+ XMEMCPY(DB, msg + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* compute MGF1 of maskedDB (hLen) */
+ if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* XOR against seed */
+ for (y = 0; y < hLen; y++) {
+ seed[y] ^= mask[y];
+ }
+
+ /* compute MGF1 of seed (k - hlen - 1) */
+ if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+
+ /* compute lhash and store it in seed [reuse temps!] */
+ x = modulus_len;
+ if (lparam != NULL) {
+ if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* can't pass hash_memory a NULL so use DB with zero length */
+ if ((err = hash_memory(lparam_hash_used, DB, 0, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* compare the lhash'es */
+ if (XMEM_NEQ(seed, DB, hLen) != 0) {
+ ret = CRYPT_INVALID_PACKET;
+ }
+
+ /* now zeroes before a 0x01 */
+ for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) {
+ /* step... */
+ }
+
+ /* error if wasn't 0x01 */
+ if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
+ ret = CRYPT_INVALID_PACKET;
+ }
+
+ /* rest is the message (and skip 0x01) */
+ if ((modulus_len - hLen - 1 - ++x) > *outlen) {
+ ret = CRYPT_INVALID_PACKET;
+ }
+
+ if (ret == CRYPT_OK) {
+ /* copy message */
+ *outlen = modulus_len - hLen - 1 - x;
+ XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x);
+
+ /* valid packet */
+ *res = 1;
+ }
+ err = ret;
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(seed, hLen);
+ zeromem(mask, modulus_len);
+#endif
+
+ XFREE(seed);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
diff --git a/Sources/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c
new file mode 100644
index 00000000..294583d9
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c
@@ -0,0 +1,172 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs_1_oaep_encode.c
+ OAEP Padding for PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ PKCS #1 v2.00 OAEP encode
+ @param msg The data to encode
+ @param msglen The length of the data to encode (octets)
+ @param lparam A session or system parameter (can be NULL)
+ @param lparamlen The length of the lparam data
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param prng An active PRNG state
+ @param prng_idx The index of the PRNG desired
+ @param hash_idx The index of the hash desired
+ @param out [out] The destination for the encoded data
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, prng_state *prng,
+ int prng_idx,
+ int mgf_hash, int lparam_hash,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned char *DB, *seed, *mask;
+ unsigned long hLen, x, y, modulus_len;
+ int err, lparam_hash_used;
+
+ LTC_ARGCHK((msglen == 0) || (msg != NULL));
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* test valid hash */
+ if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
+ return err;
+ }
+ if (lparam_hash != -1) {
+ if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) {
+ return err;
+ }
+ lparam_hash_used = lparam_hash;
+ } else {
+ lparam_hash_used = mgf_hash;
+ }
+
+ /* valid prng */
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_descriptor[lparam_hash_used].hashsize;
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+ if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ seed = XMALLOC(hLen);
+ if (DB == NULL || mask == NULL || seed == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (seed != NULL) {
+ XFREE(seed);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* get lhash */
+ /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+ x = modulus_len;
+ if (lparam != NULL) {
+ if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* can't pass hash_memory a NULL so use DB with zero length */
+ if ((err = hash_memory(lparam_hash_used, DB, 0, DB, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* append PS then 0x01 (to lhash) */
+ x = hLen;
+ y = modulus_len - msglen - 2*hLen - 2;
+ XMEMSET(DB+x, 0, y);
+ x += y;
+
+ /* 0x01 byte */
+ DB[x++] = 0x01;
+
+ if (msglen != 0) {
+ /* message (length = msglen) */
+ XMEMCPY(DB+x, msg, msglen);
+ x += msglen;
+ }
+
+ /* now choose a random seed */
+ if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+
+ /* compute MGF1 of seed (k - hlen - 1) */
+ if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* compute MGF1 of maskedDB (hLen) */
+ if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* XOR against seed */
+ for (y = 0; y < hLen; y++) {
+ seed[y] ^= mask[y];
+ }
+
+ /* create string of length modulus_len */
+ if (*outlen < modulus_len) {
+ *outlen = modulus_len;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* start output which is 0x00 || maskedSeed || maskedDB */
+ x = 0;
+ out[x++] = 0x00;
+ XMEMCPY(out+x, seed, hLen);
+ x += hLen;
+ XMEMCPY(out+x, DB, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ *outlen = x;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(seed, hLen);
+ zeromem(mask, modulus_len);
+#endif
+
+ XFREE(seed);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
diff --git a/Sources/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c
new file mode 100644
index 00000000..438030e5
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c
@@ -0,0 +1,24 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs_1_os2ip.c
+ Octet to Integer OS2IP, Tom St Denis
+*/
+#ifdef LTC_PKCS_1
+
+/**
+ Read a binary string into an mp_int
+ @param n [out] The mp_int destination
+ @param in The binary string to read
+ @param inlen The length of the binary string
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen)
+{
+ return mp_read_unsigned_bin(n, in, inlen);
+}
+
+#endif /* LTC_PKCS_1 */
+
diff --git a/Sources/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c
new file mode 100644
index 00000000..fad401d1
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c
@@ -0,0 +1,166 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs_1_pss_decode.c
+ PKCS #1 PSS Signature Padding, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ PKCS #1 v2.00 PSS decode
+ @param msghash The hash to verify
+ @param msghashlen The length of the hash (octets)
+ @param sig The signature data (encoded data)
+ @param siglen The length of the signature data (octets)
+ @param saltlen The length of the salt used (octets)
+ @param hash_idx The index of the hash desired
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param res [out] The result of the comparison, 1==valid, 0==invalid
+ @return CRYPT_OK if successful (even if the comparison failed)
+*/
+int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
+ const unsigned char *sig, unsigned long siglen,
+ unsigned long saltlen, int hash_idx,
+ unsigned long modulus_bitlen, int *res)
+{
+ unsigned char *DB, *mask, *salt, *hash;
+ unsigned long x, y, hLen, modulus_len;
+ int err;
+ hash_state md;
+
+ LTC_ARGCHK(msghash != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid */
+ *res = 0;
+
+ /* ensure hash is valid */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_descriptor[hash_idx].hashsize;
+ modulus_bitlen--;
+ modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* check sizes */
+ if ((saltlen > modulus_len) ||
+ (modulus_len < hLen + saltlen + 2)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt/hash of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ salt = XMALLOC(modulus_len);
+ hash = XMALLOC(modulus_len);
+ if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (salt != NULL) {
+ XFREE(salt);
+ }
+ if (hash != NULL) {
+ XFREE(hash);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ensure the 0xBC byte */
+ if (sig[siglen-1] != 0xBC) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* copy out the DB */
+ x = 0;
+ XMEMCPY(DB, sig + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* copy out the hash */
+ XMEMCPY(hash, sig + x, hLen);
+ /* x += hLen; */
+
+ /* check the MSB */
+ if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen)))) != 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* generate mask of length modulus_len - hLen - 1 from hash */
+ if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now clear the first byte [make sure smaller than modulus] */
+ DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen));
+
+ /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+
+ /* check for zeroes and 0x01 */
+ for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) {
+ if (DB[x] != 0x00) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+
+ /* check for the 0x01 */
+ if (DB[x++] != 0x01) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* M = (eight) 0x00 || msghash || salt, mask = H(M) */
+ if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ zeromem(mask, 8);
+ if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* mask == hash means valid signature */
+ if (XMEM_NEQ(mask, hash, hLen) == 0) {
+ *res = 1;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(mask, modulus_len);
+ zeromem(salt, modulus_len);
+ zeromem(hash, modulus_len);
+#endif
+
+ XFREE(hash);
+ XFREE(salt);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
diff --git a/Sources/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c
new file mode 100644
index 00000000..2a4e3728
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c
@@ -0,0 +1,164 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file pkcs_1_pss_encode.c
+ PKCS #1 PSS Signature Padding, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ PKCS #1 v2.00 Signature Encoding
+ @param msghash The hash to encode
+ @param msghashlen The length of the hash (octets)
+ @param saltlen The length of the salt desired (octets)
+ @param prng An active PRNG context
+ @param prng_idx The index of the PRNG desired
+ @param hash_idx The index of the hash desired
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param out [out] The destination of the encoding
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
+ unsigned long saltlen, prng_state *prng,
+ int prng_idx, int hash_idx,
+ unsigned long modulus_bitlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned char *DB, *mask, *salt, *hash;
+ unsigned long x, y, hLen, modulus_len;
+ int err;
+ hash_state md;
+
+ LTC_ARGCHK(msghash != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* ensure hash and PRNG are valid */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_descriptor[hash_idx].hashsize;
+ modulus_bitlen--;
+ modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* check sizes */
+ if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt/hash of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ salt = XMALLOC(modulus_len);
+ hash = XMALLOC(modulus_len);
+ if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (salt != NULL) {
+ XFREE(salt);
+ }
+ if (hash != NULL) {
+ XFREE(hash);
+ }
+ return CRYPT_MEM;
+ }
+
+
+ /* generate random salt */
+ if (saltlen > 0) {
+ if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+ }
+
+ /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
+ if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ zeromem(DB, 8);
+ if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+ x = 0;
+ XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2);
+ x += modulus_len - saltlen - hLen - 2;
+ DB[x++] = 0x01;
+ XMEMCPY(DB + x, salt, saltlen);
+ /* x += saltlen; */
+
+ /* generate mask of length modulus_len - hLen - 1 from hash */
+ if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* output is DB || hash || 0xBC */
+ if (*outlen < modulus_len) {
+ *outlen = modulus_len;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* DB len = modulus_len - hLen - 1 */
+ y = 0;
+ XMEMCPY(out + y, DB, modulus_len - hLen - 1);
+ y += modulus_len - hLen - 1;
+
+ /* hash */
+ XMEMCPY(out + y, hash, hLen);
+ y += hLen;
+
+ /* 0xBC */
+ out[y] = 0xBC;
+
+ /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
+ out[0] &= 0xFF >> ((modulus_len<<3) - modulus_bitlen);
+
+ /* store output size */
+ *outlen = modulus_len;
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(mask, modulus_len);
+ zeromem(salt, modulus_len);
+ zeromem(hash, modulus_len);
+#endif
+
+ XFREE(hash);
+ XFREE(salt);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
diff --git a/Sources/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c
new file mode 100644
index 00000000..e9880607
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c
@@ -0,0 +1,102 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/** @file pkcs_1_v1_5_decode.c
+ *
+ * PKCS #1 v1.5 Padding. (Andreas Lange)
+ */
+
+#ifdef LTC_PKCS_1
+
+/** @brief PKCS #1 v1.5 decode.
+ *
+ * @param msg The encoded data to decode
+ * @param msglen The length of the encoded data (octets)
+ * @param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks)
+ * @param modulus_bitlen The bit length of the RSA modulus
+ * @param out [out] Destination of decoding
+ * @param outlen [in/out] The max size and resulting size of the decoding
+ * @param is_valid [out] Boolean whether the padding was valid
+ *
+ * @return CRYPT_OK if successful
+ */
+int pkcs_1_v1_5_decode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen,
+ int *is_valid)
+{
+ unsigned long modulus_len, ps_len, i;
+ int result;
+
+ /* default to invalid packet */
+ *is_valid = 0;
+
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+
+ if ((msglen > modulus_len) || (modulus_len < 11)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ result = CRYPT_OK;
+
+ /* separate encoded message */
+
+ if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) {
+ result = CRYPT_INVALID_PACKET;
+ }
+
+ if (block_type == LTC_PKCS_1_EME) {
+ for (i = 2; i < modulus_len; i++) {
+ /* separator */
+ if (msg[i] == 0x00) { break; }
+ }
+ ps_len = i++ - 2;
+
+ if (i > modulus_len) {
+ /* There was no octet with hexadecimal value 0x00 to separate ps from m.
+ */
+ result = CRYPT_INVALID_PACKET;
+ }
+ } else {
+ for (i = 2; i < modulus_len - 1; i++) {
+ if (msg[i] != 0xFF) { break; }
+ }
+
+ /* separator check */
+ if (msg[i] != 0) {
+ /* There was no octet with hexadecimal value 0x00 to separate ps from m. */
+ result = CRYPT_INVALID_PACKET;
+ }
+
+ ps_len = i - 2;
+ }
+
+ if (ps_len < 8)
+ {
+ /* The length of ps is less than 8 octets.
+ */
+ result = CRYPT_INVALID_PACKET;
+ }
+
+ if (*outlen < (msglen - (2 + ps_len + 1))) {
+ result = CRYPT_INVALID_PACKET;
+ }
+
+ if (result == CRYPT_OK) {
+ *outlen = (msglen - (2 + ps_len + 1));
+ XMEMCPY(out, &msg[2 + ps_len + 1], *outlen);
+
+ /* valid packet */
+ *is_valid = 1;
+ }
+
+ return result;
+} /* pkcs_1_v1_5_decode */
+
+#endif /* #ifdef LTC_PKCS_1 */
diff --git a/Sources/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c
new file mode 100644
index 00000000..a21df4bf
--- /dev/null
+++ b/Sources/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c
@@ -0,0 +1,105 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/*! \file pkcs_1_v1_5_encode.c
+ *
+ * PKCS #1 v1.5 Padding (Andreas Lange)
+ */
+
+#ifdef LTC_PKCS_1
+
+/*! \brief PKCS #1 v1.5 encode.
+ *
+ * \param msg The data to encode
+ * \param msglen The length of the data to encode (octets)
+ * \param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks)
+ * \param modulus_bitlen The bit length of the RSA modulus
+ * \param prng An active PRNG state (only for LTC_PKCS_1_EME)
+ * \param prng_idx The index of the PRNG desired (only for LTC_PKCS_1_EME)
+ * \param out [out] The destination for the encoded data
+ * \param outlen [in/out] The max size and resulting size of the encoded data
+ *
+ * \return CRYPT_OK if successful
+ */
+int pkcs_1_v1_5_encode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ prng_state *prng,
+ int prng_idx,
+ unsigned char *out,
+ unsigned long *outlen)
+{
+ unsigned long modulus_len, ps_len, i;
+ unsigned char *ps;
+ int result;
+
+ LTC_ARGCHK((msglen == 0) || (msg != NULL));
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* valid block_type? */
+ if ((block_type != LTC_PKCS_1_EMSA) &&
+ (block_type != LTC_PKCS_1_EME)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (block_type == LTC_PKCS_1_EME) { /* encryption padding, we need a valid PRNG */
+ if ((result = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return result;
+ }
+ }
+
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+ if ((msglen + 11) > modulus_len) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ if (*outlen < modulus_len) {
+ *outlen = modulus_len;
+ result = CRYPT_BUFFER_OVERFLOW;
+ goto bail;
+ }
+
+ /* generate an octets string PS */
+ ps = &out[2];
+ ps_len = modulus_len - msglen - 3;
+
+ if (block_type == LTC_PKCS_1_EME) {
+ /* now choose a random ps */
+ if (prng_descriptor[prng_idx].read(ps, ps_len, prng) != ps_len) {
+ result = CRYPT_ERROR_READPRNG;
+ goto bail;
+ }
+
+ /* transform zero bytes (if any) to non-zero random bytes */
+ for (i = 0; i < ps_len; i++) {
+ while (ps[i] == 0) {
+ if (prng_descriptor[prng_idx].read(&ps[i], 1, prng) != 1) {
+ result = CRYPT_ERROR_READPRNG;
+ goto bail;
+ }
+ }
+ }
+ } else {
+ XMEMSET(ps, 0xFF, ps_len);
+ }
+
+ /* create string of length modulus_len */
+ out[0] = 0x00;
+ out[1] = (unsigned char)block_type; /* block_type 1 or 2 */
+ out[2 + ps_len] = 0x00;
+ if (msglen != 0) {
+ XMEMCPY(&out[2 + ps_len + 1], msg, msglen);
+ }
+ *outlen = modulus_len;
+
+ result = CRYPT_OK;
+bail:
+ return result;
+} /* pkcs_1_v1_5_encode */
+
+#endif /* #ifdef LTC_PKCS_1 */
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_decrypt_key.c b/Sources/libtomcrypt/pk/rsa/rsa_decrypt_key.c
new file mode 100644
index 00000000..ea1ec99f
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_decrypt_key.c
@@ -0,0 +1,95 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_decrypt_key.c
+ RSA PKCS #1 Decryption, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ PKCS #1 decrypt then v1.5 or OAEP depad
+ @param in The ciphertext
+ @param inlen The length of the ciphertext (octets)
+ @param out [out] The plaintext
+ @param outlen [in/out] The max size and resulting size of the plaintext (octets)
+ @param lparam The system "lparam" value
+ @param lparamlen The length of the lparam value (octets)
+ @param mgf_hash The hash algorithm used for the MGF
+ @param lparam_hash The hash algorithm used when hashing the lparam (can be -1)
+ @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5)
+ @param stat [out] Result of the decryption, 1==valid, 0==invalid
+ @param key The corresponding private RSA key
+ @return CRYPT_OK if succcessul (even if invalid)
+*/
+int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ int mgf_hash, int lparam_hash,
+ int padding,
+ int *stat, const rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+ unsigned char *tmp;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* valid padding? */
+ if ((padding != LTC_PKCS_1_V1_5) &&
+ (padding != LTC_PKCS_1_OAEP)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding == LTC_PKCS_1_OAEP) {
+ /* valid hash ? */
+ if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (key->N));
+ if (modulus_bytelen != inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate ram */
+ tmp = XMALLOC(inlen);
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* rsa decode the packet */
+ x = inlen;
+ if ((err = ltc_mp.rsa_me(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) {
+ XFREE(tmp);
+ return err;
+ }
+
+ if (padding == LTC_PKCS_1_OAEP) {
+ /* now OAEP decode the packet */
+ err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, mgf_hash,
+ lparam_hash, out, outlen, stat);
+ } else {
+ /* now PKCS #1 v1.5 depad the packet */
+ err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat);
+ }
+
+ XFREE(tmp);
+ return err;
+}
+
+#endif /* LTC_MRSA */
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_encrypt_key.c b/Sources/libtomcrypt/pk/rsa/rsa_encrypt_key.c
new file mode 100644
index 00000000..8739bb27
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_encrypt_key.c
@@ -0,0 +1,93 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_encrypt_key.c
+ RSA PKCS #1 encryption, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ (PKCS #1 v2.0) OAEP pad then encrypt
+ @param in The plaintext
+ @param inlen The length of the plaintext (octets)
+ @param out [out] The ciphertext
+ @param outlen [in/out] The max size and resulting size of the ciphertext
+ @param lparam The system "lparam" for the encryption
+ @param lparamlen The length of lparam (octets)
+ @param prng An active PRNG
+ @param prng_idx The index of the desired prng
+ @param hash_idx The index of the desired hash
+ @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5)
+ @param key The RSA key to encrypt to
+ @return CRYPT_OK if successful
+*/
+int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ prng_state *prng, int prng_idx,
+ int mgf_hash, int lparam_hash,
+ int padding,
+ const rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+
+ LTC_ARGCHK((inlen == 0) || (in != NULL));
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* valid padding? */
+ if ((padding != LTC_PKCS_1_V1_5) &&
+ (padding != LTC_PKCS_1_OAEP)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ /* valid prng? */
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (padding == LTC_PKCS_1_OAEP) {
+ /* valid hash? */
+ if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (key->N));
+ if (modulus_bytelen > *outlen) {
+ *outlen = modulus_bytelen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (padding == LTC_PKCS_1_OAEP) {
+ /* OAEP pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_oaep_encode(in, inlen, lparam,
+ lparamlen, modulus_bitlen, prng, prng_idx, mgf_hash,
+ lparam_hash, out, &x)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ /* PKCS #1 v1.5 pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EME,
+ modulus_bitlen, prng, prng_idx,
+ out, &x)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* rsa exptmod the OAEP or PKCS #1 v1.5 pad */
+ return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key);
+}
+
+#endif /* LTC_MRSA */
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_export.c b/Sources/libtomcrypt/pk/rsa/rsa_export.c
new file mode 100644
index 00000000..225224d0
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_export.c
@@ -0,0 +1,91 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_export.c
+ Export RSA PKCS keys, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ This will export either an RSAPublicKey or RSAPrivateKey [defined in PKCS #1 v2.1]
+ @param out [out] Destination of the packet
+ @param outlen [in/out] The max size and resulting size of the packet
+ @param type The type of exported key (PK_PRIVATE or PK_PUBLIC)
+ @param key The RSA key to export
+ @return CRYPT_OK if successful
+*/
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_key *key)
+{
+ unsigned long zero=0;
+ int err, std;
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ std = type & PK_STD;
+ type &= ~PK_STD;
+
+ if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ if (type == PK_PRIVATE) {
+ /* private key */
+ /* output is
+ Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p
+ */
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_INTEGER, 1UL, key->d,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->dP,
+ LTC_ASN1_INTEGER, 1UL, key->dQ,
+ LTC_ASN1_INTEGER, 1UL, key->qP,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+
+ if (type == PK_PUBLIC) {
+ /* public key */
+ unsigned long tmplen, *ptmplen;
+ unsigned char* tmp = NULL;
+
+ if (std) {
+ tmplen = (unsigned long)(mp_count_bits(key->N) / 8) * 2 + 8;
+ tmp = XMALLOC(tmplen);
+ ptmplen = &tmplen;
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+ }
+ else {
+ tmp = out;
+ ptmplen = outlen;
+ }
+
+ err = der_encode_sequence_multi(tmp, ptmplen,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+ if ((err != CRYPT_OK) || !std) {
+ goto finish;
+ }
+
+ err = x509_encode_subject_public_key_info(out, outlen,
+ LTC_OID_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
+
+finish:
+ if (tmp != out) XFREE(tmp);
+ return err;
+ }
+
+ return CRYPT_INVALID_ARG;
+}
+
+#endif /* LTC_MRSA */
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_exptmod.c b/Sources/libtomcrypt/pk/rsa/rsa_exptmod.c
new file mode 100644
index 00000000..73daee59
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_exptmod.c
@@ -0,0 +1,172 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_exptmod.c
+ RSA PKCS exptmod, Tom St Denis
+ Added RSA blinding --nmav
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Compute an RSA modular exponentiation
+ @param in The input data to send into RSA
+ @param inlen The length of the input (octets)
+ @param out [out] The destination
+ @param outlen [in/out] The max size and resulting size of the output
+ @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
+ @param key The RSA key to use
+ @return CRYPT_OK if successful
+*/
+int rsa_exptmod(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ const rsa_key *key)
+{
+ void *tmp, *tmpa, *tmpb;
+ #ifdef LTC_RSA_BLINDING
+ void *rnd, *rndi /* inverse of rnd */;
+ #endif
+ unsigned long x;
+ int err, has_crt_parameters;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* is the key of the right type for the operation? */
+ if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* must be a private or public operation */
+ if (which != PK_PRIVATE && which != PK_PUBLIC) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ /* init and copy into tmp */
+ if ((err = mp_init_multi(&tmp, &tmpa, &tmpb,
+#ifdef LTC_RSA_BLINDING
+ &rnd, &rndi,
+#endif /* LTC_RSA_BLINDING */
+ NULL)) != CRYPT_OK)
+ { return err; }
+ if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK)
+ { goto error; }
+
+
+ /* sanity check on the input */
+ if (mp_cmp(key->N, tmp) == LTC_MP_LT) {
+ err = CRYPT_PK_INVALID_SIZE;
+ goto error;
+ }
+
+ /* are we using the private exponent and is the key optimized? */
+ if (which == PK_PRIVATE) {
+ #ifdef LTC_RSA_BLINDING
+ /* do blinding */
+ err = mp_rand(rnd, mp_get_digit_count(key->N));
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* rndi = 1/rnd mod N */
+ err = mp_invmod(rnd, key->N, rndi);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* rnd = rnd^e */
+ err = mp_exptmod( rnd, key->e, key->N, rnd);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* tmp = tmp*rnd mod N */
+ err = mp_mulmod( tmp, rnd, key->N, tmp);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+ #endif /* LTC_RSA_BLINDING */
+
+ has_crt_parameters = (key->p != NULL) && (mp_get_digit_count(key->p) != 0) &&
+ (key->q != NULL) && (mp_get_digit_count(key->q) != 0) &&
+ (key->dP != NULL) && (mp_get_digit_count(key->dP) != 0) &&
+ (key->dQ != NULL) && (mp_get_digit_count(key->dQ) != 0) &&
+ (key->qP != NULL) && (mp_get_digit_count(key->qP) != 0);
+
+ if (!has_crt_parameters) {
+ /*
+ * In case CRT optimization parameters are not provided,
+ * the private key is directly used to exptmod it
+ */
+ if ((err = mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK) { goto error; }
+ } else {
+ /* tmpa = tmp^dP mod p */
+ if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; }
+
+ /* tmpb = tmp^dQ mod q */
+ if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; }
+
+ /* tmp = (tmpa - tmpb) * qInv (mod p) */
+ if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; }
+
+ /* tmp = tmpb + q * tmp */
+ if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; }
+ }
+
+ #ifdef LTC_RSA_BLINDING
+ /* unblind */
+ err = mp_mulmod( tmp, rndi, key->N, tmp);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+ #endif
+
+ #ifdef LTC_RSA_CRT_HARDENING
+ if (has_crt_parameters) {
+ if ((err = mp_exptmod(tmp, key->e, key->N, tmpa)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(tmpb, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(tmpa, tmpb) != LTC_MP_EQ) { err = CRYPT_ERROR; goto error; }
+ }
+ #endif
+ } else {
+ /* exptmod it */
+ if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) { goto error; }
+ }
+
+ /* read it back */
+ x = (unsigned long)mp_unsigned_bin_size(key->N);
+ if (x > *outlen) {
+ *outlen = x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto error;
+ }
+
+ /* this should never happen ... */
+ if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) {
+ err = CRYPT_ERROR;
+ goto error;
+ }
+ *outlen = x;
+
+ /* convert it */
+ zeromem(out, x);
+ if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK) { goto error; }
+
+ /* clean up and return */
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(
+#ifdef LTC_RSA_BLINDING
+ rndi, rnd,
+#endif /* LTC_RSA_BLINDING */
+ tmpb, tmpa, tmp, NULL);
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_get_size.c b/Sources/libtomcrypt/pk/rsa/rsa_get_size.c
new file mode 100644
index 00000000..72d3f7a5
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_get_size.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_get_size.c
+ Retrieve the size of an RSA key, Steffen Jaeckel.
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Retrieve the size in bytes of an RSA key.
+ @param key The RSA key
+ @return The size in bytes of the RSA key or INT_MAX on error.
+*/
+int rsa_get_size(const rsa_key *key)
+{
+ int ret = INT_MAX;
+ LTC_ARGCHK(key != NULL);
+
+ if (key)
+ {
+ ret = mp_unsigned_bin_size(key->N);
+ } /* if */
+
+ return ret;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_import.c b/Sources/libtomcrypt/pk/rsa/rsa_import.c
new file mode 100644
index 00000000..1240a77e
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_import.c
@@ -0,0 +1,143 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_import.c
+ Import a PKCS RSA key, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+
+/**
+ Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
+
+ The `key` passed into this function has to be already initialized and will
+ NOT be free'd on error!
+
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful
+*/
+int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ int err;
+ unsigned long version = -1;
+
+ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+ if (err == CRYPT_OVERFLOW) {
+ /* the version would fit into an LTC_ASN1_SHORT_INTEGER
+ * so we try to decode as a public key
+ */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) {
+ key->type = PK_PUBLIC;
+ }
+ goto LBL_OUT;
+ } else if (err != CRYPT_INPUT_TOO_LONG) {
+ /* couldn't decode the version, so error out */
+ goto LBL_OUT;
+ }
+
+ if (version == 0) {
+ /* it's a private key */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_INTEGER, 1UL, key->d,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->dP,
+ LTC_ASN1_INTEGER, 1UL, key->dQ,
+ LTC_ASN1_INTEGER, 1UL, key->qP,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_OUT;
+ }
+ key->type = PK_PRIVATE;
+ } else if (version == 1) {
+ /* we don't support multi-prime RSA */
+ err = CRYPT_PK_INVALID_TYPE;
+ goto LBL_OUT;
+ }
+ err = CRYPT_OK;
+LBL_OUT:
+ return err;
+}
+
+/**
+ Import multiple formats of RSA public and private keys.
+
+ RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
+ SubjectPublicKeyInfo formatted public keys
+
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ int err;
+ unsigned char *tmpbuf=NULL;
+ unsigned long tmpbuf_len, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* init key */
+ if ((err = rsa_init(key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* see if the OpenSSL DER format RSA public key will work */
+ tmpbuf_len = inlen;
+ tmpbuf = XCALLOC(1, tmpbuf_len);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ len = 0;
+ err = x509_decode_subject_public_key_info(in, inlen,
+ LTC_OID_RSA, tmpbuf, &tmpbuf_len,
+ LTC_ASN1_NULL, NULL, &len);
+
+ if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */
+
+ /* now it should be SEQUENCE { INTEGER, INTEGER } */
+ if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ key->type = PK_PUBLIC;
+ err = CRYPT_OK;
+ goto LBL_FREE;
+ }
+
+ /* not SSL public key, try to match against PKCS #1 standards */
+ if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) {
+ goto LBL_FREE;
+ }
+
+LBL_ERR:
+ rsa_free(key);
+
+LBL_FREE:
+ if (tmpbuf != NULL) {
+ XFREE(tmpbuf);
+ }
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_import_pkcs8.c b/Sources/libtomcrypt/pk/rsa/rsa_import_pkcs8.c
new file mode 100644
index 00000000..0a4570c0
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_import_pkcs8.c
@@ -0,0 +1,70 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_import_pkcs8.c
+ Import a PKCS RSA key
+*/
+
+#ifdef LTC_MRSA
+
+int rsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, rsa_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+
+ LTC_UNUSED_PARAM(alg_id);
+
+ if ((err = rsa_init(key)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = rsa_import_pkcs1(priv_key->data, priv_key->size, key)) != CRYPT_OK) {
+ rsa_free(key);
+ return err;
+ }
+ key->type = PK_PRIVATE;
+
+ return err;
+}
+
+/**
+ Import an RSAPrivateKey in PKCS#8 format
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param pw_ctx The password context when decrypting the private key
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ rsa_key *key)
+{
+ int err;
+ ltc_asn1_list *l = NULL;
+ ltc_asn1_list *alg_id, *priv_key;
+ enum ltc_oid_id pka;
+
+ LTC_ARGCHK(in != NULL);
+
+ if ((err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) {
+ goto LBL_DER_FREE;
+ }
+ if (pka != LTC_OID_RSA) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DER_FREE;
+ }
+
+ err = rsa_import_pkcs8_asn1(alg_id, priv_key, key);
+
+LBL_DER_FREE:
+ der_free_sequence_flexi(l);
+ return err;
+}
+
+#endif /* LTC_MRSA */
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_import_x509.c b/Sources/libtomcrypt/pk/rsa/rsa_import_x509.c
new file mode 100644
index 00000000..4d157ead
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_import_x509.c
@@ -0,0 +1,54 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_import.c
+ Import an RSA key from a X.509 certificate, Steffen Jaeckel
+*/
+
+#ifdef LTC_MRSA
+
+static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ /* now it should be SEQUENCE { INTEGER, INTEGER } */
+ return der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_EOL, 0UL, NULL);
+}
+
+/**
+ Import an RSA key from a X.509 certificate
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* init key */
+ if ((err = rsa_init(key)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = x509_decode_public_key_from_certificate(in, inlen,
+ LTC_OID_RSA,
+ LTC_ASN1_NULL, NULL, NULL,
+ (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) {
+ rsa_free(key);
+ } else {
+ key->type = PK_PUBLIC;
+ }
+
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_key.c b/Sources/libtomcrypt/pk/rsa/rsa_key.c
new file mode 100644
index 00000000..425684fa
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_key.c
@@ -0,0 +1,103 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_key.c
+ Free an RSA key, Tom St Denis
+ Basic operations on an RSA key, Steffen Jaeckel
+*/
+
+#ifdef LTC_MRSA
+#include
+
+static void s_mpi_shrink_multi(void **a, ...)
+{
+ void **cur;
+ unsigned n;
+ int err;
+ va_list args;
+ void *tmp[10] = { 0 };
+ void **arg[10] = { 0 };
+
+ /* We re-allocate in the order that we received the varargs */
+ n = 0;
+ err = CRYPT_ERROR;
+ cur = a;
+ va_start(args, a);
+ while (cur != NULL) {
+ if (n >= sizeof(tmp)/sizeof(tmp[0])) {
+ goto out;
+ }
+ if (*cur != NULL) {
+ arg[n] = cur;
+ if ((err = mp_init_copy(&tmp[n], *arg[n])) != CRYPT_OK) {
+ goto out;
+ }
+ n++;
+ }
+ cur = va_arg(args, void**);
+ }
+ va_end(args);
+
+ /* but we clear the old values in the reverse order */
+ while (n != 0 && arg[--n] != NULL) {
+ mp_clear(*arg[n]);
+ *arg[n] = tmp[n];
+ }
+out:
+ va_end(args);
+ /* clean-up after an error
+ * or after this was called with too many args
+ */
+ if ((err != CRYPT_OK) ||
+ (n >= sizeof(tmp)/sizeof(tmp[0]))) {
+ for (n = 0; n < sizeof(tmp)/sizeof(tmp[0]); ++n) {
+ if (tmp[n] != NULL) {
+ mp_clear(tmp[n]);
+ }
+ }
+ }
+}
+
+/**
+ This shrinks the allocated memory of a RSA key
+
+ It will use up some more memory temporarily,
+ but then it will free-up the entire sequence that
+ was once allocated when the key was created/populated.
+
+ This only works with libtommath >= 1.2.0 in earlier versions
+ it has the inverse effect due to the way it worked internally.
+ Also works for GNU MP, tomsfastmath naturally shows no effect.
+
+ @param key The RSA key to shrink
+*/
+void rsa_shrink_key(rsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ s_mpi_shrink_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
+}
+
+/**
+ Init an RSA key
+ @param key The RSA key to initialize
+ @return CRYPT_OK if successful
+*/
+int rsa_init(rsa_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ return mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, LTC_NULL);
+}
+
+/**
+ Free an RSA key from memory
+ @param key The RSA key to free
+*/
+void rsa_free(rsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, LTC_NULL);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_make_key.c b/Sources/libtomcrypt/pk/rsa/rsa_make_key.c
new file mode 100644
index 00000000..6bfc0419
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_make_key.c
@@ -0,0 +1,165 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_make_key.c
+ RSA key generation, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+static int s_rsa_make_key(prng_state *prng, int wprng, int size, void *e, rsa_key *key)
+{
+ void *p, *q, *tmp1, *tmp2;
+ int err;
+
+ LTC_ARGCHK(ltc_mp.name != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(size > 0);
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* make primes p and q (optimization provided by Wayne Scott) */
+
+ /* make prime "p" */
+ do {
+ if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = p-1 */
+ if ((err = mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(p-1, e) */
+ } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides p-1 */
+
+ /* make prime "q" */
+ do {
+ if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = q-1 */
+ if ((err = mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(q-1, e) */
+ } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides q-1 */
+
+ /* tmp1 = lcm(p-1, q-1) */
+ if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = p-1 */
+ /* tmp1 = q-1 (previous do/while loop) */
+ if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = lcm(p-1, q-1) */
+
+ /* make key */
+ if ((err = rsa_init(key)) != CRYPT_OK) {
+ goto errkey;
+ }
+
+ if ((err = mp_copy( e, key->e)) != CRYPT_OK) { goto errkey; } /* key->e = e */
+ if ((err = mp_invmod( key->e, tmp1, key->d)) != CRYPT_OK) { goto errkey; } /* key->d = 1/e mod lcm(p-1,q-1) */
+ if ((err = mp_mul( p, q, key->N)) != CRYPT_OK) { goto errkey; } /* key->N = pq */
+
+ /* optimize for CRT now */
+ /* find d mod q-1 and d mod p-1 */
+ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = p-1 */
+ if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = q-1 */
+ if ((err = mp_mod( key->d, tmp1, key->dP)) != CRYPT_OK) { goto errkey; } /* dP = d mod p-1 */
+ if ((err = mp_mod( key->d, tmp2, key->dQ)) != CRYPT_OK) { goto errkey; } /* dQ = d mod q-1 */
+ if ((err = mp_invmod( q, p, key->qP)) != CRYPT_OK) { goto errkey; } /* qP = 1/q mod p */
+
+ if ((err = mp_copy( p, key->p)) != CRYPT_OK) { goto errkey; }
+ if ((err = mp_copy( q, key->q)) != CRYPT_OK) { goto errkey; }
+
+ /* set key type (in this case it's CRT optimized) */
+ key->type = PK_PRIVATE;
+
+ /* return ok and free temps */
+ err = CRYPT_OK;
+ goto cleanup;
+errkey:
+ rsa_free(key);
+cleanup:
+ mp_clear_multi(tmp2, tmp1, q, p, LTC_NULL);
+ return err;
+}
+
+/**
+ Create an RSA key based on a long public exponent type
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param size The size of the modulus (key size) desired (octets)
+ @param e The "e" value (public key). e==65537 is a good choice
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful, upon error all allocated ram is freed
+*/
+int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
+{
+ void *tmp_e;
+ int err;
+
+ if ((e < 3) || ((e & 1) == 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = mp_init(&tmp_e)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_set_int(tmp_e, e)) == CRYPT_OK)
+ err = s_rsa_make_key(prng, wprng, size, tmp_e, key);
+
+ mp_clear(tmp_e);
+
+ return err;
+}
+
+/**
+ Create an RSA key based on a hexadecimal public exponent type
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param size The size of the modulus (key size) desired (octets)
+ @param e The "e" value (public key). e==65537 is a good choice
+ @param elen The length of e (octets)
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful, upon error all allocated ram is freed
+*/
+int rsa_make_key_ubin_e(prng_state *prng, int wprng, int size,
+ const unsigned char *e, unsigned long elen, rsa_key *key)
+{
+ int err;
+ void *tmp_e;
+
+ if ((err = mp_init(&tmp_e)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_read_unsigned_bin(tmp_e, (unsigned char *)e, elen)) == CRYPT_OK)
+ err = rsa_make_key_bn_e(prng, wprng, size, tmp_e, key);
+
+ mp_clear(tmp_e);
+
+ return err;
+}
+
+/**
+ Create an RSA key based on a bignumber public exponent type
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param size The size of the modulus (key size) desired (octets)
+ @param e The "e" value (public key). e==65537 is a good choice
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful, upon error all allocated ram is freed
+*/
+int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key)
+{
+ int err;
+ int e_bits;
+
+ e_bits = mp_count_bits(e);
+ if ((e_bits > 1 && e_bits < 256) && (mp_get_digit(e, 0) & 1)) {
+ err = s_rsa_make_key(prng, wprng, size, e, key);
+ } else {
+ err = CRYPT_INVALID_ARG;
+ }
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_set.c b/Sources/libtomcrypt/pk/rsa/rsa_set.c
new file mode 100644
index 00000000..d4dc6ed0
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_set.c
@@ -0,0 +1,123 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+
+#ifdef LTC_MRSA
+
+/**
+ Import RSA key from raw numbers
+
+ @param N RSA's N
+ @param Nlen RSA's N's length
+ @param e RSA's e
+ @param elen RSA's e's length
+ @param d RSA's d (only private key, NULL for public key)
+ @param dlen RSA's d's length
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful
+*/
+int rsa_set_key(const unsigned char *N, unsigned long Nlen,
+ const unsigned char *e, unsigned long elen,
+ const unsigned char *d, unsigned long dlen,
+ rsa_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(N != NULL);
+ LTC_ARGCHK(e != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ if ((err = rsa_init(key)) != CRYPT_OK) return err;
+
+ if ((err = mp_read_unsigned_bin(key->N , (unsigned char *)N , Nlen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->e , (unsigned char *)e , elen)) != CRYPT_OK) { goto LBL_ERR; }
+ if (d && dlen) {
+ if ((err = mp_read_unsigned_bin(key->d , (unsigned char *)d , dlen)) != CRYPT_OK) { goto LBL_ERR; }
+ key->type = PK_PRIVATE;
+ }
+ else {
+ key->type = PK_PUBLIC;
+ }
+ return CRYPT_OK;
+
+LBL_ERR:
+ rsa_free(key);
+ return err;
+}
+
+/**
+ Import factors of an RSA key from raw numbers
+
+ Only for private keys.
+
+ @param p RSA's p
+ @param plen RSA's p's length
+ @param q RSA's q
+ @param qlen RSA's q's length
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful
+*/
+int rsa_set_factors(const unsigned char *p, unsigned long plen,
+ const unsigned char *q, unsigned long qlen,
+ rsa_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(p != NULL);
+ LTC_ARGCHK(q != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
+
+ if ((err = mp_read_unsigned_bin(key->p , (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->q , (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; }
+ return CRYPT_OK;
+
+LBL_ERR:
+ rsa_free(key);
+ return err;
+}
+
+/**
+ Import CRT parameters of an RSA key from raw numbers
+
+ Only for private keys.
+
+ @param dP RSA's dP
+ @param dPlen RSA's dP's length
+ @param dQ RSA's dQ
+ @param dQlen RSA's dQ's length
+ @param qP RSA's qP
+ @param qPlen RSA's qP's length
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful
+*/
+int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen,
+ const unsigned char *dQ, unsigned long dQlen,
+ const unsigned char *qP, unsigned long qPlen,
+ rsa_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(dP != NULL);
+ LTC_ARGCHK(dQ != NULL);
+ LTC_ARGCHK(qP != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
+
+ if ((err = mp_read_unsigned_bin(key->dP, (unsigned char *)dP, dPlen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->dQ, (unsigned char *)dQ, dQlen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->qP, (unsigned char *)qP, qPlen)) != CRYPT_OK) { goto LBL_ERR; }
+ return CRYPT_OK;
+
+LBL_ERR:
+ rsa_free(key);
+ return err;
+}
+
+#endif /* LTC_MRSA */
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_sign_hash.c b/Sources/libtomcrypt/pk/rsa/rsa_sign_hash.c
new file mode 100644
index 00000000..aec30e2a
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_sign_hash.c
@@ -0,0 +1,136 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_sign_hash.c
+ RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ PKCS #1 pad then sign
+ @param in The hash to sign
+ @param inlen The length of the hash to sign (octets)
+ @param out [out] The signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1)
+ @param prng An active PRNG state
+ @param prng_idx The index of the PRNG desired
+ @param hash_idx The index of the hash desired
+ @param saltlen The length of the salt desired (octets)
+ @param key The private RSA key to use
+ @return CRYPT_OK if successful
+*/
+int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ int padding,
+ prng_state *prng, int prng_idx,
+ int hash_idx, unsigned long saltlen,
+ const rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x, y;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* valid padding? */
+ if ((padding != LTC_PKCS_1_V1_5) &&
+ (padding != LTC_PKCS_1_PSS) &&
+ (padding != LTC_PKCS_1_V1_5_NA1)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding == LTC_PKCS_1_PSS) {
+ /* valid prng ? */
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ if (padding != LTC_PKCS_1_V1_5_NA1) {
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits((key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size((key->N));
+ if (modulus_bytelen > *outlen) {
+ *outlen = modulus_bytelen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (padding == LTC_PKCS_1_PSS) {
+ /* PSS pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx,
+ hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ /* PKCS #1 v1.5 pad the hash */
+ unsigned char *tmpin;
+
+ if (padding == LTC_PKCS_1_V1_5) {
+ ltc_asn1_list digestinfo[2], siginfo[2];
+ /* not all hashes have OIDs... so sad */
+ if (hash_descriptor[hash_idx].OIDlen == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* construct the SEQUENCE
+ SEQUENCE {
+ SEQUENCE {hashoid OID
+ blah NULL
+ }
+ hash OCTET STRING
+ }
+ */
+ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen);
+ LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
+ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
+ LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen);
+
+ /* allocate memory for the encoding */
+ y = mp_unsigned_bin_size(key->N);
+ tmpin = XMALLOC(y);
+ if (tmpin == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) {
+ XFREE(tmpin);
+ return err;
+ }
+ } else {
+ /* set the pointer and data-length to the input values */
+ tmpin = (unsigned char *)in;
+ y = inlen;
+ }
+
+ x = *outlen;
+ err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x);
+
+ if (padding == LTC_PKCS_1_V1_5) {
+ XFREE(tmpin);
+ }
+
+ if (err != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* RSA encode it */
+ return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key);
+}
+
+#endif /* LTC_MRSA */
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_sign_saltlen_get.c b/Sources/libtomcrypt/pk/rsa/rsa_sign_saltlen_get.c
new file mode 100644
index 00000000..f1ae2638
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_sign_saltlen_get.c
@@ -0,0 +1,37 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_sign_saltlen_get.c
+ Retrieve the maximum size of the salt, Steffen Jaeckel.
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Retrieve the maximum possible size of the salt when creating a PKCS#1 PSS signature.
+ @param padding Type of padding (LTC_PKCS_1_PSS only)
+ @param hash_idx The index of the desired hash
+ @param key The RSA key
+ @return The maximum salt length in bytes or INT_MAX on error.
+*/
+int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key)
+{
+ int ret = INT_MAX;
+ LTC_ARGCHK(key != NULL);
+
+ if ((hash_is_valid(hash_idx) == CRYPT_OK) &&
+ (padding == LTC_PKCS_1_PSS))
+ {
+ ret = rsa_get_size(key);
+ if (ret < INT_MAX)
+ {
+ ret -= (hash_descriptor[hash_idx].hashsize + 2);
+ } /* if */
+ } /* if */
+
+ return ret;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/rsa/rsa_verify_hash.c b/Sources/libtomcrypt/pk/rsa/rsa_verify_hash.c
new file mode 100644
index 00000000..d946a202
--- /dev/null
+++ b/Sources/libtomcrypt/pk/rsa/rsa_verify_hash.c
@@ -0,0 +1,183 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_verify_hash.c
+ RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ PKCS #1 de-sign then v1.5 or PSS depad
+ @param sig The signature data
+ @param siglen The length of the signature data (octets)
+ @param hash The hash of the message that was signed
+ @param hashlen The length of the hash of the message that was signed (octets)
+ @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1)
+ @param hash_idx The index of the desired hash
+ @param saltlen The length of the salt used during signature
+ @param stat [out] The result of the signature comparison, 1==valid, 0==invalid
+ @param key The public RSA key corresponding to the key that performed the signature
+ @return CRYPT_OK on success (even if the signature is invalid)
+*/
+int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int padding,
+ int hash_idx, unsigned long saltlen,
+ int *stat, const rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+ unsigned char *tmpbuf;
+
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* valid padding? */
+
+ if ((padding != LTC_PKCS_1_V1_5) &&
+ (padding != LTC_PKCS_1_PSS) &&
+ (padding != LTC_PKCS_1_V1_5_NA1)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding != LTC_PKCS_1_V1_5_NA1) {
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (key->N));
+ if (modulus_bytelen != siglen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate temp buffer for decoded sig */
+ tmpbuf = XMALLOC(siglen);
+ if (tmpbuf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* RSA decode it */
+ x = siglen;
+ if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) {
+ XFREE(tmpbuf);
+ return err;
+ }
+
+ /* make sure the output is the right size */
+ if (x != siglen) {
+ XFREE(tmpbuf);
+ return CRYPT_INVALID_PACKET;
+ }
+
+ if (padding == LTC_PKCS_1_PSS) {
+ /* PSS decode and verify it */
+
+ if(modulus_bitlen%8 == 1){
+ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat);
+ }
+ else{
+ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
+ }
+
+ } else {
+ /* PKCS #1 v1.5 decode it */
+ unsigned char *out;
+ unsigned long outlen;
+ int decoded;
+
+ /* allocate temp buffer for decoded hash */
+ outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3;
+ out = XMALLOC(outlen);
+ if (out == NULL) {
+ err = CRYPT_MEM;
+ goto bail_2;
+ }
+
+ if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) {
+ XFREE(out);
+ goto bail_2;
+ }
+
+ if (padding == LTC_PKCS_1_V1_5) {
+ unsigned long loid[16], reallen;
+ ltc_asn1_list digestinfo[2], siginfo[2];
+
+ /* not all hashes have OIDs... so sad */
+ if (hash_descriptor[hash_idx].OIDlen == 0) {
+ err = CRYPT_INVALID_ARG;
+ goto bail_2;
+ }
+
+ /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */
+ /* construct the SEQUENCE
+ SEQUENCE {
+ SEQUENCE {hashoid OID
+ blah NULL
+ }
+ hash OCTET STRING
+ }
+ */
+ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0]));
+ LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
+ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
+ LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);
+
+ if (der_decode_sequence_strict(out, outlen, siginfo, 2) != CRYPT_OK) {
+ /* fallback to Legacy:missing NULL */
+ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1);
+ if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
+ XFREE(out);
+ goto bail_2;
+ }
+ }
+
+ if ((err = der_length_sequence(siginfo, 2, &reallen)) != CRYPT_OK) {
+ XFREE(out);
+ goto bail_2;
+ }
+
+ /* test OID */
+ if ((reallen == outlen) &&
+ (digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) &&
+ (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) &&
+ (siginfo[1].size == hashlen) &&
+ (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) {
+ *stat = 1;
+ }
+ } else {
+ /* only check if the hash is equal */
+ if ((hashlen == outlen) &&
+ (XMEMCMP(out, hash, hashlen) == 0)) {
+ *stat = 1;
+ }
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(out, outlen);
+#endif
+ XFREE(out);
+ }
+
+bail_2:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmpbuf, siglen);
+#endif
+ XFREE(tmpbuf);
+ return err;
+}
+
+#endif /* LTC_MRSA */
diff --git a/Sources/libtomcrypt/pk/x25519/x25519_export.c b/Sources/libtomcrypt/pk/x25519/x25519_export.c
new file mode 100644
index 00000000..fd997223
--- /dev/null
+++ b/Sources/libtomcrypt/pk/x25519/x25519_export.c
@@ -0,0 +1,31 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x25519_export.c
+ Export a X25519 key to a binary packet, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Export a X25519 key to a binary packet
+ @param out [out] The destination for the key
+ @param outlen [in/out] The max size and resulting size of the X25519 key
+ @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC)
+ @param key The key you wish to export
+ @return CRYPT_OK if successful
+*/
+int x25519_export( unsigned char *out, unsigned long *outlen,
+ int which,
+ const curve25519_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+
+ if (key->pka != LTC_PKA_X25519) return CRYPT_PK_INVALID_TYPE;
+
+ return ec25519_export(out, outlen, which, key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/x25519/x25519_import.c b/Sources/libtomcrypt/pk/x25519/x25519_import.c
new file mode 100644
index 00000000..a16c624d
--- /dev/null
+++ b/Sources/libtomcrypt/pk/x25519/x25519_import.c
@@ -0,0 +1,35 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x25519_import.c
+ Import a X25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Import a X25519 key
+ @param in The packet to read
+ @param inlen The length of the input packet
+ @param key [out] Where to import the key to
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key)
+{
+ int err;
+ unsigned long key_len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ key_len = sizeof(key->pub);
+ if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) {
+ key->type = PK_PUBLIC;
+ key->pka = LTC_PKA_X25519;
+ }
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/x25519/x25519_import_pkcs8.c b/Sources/libtomcrypt/pk/x25519/x25519_import_pkcs8.c
new file mode 100644
index 00000000..5c8e9b68
--- /dev/null
+++ b/Sources/libtomcrypt/pk/x25519/x25519_import_pkcs8.c
@@ -0,0 +1,32 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x25519_import_pkcs8.c
+ Import a X25519 key in PKCS#8 format, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+int x25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
+ curve25519_key *key)
+{
+ return ec25519_import_pkcs8_asn1(alg_id, priv_key, LTC_OID_X25519, key);
+}
+/**
+ Import a X25519 private key in PKCS#8 format
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param pw_ctx The password context when decrypting the private key
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const password_ctx *pw_ctx,
+ curve25519_key *key)
+{
+ return ec25519_import_pkcs8(in, inlen, pw_ctx, LTC_OID_X25519, key);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/x25519/x25519_import_raw.c b/Sources/libtomcrypt/pk/x25519/x25519_import_raw.c
new file mode 100644
index 00000000..da659201
--- /dev/null
+++ b/Sources/libtomcrypt/pk/x25519/x25519_import_raw.c
@@ -0,0 +1,41 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x25519_import_raw.c
+ Set the parameters of a X25519 key, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Set the parameters of a X25519 key
+
+ @param in The key
+ @param inlen The length of the key
+ @param which Which type of key (PK_PRIVATE or PK_PUBLIC)
+ @param key [out] Destination of the key
+ @return CRYPT_OK if successful
+*/
+int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key)
+{
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen == 32uL);
+ LTC_ARGCHK(key != NULL);
+
+ if (which == PK_PRIVATE) {
+ XMEMCPY(key->priv, in, sizeof(key->priv));
+ tweetnacl_crypto_scalarmult_base(key->pub, key->priv);
+ } else if (which == PK_PUBLIC) {
+ XMEMCPY(key->pub, in, sizeof(key->pub));
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+ key->pka = LTC_PKA_X25519;
+ key->type = which;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/x25519/x25519_import_x509.c b/Sources/libtomcrypt/pk/x25519/x25519_import_x509.c
new file mode 100644
index 00000000..a3d90cdc
--- /dev/null
+++ b/Sources/libtomcrypt/pk/x25519/x25519_import_x509.c
@@ -0,0 +1,45 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x25519_import_x509.c
+ Import a X25519 key from a X.509 certificate, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+static int s_x25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key)
+{
+ if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE;
+ XMEMCPY(key->pub, in, sizeof(key->pub));
+ return CRYPT_OK;
+}
+
+/**
+ Import a X25519 public key from a X.509 certificate
+ @param in The DER encoded X.509 certificate
+ @param inlen The length of the certificate
+ @param key [out] Where to import the key to
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((err = x509_decode_public_key_from_certificate(in, inlen,
+ LTC_OID_X25519,
+ LTC_ASN1_EOL, NULL, NULL,
+ (public_key_decode_cb)s_x25519_decode, key)) != CRYPT_OK) {
+ return err;
+ }
+ key->type = PK_PUBLIC;
+ key->pka = LTC_PKA_X25519;
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/x25519/x25519_make_key.c b/Sources/libtomcrypt/pk/x25519/x25519_make_key.c
new file mode 100644
index 00000000..a30003cc
--- /dev/null
+++ b/Sources/libtomcrypt/pk/x25519/x25519_make_key.c
@@ -0,0 +1,42 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x25519_make_key.c
+ Create a X25519 key, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Create a X25519 key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful
+*/
+int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (prng_descriptor[wprng].read(key->priv, sizeof(key->priv), prng) != sizeof(key->priv)) {
+ return CRYPT_ERROR_READPRNG;
+ }
+
+ tweetnacl_crypto_scalarmult_base(key->pub, key->priv);
+
+ key->type = PK_PRIVATE;
+ key->pka = LTC_PKA_X25519;
+
+ return err;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/pk/x25519/x25519_shared_secret.c b/Sources/libtomcrypt/pk/x25519/x25519_shared_secret.c
new file mode 100644
index 00000000..d7e9ea8c
--- /dev/null
+++ b/Sources/libtomcrypt/pk/x25519/x25519_shared_secret.c
@@ -0,0 +1,43 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file x25519_shared_secret.c
+ Create a X25519 shared secret, Steffen Jaeckel
+*/
+
+#ifdef LTC_CURVE25519
+
+/**
+ Create a X25519 shared secret.
+ @param private_key The private X25519 key in the pair
+ @param public_key The public X25519 key in the pair
+ @param out [out] The destination of the shared data
+ @param outlen [in/out] The max size and resulting size of the shared data.
+ @return CRYPT_OK if successful
+*/
+int x25519_shared_secret(const curve25519_key *private_key,
+ const curve25519_key *public_key,
+ unsigned char *out, unsigned long *outlen)
+{
+ LTC_ARGCHK(private_key != NULL);
+ LTC_ARGCHK(public_key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (public_key->pka != LTC_PKA_X25519) return CRYPT_PK_INVALID_TYPE;
+ if (private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE;
+
+ if (*outlen < 32uL) {
+ *outlen = 32uL;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ tweetnacl_crypto_scalarmult(out, private_key->priv, public_key->pub);
+ *outlen = 32uL;
+
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/prngs/chacha20.c b/Sources/libtomcrypt/prngs/chacha20.c
new file mode 100644
index 00000000..d9bd7b07
--- /dev/null
+++ b/Sources/libtomcrypt/prngs/chacha20.c
@@ -0,0 +1,218 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+ /* the idea of re-keying loosely follows the approach used in:
+ * http://bxr.su/OpenBSD/lib/libc/crypt/arc4random.c
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA20_PRNG
+
+const struct ltc_prng_descriptor chacha20_prng_desc =
+{
+ "chacha20",
+ 40,
+ &chacha20_prng_start,
+ &chacha20_prng_add_entropy,
+ &chacha20_prng_ready,
+ &chacha20_prng_read,
+ &chacha20_prng_done,
+ &chacha20_prng_export,
+ &chacha20_prng_import,
+ &chacha20_prng_test
+};
+
+/**
+ Start the PRNG
+ @param prng The PRNG state to initialize
+ @return CRYPT_OK if successful
+*/
+int chacha20_prng_start(prng_state *prng)
+{
+ LTC_ARGCHK(prng != NULL);
+ prng->ready = 0;
+ XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent));
+ prng->u.chacha.idx = 0;
+ LTC_MUTEX_INIT(&prng->lock)
+ return CRYPT_OK;
+}
+
+/**
+ Add entropy to the PRNG state
+ @param in The data to add
+ @param inlen Length of the data to add
+ @param prng PRNG state to update
+ @return CRYPT_OK if successful
+*/
+int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ unsigned char buf[40];
+ unsigned long i;
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen > 0);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ if (prng->ready) {
+ /* chacha20_prng_ready() was already called, do "rekey" operation */
+ if ((err = chacha_keystream(&prng->u.chacha.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK;
+ for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i];
+ /* key 32 bytes, 20 rounds */
+ if ((err = chacha_setup(&prng->u.chacha.s, buf, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK;
+ /* iv 8 bytes */
+ if ((err = chacha_ivctr64(&prng->u.chacha.s, buf + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK;
+ /* clear KEY + IV */
+ zeromem(buf, sizeof(buf));
+ }
+ else {
+ /* chacha20_prng_ready() was not called yet, add entropy to ent buffer */
+ while (inlen--) prng->u.chacha.ent[prng->u.chacha.idx++ % sizeof(prng->u.chacha.ent)] ^= *in++;
+ }
+ err = CRYPT_OK;
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return err;
+}
+
+/**
+ Make the PRNG ready to read from
+ @param prng The PRNG to make active
+ @return CRYPT_OK if successful
+*/
+int chacha20_prng_ready(prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; }
+ /* key 32 bytes, 20 rounds */
+ if ((err = chacha_setup(&prng->u.chacha.s, prng->u.chacha.ent, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK;
+ /* iv 8 bytes */
+ if ((err = chacha_ivctr64(&prng->u.chacha.s, prng->u.chacha.ent + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK;
+ XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent));
+ prng->u.chacha.idx = 0;
+ prng->ready = 1;
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return err;
+}
+
+/**
+ Read from the PRNG
+ @param out Destination
+ @param outlen Length of output
+ @param prng The active PRNG to read from
+ @return Number of octets read
+*/
+unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng)
+{
+ if (outlen == 0 || prng == NULL || out == NULL) return 0;
+ LTC_MUTEX_LOCK(&prng->lock);
+ if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; }
+ if (chacha_keystream(&prng->u.chacha.s, out, outlen) != CRYPT_OK) outlen = 0;
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return outlen;
+}
+
+/**
+ Terminate the PRNG
+ @param prng The PRNG to terminate
+ @return CRYPT_OK if successful
+*/
+int chacha20_prng_done(prng_state *prng)
+{
+ int err;
+ LTC_ARGCHK(prng != NULL);
+ LTC_MUTEX_LOCK(&prng->lock);
+ prng->ready = 0;
+ err = chacha_done(&prng->u.chacha.s);
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ LTC_MUTEX_DESTROY(&prng->lock);
+ return err;
+}
+
+/**
+ Export the PRNG state
+ @param out [out] Destination
+ @param outlen [in/out] Max size and resulting size of the state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+*/
+LTC_PRNG_EXPORT(chacha20_prng)
+
+/**
+ Import a PRNG state
+ @param in The PRNG state
+ @param inlen Size of the state
+ @param prng The PRNG to import
+ @return CRYPT_OK if successful
+*/
+int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ if (inlen < (unsigned long)chacha20_prng_desc.export_size) return CRYPT_INVALID_ARG;
+
+ if ((err = chacha20_prng_start(prng)) != CRYPT_OK) return err;
+ if ((err = chacha20_prng_add_entropy(in, inlen, prng)) != CRYPT_OK) return err;
+ return CRYPT_OK;
+}
+
+/**
+ PRNG self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+*/
+int chacha20_prng_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ prng_state st;
+ unsigned char en[] = { 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, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 };
+ unsigned char dmp[300];
+ unsigned long dmplen = sizeof(dmp);
+ unsigned char out[500];
+ unsigned char t1[] = { 0x59, 0xB2, 0x26, 0x95, 0x2B, 0x01, 0x8F, 0x05, 0xBE, 0xD8 };
+ unsigned char t2[] = { 0x47, 0xC9, 0x0D, 0x03, 0xE4, 0x75, 0x34, 0x27, 0xBD, 0xDE };
+ unsigned char t3[] = { 0xBC, 0xFA, 0xEF, 0x59, 0x37, 0x7F, 0x1A, 0x91, 0x1A, 0xA6 };
+ int err;
+
+ if ((err = chacha20_prng_start(&st)) != CRYPT_OK) return err;
+ /* add entropy to uninitialized prng */
+ if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err;
+ if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err;
+ if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */
+ if (compare_testvector(out, 10, t1, sizeof(t1), "CHACHA-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR;
+ if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ /* add entropy to already initialized prng */
+ if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err;
+ if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if ((err = chacha20_prng_export(dmp, &dmplen, &st)) != CRYPT_OK) return err;
+ if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */
+ if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR;
+ if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err;
+ if ((err = chacha20_prng_import(dmp, dmplen, &st)) != CRYPT_OK) return err;
+ if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err;
+ if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */
+ if (compare_testvector(out, 10, t3, sizeof(t3), "CHACHA-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR;
+ if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err;
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/prngs/fortuna.c b/Sources/libtomcrypt/prngs/fortuna.c
new file mode 100644
index 00000000..9c92595e
--- /dev/null
+++ b/Sources/libtomcrypt/prngs/fortuna.c
@@ -0,0 +1,532 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED
+#if defined(_WIN32)
+ #include
+#elif defined(LTC_CLOCK_GETTIME)
+ #include /* struct timespec + clock_gettime */
+#else
+ #include /* struct timeval + gettimeofday */
+#endif
+#endif
+
+/**
+ @file fortuna.c
+ Fortuna PRNG, Tom St Denis
+*/
+
+/* Implementation of Fortuna by Tom St Denis
+
+We deviate slightly here for reasons of simplicity [and to fit in the API]. First all "sources"
+in the AddEntropy function are fixed to 0. Second since no reliable timer is provided
+we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to the read function */
+
+#ifdef LTC_FORTUNA
+
+/* requries LTC_SHA256 and AES */
+#if !(defined(LTC_RIJNDAEL) && defined(LTC_SHA256))
+ #error LTC_FORTUNA requires LTC_SHA256 and LTC_RIJNDAEL (AES)
+#endif
+
+#ifndef LTC_FORTUNA_POOLS
+ #warning LTC_FORTUNA_POOLS was not previously defined (old headers?)
+ #define LTC_FORTUNA_POOLS 32
+#endif
+
+#if LTC_FORTUNA_POOLS < 4 || LTC_FORTUNA_POOLS > 32
+ #error LTC_FORTUNA_POOLS must be in [4..32]
+#endif
+
+#ifdef LTC_FORTUNA_USE_ENCRYPT_ONLY
+#define AES_SETUP aes_enc_setup
+#define AES_ENC aes_enc_ecb_encrypt
+#define AES_DONE aes_enc_done
+#define AES_TEST aes_enc_test
+#else
+#define AES_SETUP aes_setup
+#define AES_ENC aes_ecb_encrypt
+#define AES_DONE aes_done
+#define AES_TEST aes_test
+#endif
+
+const struct ltc_prng_descriptor fortuna_desc = {
+ "fortuna",
+ 64,
+ &fortuna_start,
+ &fortuna_add_entropy,
+ &fortuna_ready,
+ &fortuna_read,
+ &fortuna_done,
+ &fortuna_export,
+ &fortuna_import,
+ &fortuna_test
+};
+
+/* update the IV */
+static void s_fortuna_update_iv(prng_state *prng)
+{
+ int x;
+ unsigned char *IV;
+ /* update IV */
+ IV = prng->u.fortuna.IV;
+ for (x = 0; x < 16; x++) {
+ IV[x] = (IV[x] + 1) & 255;
+ if (IV[x] != 0) break;
+ }
+}
+
+#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED
+/* get the current time in 100ms steps */
+static ulong64 s_fortuna_current_time(void)
+{
+ ulong64 cur_time;
+#if defined(_WIN32)
+ FILETIME CurrentTime;
+ ULARGE_INTEGER ul;
+ GetSystemTimeAsFileTime(&CurrentTime);
+ ul.LowPart = CurrentTime.dwLowDateTime;
+ ul.HighPart = CurrentTime.dwHighDateTime;
+ cur_time = ul.QuadPart; /* now we have 100ns intervals since 1 January 1601 */
+ cur_time -= CONST64(116444736000000000); /* subtract 100ns intervals between 1601-1970 */
+ cur_time /= 10; /* 100ns intervals > microseconds */
+#elif defined(LTC_CLOCK_GETTIME)
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ cur_time = (ulong64)(ts.tv_sec) * 1000000 + (ulong64)(ts.tv_nsec) / 1000; /* get microseconds */
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ cur_time = (ulong64)(tv.tv_sec) * 1000000 + (ulong64)(tv.tv_usec); /* get microseconds */
+#endif
+ return cur_time / 100;
+}
+#endif
+
+/* reseed the PRNG */
+static int s_fortuna_reseed(prng_state *prng)
+{
+ unsigned char tmp[MAXBLOCKSIZE];
+ hash_state md;
+ ulong64 reset_cnt;
+ int err, x;
+
+#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED
+ ulong64 now = s_fortuna_current_time();
+ if (now == prng->u.fortuna.wd) {
+ return CRYPT_OK;
+ }
+#else
+ if (++prng->u.fortuna.wd < LTC_FORTUNA_WD) {
+ return CRYPT_OK;
+ }
+#endif
+
+ /* new K == LTC_SHA256(K || s) where s == LTC_SHA256(P0) || LTC_SHA256(P1) ... */
+ sha256_init(&md);
+ if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) {
+ sha256_done(&md, tmp);
+ return err;
+ }
+
+ reset_cnt = prng->u.fortuna.reset_cnt + 1;
+
+ for (x = 0; x < LTC_FORTUNA_POOLS; x++) {
+ if (x == 0 || ((reset_cnt >> (x-1)) & 1) == 0) {
+ /* terminate this hash */
+ if ((err = sha256_done(&prng->u.fortuna.pool[x], tmp)) != CRYPT_OK) {
+ sha256_done(&md, tmp);
+ return err;
+ }
+ /* add it to the string */
+ if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) {
+ sha256_done(&md, tmp);
+ return err;
+ }
+ /* reset this pool */
+ if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) {
+ sha256_done(&md, tmp);
+ return err;
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* finish key */
+ if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) {
+ return err;
+ }
+ s_fortuna_update_iv(prng);
+
+ /* reset/update internals */
+ prng->u.fortuna.pool0_len = 0;
+#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED
+ prng->u.fortuna.wd = now;
+#else
+ prng->u.fortuna.wd = 0;
+#endif
+ prng->u.fortuna.reset_cnt = reset_cnt;
+
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(&md, sizeof(md));
+ zeromem(tmp, sizeof(tmp));
+#endif
+
+ return CRYPT_OK;
+}
+
+/**
+ "Update Seed File"-compliant update of K
+
+ @param in The PRNG state
+ @param inlen Size of the state
+ @param prng The PRNG to import
+ @return CRYPT_OK if successful
+*/
+int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ int err;
+ unsigned char tmp[MAXBLOCKSIZE];
+ hash_state md;
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ /* new K = LTC_SHA256(K || in) */
+ sha256_init(&md);
+ if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) {
+ sha256_done(&md, tmp);
+ goto LBL_UNLOCK;
+ }
+ if ((err = sha256_process(&md, in, inlen)) != CRYPT_OK) {
+ sha256_done(&md, tmp);
+ goto LBL_UNLOCK;
+ }
+ /* finish key */
+ if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+ s_fortuna_update_iv(prng);
+
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+#ifdef LTC_CLEAN_STACK
+ zeromem(&md, sizeof(md));
+#endif
+
+ return err;
+}
+
+/**
+ Start the PRNG
+ @param prng [out] The PRNG state to initialize
+ @return CRYPT_OK if successful
+*/
+int fortuna_start(prng_state *prng)
+{
+ int err, x, y;
+ unsigned char tmp[MAXBLOCKSIZE];
+
+ LTC_ARGCHK(prng != NULL);
+ prng->ready = 0;
+
+ /* initialize the pools */
+ for (x = 0; x < LTC_FORTUNA_POOLS; x++) {
+ if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) {
+ for (y = 0; y < x; y++) {
+ sha256_done(&prng->u.fortuna.pool[y], tmp);
+ }
+ return err;
+ }
+ }
+ prng->u.fortuna.pool_idx = prng->u.fortuna.pool0_len = 0;
+ prng->u.fortuna.reset_cnt = prng->u.fortuna.wd = 0;
+
+ /* reset bufs */
+ zeromem(prng->u.fortuna.K, 32);
+ if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) {
+ for (x = 0; x < LTC_FORTUNA_POOLS; x++) {
+ sha256_done(&prng->u.fortuna.pool[x], tmp);
+ }
+ return err;
+ }
+ zeromem(prng->u.fortuna.IV, 16);
+
+ LTC_MUTEX_INIT(&prng->lock)
+
+ return CRYPT_OK;
+}
+
+static int s_fortuna_add(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ unsigned char tmp[2];
+ int err;
+
+ /* ensure inlen <= 32 */
+ if (inlen > 32) {
+ inlen = 32;
+ }
+
+ /* add s || length(in) || in to pool[pool_idx] */
+ tmp[0] = (unsigned char)source;
+ tmp[1] = (unsigned char)inlen;
+
+ if ((err = sha256_process(&prng->u.fortuna.pool[pool], tmp, 2)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = sha256_process(&prng->u.fortuna.pool[pool], in, inlen)) != CRYPT_OK) {
+ return err;
+ }
+ if (pool == 0) {
+ prng->u.fortuna.pool0_len += inlen;
+ }
+ return CRYPT_OK; /* success */
+}
+
+/**
+ Add random event to the PRNG state as proposed by the original paper.
+ @param source The source this random event comes from (0 .. 255)
+ @param pool The pool where to add the data to (0 .. LTC_FORTUNA_POOLS)
+ @param in The data to add
+ @param inlen Length of the data to add
+ @param prng PRNG state to update
+ @return CRYPT_OK if successful
+*/
+int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen > 0);
+ LTC_ARGCHK(source <= 255);
+ LTC_ARGCHK(pool < LTC_FORTUNA_POOLS);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+
+ err = s_fortuna_add(source, pool, in, inlen, prng);
+
+ LTC_MUTEX_UNLOCK(&prng->lock);
+
+ return err;
+}
+
+/**
+ Add entropy to the PRNG state
+ @param in The data to add
+ @param inlen Length of the data to add
+ @param prng PRNG state to update
+ @return CRYPT_OK if successful
+*/
+int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen > 0);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+
+ err = s_fortuna_add(0, prng->u.fortuna.pool_idx, in, inlen, prng);
+
+ if (err == CRYPT_OK) {
+ ++(prng->u.fortuna.pool_idx);
+ prng->u.fortuna.pool_idx %= LTC_FORTUNA_POOLS;
+ }
+
+ LTC_MUTEX_UNLOCK(&prng->lock);
+
+ return err;
+}
+
+/**
+ Make the PRNG ready to read from
+ @param prng The PRNG to make active
+ @return CRYPT_OK if successful
+*/
+int fortuna_ready(prng_state *prng)
+{
+ int err;
+ LTC_ARGCHK(prng != NULL);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ /* make sure the reseed doesn't fail because
+ * of the chosen rate limit */
+#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED
+ prng->u.fortuna.wd = s_fortuna_current_time() - 1;
+#else
+ prng->u.fortuna.wd = LTC_FORTUNA_WD;
+#endif
+ err = s_fortuna_reseed(prng);
+ prng->ready = (err == CRYPT_OK) ? 1 : 0;
+
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return err;
+}
+
+/**
+ Read from the PRNG
+ @param out Destination
+ @param outlen Length of output
+ @param prng The active PRNG to read from
+ @return Number of octets read
+*/
+unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng)
+{
+ unsigned char tmp[16];
+ unsigned long tlen = 0;
+
+ if (outlen == 0 || prng == NULL || out == NULL) return 0;
+
+ LTC_MUTEX_LOCK(&prng->lock);
+
+ if (!prng->ready) {
+ goto LBL_UNLOCK;
+ }
+
+ /* do we have to reseed? */
+ if (prng->u.fortuna.pool0_len >= 64) {
+ if (s_fortuna_reseed(prng) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+ }
+
+ /* ensure that one reseed happened before allowing to read */
+ if (prng->u.fortuna.reset_cnt == 0) {
+ goto LBL_UNLOCK;
+ }
+
+ /* now generate the blocks required */
+ tlen = outlen;
+
+ /* handle whole blocks without the extra XMEMCPY */
+ while (outlen >= 16) {
+ /* encrypt the IV and store it */
+ AES_ENC(prng->u.fortuna.IV, out, &prng->u.fortuna.skey);
+ out += 16;
+ outlen -= 16;
+ s_fortuna_update_iv(prng);
+ }
+
+ /* left over bytes? */
+ if (outlen > 0) {
+ AES_ENC(prng->u.fortuna.IV, tmp, &prng->u.fortuna.skey);
+ XMEMCPY(out, tmp, outlen);
+ s_fortuna_update_iv(prng);
+ }
+
+ /* generate new key */
+ AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K , &prng->u.fortuna.skey);
+ s_fortuna_update_iv(prng);
+
+ AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K+16, &prng->u.fortuna.skey);
+ s_fortuna_update_iv(prng);
+
+ if (AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey) != CRYPT_OK) {
+ tlen = 0;
+ }
+
+LBL_UNLOCK:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmp, sizeof(tmp));
+#endif
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return tlen;
+}
+
+/**
+ Terminate the PRNG
+ @param prng The PRNG to terminate
+ @return CRYPT_OK if successful
+*/
+int fortuna_done(prng_state *prng)
+{
+ int err, x;
+ unsigned char tmp[32];
+
+ LTC_ARGCHK(prng != NULL);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ prng->ready = 0;
+
+ /* terminate all the hashes */
+ for (x = 0; x < LTC_FORTUNA_POOLS; x++) {
+ if ((err = sha256_done(&(prng->u.fortuna.pool[x]), tmp)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+ }
+ /* call cipher done when we invent one ;-) */
+ err = CRYPT_OK; /* success */
+
+LBL_UNLOCK:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmp, sizeof(tmp));
+#endif
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ LTC_MUTEX_DESTROY(&prng->lock);
+ return err;
+}
+
+/**
+ Export the PRNG state
+ @param out [out] Destination
+ @param outlen [in/out] Max size and resulting size of the state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+*/
+LTC_PRNG_EXPORT(fortuna)
+
+/**
+ Import a PRNG state
+ @param in The PRNG state
+ @param inlen Size of the state
+ @param prng The PRNG to import
+ @return CRYPT_OK if successful
+*/
+int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(prng != NULL);
+
+ if (inlen < (unsigned long)fortuna_desc.export_size) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = fortuna_start(prng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = fortuna_update_seed(in, inlen, prng)) != CRYPT_OK) {
+ return err;
+ }
+
+ return err;
+}
+
+/**
+ PRNG self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+*/
+int fortuna_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ int err;
+
+ if ((err = sha256_test()) != CRYPT_OK) {
+ return err;
+ }
+ return AES_TEST();
+#endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/prngs/rc4.c b/Sources/libtomcrypt/prngs/rc4.c
new file mode 100644
index 00000000..edcd73f7
--- /dev/null
+++ b/Sources/libtomcrypt/prngs/rc4.c
@@ -0,0 +1,221 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file prngs/rc4.c
+ RC4 PRNG, Tom St Denis
+*/
+
+#ifdef LTC_RC4
+
+const struct ltc_prng_descriptor rc4_desc =
+{
+ "rc4",
+ 32,
+ &rc4_start,
+ &rc4_add_entropy,
+ &rc4_ready,
+ &rc4_read,
+ &rc4_done,
+ &rc4_export,
+ &rc4_import,
+ &rc4_test
+};
+
+/**
+ Start the PRNG
+ @param prng [out] The PRNG state to initialize
+ @return CRYPT_OK if successful
+*/
+int rc4_start(prng_state *prng)
+{
+ LTC_ARGCHK(prng != NULL);
+ prng->ready = 0;
+ /* set entropy (key) size to zero */
+ prng->u.rc4.s.x = 0;
+ /* clear entropy (key) buffer */
+ XMEMSET(&prng->u.rc4.s.buf, 0, sizeof(prng->u.rc4.s.buf));
+ LTC_MUTEX_INIT(&prng->lock)
+ return CRYPT_OK;
+}
+
+/**
+ Add entropy to the PRNG state
+ @param in The data to add
+ @param inlen Length of the data to add
+ @param prng PRNG state to update
+ @return CRYPT_OK if successful
+*/
+int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ unsigned char buf[256];
+ unsigned long i;
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen > 0);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ if (prng->ready) {
+ /* rc4_ready() was already called, do "rekey" operation */
+ if ((err = rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK;
+ for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i];
+ /* initialize RC4 */
+ if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK;
+ /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */
+ for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf));
+ zeromem(buf, sizeof(buf));
+ }
+ else {
+ /* rc4_ready() was not called yet, add entropy to the buffer */
+ while (inlen--) prng->u.rc4.s.buf[prng->u.rc4.s.x++ % sizeof(prng->u.rc4.s.buf)] ^= *in++;
+ }
+ err = CRYPT_OK;
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return err;
+}
+
+/**
+ Make the PRNG ready to read from
+ @param prng The PRNG to make active
+ @return CRYPT_OK if successful
+*/
+int rc4_ready(prng_state *prng)
+{
+ unsigned char buf[256] = { 0 };
+ unsigned long len;
+ int err, i;
+
+ LTC_ARGCHK(prng != NULL);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; }
+ XMEMCPY(buf, prng->u.rc4.s.buf, sizeof(buf));
+ /* initialize RC4 */
+ len = MIN(prng->u.rc4.s.x, 256); /* TODO: we can perhaps always use all 256 bytes */
+ if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, len)) != CRYPT_OK) goto LBL_UNLOCK;
+ /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */
+ for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf));
+ prng->ready = 1;
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return err;
+}
+
+/**
+ Read from the PRNG
+ @param out Destination
+ @param outlen Length of output
+ @param prng The active PRNG to read from
+ @return Number of octets read
+*/
+unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng)
+{
+ if (outlen == 0 || prng == NULL || out == NULL) return 0;
+ LTC_MUTEX_LOCK(&prng->lock);
+ if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; }
+ if (rc4_stream_keystream(&prng->u.rc4.s, out, outlen) != CRYPT_OK) outlen = 0;
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return outlen;
+}
+
+/**
+ Terminate the PRNG
+ @param prng The PRNG to terminate
+ @return CRYPT_OK if successful
+*/
+int rc4_done(prng_state *prng)
+{
+ int err;
+ LTC_ARGCHK(prng != NULL);
+ LTC_MUTEX_LOCK(&prng->lock);
+ prng->ready = 0;
+ err = rc4_stream_done(&prng->u.rc4.s);
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ LTC_MUTEX_DESTROY(&prng->lock);
+ return err;
+}
+
+/**
+ Export the PRNG state
+ @param out [out] Destination
+ @param outlen [in/out] Max size and resulting size of the state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+*/
+LTC_PRNG_EXPORT(rc4)
+
+/**
+ Import a PRNG state
+ @param in The PRNG state
+ @param inlen Size of the state
+ @param prng The PRNG to import
+ @return CRYPT_OK if successful
+*/
+int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ if (inlen < (unsigned long)rc4_desc.export_size) return CRYPT_INVALID_ARG;
+
+ if ((err = rc4_start(prng)) != CRYPT_OK) return err;
+ if ((err = rc4_add_entropy(in, inlen, prng)) != CRYPT_OK) return err;
+ return CRYPT_OK;
+}
+
+/**
+ PRNG self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+*/
+int rc4_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ prng_state st;
+ unsigned char en[] = { 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, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 };
+ unsigned char dmp[500];
+ unsigned long dmplen = sizeof(dmp);
+ unsigned char out[1000];
+ unsigned char t1[] = { 0xE0, 0x4D, 0x9A, 0xF6, 0xA8, 0x9D, 0x77, 0x53, 0xAE, 0x09 };
+ unsigned char t2[] = { 0xEF, 0x80, 0xA2, 0xE6, 0x50, 0x91, 0xF3, 0x17, 0x4A, 0x8A };
+ unsigned char t3[] = { 0x4B, 0xD6, 0x5C, 0x67, 0x99, 0x03, 0x56, 0x12, 0x80, 0x48 };
+ int err;
+
+ if ((err = rc4_start(&st)) != CRYPT_OK) return err;
+ /* add entropy to uninitialized prng */
+ if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err;
+ if ((err = rc4_ready(&st)) != CRYPT_OK) return err;
+ if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */
+ if (compare_testvector(out, 10, t1, sizeof(t1), "RC4-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR;
+ if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ /* add entropy to already initialized prng */
+ if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err;
+ if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if ((err = rc4_export(dmp, &dmplen, &st)) != CRYPT_OK) return err;
+ if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */
+ if (compare_testvector(out, 10, t2, sizeof(t2), "RC4-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR;
+ if ((err = rc4_done(&st)) != CRYPT_OK) return err;
+ if ((err = rc4_import(dmp, dmplen, &st)) != CRYPT_OK) return err;
+ if ((err = rc4_ready(&st)) != CRYPT_OK) return err;
+ if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */
+ if (compare_testvector(out, 10, t3, sizeof(t3), "RC4-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR;
+ if ((err = rc4_done(&st)) != CRYPT_OK) return err;
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/prngs/rng_get_bytes.c b/Sources/libtomcrypt/prngs/rng_get_bytes.c
new file mode 100644
index 00000000..ecb1ed56
--- /dev/null
+++ b/Sources/libtomcrypt/prngs/rng_get_bytes.c
@@ -0,0 +1,167 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RNG_GET_BYTES
+/**
+ @file rng_get_bytes.c
+ portable way to get secure random bits to feed a PRNG (Tom St Denis)
+*/
+
+#if defined(LTC_DEVRANDOM) && !defined(_WIN32)
+/* on *NIX read /dev/random */
+static unsigned long s_rng_nix(unsigned char *buf, unsigned long len,
+ void (*callback)(void))
+{
+#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(callback);
+ LTC_UNUSED_PARAM(buf);
+ LTC_UNUSED_PARAM(len);
+ return 0;
+#else
+ FILE *f;
+ unsigned long x;
+ LTC_UNUSED_PARAM(callback);
+#ifdef LTC_TRY_URANDOM_FIRST
+ f = fopen("/dev/urandom", "rb");
+ if (f == NULL) {
+ f = fopen("/dev/random", "rb");
+ }
+#else
+ f = fopen("/dev/random", "rb");
+#endif /* LTC_TRY_URANDOM_FIRST */
+
+ if (f == NULL) {
+ return 0;
+ }
+
+ /* disable buffering */
+ if (setvbuf(f, NULL, _IONBF, 0) != 0) {
+ fclose(f);
+ return 0;
+ }
+
+ x = (unsigned long)fread(buf, 1, (size_t)len, f);
+ fclose(f);
+ return x;
+#endif /* LTC_NO_FILE */
+}
+
+#endif /* LTC_DEVRANDOM */
+
+#if !defined(_WIN32_WCE)
+
+#define ANSI_RNG
+
+static unsigned long s_rng_ansic(unsigned char *buf, unsigned long len,
+ void (*callback)(void))
+{
+ clock_t t1;
+ int l, acc, bits, a, b;
+
+ l = len;
+ bits = 8;
+ acc = a = b = 0;
+ while (len--) {
+ if (callback != NULL) callback();
+ while (bits--) {
+ do {
+ t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
+ t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
+ } while (a == b);
+ acc = (acc << 1) | a;
+ }
+ *buf++ = acc;
+ acc = 0;
+ bits = 8;
+ }
+ return l;
+}
+
+#endif
+
+/* Try the Microsoft CSP */
+#if defined(_WIN32) || defined(_WIN32_WCE)
+#if defined(LTC_WIN32_BCRYPT)
+
+#include
+#include
+#pragma comment(lib, "bcrypt.lib")
+
+static unsigned long s_rng_win32(unsigned char *buf, unsigned long len,
+ void (*callback)(void))
+{
+ LTC_UNUSED_PARAM(callback);
+
+ return BCRYPT_SUCCESS(BCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG)) ? len : 0;
+}
+
+#else
+
+#ifndef _WIN32_WINNT
+ #define _WIN32_WINNT 0x0501
+#endif
+#ifndef WINVER
+ #define WINVER 0x0501
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+
+static unsigned long s_rng_win32(unsigned char *buf, unsigned long len,
+ void (*callback)(void))
+{
+ static HCRYPTPROV hProv = 0;
+ LTC_UNUSED_PARAM(callback);
+
+ if (hProv == 0) {
+ HCRYPTPROV h = 0;
+ if (!CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL,
+ (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
+ !CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) {
+ return 0;
+ }
+ hProv = h;
+ }
+
+ return CryptGenRandom(hProv, (DWORD)len, (BYTE *)buf) == TRUE ? len : 0;
+}
+#endif /* Old WIN32 versions */
+#endif /* WIN32 */
+
+/**
+ Read the system RNG
+ @param out Destination
+ @param outlen Length desired (octets)
+ @param callback Pointer to void function to act as "callback" when RNG is slow. This can be NULL
+ @return Number of octets read
+*/
+unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen,
+ void (*callback)(void))
+{
+ unsigned long x;
+
+ LTC_ARGCHK(out != NULL);
+
+#ifdef LTC_PRNG_ENABLE_LTC_RNG
+ if (ltc_rng) {
+ x = ltc_rng(out, outlen, callback);
+ if (x != 0) {
+ return x;
+ }
+ }
+#endif
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ x = s_rng_win32(out, outlen, callback); if (x != 0) { return x; }
+#elif defined(LTC_DEVRANDOM)
+ x = s_rng_nix(out, outlen, callback); if (x != 0) { return x; }
+#endif
+#ifdef ANSI_RNG
+ x = s_rng_ansic(out, outlen, callback); if (x != 0) { return x; }
+#endif
+ return 0;
+}
+#endif /* #ifdef LTC_RNG_GET_BYTES */
diff --git a/Sources/libtomcrypt/prngs/rng_make_prng.c b/Sources/libtomcrypt/prngs/rng_make_prng.c
new file mode 100644
index 00000000..a7b726ca
--- /dev/null
+++ b/Sources/libtomcrypt/prngs/rng_make_prng.c
@@ -0,0 +1,81 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RNG_MAKE_PRNG
+/**
+ @file rng_make_prng.c
+ portable way to get secure random bits to feed a PRNG (Tom St Denis)
+*/
+
+/**
+ Create a PRNG from a RNG
+
+ In case you pass bits as '-1' the PRNG will be setup
+ as if the export/import functionality has been used,
+ but the imported data comes directly from the RNG.
+
+ @param bits Number of bits of entropy desired (-1 or 64 ... 1024)
+ @param wprng Index of which PRNG to setup
+ @param prng [out] PRNG state to initialize
+ @param callback A pointer to a void function for when the RNG is slow, this can be NULL
+ @return CRYPT_OK if successful
+*/
+int rng_make_prng(int bits, int wprng, prng_state *prng,
+ void (*callback)(void))
+{
+ unsigned char* buf;
+ unsigned long bytes;
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+
+ /* check parameter */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (bits == -1) {
+ bytes = prng_descriptor[wprng].export_size;
+ } else if (bits < 64 || bits > 1024) {
+ return CRYPT_INVALID_PRNGSIZE;
+ } else {
+ bytes = (unsigned long)((bits+7)/8) * 2;
+ }
+
+ if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) {
+ return err;
+ }
+
+ buf = XMALLOC(bytes);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if (rng_get_bytes(buf, bytes, callback) != bytes) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+
+ if (bits == -1) {
+ if ((err = prng_descriptor[wprng].pimport(buf, bytes, prng)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ if ((err = prng_descriptor[wprng].add_entropy(buf, bytes, prng)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+ if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+LBL_ERR:
+ #ifdef LTC_CLEAN_STACK
+ zeromem(buf, bytes);
+ #endif
+ XFREE(buf);
+ return err;
+}
+#endif /* #ifdef LTC_RNG_MAKE_PRNG */
+
diff --git a/Sources/libtomcrypt/prngs/sober128.c b/Sources/libtomcrypt/prngs/sober128.c
new file mode 100644
index 00000000..64545784
--- /dev/null
+++ b/Sources/libtomcrypt/prngs/sober128.c
@@ -0,0 +1,220 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+/**
+ @file prngs/sober128.c
+ Implementation of SOBER-128 by Tom St Denis.
+ Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
+*/
+
+#ifdef LTC_SOBER128
+
+const struct ltc_prng_descriptor sober128_desc =
+{
+ "sober128",
+ 40,
+ &sober128_start,
+ &sober128_add_entropy,
+ &sober128_ready,
+ &sober128_read,
+ &sober128_done,
+ &sober128_export,
+ &sober128_import,
+ &sober128_test
+};
+
+/**
+ Start the PRNG
+ @param prng [out] The PRNG state to initialize
+ @return CRYPT_OK if successful
+*/
+int sober128_start(prng_state *prng)
+{
+ LTC_ARGCHK(prng != NULL);
+ prng->ready = 0;
+ XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent));
+ prng->u.sober128.idx = 0;
+ LTC_MUTEX_INIT(&prng->lock)
+ return CRYPT_OK;
+}
+
+/**
+ Add entropy to the PRNG state
+ @param in The data to add
+ @param inlen Length of the data to add
+ @param prng PRNG state to update
+ @return CRYPT_OK if successful
+*/
+int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ unsigned char buf[40];
+ unsigned long i;
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen > 0);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ if (prng->ready) {
+ /* sober128_ready() was already called, do "rekey" operation */
+ if ((err = sober128_stream_keystream(&prng->u.sober128.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK;
+ for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i];
+ /* key 32 bytes, 20 rounds */
+ if ((err = sober128_stream_setup(&prng->u.sober128.s, buf, 32)) != CRYPT_OK) goto LBL_UNLOCK;
+ /* iv 8 bytes */
+ if ((err = sober128_stream_setiv(&prng->u.sober128.s, buf + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK;
+ /* clear KEY + IV */
+ zeromem(buf, sizeof(buf));
+ }
+ else {
+ /* sober128_ready() was not called yet, add entropy to ent buffer */
+ while (inlen--) prng->u.sober128.ent[prng->u.sober128.idx++ % sizeof(prng->u.sober128.ent)] ^= *in++;
+ }
+ err = CRYPT_OK;
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return err;
+}
+
+/**
+ Make the PRNG ready to read from
+ @param prng The PRNG to make active
+ @return CRYPT_OK if successful
+*/
+int sober128_ready(prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; }
+ /* key 32 bytes, 20 rounds */
+ if ((err = sober128_stream_setup(&prng->u.sober128.s, prng->u.sober128.ent, 32)) != CRYPT_OK) goto LBL_UNLOCK;
+ /* iv 8 bytes */
+ if ((err = sober128_stream_setiv(&prng->u.sober128.s, prng->u.sober128.ent + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK;
+ XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent));
+ prng->u.sober128.idx = 0;
+ prng->ready = 1;
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return err;
+}
+
+/**
+ Read from the PRNG
+ @param out Destination
+ @param outlen Length of output
+ @param prng The active PRNG to read from
+ @return Number of octets read
+*/
+unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng)
+{
+ if (outlen == 0 || prng == NULL || out == NULL) return 0;
+ LTC_MUTEX_LOCK(&prng->lock);
+ if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; }
+ if (sober128_stream_keystream(&prng->u.sober128.s, out, outlen) != CRYPT_OK) outlen = 0;
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return outlen;
+}
+
+/**
+ Terminate the PRNG
+ @param prng The PRNG to terminate
+ @return CRYPT_OK if successful
+*/
+int sober128_done(prng_state *prng)
+{
+ int err;
+ LTC_ARGCHK(prng != NULL);
+ LTC_MUTEX_LOCK(&prng->lock);
+ prng->ready = 0;
+ err = sober128_stream_done(&prng->u.sober128.s);
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ LTC_MUTEX_DESTROY(&prng->lock);
+ return err;
+}
+
+/**
+ Export the PRNG state
+ @param out [out] Destination
+ @param outlen [in/out] Max size and resulting size of the state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+*/
+LTC_PRNG_EXPORT(sober128)
+
+/**
+ Import a PRNG state
+ @param in The PRNG state
+ @param inlen Size of the state
+ @param prng The PRNG to import
+ @return CRYPT_OK if successful
+*/
+int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ if (inlen < (unsigned long)sober128_desc.export_size) return CRYPT_INVALID_ARG;
+
+ if ((err = sober128_start(prng)) != CRYPT_OK) return err;
+ if ((err = sober128_add_entropy(in, inlen, prng)) != CRYPT_OK) return err;
+ return CRYPT_OK;
+}
+
+/**
+ PRNG self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+*/
+int sober128_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ prng_state st;
+ unsigned char en[] = { 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, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 };
+ unsigned char dmp[300];
+ unsigned long dmplen = sizeof(dmp);
+ unsigned char out[500];
+ unsigned char t1[] = { 0x31, 0x82, 0xA7, 0xA5, 0x8B, 0xD7, 0xCB, 0x39, 0x86, 0x1A };
+ unsigned char t2[] = { 0x6B, 0x43, 0x9E, 0xBC, 0xE7, 0x62, 0x9B, 0xE6, 0x9B, 0x83 };
+ unsigned char t3[] = { 0x4A, 0x0E, 0x6C, 0xC1, 0xCF, 0xB4, 0x73, 0x49, 0x99, 0x05 };
+ int err;
+
+ if ((err = sober128_start(&st)) != CRYPT_OK) return err;
+ /* add entropy to uninitialized prng */
+ if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err;
+ if ((err = sober128_ready(&st)) != CRYPT_OK) return err;
+ if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */
+ if (compare_testvector(out, 10, t1, sizeof(t1), "SOBER128-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR;
+ if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ /* add entropy to already initialized prng */
+ if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err;
+ if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if ((err = sober128_export(dmp, &dmplen, &st)) != CRYPT_OK) return err;
+ if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */
+ if (compare_testvector(out, 10, t2, sizeof(t2), "SOBER128-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR;
+ if ((err = sober128_done(&st)) != CRYPT_OK) return err;
+ if ((err = sober128_import(dmp, dmplen, &st)) != CRYPT_OK) return err;
+ if ((err = sober128_ready(&st)) != CRYPT_OK) return err;
+ if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */
+ if (compare_testvector(out, 10, t3, sizeof(t3), "SOBER128-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR;
+ if ((err = sober128_done(&st)) != CRYPT_OK) return err;
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/prngs/sprng.c b/Sources/libtomcrypt/prngs/sprng.c
new file mode 100644
index 00000000..e4047182
--- /dev/null
+++ b/Sources/libtomcrypt/prngs/sprng.c
@@ -0,0 +1,152 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file sprng.c
+ Secure PRNG, Tom St Denis
+*/
+
+/* A secure PRNG using the RNG functions. Basically this is a
+ * wrapper that allows you to use a secure RNG as a PRNG
+ * in the various other functions.
+ */
+
+#ifdef LTC_SPRNG
+
+const struct ltc_prng_descriptor sprng_desc =
+{
+ "sprng", 0,
+ &sprng_start,
+ &sprng_add_entropy,
+ &sprng_ready,
+ &sprng_read,
+ &sprng_done,
+ &sprng_export,
+ &sprng_import,
+ &sprng_test
+};
+
+/**
+ Start the PRNG
+ @param prng [out] The PRNG state to initialize
+ @return CRYPT_OK if successful
+*/
+int sprng_start(prng_state *prng)
+{
+ LTC_UNUSED_PARAM(prng);
+ return CRYPT_OK;
+}
+
+/**
+ Add entropy to the PRNG state
+ @param in The data to add
+ @param inlen Length of the data to add
+ @param prng PRNG state to update
+ @return CRYPT_OK if successful
+*/
+int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ LTC_UNUSED_PARAM(in);
+ LTC_UNUSED_PARAM(inlen);
+ LTC_UNUSED_PARAM(prng);
+ return CRYPT_OK;
+}
+
+/**
+ Make the PRNG ready to read from
+ @param prng The PRNG to make active
+ @return CRYPT_OK if successful
+*/
+int sprng_ready(prng_state *prng)
+{
+ LTC_UNUSED_PARAM(prng);
+ return CRYPT_OK;
+}
+
+/**
+ Read from the PRNG
+ @param out Destination
+ @param outlen Length of output
+ @param prng The active PRNG to read from
+ @return Number of octets read
+*/
+unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng)
+{
+ LTC_ARGCHK(out != NULL);
+ LTC_UNUSED_PARAM(prng);
+ return rng_get_bytes(out, outlen, NULL);
+}
+
+/**
+ Terminate the PRNG
+ @param prng The PRNG to terminate
+ @return CRYPT_OK if successful
+*/
+int sprng_done(prng_state *prng)
+{
+ LTC_UNUSED_PARAM(prng);
+ return CRYPT_OK;
+}
+
+/**
+ Export the PRNG state
+ @param out [out] Destination
+ @param outlen [in/out] Max size and resulting size of the state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+*/
+/* NOLINTNEXTLINE(readability-non-const-parameter) - silence clang-tidy warning */
+int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
+{
+ LTC_ARGCHK(outlen != NULL);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(prng);
+
+ *outlen = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Import a PRNG state
+ @param in The PRNG state
+ @param inlen Size of the state
+ @param prng The PRNG to import
+ @return CRYPT_OK if successful
+*/
+int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ LTC_UNUSED_PARAM(in);
+ LTC_UNUSED_PARAM(inlen);
+ LTC_UNUSED_PARAM(prng);
+ return CRYPT_OK;
+}
+
+/**
+ PRNG self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+*/
+int sprng_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ prng_state st;
+ unsigned char en[] = { 0x01, 0x02, 0x03, 0x04 };
+ unsigned char out[1000];
+ int err;
+
+ if ((err = sprng_start(&st)) != CRYPT_OK) return err;
+ if ((err = sprng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err;
+ if ((err = sprng_ready(&st)) != CRYPT_OK) return err;
+ if (sprng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */
+ if ((err = sprng_done(&st)) != CRYPT_OK) return err;
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
+
+
diff --git a/Sources/libtomcrypt/prngs/yarrow.c b/Sources/libtomcrypt/prngs/yarrow.c
new file mode 100644
index 00000000..40cb46a6
--- /dev/null
+++ b/Sources/libtomcrypt/prngs/yarrow.c
@@ -0,0 +1,323 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file yarrow.c
+ Yarrow PRNG, Tom St Denis
+*/
+
+#ifdef LTC_YARROW
+
+const struct ltc_prng_descriptor yarrow_desc =
+{
+ "yarrow", 64,
+ &yarrow_start,
+ &yarrow_add_entropy,
+ &yarrow_ready,
+ &yarrow_read,
+ &yarrow_done,
+ &yarrow_export,
+ &yarrow_import,
+ &yarrow_test
+};
+
+/**
+ Start the PRNG
+ @param prng [out] The PRNG state to initialize
+ @return CRYPT_OK if successful
+*/
+int yarrow_start(prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ prng->ready = 0;
+
+ /* these are the default hash/cipher combo used */
+#ifdef LTC_RIJNDAEL
+#if LTC_YARROW_AES==0
+ prng->u.yarrow.cipher = register_cipher(&rijndael_enc_desc);
+#elif LTC_YARROW_AES==1
+ prng->u.yarrow.cipher = register_cipher(&aes_enc_desc);
+#elif LTC_YARROW_AES==2
+ prng->u.yarrow.cipher = register_cipher(&rijndael_desc);
+#elif LTC_YARROW_AES==3
+ prng->u.yarrow.cipher = register_cipher(&aes_desc);
+#endif
+#elif defined(LTC_BLOWFISH)
+ prng->u.yarrow.cipher = register_cipher(&blowfish_desc);
+#elif defined(LTC_TWOFISH)
+ prng->u.yarrow.cipher = register_cipher(&twofish_desc);
+#elif defined(LTC_RC6)
+ prng->u.yarrow.cipher = register_cipher(&rc6_desc);
+#elif defined(LTC_RC5)
+ prng->u.yarrow.cipher = register_cipher(&rc5_desc);
+#elif defined(LTC_SAFERP)
+ prng->u.yarrow.cipher = register_cipher(&saferp_desc);
+#elif defined(LTC_RC2)
+ prng->u.yarrow.cipher = register_cipher(&rc2_desc);
+#elif defined(LTC_NOEKEON)
+ prng->u.yarrow.cipher = register_cipher(&noekeon_desc);
+#elif defined(LTC_ANUBIS)
+ prng->u.yarrow.cipher = register_cipher(&anubis_desc);
+#elif defined(LTC_KSEED)
+ prng->u.yarrow.cipher = register_cipher(&kseed_desc);
+#elif defined(LTC_KHAZAD)
+ prng->u.yarrow.cipher = register_cipher(&khazad_desc);
+#elif defined(LTC_CAST5)
+ prng->u.yarrow.cipher = register_cipher(&cast5_desc);
+#elif defined(LTC_XTEA)
+ prng->u.yarrow.cipher = register_cipher(&xtea_desc);
+#elif defined(LTC_SAFER)
+ prng->u.yarrow.cipher = register_cipher(&safer_sk128_desc);
+#elif defined(LTC_DES)
+ prng->u.yarrow.cipher = register_cipher(&des3_desc);
+#else
+ #error LTC_YARROW needs at least one CIPHER
+#endif
+ if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+#ifdef LTC_SHA256
+ prng->u.yarrow.hash = register_hash(&sha256_desc);
+#elif defined(LTC_SHA512)
+ prng->u.yarrow.hash = register_hash(&sha512_desc);
+#elif defined(LTC_TIGER)
+ prng->u.yarrow.hash = register_hash(&tiger_desc);
+#elif defined(LTC_SHA1)
+ prng->u.yarrow.hash = register_hash(&sha1_desc);
+#elif defined(LTC_RIPEMD320)
+ prng->u.yarrow.hash = register_hash(&rmd320_desc);
+#elif defined(LTC_RIPEMD256)
+ prng->u.yarrow.hash = register_hash(&rmd256_desc);
+#elif defined(LTC_RIPEMD160)
+ prng->u.yarrow.hash = register_hash(&rmd160_desc);
+#elif defined(LTC_RIPEMD128)
+ prng->u.yarrow.hash = register_hash(&rmd128_desc);
+#elif defined(LTC_MD5)
+ prng->u.yarrow.hash = register_hash(&md5_desc);
+#elif defined(LTC_MD4)
+ prng->u.yarrow.hash = register_hash(&md4_desc);
+#elif defined(LTC_MD2)
+ prng->u.yarrow.hash = register_hash(&md2_desc);
+#elif defined(LTC_WHIRLPOOL)
+ prng->u.yarrow.hash = register_hash(&whirlpool_desc);
+#else
+ #error LTC_YARROW needs at least one HASH
+#endif
+ if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* zero the memory used */
+ zeromem(prng->u.yarrow.pool, sizeof(prng->u.yarrow.pool));
+ LTC_MUTEX_INIT(&prng->lock)
+
+ return CRYPT_OK;
+}
+
+/**
+ Add entropy to the PRNG state
+ @param in The data to add
+ @param inlen Length of the data to add
+ @param prng PRNG state to update
+ @return CRYPT_OK if successful
+*/
+int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ hash_state md;
+ int err;
+
+ LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen > 0);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+
+ if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+
+ /* start the hash */
+ if ((err = hash_descriptor[prng->u.yarrow.hash].init(&md)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+
+ /* hash the current pool */
+ if ((err = hash_descriptor[prng->u.yarrow.hash].process(&md, prng->u.yarrow.pool,
+ hash_descriptor[prng->u.yarrow.hash].hashsize)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+
+ /* add the new entropy */
+ if ((err = hash_descriptor[prng->u.yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+
+ /* store result */
+ err = hash_descriptor[prng->u.yarrow.hash].done(&md, prng->u.yarrow.pool);
+
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return err;
+}
+
+/**
+ Make the PRNG ready to read from
+ @param prng The PRNG to make active
+ @return CRYPT_OK if successful
+*/
+int yarrow_ready(prng_state *prng)
+{
+ int ks, err;
+
+ LTC_ARGCHK(prng != NULL);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+
+ if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+
+ if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+
+ /* setup CTR mode using the "pool" as the key */
+ ks = (int)hash_descriptor[prng->u.yarrow.hash].hashsize;
+ if ((err = cipher_descriptor[prng->u.yarrow.cipher].keysize(&ks)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+
+ if ((err = ctr_start(prng->u.yarrow.cipher, /* what cipher to use */
+ prng->u.yarrow.pool, /* IV */
+ prng->u.yarrow.pool, ks, /* KEY and key size */
+ 0, /* number of rounds */
+ CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */
+ &prng->u.yarrow.ctr)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+ prng->ready = 1;
+
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return err;
+}
+
+/**
+ Read from the PRNG
+ @param out Destination
+ @param outlen Length of output
+ @param prng The active PRNG to read from
+ @return Number of octets read
+*/
+unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng)
+{
+ if (outlen == 0 || prng == NULL || out == NULL) return 0;
+
+ LTC_MUTEX_LOCK(&prng->lock);
+
+ if (!prng->ready) {
+ outlen = 0;
+ goto LBL_UNLOCK;
+ }
+
+ /* put out in predictable state first */
+ zeromem(out, outlen);
+
+ /* now randomize it */
+ if (ctr_encrypt(out, out, outlen, &prng->u.yarrow.ctr) != CRYPT_OK) {
+ outlen = 0;
+ }
+
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ return outlen;
+}
+
+/**
+ Terminate the PRNG
+ @param prng The PRNG to terminate
+ @return CRYPT_OK if successful
+*/
+int yarrow_done(prng_state *prng)
+{
+ int err;
+ LTC_ARGCHK(prng != NULL);
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ prng->ready = 0;
+
+ /* call cipher done when we invent one ;-) */
+
+ /* we invented one */
+ err = ctr_done(&prng->u.yarrow.ctr);
+
+ LTC_MUTEX_UNLOCK(&prng->lock);
+ LTC_MUTEX_DESTROY(&prng->lock);
+ return err;
+}
+
+/**
+ Export the PRNG state
+ @param out [out] Destination
+ @param outlen [in/out] Max size and resulting size of the state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+*/
+LTC_PRNG_EXPORT(yarrow)
+
+/**
+ Import a PRNG state
+ @param in The PRNG state
+ @param inlen Size of the state
+ @param prng The PRNG to import
+ @return CRYPT_OK if successful
+*/
+int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(prng != NULL);
+ if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG;
+
+ if ((err = yarrow_start(prng)) != CRYPT_OK) return err;
+ if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err;
+ return CRYPT_OK;
+}
+
+/**
+ PRNG self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+*/
+int yarrow_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ int err;
+ prng_state prng;
+
+ if ((err = yarrow_start(&prng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* now let's test the hash/cipher that was chosen */
+ if (cipher_descriptor[prng.u.yarrow.cipher].test &&
+ ((err = cipher_descriptor[prng.u.yarrow.cipher].test()) != CRYPT_OK)) {
+ return err;
+ }
+ if (hash_descriptor[prng.u.yarrow.hash].test &&
+ ((err = hash_descriptor[prng.u.yarrow.hash].test()) != CRYPT_OK)) {
+ return err;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
diff --git a/Sources/libtomcrypt/stream/chacha/chacha_crypt.c b/Sources/libtomcrypt/stream/chacha/chacha_crypt.c
new file mode 100644
index 00000000..27988006
--- /dev/null
+++ b/Sources/libtomcrypt/stream/chacha/chacha_crypt.c
@@ -0,0 +1,91 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * chacha-ref.c version 20080118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA
+
+#define QUARTERROUND(a,b,c,d) \
+ x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 16); \
+ x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 12); \
+ x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 8); \
+ x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 7);
+
+static void s_chacha_block(unsigned char *output, const ulong32 *input, int rounds)
+{
+ ulong32 x[16];
+ int i;
+ XMEMCPY(x, input, sizeof(x));
+ for (i = rounds; i > 0; i -= 2) {
+ QUARTERROUND(0, 4, 8,12)
+ QUARTERROUND(1, 5, 9,13)
+ QUARTERROUND(2, 6,10,14)
+ QUARTERROUND(3, 7,11,15)
+ QUARTERROUND(0, 5,10,15)
+ QUARTERROUND(1, 6,11,12)
+ QUARTERROUND(2, 7, 8,13)
+ QUARTERROUND(3, 4, 9,14)
+ }
+ for (i = 0; i < 16; ++i) {
+ x[i] += input[i];
+ STORE32L(x[i], output + 4 * i);
+ }
+}
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha
+ @param st The ChaCha state
+ @param in The plaintext (or ciphertext)
+ @param inlen The length of the input (octets)
+ @param out [out] The ciphertext (or plaintext), length inlen
+ @return CRYPT_OK if successful
+*/
+int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out)
+{
+ unsigned char buf[64];
+ unsigned long i, j;
+
+ if (inlen == 0) return CRYPT_OK; /* nothing to do */
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(st->ivlen != 0);
+
+ if (st->ksleft > 0) {
+ j = MIN(st->ksleft, inlen);
+ for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft];
+ inlen -= j;
+ if (inlen == 0) return CRYPT_OK;
+ out += j;
+ in += j;
+ }
+ for (;;) {
+ s_chacha_block(buf, st->input, st->rounds);
+ if (st->ivlen == 8) {
+ /* IV-64bit, increment 64bit counter */
+ if (0 == ++st->input[12] && 0 == ++st->input[13]) return CRYPT_OVERFLOW;
+ }
+ else {
+ /* IV-96bit, increment 32bit counter */
+ if (0 == ++st->input[12]) return CRYPT_OVERFLOW;
+ }
+ if (inlen <= 64) {
+ for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i];
+ st->ksleft = 64 - inlen;
+ for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i];
+ return CRYPT_OK;
+ }
+ for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i];
+ inlen -= 64;
+ out += 64;
+ in += 64;
+ }
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/chacha/chacha_done.c b/Sources/libtomcrypt/stream/chacha/chacha_done.c
new file mode 100644
index 00000000..1dc641e4
--- /dev/null
+++ b/Sources/libtomcrypt/stream/chacha/chacha_done.c
@@ -0,0 +1,20 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA
+
+/**
+ Terminate and clear ChaCha state
+ @param st The ChaCha state
+ @return CRYPT_OK on success
+*/
+int chacha_done(chacha_state *st)
+{
+ LTC_ARGCHK(st != NULL);
+ zeromem(st, sizeof(chacha_state));
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/chacha/chacha_ivctr32.c b/Sources/libtomcrypt/stream/chacha/chacha_ivctr32.c
new file mode 100644
index 00000000..08416f52
--- /dev/null
+++ b/Sources/libtomcrypt/stream/chacha/chacha_ivctr32.c
@@ -0,0 +1,37 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * chacha-ref.c version 20080118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA
+
+/**
+ Set IV + counter data to the ChaCha state
+ @param st The ChaCha20 state
+ @param iv The IV data to add
+ @param ivlen The length of the IV (must be 12)
+ @param counter 32bit (unsigned) initial counter value
+ @return CRYPT_OK on success
+ */
+int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter)
+{
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(iv != NULL);
+ /* 96bit IV + 32bit counter */
+ LTC_ARGCHK(ivlen == 12);
+
+ st->input[12] = counter;
+ LOAD32L(st->input[13], iv + 0);
+ LOAD32L(st->input[14], iv + 4);
+ LOAD32L(st->input[15], iv + 8);
+ st->ksleft = 0;
+ st->ivlen = ivlen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/chacha/chacha_ivctr64.c b/Sources/libtomcrypt/stream/chacha/chacha_ivctr64.c
new file mode 100644
index 00000000..49c54590
--- /dev/null
+++ b/Sources/libtomcrypt/stream/chacha/chacha_ivctr64.c
@@ -0,0 +1,37 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * chacha-ref.c version 20080118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA
+
+/**
+ Set IV + counter data to the ChaCha state
+ @param st The ChaCha20 state
+ @param iv The IV data to add
+ @param ivlen The length of the IV (must be 8)
+ @param counter 64bit (unsigned) initial counter value
+ @return CRYPT_OK on success
+ */
+int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter)
+{
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(iv != NULL);
+ /* 64bit IV + 64bit counter */
+ LTC_ARGCHK(ivlen == 8);
+
+ st->input[12] = (ulong32)(counter & 0xFFFFFFFF);
+ st->input[13] = (ulong32)(counter >> 32);
+ LOAD32L(st->input[14], iv + 0);
+ LOAD32L(st->input[15], iv + 4);
+ st->ksleft = 0;
+ st->ivlen = ivlen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/chacha/chacha_keystream.c b/Sources/libtomcrypt/stream/chacha/chacha_keystream.c
new file mode 100644
index 00000000..b7fe6888
--- /dev/null
+++ b/Sources/libtomcrypt/stream/chacha/chacha_keystream.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * chacha-ref.c version 20080118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA
+
+/**
+ Generate a stream of random bytes via ChaCha
+ @param st The ChaCha20 state
+ @param out [out] The output buffer
+ @param outlen The output length
+ @return CRYPT_OK on success
+ */
+int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen)
+{
+ if (outlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(out != NULL);
+ XMEMSET(out, 0, outlen);
+ return chacha_crypt(st, out, outlen, out);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/chacha/chacha_memory.c b/Sources/libtomcrypt/stream/chacha/chacha_memory.c
new file mode 100644
index 00000000..957af0f3
--- /dev/null
+++ b/Sources/libtomcrypt/stream/chacha/chacha_memory.c
@@ -0,0 +1,51 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha
+ @param key The key
+ @param keylen The key length
+ @param rounds The number of rounds
+ @param iv The initial vector
+ @param ivlen The initial vector length
+ @param counter initial counter value, either ignored, 32- or 64-bit, depending on ivlen
+ @param datain The plaintext (or ciphertext)
+ @param datalen The length of the input and output (octets)
+ @param dataout [out] The ciphertext (or plaintext)
+ @return CRYPT_OK if successful
+*/
+int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds,
+ const unsigned char *iv, unsigned long ivlen, ulong64 counter,
+ const unsigned char *datain, unsigned long datalen, unsigned char *dataout)
+{
+ chacha_state st;
+ int err;
+ const unsigned char *iv_ = iv;
+ unsigned long ivlen_ = ivlen;
+ ulong64 counter_ = counter;
+
+ if (ivlen == 16) {
+ LOAD64L(counter_, iv);
+ iv_ += 8;
+ ivlen_ -=8;
+ }
+
+ LTC_ARGCHK(ivlen_ <= 8 || counter_ < CONST64(4294967296)); /* 2**32 */
+
+ if ((err = chacha_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY;
+ if (ivlen_ > 8) {
+ if ((err = chacha_ivctr32(&st, iv_, ivlen_, (ulong32)counter_)) != CRYPT_OK) goto WIPE_KEY;
+ } else {
+ if ((err = chacha_ivctr64(&st, iv_, ivlen_, counter_)) != CRYPT_OK) goto WIPE_KEY;
+ }
+ err = chacha_crypt(&st, datain, datalen, dataout);
+WIPE_KEY:
+ chacha_done(&st);
+ return err;
+}
+
+#endif /* LTC_CHACHA */
diff --git a/Sources/libtomcrypt/stream/chacha/chacha_setup.c b/Sources/libtomcrypt/stream/chacha/chacha_setup.c
new file mode 100644
index 00000000..60896074
--- /dev/null
+++ b/Sources/libtomcrypt/stream/chacha/chacha_setup.c
@@ -0,0 +1,57 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * chacha-ref.c version 20080118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA
+
+static const char * const sigma = "expand 32-byte k";
+static const char * const tau = "expand 16-byte k";
+
+/**
+ Initialize an ChaCha context (only the key)
+ @param st [out] The destination of the ChaCha state
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param rounds Number of rounds (e.g. 20 for ChaCha20)
+ @return CRYPT_OK if successful
+*/
+int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds)
+{
+ const char *constants;
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(keylen == 32 || keylen == 16);
+
+ if (rounds == 0) rounds = 20;
+
+ LOAD32L(st->input[4], key + 0);
+ LOAD32L(st->input[5], key + 4);
+ LOAD32L(st->input[6], key + 8);
+ LOAD32L(st->input[7], key + 12);
+ if (keylen == 32) { /* 256bit */
+ key += 16;
+ constants = sigma;
+ } else { /* 128bit */
+ constants = tau;
+ }
+ LOAD32L(st->input[8], key + 0);
+ LOAD32L(st->input[9], key + 4);
+ LOAD32L(st->input[10], key + 8);
+ LOAD32L(st->input[11], key + 12);
+ LOAD32L(st->input[0], constants + 0);
+ LOAD32L(st->input[1], constants + 4);
+ LOAD32L(st->input[2], constants + 8);
+ LOAD32L(st->input[3], constants + 12);
+ st->rounds = rounds; /* e.g. 20 for chacha20 */
+ st->ivlen = 0; /* will be set later by chacha_ivctr(32|64) */
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/chacha/chacha_test.c b/Sources/libtomcrypt/stream/chacha/chacha_test.c
new file mode 100644
index 00000000..cdd5f4f5
--- /dev/null
+++ b/Sources/libtomcrypt/stream/chacha/chacha_test.c
@@ -0,0 +1,74 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * chacha-ref.c version 20080118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_CHACHA
+
+int chacha_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ unsigned long len;
+ unsigned char out[1000];
+ /* https://tools.ietf.org/html/rfc7539#section-2.4.2 */
+ unsigned char k[] = { 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 };
+ unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00 };
+ unsigned char ct[] = { 0x6E, 0x2E, 0x35, 0x9A, 0x25, 0x68, 0xF9, 0x80, 0x41, 0xBA, 0x07, 0x28, 0xDD, 0x0D, 0x69, 0x81,
+ 0xE9, 0x7E, 0x7A, 0xEC, 0x1D, 0x43, 0x60, 0xC2, 0x0A, 0x27, 0xAF, 0xCC, 0xFD, 0x9F, 0xAE, 0x0B,
+ 0xF9, 0x1B, 0x65, 0xC5, 0x52, 0x47, 0x33, 0xAB, 0x8F, 0x59, 0x3D, 0xAB, 0xCD, 0x62, 0xB3, 0x57,
+ 0x16, 0x39, 0xD6, 0x24, 0xE6, 0x51, 0x52, 0xAB, 0x8F, 0x53, 0x0C, 0x35, 0x9F, 0x08, 0x61, 0xD8,
+ 0x07, 0xCA, 0x0D, 0xBF, 0x50, 0x0D, 0x6A, 0x61, 0x56, 0xA3, 0x8E, 0x08, 0x8A, 0x22, 0xB6, 0x5E,
+ 0x52, 0xBC, 0x51, 0x4D, 0x16, 0xCC, 0xF8, 0x06, 0x81, 0x8C, 0xE9, 0x1A, 0xB7, 0x79, 0x37, 0x36,
+ 0x5A, 0xF9, 0x0B, 0xBF, 0x74, 0xA3, 0x5B, 0xE6, 0xB4, 0x0B, 0x8E, 0xED, 0xF2, 0x78, 0x5E, 0x42,
+ 0x87, 0x4D };
+ char pt[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
+ chacha_state st;
+ int err;
+
+ len = XSTRLEN(pt);
+
+ /* crypt piece by piece - using chacha_ivctr32() */
+ if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err;
+ if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err;
+ if ((err = chacha_crypt(&st, (unsigned char*)pt, 35, out )) != CRYPT_OK) return err;
+ if ((err = chacha_crypt(&st, (unsigned char*)pt + 35, 35, out + 35)) != CRYPT_OK) return err;
+ if ((err = chacha_crypt(&st, (unsigned char*)pt + 70, 5, out + 70)) != CRYPT_OK) return err;
+ if ((err = chacha_crypt(&st, (unsigned char*)pt + 75, 5, out + 75)) != CRYPT_OK) return err;
+ if ((err = chacha_crypt(&st, (unsigned char*)pt + 80, len - 80, out + 80)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV1", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* crypt in one go - using chacha_ivctr32() */
+ if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err;
+ if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err;
+ if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV2", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* crypt in one go - using chacha_ivctr64() */
+ if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err;
+ if ((err = chacha_ivctr64(&st, n + 4, sizeof(n) - 4, 1)) != CRYPT_OK) return err;
+ if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV3", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* crypt in a single call using 32-bit counter with a value of 1 */
+ if ((err = chacha_memory(k, sizeof(k), 20,
+ n, sizeof(n), 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV4", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* crypt in a single call using 64-bit counter with a value of 1 */
+ if ((err = chacha_memory(k, sizeof(k), 20,
+ n + 4, sizeof(n) - 4, 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV5", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/rabbit/rabbit.c b/Sources/libtomcrypt/stream/rabbit/rabbit.c
new file mode 100644
index 00000000..075f4c02
--- /dev/null
+++ b/Sources/libtomcrypt/stream/rabbit/rabbit.c
@@ -0,0 +1,447 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/******************************************************************************
+ * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission
+ * and should run on any conforming C implementation (C90 or later).
+ *
+ * This implementation supports any key length up to 128 bits (16 bytes) and
+ * works in increments of 8-bit bytes. Keys must be submitted as whole bytes
+ * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv
+ * may be any length up to 8 bytes and will be padded out to 8 bytes.
+ *
+ * The eSTREAM submission was rather picky about the calling sequence of
+ * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed
+ * calling ECRYPT_process_blocks() multiple times for a multiple of whole
+ * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls
+ * were supported correctly. This implementation handles the keystream
+ * differently and rabbit_crypt() may be called as many times as desired,
+ * crypting any number of bytes each time.
+ *
+ * http://www.ecrypt.eu.org/stream/e2-rabbit.html
+ *
+ * NB: One of the test vectors distributed by the eSTREAM site in the file
+ * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt"
+ * in that ZIP file, the 3rd line in "out1" should be
+ * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4".
+ *
+ * Here is the original legal notice accompanying the Rabbit submission
+ * to the EU eSTREAM competition.
+ *---------------------------------------------------------------------------
+ * Copyright (C) Cryptico A/S. All rights reserved.
+ *
+ * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE.
+ *
+ * This software is developed by Cryptico A/S and/or its suppliers.
+ * All title and intellectual property rights in and to the software,
+ * including but not limited to patent rights and copyrights, are owned
+ * by Cryptico A/S and/or its suppliers.
+ *
+ * The software may be used solely for non-commercial purposes
+ * without the prior written consent of Cryptico A/S. For further
+ * information on licensing terms and conditions please contact
+ * Cryptico A/S at info@cryptico.com
+ *
+ * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption"
+ * are either trademarks or registered trademarks of Cryptico A/S.
+ *
+ * Cryptico A/S shall not in any way be liable for any use of this
+ * software. The software is provided "as is" without any express or
+ * implied warranty.
+ *---------------------------------------------------------------------------
+ * On October 6, 2008, Rabbit was "released into the public domain and
+ * may be used freely for any purpose."
+ * http://www.ecrypt.eu.org/stream/rabbitpf.html
+ * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244
+ ******************************************************************************/
+
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RABBIT
+
+/* local/private prototypes (NB: rabbit_ctx and rabbit_state are different) */
+static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x);
+static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance);
+static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out);
+
+/* -------------------------------------------------------------------------- */
+
+/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */
+/* the upper 32 bits XOR the lower 32 bits */
+static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x)
+{
+ ulong32 a, b, h, l;
+
+ /* Construct high and low argument for squaring */
+ a = x & 0xFFFF;
+ b = x >> 16;
+
+ /* Calculate high and low result of squaring */
+ h = ((((ulong32)(a*a)>>17) + (ulong32)(a*b))>>15) + b*b;
+ l = x * x;
+
+ /* Return high XOR low */
+ return (ulong32)(h^l);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Calculate the next internal state */
+static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance)
+{
+ ulong32 g[8], c_old[8], i;
+
+ /* Save old counter values */
+ for (i=0; i<8; i++) {
+ c_old[i] = p_instance->c[i];
+ }
+
+ /* Calculate new counter values */
+ p_instance->c[0] = (ulong32)(p_instance->c[0] + 0x4D34D34D + p_instance->carry);
+ p_instance->c[1] = (ulong32)(p_instance->c[1] + 0xD34D34D3 + (p_instance->c[0] < c_old[0]));
+ p_instance->c[2] = (ulong32)(p_instance->c[2] + 0x34D34D34 + (p_instance->c[1] < c_old[1]));
+ p_instance->c[3] = (ulong32)(p_instance->c[3] + 0x4D34D34D + (p_instance->c[2] < c_old[2]));
+ p_instance->c[4] = (ulong32)(p_instance->c[4] + 0xD34D34D3 + (p_instance->c[3] < c_old[3]));
+ p_instance->c[5] = (ulong32)(p_instance->c[5] + 0x34D34D34 + (p_instance->c[4] < c_old[4]));
+ p_instance->c[6] = (ulong32)(p_instance->c[6] + 0x4D34D34D + (p_instance->c[5] < c_old[5]));
+ p_instance->c[7] = (ulong32)(p_instance->c[7] + 0xD34D34D3 + (p_instance->c[6] < c_old[6]));
+ p_instance->carry = (p_instance->c[7] < c_old[7]);
+
+ /* Calculate the g-values */
+ for (i=0;i<8;i++) {
+ g[i] = ss_rabbit_g_func((ulong32)(p_instance->x[i] + p_instance->c[i]));
+ }
+
+ /* Calculate new state values */
+ p_instance->x[0] = (ulong32)(g[0] + ROLc(g[7],16) + ROLc(g[6], 16));
+ p_instance->x[1] = (ulong32)(g[1] + ROLc(g[0], 8) + g[7]);
+ p_instance->x[2] = (ulong32)(g[2] + ROLc(g[1],16) + ROLc(g[0], 16));
+ p_instance->x[3] = (ulong32)(g[3] + ROLc(g[2], 8) + g[1]);
+ p_instance->x[4] = (ulong32)(g[4] + ROLc(g[3],16) + ROLc(g[2], 16));
+ p_instance->x[5] = (ulong32)(g[5] + ROLc(g[4], 8) + g[3]);
+ p_instance->x[6] = (ulong32)(g[6] + ROLc(g[5],16) + ROLc(g[4], 16));
+ p_instance->x[7] = (ulong32)(g[7] + ROLc(g[6], 8) + g[5]);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out)
+{
+ ulong32 *ptr;
+
+ /* Iterate the work context once */
+ ss_rabbit_next_state(&(st->work_ctx));
+
+ /* Generate 16 bytes of pseudo-random data */
+ ptr = (ulong32*)&(st->work_ctx.x);
+ STORE32L((ptr[0] ^ (ptr[5]>>16) ^ (ulong32)(ptr[3]<<16)), out+ 0);
+ STORE32L((ptr[2] ^ (ptr[7]>>16) ^ (ulong32)(ptr[5]<<16)), out+ 4);
+ STORE32L((ptr[4] ^ (ptr[1]>>16) ^ (ulong32)(ptr[7]<<16)), out+ 8);
+ STORE32L((ptr[6] ^ (ptr[3]>>16) ^ (ulong32)(ptr[1]<<16)), out+12);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Key setup */
+int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen)
+{
+ ulong32 k0, k1, k2, k3, i;
+ unsigned char tmpkey[16] = {0};
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(keylen <= 16);
+
+ /* init state */
+ XMEMSET(st, 0, sizeof(rabbit_state));
+
+ /* pad key in tmpkey */
+ XMEMCPY(tmpkey, key, keylen);
+
+ /* Generate four subkeys */
+ LOAD32L(k0, tmpkey+ 0);
+ LOAD32L(k1, tmpkey+ 4);
+ LOAD32L(k2, tmpkey+ 8);
+ LOAD32L(k3, tmpkey+12);
+
+#ifdef LTC_CLEAN_STACK
+ /* done with tmpkey, wipe it */
+ zeromem(tmpkey, sizeof(tmpkey));
+#endif
+
+ /* Generate initial state variables */
+ st->master_ctx.x[0] = k0;
+ st->master_ctx.x[2] = k1;
+ st->master_ctx.x[4] = k2;
+ st->master_ctx.x[6] = k3;
+ st->master_ctx.x[1] = (ulong32)(k3<<16) | (k2>>16);
+ st->master_ctx.x[3] = (ulong32)(k0<<16) | (k3>>16);
+ st->master_ctx.x[5] = (ulong32)(k1<<16) | (k0>>16);
+ st->master_ctx.x[7] = (ulong32)(k2<<16) | (k1>>16);
+
+ /* Generate initial counter values */
+ st->master_ctx.c[0] = ROLc(k2, 16);
+ st->master_ctx.c[2] = ROLc(k3, 16);
+ st->master_ctx.c[4] = ROLc(k0, 16);
+ st->master_ctx.c[6] = ROLc(k1, 16);
+ st->master_ctx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF);
+ st->master_ctx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF);
+ st->master_ctx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF);
+ st->master_ctx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF);
+
+ /* Clear carry bit */
+ st->master_ctx.carry = 0;
+
+ /* Iterate the master context four times */
+ for (i=0; i<4; i++) {
+ ss_rabbit_next_state(&(st->master_ctx));
+ }
+
+ /* Modify the counters */
+ for (i=0; i<8; i++) {
+ st->master_ctx.c[i] ^= st->master_ctx.x[(i+4)&0x7];
+ }
+
+ /* Copy master instance to work instance */
+ for (i=0; i<8; i++) {
+ st->work_ctx.x[i] = st->master_ctx.x[i];
+ st->work_ctx.c[i] = st->master_ctx.c[i];
+ }
+ st->work_ctx.carry = st->master_ctx.carry;
+ /* ...and prepare block for crypt() */
+ XMEMSET(&(st->block), 0, sizeof(st->block));
+ st->unused = 0;
+
+ return CRYPT_OK;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* IV setup */
+int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen)
+{
+ ulong32 i0, i1, i2, i3, i;
+ unsigned char tmpiv[8] = {0};
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(iv != NULL || ivlen == 0);
+ LTC_ARGCHK(ivlen <= 8);
+
+ /* pad iv in tmpiv */
+ if (iv && ivlen > 0) XMEMCPY(tmpiv, iv, ivlen);
+
+ /* Generate four subvectors */
+ LOAD32L(i0, tmpiv+0);
+ LOAD32L(i2, tmpiv+4);
+ i1 = (i0>>16) | (i2&0xFFFF0000);
+ i3 = (i2<<16) | (i0&0x0000FFFF);
+
+ /* Modify counter values */
+ st->work_ctx.c[0] = st->master_ctx.c[0] ^ i0;
+ st->work_ctx.c[1] = st->master_ctx.c[1] ^ i1;
+ st->work_ctx.c[2] = st->master_ctx.c[2] ^ i2;
+ st->work_ctx.c[3] = st->master_ctx.c[3] ^ i3;
+ st->work_ctx.c[4] = st->master_ctx.c[4] ^ i0;
+ st->work_ctx.c[5] = st->master_ctx.c[5] ^ i1;
+ st->work_ctx.c[6] = st->master_ctx.c[6] ^ i2;
+ st->work_ctx.c[7] = st->master_ctx.c[7] ^ i3;
+
+ /* Copy state variables */
+ for (i=0; i<8; i++) {
+ st->work_ctx.x[i] = st->master_ctx.x[i];
+ }
+ st->work_ctx.carry = st->master_ctx.carry;
+
+ /* Iterate the work context four times */
+ for (i=0; i<4; i++) {
+ ss_rabbit_next_state(&(st->work_ctx));
+ }
+
+ /* reset keystream buffer and unused count */
+ XMEMSET(&(st->block), 0, sizeof(st->block));
+ st->unused = 0;
+
+ return CRYPT_OK;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Crypt a chunk of any size (encrypt/decrypt) */
+int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out)
+{
+ unsigned char buf[16];
+ unsigned long i, j;
+
+ if (inlen == 0) return CRYPT_OK; /* nothing to do */
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (st->unused > 0) {
+ j = MIN(st->unused, inlen);
+ for (i = 0; i < j; ++i, st->unused--) out[i] = in[i] ^ st->block[16 - st->unused];
+ inlen -= j;
+ if (inlen == 0) return CRYPT_OK;
+ out += j;
+ in += j;
+ }
+ for (;;) {
+ /* gen a block for buf */
+ ss_rabbit_gen_1_block(st, buf);
+ if (inlen <= 16) {
+ /* XOR and send to out */
+ for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i];
+ st->unused = 16 - inlen;
+ /* copy remainder to block */
+ for (i = inlen; i < 16; ++i) st->block[i] = buf[i];
+ return CRYPT_OK;
+ }
+ /* XOR entire buf and send to out */
+ for (i = 0; i < 16; ++i) out[i] = in[i] ^ buf[i];
+ inlen -= 16;
+ out += 16;
+ in += 16;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+int rabbit_keystream(rabbit_state *st, unsigned char *out, unsigned long outlen)
+{
+ if (outlen == 0) return CRYPT_OK; /* nothing to do */
+
+ LTC_ARGCHK(out != NULL);
+
+ XMEMSET(out, 0, outlen);
+ return rabbit_crypt(st, out, outlen, out);
+}
+
+/* -------------------------------------------------------------------------- */
+
+int rabbit_done(rabbit_state *st)
+{
+ LTC_ARGCHK(st != NULL);
+
+ zeromem(st, sizeof(rabbit_state));
+ return CRYPT_OK;
+}
+
+/* -------------------------------------------------------------------------- */
+
+int rabbit_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ rabbit_state st;
+ int err;
+ unsigned char out[1000] = { 0 };
+ {
+ /* all 3 tests use key and iv fm set 6, vector 3, the last vector in:
+ http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/rabbit/verified.test-vectors?rev=210&view=log
+ */
+
+ /* --- Test 1 (generate whole blocks) --------------------------------- */
+
+ {
+ unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54,
+ 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC };
+ unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 };
+ char pt[64] = { 0 };
+ unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA,
+ 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78,
+ 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40,
+ 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5,
+ 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D, 0x7C,
+ 0x0C, 0x10, 0x9B, 0x79, 0xD5, 0x74, 0x94, 0x39,
+ 0xB7, 0xEF, 0xA4, 0xC4, 0xC9, 0xC8, 0xD2, 0x9D,
+ 0xC5, 0xB3, 0x88, 0x83, 0x14, 0xA6, 0x81, 0x6F };
+ unsigned long ptlen = sizeof(pt);
+
+ /* crypt 64 nulls */
+ if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, (unsigned char*)pt, ptlen, out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV1", 1)) return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* --- Test 2 (generate unusual number of bytes each time) ------------ */
+
+ {
+ unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54,
+ 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC };
+ unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 };
+ char pt[39] = { 0 };
+ unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA,
+ 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78,
+ 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40,
+ 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5,
+ 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D };
+ unsigned long ptlen = sizeof(pt);
+
+ /* crypt piece by piece (hit at least one 16-byte boundary) */
+ if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 11, out + 5)) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, (unsigned char*)pt + 16, 14, out + 16)) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, (unsigned char*)pt + 30, 2, out + 30)) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, (unsigned char*)pt + 32, 7, out + 32)) != CRYPT_OK) return err;
+ if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV2", 1)) return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* --- Test 3 (use non-null data) ------------------------------------- */
+
+ {
+ unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54,
+ 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC };
+ unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 };
+ char pt[] = "Kilroy was here, there, and everywhere!";
+ unsigned char ct[] = { 0x2a, 0x55, 0xdc, 0xc8, 0xf9, 0xd6, 0xd6, 0xbd,
+ 0xae, 0x59, 0x65, 0xf2, 0x75, 0x58, 0x1a, 0x54,
+ 0xea, 0xec, 0x34, 0x9d, 0x8f, 0xb4, 0x6b, 0x60,
+ 0x79, 0x1b, 0xea, 0x16, 0xcb, 0xef, 0x46, 0x87,
+ 0x60, 0xa6, 0x55, 0x14, 0xff, 0xca, 0xac };
+ unsigned long ptlen = XSTRLEN(pt);
+ unsigned char out2[1000] = { 0 };
+ unsigned char nulls[1000] = { 0 };
+
+ /* crypt piece by piece */
+ if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 29, out + 5)) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, (unsigned char*)pt + 34, 5, out + 34)) != CRYPT_OK) return err;
+ if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV3", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* --- Test 4 (crypt in a single call) ------------------------------------ */
+
+ if ((err = rabbit_memory(k, sizeof(k), iv, sizeof(iv),
+ (unsigned char*)pt, sizeof(pt), out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV4", 1)) return CRYPT_FAIL_TESTVECTOR;
+ /* use 'out' (ciphertext) in the next decryption test */
+
+ /* --- Test 5 (decrypt ciphertext) ------------------------------------ */
+
+ /* decrypt ct (out) and compare with pt (start with only setiv() to reset) */
+ if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err;
+ if ((err = rabbit_crypt(&st, out, ptlen, out2)) != CRYPT_OK) return err;
+ if (compare_testvector(out2, ptlen, pt, ptlen, "RABBIT-TV5", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* --- Test 6 (wipe state, incl key) ---------------------------------- */
+
+ if ((err = rabbit_done(&st)) != CRYPT_OK) return err;
+ if (compare_testvector(&st, sizeof(st), nulls, sizeof(st), "RABBIT-TV6", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ }
+
+ return CRYPT_OK;
+ }
+#endif
+}
+
+/* -------------------------------------------------------------------------- */
+
+#endif
diff --git a/Sources/libtomcrypt/stream/rabbit/rabbit_memory.c b/Sources/libtomcrypt/stream/rabbit/rabbit_memory.c
new file mode 100644
index 00000000..fee0234e
--- /dev/null
+++ b/Sources/libtomcrypt/stream/rabbit/rabbit_memory.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * chacha-ref.c version 20080118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RABBIT
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Rabbit
+ @param key The key
+ @param keylen The key length
+ @param iv The initial vector
+ @param ivlen The initial vector length
+ @param datain The plaintext (or ciphertext)
+ @param datalen The length of the input and output (octets)
+ @param dataout [out] The ciphertext (or plaintext)
+ @return CRYPT_OK if successful
+*/
+int rabbit_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout)
+{
+ rabbit_state st;
+ int err;
+
+ if ((err = rabbit_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY;
+ if ((err = rabbit_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY;
+ err = rabbit_crypt(&st, datain, datalen, dataout);
+WIPE_KEY:
+ rabbit_done(&st);
+ return err;
+}
+
+#endif /* LTC_RABBIT */
diff --git a/Sources/libtomcrypt/stream/rc4/rc4_stream.c b/Sources/libtomcrypt/stream/rc4/rc4_stream.c
new file mode 100644
index 00000000..25877649
--- /dev/null
+++ b/Sources/libtomcrypt/stream/rc4/rc4_stream.c
@@ -0,0 +1,101 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RC4_STREAM
+
+/**
+ Initialize an RC4 context (only the key)
+ @param st [out] The destination of the RC4 state
+ @param key The secret key
+ @param keylen The length of the secret key (8 - 256 bytes)
+ @return CRYPT_OK if successful
+*/
+int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen)
+{
+ unsigned char tmp, *s;
+ int x, y;
+ unsigned long j;
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(keylen >= 5); /* 40-2048 bits */
+
+ s = st->buf;
+ for (x = 0; x < 256; x++) {
+ s[x] = x;
+ }
+
+ for (j = x = y = 0; x < 256; x++) {
+ y = (y + s[x] + key[j++]) & 255;
+ if (j == keylen) {
+ j = 0;
+ }
+ tmp = s[x]; s[x] = s[y]; s[y] = tmp;
+ }
+ st->x = 0;
+ st->y = 0;
+
+ return CRYPT_OK;
+}
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4
+ @param st The RC4 state
+ @param in The plaintext (or ciphertext)
+ @param inlen The length of the input (octets)
+ @param out [out] The ciphertext (or plaintext), length inlen
+ @return CRYPT_OK if successful
+*/
+int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out)
+{
+ unsigned char x, y, *s, tmp;
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ x = st->x;
+ y = st->y;
+ s = st->buf;
+ while (inlen--) {
+ x = (x + 1) & 255;
+ y = (y + s[x]) & 255;
+ tmp = s[x]; s[x] = s[y]; s[y] = tmp;
+ tmp = (s[x] + s[y]) & 255;
+ *out++ = *in++ ^ s[tmp];
+ }
+ st->x = x;
+ st->y = y;
+ return CRYPT_OK;
+}
+
+/**
+ Generate a stream of random bytes via RC4
+ @param st The RC420 state
+ @param out [out] The output buffer
+ @param outlen The output length
+ @return CRYPT_OK on success
+ */
+int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen)
+{
+ if (outlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(out != NULL);
+ XMEMSET(out, 0, outlen);
+ return rc4_stream_crypt(st, out, outlen, out);
+}
+
+/**
+ Terminate and clear RC4 state
+ @param st The RC4 state
+ @return CRYPT_OK on success
+*/
+int rc4_stream_done(rc4_state *st)
+{
+ LTC_ARGCHK(st != NULL);
+ zeromem(st, sizeof(rc4_state));
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/rc4/rc4_stream_memory.c b/Sources/libtomcrypt/stream/rc4/rc4_stream_memory.c
new file mode 100644
index 00000000..efe4888f
--- /dev/null
+++ b/Sources/libtomcrypt/stream/rc4/rc4_stream_memory.c
@@ -0,0 +1,31 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RC4_STREAM
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4
+ @param key The key
+ @param keylen The key length
+ @param datain The plaintext (or ciphertext)
+ @param datalen The length of the input and output (octets)
+ @param dataout [out] The ciphertext (or plaintext)
+ @return CRYPT_OK if successful
+*/
+int rc4_stream_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout)
+{
+ rc4_state st;
+ int err;
+
+ if ((err = rc4_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY;
+ err = rc4_stream_crypt(&st, datain, datalen, dataout);
+WIPE_KEY:
+ rc4_stream_done(&st);
+ return err;
+}
+
+#endif /* LTC_RC4_STREAM */
diff --git a/Sources/libtomcrypt/stream/rc4/rc4_test.c b/Sources/libtomcrypt/stream/rc4/rc4_test.c
new file mode 100644
index 00000000..d78022b9
--- /dev/null
+++ b/Sources/libtomcrypt/stream/rc4/rc4_test.c
@@ -0,0 +1,33 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_RC4_STREAM
+
+int rc4_stream_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ rc4_state st;
+ int err;
+ const unsigned char key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ const unsigned char pt[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ const unsigned char ct[] = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 };
+ unsigned char buf[10];
+
+ if ((err = rc4_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err;
+ if ((err = rc4_stream_crypt(&st, pt, sizeof(pt), buf)) != CRYPT_OK) return err;
+ if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV1", 0)) return CRYPT_FAIL_TESTVECTOR;
+ if ((err = rc4_stream_done(&st)) != CRYPT_OK) return err;
+
+ /* crypt in a single call */
+ if ((err = rc4_stream_memory(key, sizeof(key), pt, sizeof(pt), buf)) != CRYPT_OK) return err;
+ if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV2", 0)) return CRYPT_FAIL_TESTVECTOR;
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/salsa20/salsa20_crypt.c b/Sources/libtomcrypt/stream/salsa20/salsa20_crypt.c
new file mode 100644
index 00000000..30583728
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/salsa20_crypt.c
@@ -0,0 +1,86 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf
+ * and salsa20-ref.c version 20051118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SALSA20
+
+#define QUARTERROUND(a,b,c,d) \
+ x[b] ^= (ROL((x[a] + x[d]), 7)); \
+ x[c] ^= (ROL((x[b] + x[a]), 9)); \
+ x[d] ^= (ROL((x[c] + x[b]), 13)); \
+ x[a] ^= (ROL((x[d] + x[c]), 18));
+
+static void s_salsa20_block(unsigned char *output, const ulong32 *input, int rounds)
+{
+ ulong32 x[16];
+ int i;
+ XMEMCPY(x, input, sizeof(x));
+ for (i = rounds; i > 0; i -= 2) {
+ QUARTERROUND( 0, 4, 8,12)
+ QUARTERROUND( 5, 9,13, 1)
+ QUARTERROUND(10,14, 2, 6)
+ QUARTERROUND(15, 3, 7,11)
+ QUARTERROUND( 0, 1, 2, 3)
+ QUARTERROUND( 5, 6, 7, 4)
+ QUARTERROUND(10,11, 8, 9)
+ QUARTERROUND(15,12,13,14)
+ }
+ for (i = 0; i < 16; ++i) {
+ x[i] += input[i];
+ STORE32L(x[i], output + 4 * i);
+ }
+}
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20
+ @param st The Salsa20 state
+ @param in The plaintext (or ciphertext)
+ @param inlen The length of the input (octets)
+ @param out [out] The ciphertext (or plaintext), length inlen
+ @return CRYPT_OK if successful
+*/
+int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out)
+{
+ unsigned char buf[64];
+ unsigned long i, j;
+
+ if (inlen == 0) return CRYPT_OK; /* nothing to do */
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(st->ivlen == 8 || st->ivlen == 24);
+
+ if (st->ksleft > 0) {
+ j = MIN(st->ksleft, inlen);
+ for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft];
+ inlen -= j;
+ if (inlen == 0) return CRYPT_OK;
+ out += j;
+ in += j;
+ }
+ for (;;) {
+ s_salsa20_block(buf, st->input, st->rounds);
+ /* Salsa20: 64-bit IV, increment 64-bit counter */
+ if (0 == ++st->input[8] && 0 == ++st->input[9]) return CRYPT_OVERFLOW;
+ if (inlen <= 64) {
+ for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i];
+ st->ksleft = 64 - inlen;
+ for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i];
+ return CRYPT_OK;
+ }
+ for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i];
+ inlen -= 64;
+ out += 64;
+ in += 64;
+ }
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/salsa20/salsa20_done.c b/Sources/libtomcrypt/stream/salsa20/salsa20_done.c
new file mode 100644
index 00000000..9b8cbb6b
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/salsa20_done.c
@@ -0,0 +1,20 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SALSA20
+
+/**
+ Terminate and clear Salsa20 state
+ @param st The Salsa20 state
+ @return CRYPT_OK on success
+*/
+int salsa20_done(salsa20_state *st)
+{
+ LTC_ARGCHK(st != NULL);
+ zeromem(st, sizeof(salsa20_state));
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/salsa20/salsa20_ivctr64.c b/Sources/libtomcrypt/stream/salsa20/salsa20_ivctr64.c
new file mode 100644
index 00000000..8b25dfb3
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/salsa20_ivctr64.c
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf
+ * and salsa20-ref.c version 20051118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SALSA20
+
+/**
+ Set IV + counter data to the Salsa20 state
+ @param st The Salsa20 state
+ @param iv The IV data to add
+ @param ivlen The length of the IV (must be 8)
+ @param counter 64bit (unsigned) initial counter value
+ @return CRYPT_OK on success
+ */
+int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter)
+{
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(iv != NULL);
+ /* Salsa20: 64-bit IV (nonce) + 64-bit counter */
+ LTC_ARGCHK(ivlen == 8);
+
+ LOAD32L(st->input[6], iv + 0);
+ LOAD32L(st->input[7], iv + 4);
+ st->input[8] = (ulong32)(counter & 0xFFFFFFFF);
+ st->input[9] = (ulong32)(counter >> 32);
+ st->ksleft = 0;
+ st->ivlen = ivlen;
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/salsa20/salsa20_keystream.c b/Sources/libtomcrypt/stream/salsa20/salsa20_keystream.c
new file mode 100644
index 00000000..c51d0d64
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/salsa20_keystream.c
@@ -0,0 +1,29 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf
+ * and salsa20-ref.c version 20051118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SALSA20
+
+/**
+ Generate a stream of random bytes via Salsa20
+ @param st The Salsa20 state
+ @param out [out] The output buffer
+ @param outlen The output length
+ @return CRYPT_OK on success
+ */
+int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen)
+{
+ if (outlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(out != NULL);
+ XMEMSET(out, 0, outlen);
+ return salsa20_crypt(st, out, outlen, out);
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/salsa20/salsa20_memory.c b/Sources/libtomcrypt/stream/salsa20/salsa20_memory.c
new file mode 100644
index 00000000..9408eb21
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/salsa20_memory.c
@@ -0,0 +1,35 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SALSA20
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20
+ @param key The key
+ @param keylen The key length
+ @param iv The initial vector
+ @param ivlen The initial vector length
+ @param datain The plaintext (or ciphertext)
+ @param datalen The length of the input and output (octets)
+ @param rounds The number of rounds
+ @param dataout [out] The ciphertext (or plaintext)
+ @return CRYPT_OK if successful
+*/
+int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds,
+ const unsigned char *iv, unsigned long ivlen, ulong64 counter,
+ const unsigned char *datain, unsigned long datalen, unsigned char *dataout)
+{
+ salsa20_state st;
+ int err;
+
+ if ((err = salsa20_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY;
+ if ((err = salsa20_ivctr64(&st, iv, ivlen, counter)) != CRYPT_OK) goto WIPE_KEY;
+ err = salsa20_crypt(&st, datain, datalen, dataout);
+WIPE_KEY:
+ salsa20_done(&st);
+ return err;
+}
+
+#endif /* LTC_SALSA20 */
diff --git a/Sources/libtomcrypt/stream/salsa20/salsa20_setup.c b/Sources/libtomcrypt/stream/salsa20/salsa20_setup.c
new file mode 100644
index 00000000..012dc95b
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/salsa20_setup.c
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf
+ * and salsa20-ref.c version 20051118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SALSA20
+
+static const char * const sigma = "expand 32-byte k";
+static const char * const tau = "expand 16-byte k";
+
+/**
+ Initialize an Salsa20 context (only the key)
+ @param st [out] The destination of the Salsa20 state
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @param rounds Number of rounds (e.g. 20 for Salsa20)
+ @return CRYPT_OK if successful
+*/
+int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds)
+{
+ const char *constants;
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(keylen == 32 || keylen == 16);
+
+ if (rounds == 0) rounds = 20;
+ LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */
+
+ LOAD32L(st->input[1], key + 0);
+ LOAD32L(st->input[2], key + 4);
+ LOAD32L(st->input[3], key + 8);
+ LOAD32L(st->input[4], key + 12);
+ if (keylen == 32) { /* 256bit */
+ key += 16;
+ constants = sigma;
+ } else { /* 128bit */
+ constants = tau;
+ }
+ LOAD32L(st->input[11], key + 0);
+ LOAD32L(st->input[12], key + 4);
+ LOAD32L(st->input[13], key + 8);
+ LOAD32L(st->input[14], key + 12);
+ LOAD32L(st->input[ 0], constants + 0);
+ LOAD32L(st->input[ 5], constants + 4);
+ LOAD32L(st->input[10], constants + 8);
+ LOAD32L(st->input[15], constants + 12);
+ st->rounds = rounds; /* default is 20 for salsa20 */
+ st->ivlen = 0; /* will be set later by salsa20_ivctr(32|64) */
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/salsa20/salsa20_test.c b/Sources/libtomcrypt/stream/salsa20/salsa20_test.c
new file mode 100644
index 00000000..c924dbe7
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/salsa20_test.c
@@ -0,0 +1,86 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf
+ * and salsa20-ref.c version 20051118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SALSA20
+
+int salsa20_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ salsa20_state st;
+ unsigned char k[] = { 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 };
+ unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a };
+ unsigned char ct[] = { 0x37, 0x37, 0x2e, 0x60, 0xb8, 0xae, 0x88, 0x1f, 0xf8, 0xdf, 0x00, 0x26, 0x6c, 0x30, 0x34, 0x2d,
+ 0xa1, 0xd7, 0x79, 0x60, 0x67, 0x72, 0xe0, 0x67, 0x26, 0x22, 0xad, 0x00, 0x9e, 0xd5, 0x59, 0x44,
+ 0x51, 0xd9, 0xe6, 0xaa, 0xc9, 0x59, 0x9e, 0x60, 0xff, 0x87, 0x90, 0xc1, 0xc9, 0x1e };
+ unsigned char ct2[] = { 0xec, 0x06, 0x32, 0xb3, 0x83, 0x5c, 0xae, 0x91, 0x01, 0x82, 0x7a, 0x71, 0xd9, 0x7d, 0x45, 0xd7,
+ 0xa6, 0x5b, 0xa0, 0x89, 0x9d, 0xd2, 0x6c, 0xaa, 0xbb, 0x2f, 0x5f, 0x30, 0x89, 0x54, 0xff, 0x3e,
+ 0x83, 0xc3, 0x34, 0x10, 0xb6, 0xe1, 0xab, 0xe7, 0xf5, 0xab, 0xab, 0xed, 0xa4, 0xff };
+ char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */
+ unsigned long len;
+ unsigned char out[1000];
+ int counter;
+ int rounds;
+ int err;
+ len = XSTRLEN(pt);
+
+ /* crypt piece by piece */
+ counter = 0;
+ rounds = 12;
+ if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err;
+ if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err;
+ if ((err = salsa20_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err;
+ if ((err = salsa20_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err;
+ if ((err = salsa20_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err;
+ if ((err = salsa20_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct, sizeof(ct), "SALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* crypt in one go - using salsa20_ivctr64() */
+ counter = 0;
+ rounds = 20;
+ if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err;
+ if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err;
+ if ((err = salsa20_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* crypt in a single call */
+ if ((err = salsa20_memory(k, sizeof(k), rounds, n, sizeof(n), counter,
+ (unsigned char*)pt, len, out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ {
+ /* keystream
+ * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?rev=161&view=markup
+ * Set 6, vector 0
+ */
+ unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD,
+ 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D };
+ unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE };
+ unsigned char ct3[] = { 0xF5, 0xFA, 0xD5, 0x3F, 0x79, 0xF9, 0xDF, 0x58, 0xC4, 0xAE, 0xA0, 0xD0, 0xED, 0x9A, 0x96, 0x01,
+ 0xF2, 0x78, 0x11, 0x2C, 0xA7, 0x18, 0x0D, 0x56, 0x5B, 0x42, 0x0A, 0x48, 0x01, 0x96, 0x70, 0xEA,
+ 0xF2, 0x4C, 0xE4, 0x93, 0xA8, 0x62, 0x63, 0xF6, 0x77, 0xB4, 0x6A, 0xCE, 0x19, 0x24, 0x77, 0x3D,
+ 0x2B, 0xB2, 0x55, 0x71, 0xE1, 0xAA, 0x85, 0x93, 0x75, 0x8F, 0xC3, 0x82, 0xB1, 0x28, 0x0B, 0x71 };
+ int counter3 = 0;
+ int rounds3 = 20;
+ if ((err = salsa20_setup(&st, k3, sizeof(k3), rounds3)) != CRYPT_OK) return err;
+ if ((err = salsa20_ivctr64(&st, n3, sizeof(n3), counter3)) != CRYPT_OK) return err;
+ if ((err = salsa20_keystream(&st, out, 64)) != CRYPT_OK) return err;
+ if ((err = salsa20_done(&st)) != CRYPT_OK) return err;
+ if (compare_testvector(out, 64, ct3, sizeof(ct3), "SALSA20-TV4", 1)) return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/salsa20/xsalsa20_memory.c b/Sources/libtomcrypt/stream/salsa20/xsalsa20_memory.c
new file mode 100644
index 00000000..1908cd56
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/xsalsa20_memory.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_XSALSA20
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with XSalsa20
+ @param key The key
+ @param keylen The key length
+ @param nonce The initial vector
+ @param noncelen The initial vector length
+ @param datain The plaintext (or ciphertext)
+ @param datalen The length of the input and output (octets)
+ @param rounds The number of rounds
+ @param dataout [out] The ciphertext (or plaintext)
+ @return CRYPT_OK if successful
+*/
+int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *datain, unsigned long datalen, unsigned char *dataout)
+{
+ salsa20_state st;
+ int err;
+
+ if ((err = xsalsa20_setup(&st, key, keylen, nonce, noncelen, rounds)) != CRYPT_OK) goto WIPE_KEY;
+ err = salsa20_crypt(&st, datain, datalen, dataout);
+WIPE_KEY:
+ salsa20_done(&st);
+ return err;
+}
+
+#endif /* LTC_XSALSA20 */
diff --git a/Sources/libtomcrypt/stream/salsa20/xsalsa20_setup.c b/Sources/libtomcrypt/stream/salsa20/xsalsa20_setup.c
new file mode 100644
index 00000000..6bfac093
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/xsalsa20_setup.c
@@ -0,0 +1,127 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf
+ * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf
+ * and salsa20-ref.c version 20051118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_XSALSA20
+
+static const char * const constants = "expand 32-byte k";
+
+#define QUARTERROUND(a,b,c,d) \
+ x[b] ^= (ROL((x[a] + x[d]), 7)); \
+ x[c] ^= (ROL((x[b] + x[a]), 9)); \
+ x[d] ^= (ROL((x[c] + x[b]), 13)); \
+ x[a] ^= (ROL((x[d] + x[c]), 18));
+
+/* use modified salsa20 doubleround (no final addition as in salsa20) */
+static void s_xsalsa20_doubleround(ulong32 *x, int rounds)
+{
+ int i;
+
+ for (i = rounds; i > 0; i -= 2) {
+ /* columnround */
+ QUARTERROUND( 0, 4, 8,12)
+ QUARTERROUND( 5, 9,13, 1)
+ QUARTERROUND(10,14, 2, 6)
+ QUARTERROUND(15, 3, 7,11)
+ /* rowround */
+ QUARTERROUND( 0, 1, 2, 3)
+ QUARTERROUND( 5, 6, 7, 4)
+ QUARTERROUND(10,11, 8, 9)
+ QUARTERROUND(15,12,13,14)
+ }
+}
+
+#undef QUARTERROUND
+
+/**
+ Initialize an XSalsa20 context
+ @param st [out] The destination of the XSalsa20 state
+ @param key The secret key
+ @param keylen The length of the secret key, must be 32 (octets)
+ @param nonce The nonce
+ @param noncelen The length of the nonce, must be 24 (octets)
+ @param rounds Number of rounds (must be evenly divisible by 2, default is 20)
+ @return CRYPT_OK if successful
+*/
+int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ int rounds)
+{
+ const int sti[] = {0, 5, 10, 15, 6, 7, 8, 9}; /* indices used to build subkey fm x */
+ ulong32 x[64]; /* input to & output fm doubleround */
+ unsigned char subkey[32];
+ int i;
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(keylen == 32);
+ LTC_ARGCHK(nonce != NULL);
+ LTC_ARGCHK(noncelen == 24);
+ if (rounds == 0) rounds = 20;
+ LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */
+
+ /* load the state to "hash" the key */
+ LOAD32L(x[ 0], constants + 0);
+ LOAD32L(x[ 5], constants + 4);
+ LOAD32L(x[10], constants + 8);
+ LOAD32L(x[15], constants + 12);
+ LOAD32L(x[ 1], key + 0);
+ LOAD32L(x[ 2], key + 4);
+ LOAD32L(x[ 3], key + 8);
+ LOAD32L(x[ 4], key + 12);
+ LOAD32L(x[11], key + 16);
+ LOAD32L(x[12], key + 20);
+ LOAD32L(x[13], key + 24);
+ LOAD32L(x[14], key + 28);
+ LOAD32L(x[ 6], nonce + 0);
+ LOAD32L(x[ 7], nonce + 4);
+ LOAD32L(x[ 8], nonce + 8);
+ LOAD32L(x[ 9], nonce + 12);
+
+ /* use modified salsa20 doubleround (no final addition) */
+ s_xsalsa20_doubleround(x, rounds);
+
+ /* extract the subkey */
+ for (i = 0; i < 8; ++i) {
+ STORE32L(x[sti[i]], subkey + 4 * i);
+ }
+
+ /* load the final initial state */
+ LOAD32L(st->input[ 0], constants + 0);
+ LOAD32L(st->input[ 5], constants + 4);
+ LOAD32L(st->input[10], constants + 8);
+ LOAD32L(st->input[15], constants + 12);
+ LOAD32L(st->input[ 1], subkey + 0);
+ LOAD32L(st->input[ 2], subkey + 4);
+ LOAD32L(st->input[ 3], subkey + 8);
+ LOAD32L(st->input[ 4], subkey + 12);
+ LOAD32L(st->input[11], subkey + 16);
+ LOAD32L(st->input[12], subkey + 20);
+ LOAD32L(st->input[13], subkey + 24);
+ LOAD32L(st->input[14], subkey + 28);
+ LOAD32L(st->input[ 6], &(nonce[16]) + 0);
+ LOAD32L(st->input[ 7], &(nonce[16]) + 4);
+ st->input[ 8] = 0;
+ st->input[ 9] = 0;
+ st->rounds = rounds;
+ st->ksleft = 0;
+ st->ivlen = 24; /* set switch to say nonce/IV has been loaded */
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(x, sizeof(x));
+ zeromem(subkey, sizeof(subkey));
+#endif
+
+ return CRYPT_OK;
+}
+
+
+#endif
diff --git a/Sources/libtomcrypt/stream/salsa20/xsalsa20_test.c b/Sources/libtomcrypt/stream/salsa20/xsalsa20_test.c
new file mode 100644
index 00000000..31522fe5
--- /dev/null
+++ b/Sources/libtomcrypt/stream/salsa20/xsalsa20_test.c
@@ -0,0 +1,90 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* The implementation is based on:
+ * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf
+ * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf
+ * and salsa20-ref.c version 20051118
+ * Public domain from D. J. Bernstein
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_XSALSA20
+
+#if defined(LTC_SHA256) && defined(LTC_TEST)
+static int s_sha256(unsigned char *hash, const unsigned char *data, const int datalen) {
+ hash_state md;
+ sha256_init(&md);
+ sha256_process(&md, data, datalen);
+ sha256_done(&md, hash);
+ return CRYPT_OK;
+}
+#endif
+
+int xsalsa20_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+
+ /***************************************************************************
+ * verify a round trip:
+ */
+ {
+ const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89};
+ const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37};
+ const void *msg = "Kilroy was here!";
+ unsigned char msglen = 17; /* includes trailing NULL */
+ int rounds = 20;
+ unsigned char ciphertext[17];
+ unsigned char msg2[17];
+ salsa20_state st;
+ int err;
+
+ if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err;
+ if ((err = salsa20_crypt(&st, msg, msglen, ciphertext)) != CRYPT_OK) return err;
+ if ((err = salsa20_done(&st)) != CRYPT_OK) return err;
+
+ if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err;
+ if ((err = salsa20_crypt(&st, ciphertext, msglen, msg2)) != CRYPT_OK) return err;
+ if ((err = salsa20_done(&st)) != CRYPT_OK) return err;
+
+ if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+
+ /* round trip with two single function calls */
+ if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), msg, msglen, ciphertext)) != CRYPT_OK) return err;
+ if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), ciphertext, msglen, msg2)) != CRYPT_OK) return err;
+ if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR;
+ }
+
+#ifdef LTC_SHA256
+ /***************************************************************************
+ * verify correct generation of a keystream
+ */
+ {
+ const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89};
+ const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37};
+ const unsigned char expecthash[] = {0x6a,0x60,0x57,0x65,0x27,0xe0,0x00,0x51,0x6d,0xb0,0xda,0x60,0x46,0x20,0xf6,0xd0,0x95,0x65,0x45,0x39,0xf4,0x86,0x83,0x43,0x64,0xdf,0xd9,0x5a,0x6f,0x3f,0xbe,0xb7};
+ int rounds = 20;
+ unsigned char keystream[91101];
+ unsigned long keystreamlen = 91101;
+ unsigned char hash[32];
+ salsa20_state st;
+ int err;
+
+ if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err;
+ if ((err = salsa20_keystream(&st, keystream, keystreamlen)) != CRYPT_OK) return err;
+ if ((err = salsa20_done(&st)) != CRYPT_OK) return err;
+ if ((err = s_sha256(hash, keystream, keystreamlen)) != CRYPT_OK) return err;
+ if (compare_testvector(hash, sizeof(hash), expecthash, sizeof(expecthash), "XSALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR;
+ }
+#endif
+
+ return CRYPT_OK;
+
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/sober128/sober128_stream.c b/Sources/libtomcrypt/stream/sober128/sober128_stream.c
new file mode 100644
index 00000000..44451519
--- /dev/null
+++ b/Sources/libtomcrypt/stream/sober128/sober128_stream.c
@@ -0,0 +1,333 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file sober128_stream.c
+ Implementation of SOBER-128 by Tom St Denis.
+ Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
+*/
+
+#ifdef LTC_SOBER128
+
+#define LTC_SOBER128TAB_C
+#include "sober128tab.c"
+
+/* don't change these... */
+#define N 17
+#define INITKONST 0x6996c53a /* value of KONST to use during key loading */
+#define KEYP 15 /* where to insert key words */
+#define FOLDP 4 /* where to insert non-linear feedback */
+
+static ulong32 BYTE2WORD(const unsigned char *b)
+{
+ ulong32 t;
+ LOAD32L(t, b);
+ return t;
+}
+
+static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out)
+{
+ ulong32 t;
+ LOAD32L(t, in);
+ t ^= w;
+ STORE32L(t, out);
+}
+
+/* give correct offset for the current position of the register,
+ * where logically R[0] is at position "zero".
+ */
+#define OFF(zero, i) (((zero)+(i)) % N)
+
+/* step the LFSR */
+/* After stepping, "zero" moves right one place */
+#define STEP(R,z) \
+ R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF];
+
+static void cycle(ulong32 *R)
+{
+ ulong32 t;
+ int i;
+
+ STEP(R,0);
+ t = R[0];
+ for (i = 1; i < N; ++i) {
+ R[i-1] = R[i];
+ }
+ R[N-1] = t;
+}
+
+/* Return a non-linear function of some parts of the register.
+ */
+#define NLFUNC(st,z) \
+{ \
+ t = st->R[OFF(z,0)] + st->R[OFF(z,16)]; \
+ t ^= Sbox[(t >> 24) & 0xFF]; \
+ t = RORc(t, 8); \
+ t = ((t + st->R[OFF(z,1)]) ^ st->konst) + st->R[OFF(z,6)]; \
+ t ^= Sbox[(t >> 24) & 0xFF]; \
+ t = t + st->R[OFF(z,13)]; \
+}
+
+static ulong32 nltap(const sober128_state *st)
+{
+ ulong32 t;
+ NLFUNC(st, 0);
+ return t;
+}
+
+/* Save the current register state
+ */
+static void s128_savestate(sober128_state *st)
+{
+ int i;
+ for (i = 0; i < N; ++i) {
+ st->initR[i] = st->R[i];
+ }
+}
+
+/* initialise to previously saved register state
+ */
+static void s128_reloadstate(sober128_state *st)
+{
+ int i;
+
+ for (i = 0; i < N; ++i) {
+ st->R[i] = st->initR[i];
+ }
+}
+
+/* Initialise "konst"
+ */
+static void s128_genkonst(sober128_state *st)
+{
+ ulong32 newkonst;
+
+ do {
+ cycle(st->R);
+ newkonst = nltap(st);
+ } while ((newkonst & 0xFF000000) == 0);
+ st->konst = newkonst;
+}
+
+/* Load key material into the register
+ */
+#define ADDKEY(k) \
+ st->R[KEYP] += (k);
+
+#define XORNL(nl) \
+ st->R[FOLDP] ^= (nl);
+
+/* nonlinear diffusion of register for key */
+#define DROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); st->R[OFF((z+1),FOLDP)] ^= t;
+static void s128_diffuse(sober128_state *st)
+{
+ ulong32 t;
+ /* relies on FOLD == N == 17! */
+ DROUND(0);
+ DROUND(1);
+ DROUND(2);
+ DROUND(3);
+ DROUND(4);
+ DROUND(5);
+ DROUND(6);
+ DROUND(7);
+ DROUND(8);
+ DROUND(9);
+ DROUND(10);
+ DROUND(11);
+ DROUND(12);
+ DROUND(13);
+ DROUND(14);
+ DROUND(15);
+ DROUND(16);
+}
+
+/**
+ Initialize an Sober128 context (only the key)
+ @param st [out] The destination of the Sober128 state
+ @param key The secret key
+ @param keylen The length of the secret key (octets)
+ @return CRYPT_OK if successful
+*/
+int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen)
+{
+ ulong32 i, k;
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(keylen > 0);
+
+ /* keylen must be multiple of 4 bytes */
+ if ((keylen & 3) != 0) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ /* Register initialised to Fibonacci numbers */
+ st->R[0] = 1;
+ st->R[1] = 1;
+ for (i = 2; i < N; ++i) {
+ st->R[i] = st->R[i-1] + st->R[i-2];
+ }
+ st->konst = INITKONST;
+
+ for (i = 0; i < keylen; i += 4) {
+ k = BYTE2WORD((unsigned char *)&key[i]);
+ ADDKEY(k);
+ cycle(st->R);
+ XORNL(nltap(st));
+ }
+
+ /* also fold in the length of the key */
+ ADDKEY(keylen);
+
+ /* now diffuse */
+ s128_diffuse(st);
+ s128_genkonst(st);
+ s128_savestate(st);
+ st->nbuf = 0;
+
+ return CRYPT_OK;
+}
+
+/**
+ Set IV to the Sober128 state
+ @param st The Sober12820 state
+ @param iv The IV data to add
+ @param ivlen The length of the IV (must be 12)
+ @return CRYPT_OK on success
+ */
+int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen)
+{
+ ulong32 i, k;
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(iv != NULL);
+ LTC_ARGCHK(ivlen > 0);
+
+ /* ok we are adding an IV then... */
+ s128_reloadstate(st);
+
+ /* ivlen must be multiple of 4 bytes */
+ if ((ivlen & 3) != 0) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ for (i = 0; i < ivlen; i += 4) {
+ k = BYTE2WORD((unsigned char *)&iv[i]);
+ ADDKEY(k);
+ cycle(st->R);
+ XORNL(nltap(st));
+ }
+
+ /* also fold in the length of the key */
+ ADDKEY(ivlen);
+
+ /* now diffuse */
+ s128_diffuse(st);
+ st->nbuf = 0;
+
+ return CRYPT_OK;
+}
+
+/* XOR pseudo-random bytes into buffer
+ */
+#define SROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); XORWORD(t, in+(z*4), out+(z*4));
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sober128
+ @param st The Sober128 state
+ @param in The plaintext (or ciphertext)
+ @param inlen The length of the input (octets)
+ @param out [out] The ciphertext (or plaintext), length inlen
+ @return CRYPT_OK if successful
+*/
+int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out)
+{
+ ulong32 t;
+
+ if (inlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(st != NULL);
+
+ /* handle any previously buffered bytes */
+ while (st->nbuf != 0 && inlen != 0) {
+ *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF);
+ st->sbuf >>= 8;
+ st->nbuf -= 8;
+ --inlen;
+ }
+
+#ifndef LTC_SMALL_CODE
+ /* do lots at a time, if there's enough to do */
+ while (inlen >= N*4) {
+ SROUND(0);
+ SROUND(1);
+ SROUND(2);
+ SROUND(3);
+ SROUND(4);
+ SROUND(5);
+ SROUND(6);
+ SROUND(7);
+ SROUND(8);
+ SROUND(9);
+ SROUND(10);
+ SROUND(11);
+ SROUND(12);
+ SROUND(13);
+ SROUND(14);
+ SROUND(15);
+ SROUND(16);
+ out += 4*N;
+ in += 4*N;
+ inlen -= 4*N;
+ }
+#endif
+
+ /* do small or odd size buffers the slow way */
+ while (4 <= inlen) {
+ cycle(st->R);
+ t = nltap(st);
+ XORWORD(t, in, out);
+ out += 4;
+ in += 4;
+ inlen -= 4;
+ }
+
+ /* handle any trailing bytes */
+ if (inlen != 0) {
+ cycle(st->R);
+ st->sbuf = nltap(st);
+ st->nbuf = 32;
+ while (st->nbuf != 0 && inlen != 0) {
+ *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF);
+ st->sbuf >>= 8;
+ st->nbuf -= 8;
+ --inlen;
+ }
+ }
+
+ return CRYPT_OK;
+}
+
+int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen)
+{
+ if (outlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(out != NULL);
+ XMEMSET(out, 0, outlen);
+ return sober128_stream_crypt(st, out, outlen, out);
+}
+
+/**
+ Terminate and clear Sober128 state
+ @param st The Sober128 state
+ @return CRYPT_OK on success
+*/
+int sober128_stream_done(sober128_state *st)
+{
+ LTC_ARGCHK(st != NULL);
+ zeromem(st, sizeof(sober128_state));
+ return CRYPT_OK;
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/sober128/sober128_stream_memory.c b/Sources/libtomcrypt/stream/sober128/sober128_stream_memory.c
new file mode 100644
index 00000000..5150b820
--- /dev/null
+++ b/Sources/libtomcrypt/stream/sober128/sober128_stream_memory.c
@@ -0,0 +1,35 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SOBER128_STREAM
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with SOBER128
+ @param key The key
+ @param keylen The key length
+ @param iv The initial vector
+ @param ivlen The initial vector length
+ @param datain The plaintext (or ciphertext)
+ @param datalen The length of the input and output (octets)
+ @param dataout [out] The ciphertext (or plaintext)
+ @return CRYPT_OK if successful
+*/
+int sober128_stream_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout)
+{
+ sober128_state st;
+ int err;
+
+ if ((err = sober128_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY;
+ if ((err = sober128_stream_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY;
+ err = sober128_stream_crypt(&st, datain, datalen, dataout);
+WIPE_KEY:
+ sober128_stream_done(&st);
+ return err;
+}
+
+#endif /* LTC_SOBER128_STREAM */
diff --git a/Sources/libtomcrypt/stream/sober128/sober128_test.c b/Sources/libtomcrypt/stream/sober128/sober128_test.c
new file mode 100644
index 00000000..52ea3a8e
--- /dev/null
+++ b/Sources/libtomcrypt/stream/sober128/sober128_test.c
@@ -0,0 +1,43 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SOBER128
+
+int sober128_stream_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ unsigned char key[16] = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6b, 0x65, 0x79,
+ 0x20, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x73 };
+ unsigned char iv[4] = { 0x00, 0x00, 0x00, 0x00 };
+ unsigned char out[20] = { 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d,
+ 0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2,
+ 0x40, 0x37, 0x8b, 0xbb };
+ int err, len = 20;
+ unsigned char src[20], dst[20];
+ sober128_state st;
+
+ XMEMSET(src, 0, len); /* input */
+ if ((err = sober128_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err;
+ if ((err = sober128_stream_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err;
+ if ((err = sober128_stream_crypt(&st, src, len, dst)) != CRYPT_OK) return err;
+ if ((err = sober128_stream_done(&st)) != CRYPT_OK) return err;
+ if (compare_testvector(dst, len, out, len, "SOBER-128-TV1", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ /* crypt in a single call */
+ if ((err = sober128_stream_memory(key, sizeof(key), iv, sizeof(iv),
+ src, len, dst)) != CRYPT_OK) return err;
+ if (compare_testvector(dst, len, out, len, "SOBER-128-TV2", 0)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtomcrypt/stream/sober128/sober128tab.c b/Sources/libtomcrypt/stream/sober128/sober128tab.c
new file mode 100644
index 00000000..e067bb68
--- /dev/null
+++ b/Sources/libtomcrypt/stream/sober128/sober128tab.c
@@ -0,0 +1,166 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/**
+ @file sober128tab.c
+ SOBER-128 Tables
+*/
+
+#ifdef LTC_SOBER128TAB_C
+
+/* $ID$ */
+/* @(#)TuringMultab.h 1.3 (QUALCOMM) 02/09/03 */
+/* Multiplication table for Turing using 0xD02B4367 */
+static const ulong32 Multab[256] = {
+ 0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9,
+ 0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478,
+ 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746,
+ 0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697,
+ 0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A,
+ 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB,
+ 0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5,
+ 0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04,
+ 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2,
+ 0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613,
+ 0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D,
+ 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC,
+ 0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51,
+ 0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80,
+ 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE,
+ 0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F,
+ 0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F,
+ 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE,
+ 0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90,
+ 0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41,
+ 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC,
+ 0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D,
+ 0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703,
+ 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2,
+ 0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14,
+ 0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5,
+ 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB,
+ 0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A,
+ 0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787,
+ 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656,
+ 0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568,
+ 0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9,
+ 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748,
+ 0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699,
+ 0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7,
+ 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476,
+ 0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB,
+ 0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A,
+ 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34,
+ 0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5,
+ 0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523,
+ 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2,
+ 0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC,
+ 0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D,
+ 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0,
+ 0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61,
+ 0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F,
+ 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E,
+ 0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E,
+ 0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F,
+ 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71,
+ 0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0,
+ 0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D,
+ 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC,
+ 0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2,
+ 0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433,
+ 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5,
+ 0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24,
+ 0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A,
+ 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB,
+ 0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566,
+ 0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7,
+ 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789,
+ 0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658,
+};
+
+/* $ID$ */
+/* Sbox for SOBER-128 */
+/*
+ * This is really the combination of two SBoxes; the least significant
+ * 24 bits comes from:
+ * 8->32 Sbox generated by Millan et. al. at Queensland University of
+ * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter,
+ * "On the Design of 8*32 S-boxes". Unpublished report, by the
+ * Information Systems Research Centre,
+ * Queensland University of Technology, 1999.
+ *
+ * The most significant 8 bits are the Skipjack "F table", which can be
+ * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf .
+ * In this optimised table, though, the intent is to XOR the word from
+ * the table selected by the high byte with the input word. Thus, the
+ * high byte is actually the Skipjack F-table entry XORED with its
+ * table index.
+ */
+static const ulong32 Sbox[256] = {
+ 0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4,
+ 0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae,
+ 0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c,
+ 0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35,
+ 0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e,
+ 0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b,
+ 0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f,
+ 0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1,
+ 0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd,
+ 0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3,
+ 0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f,
+ 0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36,
+ 0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf,
+ 0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816,
+ 0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d,
+ 0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af,
+ 0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6,
+ 0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418,
+ 0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0,
+ 0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd,
+ 0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088,
+ 0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759,
+ 0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895,
+ 0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66,
+ 0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc,
+ 0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1,
+ 0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911,
+ 0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e,
+ 0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515,
+ 0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133,
+ 0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226,
+ 0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084,
+ 0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb,
+ 0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184,
+ 0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420,
+ 0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02,
+ 0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655,
+ 0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c,
+ 0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418,
+ 0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473,
+ 0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a,
+ 0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0,
+ 0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21,
+ 0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36,
+ 0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5,
+ 0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6,
+ 0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0,
+ 0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795,
+ 0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0,
+ 0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78,
+ 0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da,
+ 0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a,
+ 0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118,
+ 0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed,
+ 0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd,
+ 0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b,
+ 0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921,
+ 0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e,
+ 0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5,
+ 0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8,
+ 0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376,
+ 0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a,
+ 0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8,
+ 0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40,
+};
+
+#endif /* LTC_SOBER128TAB_C */
diff --git a/Sources/libtomcrypt/stream/sosemanuk/sosemanuk.c b/Sources/libtomcrypt/stream/sosemanuk/sosemanuk.c
new file mode 100644
index 00000000..6733450e
--- /dev/null
+++ b/Sources/libtomcrypt/stream/sosemanuk/sosemanuk.c
@@ -0,0 +1,807 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/*
+ * This LTC implementation was adapted from:
+ * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html
+ */
+
+/*
+ * SOSEMANUK reference implementation.
+ *
+ * This code is supposed to run on any conforming C implementation (C90
+ * or later).
+ *
+ * (c) 2005 X-CRYPT project. This software is provided 'as-is', without
+ * any express or implied warranty. In no event will the authors be held
+ * liable for any damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to no restriction.
+ *
+ * Technical remarks and questions can be addressed to
+ *
+ */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SOSEMANUK
+
+/* ======================================================================== */
+
+/*
+ * We want (and sometimes need) to perform explicit truncations to 32 bits.
+ */
+#define T32(x) ((x) & (ulong32)0xFFFFFFFF)
+
+/*
+ * Some of our functions will be tagged as "inline" to help the compiler
+ * optimize things. We use "inline" only if the compiler is advanced
+ * enough to understand it; C99 compilers, and pre-C99 versions of gcc,
+ * understand enough "inline" for our purposes.
+ */
+
+/* ======================================================================== */
+
+/*
+ * Serpent S-boxes, implemented in bitslice mode. These circuits have
+ * been published by Dag Arne Osvik ("Speeding up Serpent", published in
+ * the 3rd AES Candidate Conference) and work on five 32-bit registers:
+ * the four inputs, and a fifth scratch register. There are meant to be
+ * quite fast on Pentium-class processors. These are not the fastest
+ * published, but they are "fast enough" and they are unencumbered as
+ * far as intellectual property is concerned (note: these are rewritten
+ * from the article itself, and hence are not covered by the GPL on
+ * Dag's code, which was not used here).
+ *
+ * The output bits are permuted. Here is the correspondance:
+ * S0: 1420
+ * S1: 2031
+ * S2: 2314
+ * S3: 1234
+ * S4: 1403
+ * S5: 1302
+ * S6: 0142
+ * S7: 4310
+ * (for instance, the output of S0 is in "r1, r4, r2, r0").
+ */
+
+#define S0(r0, r1, r2, r3, r4) do { \
+ r3 ^= r0; r4 = r1; \
+ r1 &= r3; r4 ^= r2; \
+ r1 ^= r0; r0 |= r3; \
+ r0 ^= r4; r4 ^= r3; \
+ r3 ^= r2; r2 |= r1; \
+ r2 ^= r4; r4 = ~r4; \
+ r4 |= r1; r1 ^= r3; \
+ r1 ^= r4; r3 |= r0; \
+ r1 ^= r3; r4 ^= r3; \
+ } while (0)
+
+#define S1(r0, r1, r2, r3, r4) do { \
+ r0 = ~r0; r2 = ~r2; \
+ r4 = r0; r0 &= r1; \
+ r2 ^= r0; r0 |= r3; \
+ r3 ^= r2; r1 ^= r0; \
+ r0 ^= r4; r4 |= r1; \
+ r1 ^= r3; r2 |= r0; \
+ r2 &= r4; r0 ^= r1; \
+ r1 &= r2; \
+ r1 ^= r0; r0 &= r2; \
+ r0 ^= r4; \
+ } while (0)
+
+#define S2(r0, r1, r2, r3, r4) do { \
+ r4 = r0; r0 &= r2; \
+ r0 ^= r3; r2 ^= r1; \
+ r2 ^= r0; r3 |= r4; \
+ r3 ^= r1; r4 ^= r2; \
+ r1 = r3; r3 |= r4; \
+ r3 ^= r0; r0 &= r1; \
+ r4 ^= r0; r1 ^= r3; \
+ r1 ^= r4; r4 = ~r4; \
+ } while (0)
+
+#define S3(r0, r1, r2, r3, r4) do { \
+ r4 = r0; r0 |= r3; \
+ r3 ^= r1; r1 &= r4; \
+ r4 ^= r2; r2 ^= r3; \
+ r3 &= r0; r4 |= r1; \
+ r3 ^= r4; r0 ^= r1; \
+ r4 &= r0; r1 ^= r3; \
+ r4 ^= r2; r1 |= r0; \
+ r1 ^= r2; r0 ^= r3; \
+ r2 = r1; r1 |= r3; \
+ r1 ^= r0; \
+ } while (0)
+
+#define S4(r0, r1, r2, r3, r4) do { \
+ r1 ^= r3; r3 = ~r3; \
+ r2 ^= r3; r3 ^= r0; \
+ r4 = r1; r1 &= r3; \
+ r1 ^= r2; r4 ^= r3; \
+ r0 ^= r4; r2 &= r4; \
+ r2 ^= r0; r0 &= r1; \
+ r3 ^= r0; r4 |= r1; \
+ r4 ^= r0; r0 |= r3; \
+ r0 ^= r2; r2 &= r3; \
+ r0 = ~r0; r4 ^= r2; \
+ } while (0)
+
+#define S5(r0, r1, r2, r3, r4) do { \
+ r0 ^= r1; r1 ^= r3; \
+ r3 = ~r3; r4 = r1; \
+ r1 &= r0; r2 ^= r3; \
+ r1 ^= r2; r2 |= r4; \
+ r4 ^= r3; r3 &= r1; \
+ r3 ^= r0; r4 ^= r1; \
+ r4 ^= r2; r2 ^= r0; \
+ r0 &= r3; r2 = ~r2; \
+ r0 ^= r4; r4 |= r3; \
+ r2 ^= r4; \
+ } while (0)
+
+#define S6(r0, r1, r2, r3, r4) do { \
+ r2 = ~r2; r4 = r3; \
+ r3 &= r0; r0 ^= r4; \
+ r3 ^= r2; r2 |= r4; \
+ r1 ^= r3; r2 ^= r0; \
+ r0 |= r1; r2 ^= r1; \
+ r4 ^= r0; r0 |= r3; \
+ r0 ^= r2; r4 ^= r3; \
+ r4 ^= r0; r3 = ~r3; \
+ r2 &= r4; \
+ r2 ^= r3; \
+ } while (0)
+
+#define S7(r0, r1, r2, r3, r4) do { \
+ r4 = r1; r1 |= r2; \
+ r1 ^= r3; r4 ^= r2; \
+ r2 ^= r1; r3 |= r4; \
+ r3 &= r0; r4 ^= r2; \
+ r3 ^= r1; r1 |= r4; \
+ r1 ^= r0; r0 |= r4; \
+ r0 ^= r2; r1 ^= r4; \
+ r2 ^= r1; r1 &= r0; \
+ r1 ^= r4; r2 = ~r2; \
+ r2 |= r0; \
+ r4 ^= r2; \
+ } while (0)
+
+/*
+ * The Serpent linear transform.
+ */
+#define SERPENT_LT(x0, x1, x2, x3) do { \
+ x0 = ROLc(x0, 13); \
+ x2 = ROLc(x2, 3); \
+ x1 = x1 ^ x0 ^ x2; \
+ x3 = x3 ^ x2 ^ T32(x0 << 3); \
+ x1 = ROLc(x1, 1); \
+ x3 = ROLc(x3, 7); \
+ x0 = x0 ^ x1 ^ x3; \
+ x2 = x2 ^ x3 ^ T32(x1 << 7); \
+ x0 = ROLc(x0, 5); \
+ x2 = ROLc(x2, 22); \
+ } while (0)
+
+/* ======================================================================== */
+
+/*
+ * Initialize Sosemanuk's state by providing a key. The key is an array of
+ * 1 to 32 bytes.
+ * @param st The Sosemanuk state
+ * @param key Key
+ * @param keylen Length of key in bytes
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen)
+{
+ /*
+ * This key schedule is actually a truncated Serpent key schedule.
+ * The key-derived words (w_i) are computed within the eight
+ * local variables w0 to w7, which are reused again and again.
+ */
+
+#define SKS(S, o0, o1, o2, o3, d0, d1, d2, d3) do { \
+ ulong32 r0, r1, r2, r3, r4; \
+ r0 = w ## o0; \
+ r1 = w ## o1; \
+ r2 = w ## o2; \
+ r3 = w ## o3; \
+ S(r0, r1, r2, r3, r4); \
+ st->kc[i ++] = r ## d0; \
+ st->kc[i ++] = r ## d1; \
+ st->kc[i ++] = r ## d2; \
+ st->kc[i ++] = r ## d3; \
+ } while (0)
+
+#define SKS0 SKS(S0, 4, 5, 6, 7, 1, 4, 2, 0)
+#define SKS1 SKS(S1, 0, 1, 2, 3, 2, 0, 3, 1)
+#define SKS2 SKS(S2, 4, 5, 6, 7, 2, 3, 1, 4)
+#define SKS3 SKS(S3, 0, 1, 2, 3, 1, 2, 3, 4)
+#define SKS4 SKS(S4, 4, 5, 6, 7, 1, 4, 0, 3)
+#define SKS5 SKS(S5, 0, 1, 2, 3, 1, 3, 0, 2)
+#define SKS6 SKS(S6, 4, 5, 6, 7, 0, 1, 4, 2)
+#define SKS7 SKS(S7, 0, 1, 2, 3, 4, 3, 1, 0)
+
+#define WUP(wi, wi5, wi3, wi1, cc) do { \
+ ulong32 tt = (wi) ^ (wi5) ^ (wi3) \
+ ^ (wi1) ^ (0x9E3779B9 ^ (ulong32)(cc)); \
+ (wi) = ROLc(tt, 11); \
+ } while (0)
+
+#define WUP0(cc) do { \
+ WUP(w0, w3, w5, w7, cc); \
+ WUP(w1, w4, w6, w0, cc + 1); \
+ WUP(w2, w5, w7, w1, cc + 2); \
+ WUP(w3, w6, w0, w2, cc + 3); \
+ } while (0)
+
+#define WUP1(cc) do { \
+ WUP(w4, w7, w1, w3, cc); \
+ WUP(w5, w0, w2, w4, cc + 1); \
+ WUP(w6, w1, w3, w5, cc + 2); \
+ WUP(w7, w2, w4, w6, cc + 3); \
+ } while (0)
+
+ unsigned char wbuf[32];
+ ulong32 w0, w1, w2, w3, w4, w5, w6, w7;
+ int i = 0;
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(keylen > 0 && keylen <= 32);
+
+ /*
+ * The key is copied into the wbuf[] buffer and padded to 256 bits
+ * as described in the Serpent specification.
+ */
+ XMEMCPY(wbuf, key, keylen);
+ if (keylen < 32) {
+ wbuf[keylen] = 0x01;
+ if (keylen < 31) {
+ XMEMSET(wbuf + keylen + 1, 0, 31 - keylen);
+ }
+ }
+
+ LOAD32L(w0, wbuf);
+ LOAD32L(w1, wbuf + 4);
+ LOAD32L(w2, wbuf + 8);
+ LOAD32L(w3, wbuf + 12);
+ LOAD32L(w4, wbuf + 16);
+ LOAD32L(w5, wbuf + 20);
+ LOAD32L(w6, wbuf + 24);
+ LOAD32L(w7, wbuf + 28);
+
+ WUP0(0); SKS3;
+ WUP1(4); SKS2;
+ WUP0(8); SKS1;
+ WUP1(12); SKS0;
+ WUP0(16); SKS7;
+ WUP1(20); SKS6;
+ WUP0(24); SKS5;
+ WUP1(28); SKS4;
+ WUP0(32); SKS3;
+ WUP1(36); SKS2;
+ WUP0(40); SKS1;
+ WUP1(44); SKS0;
+ WUP0(48); SKS7;
+ WUP1(52); SKS6;
+ WUP0(56); SKS5;
+ WUP1(60); SKS4;
+ WUP0(64); SKS3;
+ WUP1(68); SKS2;
+ WUP0(72); SKS1;
+ WUP1(76); SKS0;
+ WUP0(80); SKS7;
+ WUP1(84); SKS6;
+ WUP0(88); SKS5;
+ WUP1(92); SKS4;
+ WUP0(96); SKS3;
+
+#undef SKS
+#undef SKS0
+#undef SKS1
+#undef SKS2
+#undef SKS3
+#undef SKS4
+#undef SKS5
+#undef SKS6
+#undef SKS7
+#undef WUP
+#undef WUP0
+#undef WUP1
+
+ return CRYPT_OK;
+}
+
+
+/*
+ * Initialization continues by setting the IV. The IV length is up to 16 bytes.
+ * If "ivlen" is 0 (no IV), then the "iv" parameter can be NULL. If multiple
+ * encryptions/decryptions are to be performed with the same key and
+ * sosemanuk_done() has not been called, only sosemanuk_setiv() need be called
+ * to set the state.
+ * @param st The Sosemanuk state
+ * @param iv Initialization vector
+ * @param ivlen Length of iv in bytes
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen)
+{
+
+ /*
+ * The Serpent key addition step.
+ */
+#define KA(zc, x0, x1, x2, x3) do { \
+ x0 ^= st->kc[(zc)]; \
+ x1 ^= st->kc[(zc) + 1]; \
+ x2 ^= st->kc[(zc) + 2]; \
+ x3 ^= st->kc[(zc) + 3]; \
+ } while (0)
+
+ /*
+ * One Serpent round.
+ * zc = current subkey counter
+ * S = S-box macro for this round
+ * i0 to i4 = input register numbers (the fifth is a scratch register)
+ * o0 to o3 = output register numbers
+ */
+#define FSS(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \
+ KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \
+ S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \
+ SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \
+ } while (0)
+
+ /*
+ * Last Serpent round. Contrary to the "true" Serpent, we keep
+ * the linear transformation for that last round.
+ */
+#define FSF(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \
+ KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \
+ S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \
+ SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \
+ KA(zc + 4, r ## o0, r ## o1, r ## o2, r ## o3); \
+ } while (0)
+
+ ulong32 r0, r1, r2, r3, r4;
+ unsigned char ivtmp[16] = {0};
+
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(ivlen <= 16);
+ LTC_ARGCHK(iv != NULL || ivlen == 0);
+
+ if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen);
+
+ /*
+ * Decode IV into four 32-bit words (little-endian).
+ */
+ LOAD32L(r0, ivtmp);
+ LOAD32L(r1, ivtmp + 4);
+ LOAD32L(r2, ivtmp + 8);
+ LOAD32L(r3, ivtmp + 12);
+
+ /*
+ * Encrypt IV with Serpent24. Some values are extracted from the
+ * output of the twelfth, eighteenth and twenty-fourth rounds.
+ */
+ FSS(0, S0, 0, 1, 2, 3, 4, 1, 4, 2, 0);
+ FSS(4, S1, 1, 4, 2, 0, 3, 2, 1, 0, 4);
+ FSS(8, S2, 2, 1, 0, 4, 3, 0, 4, 1, 3);
+ FSS(12, S3, 0, 4, 1, 3, 2, 4, 1, 3, 2);
+ FSS(16, S4, 4, 1, 3, 2, 0, 1, 0, 4, 2);
+ FSS(20, S5, 1, 0, 4, 2, 3, 0, 2, 1, 4);
+ FSS(24, S6, 0, 2, 1, 4, 3, 0, 2, 3, 1);
+ FSS(28, S7, 0, 2, 3, 1, 4, 4, 1, 2, 0);
+ FSS(32, S0, 4, 1, 2, 0, 3, 1, 3, 2, 4);
+ FSS(36, S1, 1, 3, 2, 4, 0, 2, 1, 4, 3);
+ FSS(40, S2, 2, 1, 4, 3, 0, 4, 3, 1, 0);
+ FSS(44, S3, 4, 3, 1, 0, 2, 3, 1, 0, 2);
+ st->s09 = r3;
+ st->s08 = r1;
+ st->s07 = r0;
+ st->s06 = r2;
+
+ FSS(48, S4, 3, 1, 0, 2, 4, 1, 4, 3, 2);
+ FSS(52, S5, 1, 4, 3, 2, 0, 4, 2, 1, 3);
+ FSS(56, S6, 4, 2, 1, 3, 0, 4, 2, 0, 1);
+ FSS(60, S7, 4, 2, 0, 1, 3, 3, 1, 2, 4);
+ FSS(64, S0, 3, 1, 2, 4, 0, 1, 0, 2, 3);
+ FSS(68, S1, 1, 0, 2, 3, 4, 2, 1, 3, 0);
+ st->r1 = r2;
+ st->s04 = r1;
+ st->r2 = r3;
+ st->s05 = r0;
+
+ FSS(72, S2, 2, 1, 3, 0, 4, 3, 0, 1, 4);
+ FSS(76, S3, 3, 0, 1, 4, 2, 0, 1, 4, 2);
+ FSS(80, S4, 0, 1, 4, 2, 3, 1, 3, 0, 2);
+ FSS(84, S5, 1, 3, 0, 2, 4, 3, 2, 1, 0);
+ FSS(88, S6, 3, 2, 1, 0, 4, 3, 2, 4, 1);
+ FSF(92, S7, 3, 2, 4, 1, 0, 0, 1, 2, 3);
+ st->s03 = r0;
+ st->s02 = r1;
+ st->s01 = r2;
+ st->s00 = r3;
+
+ st->ptr = sizeof(st->buf);
+
+#undef KA
+#undef FSS
+#undef FSF
+
+ return CRYPT_OK;
+}
+
+/*
+ * Multiplication by alpha: alpha * x = T32(x << 8) ^ mul_a[x >> 24]
+ */
+static const ulong32 mul_a[] = {
+ 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835,
+ 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679,
+ 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD,
+ 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1,
+ 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC,
+ 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0,
+ 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534,
+ 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78,
+ 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE,
+ 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2,
+ 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636,
+ 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A,
+ 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37,
+ 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B,
+ 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF,
+ 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3,
+ 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA,
+ 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6,
+ 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032,
+ 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E,
+ 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33,
+ 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F,
+ 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB,
+ 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7,
+ 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31,
+ 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D,
+ 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9,
+ 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5,
+ 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8,
+ 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4,
+ 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330,
+ 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C,
+ 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2,
+ 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE,
+ 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A,
+ 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276,
+ 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B,
+ 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77,
+ 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3,
+ 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF,
+ 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239,
+ 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75,
+ 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1,
+ 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED,
+ 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0,
+ 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC,
+ 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38,
+ 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174,
+ 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D,
+ 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71,
+ 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5,
+ 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9,
+ 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4,
+ 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8,
+ 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C,
+ 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770,
+ 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6,
+ 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA,
+ 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E,
+ 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472,
+ 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F,
+ 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973,
+ 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7,
+ 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB
+};
+
+/*
+ * Multiplication by 1/alpha: 1/alpha * x = (x >> 8) ^ mul_ia[x & 0xFF]
+ */
+static const ulong32 mul_ia[] = {
+ 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE,
+ 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998,
+ 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32,
+ 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254,
+ 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF,
+ 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9,
+ 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403,
+ 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65,
+ 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C,
+ 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA,
+ 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550,
+ 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36,
+ 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD,
+ 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB,
+ 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61,
+ 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307,
+ 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A,
+ 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C,
+ 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6,
+ 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790,
+ 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B,
+ 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D,
+ 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7,
+ 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1,
+ 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58,
+ 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E,
+ 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094,
+ 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2,
+ 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469,
+ 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F,
+ 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5,
+ 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3,
+ 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF,
+ 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9,
+ 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813,
+ 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175,
+ 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE,
+ 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588,
+ 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722,
+ 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44,
+ 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD,
+ 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB,
+ 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671,
+ 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17,
+ 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C,
+ 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA,
+ 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940,
+ 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026,
+ 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B,
+ 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D,
+ 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7,
+ 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1,
+ 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A,
+ 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C,
+ 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6,
+ 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80,
+ 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879,
+ 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F,
+ 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5,
+ 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3,
+ 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748,
+ 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E,
+ 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84,
+ 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2
+};
+
+
+/*
+ * Compute the next block of bits of output stream. This is equivalent
+ * to one full rotation of the shift register.
+ */
+static LTC_INLINE void s_sosemanuk_internal(sosemanuk_state *st)
+{
+ /*
+ * MUL_A(x) computes alpha * x (in F_{2^32}).
+ * MUL_G(x) computes 1/alpha * x (in F_{2^32}).
+ */
+#define MUL_A(x) (T32((x) << 8) ^ mul_a[(x) >> 24])
+#define MUL_G(x) (((x) >> 8) ^ mul_ia[(x) & 0xFF])
+
+ /*
+ * This macro computes the special multiplexer, which chooses
+ * between "x" and "x xor y", depending on the least significant
+ * bit of the control word. We use the C "?:" selection operator
+ * (which most compilers know how to optimise) except for Alpha,
+ * where the manual sign extension seems to perform equally well
+ * with DEC/Compaq/HP compiler, and much better with gcc.
+ */
+#ifdef __alpha
+#define XMUX(c, x, y) ((((signed int)((c) << 31) >> 31) & (y)) ^ (x))
+#else
+#define XMUX(c, x, y) (((c) & 0x1) ? ((x) ^ (y)) : (x))
+#endif
+
+ /*
+ * FSM() updates the finite state machine.
+ */
+#define FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) do { \
+ ulong32 tt, or1; \
+ tt = XMUX(r1, s ## x1, s ## x8); \
+ or1 = r1; \
+ r1 = T32(r2 + tt); \
+ tt = T32(or1 * 0x54655307); \
+ r2 = ROLc(tt, 7); \
+ } while (0)
+
+ /*
+ * LRU updates the shift register; the dropped value is stored
+ * in variable "dd".
+ */
+#define LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd) do { \
+ dd = s ## x0; \
+ s ## x0 = MUL_A(s ## x0) ^ MUL_G(s ## x3) ^ s ## x9; \
+ } while (0)
+
+ /*
+ * CC1 stores into variable "ee" the next intermediate word
+ * (combination of the new states of the LFSR and the FSM).
+ */
+#define CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee) do { \
+ ee = T32(s ## x9 + r1) ^ r2; \
+ } while (0)
+
+ /*
+ * STEP computes one internal round. "dd" receives the "s_t"
+ * value (dropped from the LFSR) and "ee" gets the value computed
+ * from the LFSR and FSM.
+ */
+#define STEP(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd, ee) do { \
+ FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9); \
+ LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd); \
+ CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee); \
+ } while (0)
+
+ /*
+ * Apply one Serpent round (with the provided S-box macro), XOR
+ * the result with the "v" values, and encode the result into
+ * the destination buffer, at the provided offset. The "x*"
+ * arguments encode the output permutation of the "S" macro.
+ */
+#define SRD(S, x0, x1, x2, x3, ooff) do { \
+ S(u0, u1, u2, u3, u4); \
+ STORE32L(u ## x0 ^ v0, st->buf + ooff); \
+ STORE32L(u ## x1 ^ v1, st->buf + ooff + 4); \
+ STORE32L(u ## x2 ^ v2, st->buf + ooff + 8); \
+ STORE32L(u ## x3 ^ v3, st->buf + ooff + 12); \
+ } while (0)
+
+ ulong32 s00 = st->s00;
+ ulong32 s01 = st->s01;
+ ulong32 s02 = st->s02;
+ ulong32 s03 = st->s03;
+ ulong32 s04 = st->s04;
+ ulong32 s05 = st->s05;
+ ulong32 s06 = st->s06;
+ ulong32 s07 = st->s07;
+ ulong32 s08 = st->s08;
+ ulong32 s09 = st->s09;
+ ulong32 r1 = st->r1;
+ ulong32 r2 = st->r2;
+ ulong32 u0, u1, u2, u3, u4;
+ ulong32 v0, v1, v2, v3;
+
+ STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v0, u0);
+ STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v1, u1);
+ STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v2, u2);
+ STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v3, u3);
+ SRD(S2, 2, 3, 1, 4, 0);
+ STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v0, u0);
+ STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v1, u1);
+ STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v2, u2);
+ STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v3, u3);
+ SRD(S2, 2, 3, 1, 4, 16);
+ STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v0, u0);
+ STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v1, u1);
+ STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v2, u2);
+ STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v3, u3);
+ SRD(S2, 2, 3, 1, 4, 32);
+ STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v0, u0);
+ STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v1, u1);
+ STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v2, u2);
+ STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v3, u3);
+ SRD(S2, 2, 3, 1, 4, 48);
+ STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v0, u0);
+ STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v1, u1);
+ STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v2, u2);
+ STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v3, u3);
+ SRD(S2, 2, 3, 1, 4, 64);
+
+ st->s00 = s00;
+ st->s01 = s01;
+ st->s02 = s02;
+ st->s03 = s03;
+ st->s04 = s04;
+ st->s05 = s05;
+ st->s06 = s06;
+ st->s07 = s07;
+ st->s08 = s08;
+ st->s09 = s09;
+ st->r1 = r1;
+ st->r2 = r2;
+}
+
+/*
+ * Combine buffers in1[] and in2[] by XOR, result in out[]. The length
+ * is "datalen" (in bytes). Partial overlap of out[] with either in1[]
+ * or in2[] is not allowed. Total overlap (out == in1 and/or out == in2)
+ * is allowed.
+ */
+static LTC_INLINE void s_xorbuf(const unsigned char *in1, const unsigned char *in2,
+ unsigned char *out, unsigned long datalen)
+{
+ while (datalen -- > 0) {
+ *out ++ = *in1 ++ ^ *in2 ++;
+ }
+}
+
+
+/*
+ * Cipher operation, as a stream cipher: data is read from the "in"
+ * buffer, combined by XOR with the stream, and the result is written
+ * in the "out" buffer. "in" and "out" must be either equal, or
+ * reference distinct buffers (no partial overlap is allowed).
+ * @param st The Sosemanuk state
+ * @param in Data in
+ * @param inlen Length of data in bytes
+ * @param out Data out
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_crypt(sosemanuk_state *st,
+ const unsigned char *in, unsigned long inlen, unsigned char *out)
+{
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (st->ptr < (sizeof(st->buf))) {
+ unsigned long rlen = (sizeof(st->buf)) - st->ptr;
+
+ if (rlen > inlen) {
+ rlen = inlen;
+ }
+ s_xorbuf(st->buf + st->ptr, in, out, rlen);
+ in += rlen;
+ out += rlen;
+ inlen -= rlen;
+ st->ptr += rlen;
+ }
+ while (inlen > 0) {
+ s_sosemanuk_internal(st);
+ if (inlen >= sizeof(st->buf)) {
+ s_xorbuf(st->buf, in, out, sizeof(st->buf));
+ in += sizeof(st->buf);
+ out += sizeof(st->buf);
+ inlen -= sizeof(st->buf);
+ } else {
+ s_xorbuf(st->buf, in, out, inlen);
+ st->ptr = inlen;
+ inlen = 0;
+ }
+ }
+ return CRYPT_OK;
+}
+
+
+
+/*
+ * Cipher operation, as a PRNG: the provided output buffer is filled with
+ * pseudo-random bytes as output from the stream cipher.
+ * @param st The Sosemanuk state
+ * @param out Data out
+ * @param outlen Length of output in bytes
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen)
+{
+ if (outlen == 0) return CRYPT_OK; /* nothing to do */
+ LTC_ARGCHK(out != NULL);
+ XMEMSET(out, 0, outlen);
+ return sosemanuk_crypt(st, out, outlen, out);
+}
+
+
+/*
+ * Terminate and clear Sosemanuk key context
+ * @param st The Sosemanuk state
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_done(sosemanuk_state *st)
+{
+ LTC_ARGCHK(st != NULL);
+ zeromem(st, sizeof(sosemanuk_state));
+ return CRYPT_OK;
+}
+
+
+#endif
diff --git a/Sources/libtomcrypt/stream/sosemanuk/sosemanuk_memory.c b/Sources/libtomcrypt/stream/sosemanuk/sosemanuk_memory.c
new file mode 100644
index 00000000..c0fac259
--- /dev/null
+++ b/Sources/libtomcrypt/stream/sosemanuk/sosemanuk_memory.c
@@ -0,0 +1,35 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SOSEMANUK
+
+/**
+ Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sosemanuk
+ @param key The key
+ @param keylen The key length
+ @param iv The initial vector
+ @param ivlen The initial vector length
+ @param datain The plaintext (or ciphertext)
+ @param datalen The length of the input and output (octets)
+ @param dataout [out] The ciphertext (or plaintext)
+ @return CRYPT_OK if successful
+*/
+int sosemanuk_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout)
+{
+ sosemanuk_state st;
+ int err;
+
+ if ((err = sosemanuk_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY;
+ if ((err = sosemanuk_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY;
+ err = sosemanuk_crypt(&st, datain, datalen, dataout);
+WIPE_KEY:
+ sosemanuk_done(&st);
+ return err;
+}
+
+#endif /* LTC_SOSEMANUK */
diff --git a/Sources/libtomcrypt/stream/sosemanuk/sosemanuk_test.c b/Sources/libtomcrypt/stream/sosemanuk/sosemanuk_test.c
new file mode 100644
index 00000000..2c0a887e
--- /dev/null
+++ b/Sources/libtomcrypt/stream/sosemanuk/sosemanuk_test.c
@@ -0,0 +1,79 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SOSEMANUK
+int sosemanuk_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ sosemanuk_state st;
+ int err;
+ unsigned char out[1000];
+
+ {
+ unsigned char k[] = { 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 };
+ unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ unsigned char ct[] = { 0x7e, 0xfe, 0x2e, 0x6f, 0x8f, 0x77, 0x15, 0x72, 0x6a, 0x88, 0x14, 0xa6, 0x56, 0x88, 0x29, 0x9a,
+ 0x86, 0x32, 0x7f, 0x14, 0xd6, 0xb1, 0x94, 0x90, 0x25, 0xbc, 0x73, 0xfd, 0x02, 0x6c, 0x6a, 0xb8,
+ 0xda, 0x8e, 0x7f, 0x61, 0x70, 0x81, 0xe3, 0xbb, 0x99, 0xaf, 0x19, 0x9f, 0x20, 0x45 };
+ char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */
+ unsigned long len;
+ len = XSTRLEN(pt);
+ /* crypt piece by piece */
+ if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err;
+ if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err;
+ if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err;
+ if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err;
+ if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV1", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* crypt in one go - using sosemanuk_ivctr64() */
+ if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err;
+ if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err;
+ if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV2", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ /* crypt in a single call */
+ if ((err = sosemanuk_memory(k, sizeof(k), n, sizeof(n),
+ (unsigned char*)pt, len, out)) != CRYPT_OK) return err;
+ if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV3", 1)) return CRYPT_FAIL_TESTVECTOR;
+
+ }
+ {
+ /* keystream
+ * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sosemanuk/unverified.test-vectors?rev=210&view=auto
+ * Set 6, vector 0
+ * key = 0053A6F94C9FF24598EB3E91E4378ADD
+ * 3083D6297CCF2275C81B6EC11467BA0D
+ * IV = 0D74DB42A91077DE45AC137AE148AF16
+ * stream[0..63] = 55EB8D174C2E0351E5A53C90E84740EB
+ * 0F5A24AAFEC8E0C9F9D2CE48B2ADB0A3
+ * 4D2E8C4E016102607368FFA43A0F9155
+ * 0706E3548AD9E5EA15A53EB6F0EDE9DC
+ *
+ */
+
+ unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD,
+ 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D };
+ unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE, 0x45, 0xAC, 0x13, 0x7A, 0xE1, 0x48, 0xAF, 0x16 };
+ unsigned char ct3[] = { 0x55, 0xEB, 0x8D, 0x17, 0x4C, 0x2E, 0x03, 0x51, 0xE5, 0xA5, 0x3C, 0x90, 0xE8, 0x47, 0x40, 0xEB,
+ 0x0F, 0x5A, 0x24, 0xAA, 0xFE, 0xC8, 0xE0, 0xC9, 0xF9, 0xD2, 0xCE, 0x48, 0xB2, 0xAD, 0xB0, 0xA3,
+ 0x4D, 0x2E, 0x8C, 0x4E, 0x01, 0x61, 0x02, 0x60, 0x73, 0x68, 0xFF, 0xA4, 0x3A, 0x0F, 0x91, 0x55,
+ 0x07, 0x06, 0xE3, 0x54, 0x8A, 0xD9, 0xE5, 0xEA, 0x15, 0xA5, 0x3E, 0xB6, 0xF0, 0xED, 0xE9, 0xDC };
+ if ((err = sosemanuk_setup(&st, k3, sizeof(k3))) != CRYPT_OK) return err;
+ if ((err = sosemanuk_setiv(&st, n3, sizeof(n3))) != CRYPT_OK) return err;
+ if ((err = sosemanuk_keystream(&st, out, 64)) != CRYPT_OK) return err;
+ if ((err = sosemanuk_done(&st)) != CRYPT_OK) return err;
+ if (compare_testvector(out, 64, ct3, sizeof(ct3), "SOSEMANUK-TV4", 1)) return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/Sources/libtommath/bn_s_mp_rand_platform.c b/Sources/libtommath/bn_s_mp_rand_platform.c
index 5624e0cb..7944f894 100644
--- a/Sources/libtommath/bn_s_mp_rand_platform.c
+++ b/Sources/libtommath/bn_s_mp_rand_platform.c
@@ -137,10 +137,14 @@ mp_err s_read_ltm_rng(void *p, size_t n);
mp_err s_mp_rand_platform(void *p, size_t n)
{
mp_err err = MP_ERR;
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n);
-// if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n);
+#elif defined(_WIN32)
+ if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n);
+#else
// if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n);
if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n);
+#endif
// if ((err != MP_OKAY) && MP_HAS(S_READ_LTM_RNG)) err = s_read_ltm_rng(p, n);
return err;
}
diff --git a/Sources/libtommath/include/bignumshim.h b/Sources/libtommath/include/bignumshim.h
index 6b63a08f..07f9a52c 100644
--- a/Sources/libtommath/include/bignumshim.h
+++ b/Sources/libtommath/include/bignumshim.h
@@ -1,8 +1,8 @@
#ifndef bignumshim_h
#define bignumshim_h
-#import
-#import "tommath.h"
+#include
+#include "tommath.h"
typedef mp_int BIGNUM;
diff --git a/Sources/zlib-1.3.1/ChangeLog b/Sources/zlib-1.3.1/ChangeLog
new file mode 100644
index 00000000..b801a103
--- /dev/null
+++ b/Sources/zlib-1.3.1/ChangeLog
@@ -0,0 +1,1618 @@
+
+ ChangeLog file for zlib
+
+Changes in 1.3.1 (22 Jan 2024)
+- Reject overflows of zip header fields in minizip
+- Fix bug in inflateSync() for data held in bit buffer
+- Add LIT_MEM define to use more memory for a small deflate speedup
+- Fix decision on the emission of Zip64 end records in minizip
+- Add bounds checking to ERR_MSG() macro, used by zError()
+- Neutralize zip file traversal attacks in miniunz
+- Fix a bug in ZLIB_DEBUG compiles in check_match()
+- Various portability and appearance improvements
+
+Changes in 1.3 (18 Aug 2023)
+- Remove K&R function definitions and zlib2ansi
+- Fix bug in deflateBound() for level 0 and memLevel 9
+- Fix bug when gzungetc() is used immediately after gzopen()
+- Fix bug when using gzflush() with a very small buffer
+- Fix crash when gzsetparams() attempted for transparent write
+- Fix test/example.c to work with FORCE_STORED
+- Rewrite of zran in examples (see zran.c version history)
+- Fix minizip to allow it to open an empty zip file
+- Fix reading disk number start on zip64 files in minizip
+- Fix logic error in minizip argument processing
+- Add minizip testing to Makefile
+- Read multiple bytes instead of byte-by-byte in minizip unzip.c
+- Add memory sanitizer to configure (--memory)
+- Various portability improvements
+- Various documentation improvements
+- Various spelling and typo corrections
+
+Changes in 1.2.13 (13 Oct 2022)
+- Fix configure issue that discarded provided CC definition
+- Correct incorrect inputs provided to the CRC functions
+- Repair prototypes and exporting of new CRC functions
+- Fix inflateBack to detect invalid input with distances too far
+- Have infback() deliver all of the available output up to any error
+- Fix a bug when getting a gzip header extra field with inflate()
+- Fix bug in block type selection when Z_FIXED used
+- Tighten deflateBound bounds
+- Remove deleted assembler code references
+- Various portability and appearance improvements
+
+Changes in 1.2.12 (27 Mar 2022)
+- Cygwin does not have _wopen(), so do not create gzopen_w() there
+- Permit a deflateParams() parameter change as soon as possible
+- Limit hash table inserts after switch from stored deflate
+- Fix bug when window full in deflate_stored()
+- Fix CLEAR_HASH macro to be usable as a single statement
+- Avoid a conversion error in gzseek when off_t type too small
+- Have Makefile return non-zero error code on test failure
+- Avoid some conversion warnings in gzread.c and gzwrite.c
+- Update use of errno for newer Windows CE versions
+- Small speedup to inflate [psumbera]
+- Return an error if the gzputs string length can't fit in an int
+- Add address checking in clang to -w option of configure
+- Don't compute check value for raw inflate if asked to validate
+- Handle case where inflateSync used when header never processed
+- Avoid the use of ptrdiff_t
+- Avoid an undefined behavior of memcpy() in gzappend()
+- Avoid undefined behaviors of memcpy() in gz*printf()
+- Avoid an undefined behavior of memcpy() in _tr_stored_block()
+- Make the names in functions declarations identical to definitions
+- Remove old assembler code in which bugs have manifested
+- Fix deflateEnd() to not report an error at start of raw deflate
+- Add legal disclaimer to README
+- Emphasize the need to continue decompressing gzip members
+- Correct the initialization requirements for deflateInit2()
+- Fix a bug that can crash deflate on some input when using Z_FIXED
+- Assure that the number of bits for deflatePrime() is valid
+- Use a structure to make globals in enough.c evident
+- Use a macro for the printf format of big_t in enough.c
+- Clean up code style in enough.c, update version
+- Use inline function instead of macro for index in enough.c
+- Clarify that prefix codes are counted in enough.c
+- Show all the codes for the maximum tables size in enough.c
+- Add gznorm.c example, which normalizes gzip files
+- Fix the zran.c example to work on a multiple-member gzip file
+- Add tables for crc32_combine(), to speed it up by a factor of 200
+- Add crc32_combine_gen() and crc32_combine_op() for fast combines
+- Speed up software CRC-32 computation by a factor of 1.5 to 3
+- Use atomic test and set, if available, for dynamic CRC tables
+- Don't bother computing check value after successful inflateSync()
+- Correct comment in crc32.c
+- Add use of the ARMv8 crc32 instructions when requested
+- Use ARM crc32 instructions if the ARM architecture has them
+- Explicitly note that the 32-bit check values are 32 bits
+- Avoid adding empty gzip member after gzflush with Z_FINISH
+- Fix memory leak on error in gzlog.c
+- Fix error in comment on the polynomial representation of a byte
+- Clarify gz* function interfaces, referring to parameter names
+- Change macro name in inflate.c to avoid collision in VxWorks
+- Correct typo in blast.c
+- Improve portability of contrib/minizip
+- Fix indentation in minizip's zip.c
+- Replace black/white with allow/block. (theresa-m)
+- minizip warning fix if MAXU32 already defined. (gvollant)
+- Fix unztell64() in minizip to work past 4GB. (Daniël Hörchner)
+- Clean up minizip to reduce warnings for testing
+- Add fallthrough comments for gcc
+- Eliminate use of ULL constants
+- Separate out address sanitizing from warnings in configure
+- Remove destructive aspects of make distclean
+- Check for cc masquerading as gcc or clang in configure
+- Fix crc32.c to compile local functions only if used
+
+Changes in 1.2.11 (15 Jan 2017)
+- Fix deflate stored bug when pulling last block from window
+- Permit immediate deflateParams changes before any deflate input
+
+Changes in 1.2.10 (2 Jan 2017)
+- Avoid warnings on snprintf() return value
+- Fix bug in deflate_stored() for zero-length input
+- Fix bug in gzwrite.c that produced corrupt gzip files
+- Remove files to be installed before copying them in Makefile.in
+- Add warnings when compiling with assembler code
+
+Changes in 1.2.9 (31 Dec 2016)
+- Fix contrib/minizip to permit unzipping with desktop API [Zouzou]
+- Improve contrib/blast to return unused bytes
+- Assure that gzoffset() is correct when appending
+- Improve compress() and uncompress() to support large lengths
+- Fix bug in test/example.c where error code not saved
+- Remedy Coverity warning [Randers-Pehrson]
+- Improve speed of gzprintf() in transparent mode
+- Fix inflateInit2() bug when windowBits is 16 or 32
+- Change DEBUG macro to ZLIB_DEBUG
+- Avoid uninitialized access by gzclose_w()
+- Allow building zlib outside of the source directory
+- Fix bug that accepted invalid zlib header when windowBits is zero
+- Fix gzseek() problem on MinGW due to buggy _lseeki64 there
+- Loop on write() calls in gzwrite.c in case of non-blocking I/O
+- Add --warn (-w) option to ./configure for more compiler warnings
+- Reject a window size of 256 bytes if not using the zlib wrapper
+- Fix bug when level 0 used with Z_HUFFMAN or Z_RLE
+- Add --debug (-d) option to ./configure to define ZLIB_DEBUG
+- Fix bugs in creating a very large gzip header
+- Add uncompress2() function, which returns the input size used
+- Assure that deflateParams() will not switch functions mid-block
+- Dramatically speed up deflation for level 0 (storing)
+- Add gzfread(), duplicating the interface of fread()
+- Add gzfwrite(), duplicating the interface of fwrite()
+- Add deflateGetDictionary() function
+- Use snprintf() for later versions of Microsoft C
+- Fix *Init macros to use z_ prefix when requested
+- Replace as400 with os400 for OS/400 support [Monnerat]
+- Add crc32_z() and adler32_z() functions with size_t lengths
+- Update Visual Studio project files [AraHaan]
+
+Changes in 1.2.8 (28 Apr 2013)
+- Update contrib/minizip/iowin32.c for Windows RT [Vollant]
+- Do not force Z_CONST for C++
+- Clean up contrib/vstudio [Roß]
+- Correct spelling error in zlib.h
+- Fix mixed line endings in contrib/vstudio
+
+Changes in 1.2.7.3 (13 Apr 2013)
+- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc
+
+Changes in 1.2.7.2 (13 Apr 2013)
+- Change check for a four-byte type back to hexadecimal
+- Fix typo in win32/Makefile.msc
+- Add casts in gzwrite.c for pointer differences
+
+Changes in 1.2.7.1 (24 Mar 2013)
+- Replace use of unsafe string functions with snprintf if available
+- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink]
+- Fix gzgetc undefine when Z_PREFIX set [Turk]
+- Eliminate use of mktemp in Makefile (not always available)
+- Fix bug in 'F' mode for gzopen()
+- Add inflateGetDictionary() function
+- Correct comment in deflate.h
+- Use _snprintf for snprintf in Microsoft C
+- On Darwin, only use /usr/bin/libtool if libtool is not Apple
+- Delete "--version" file if created by "ar --version" [Richard G.]
+- Fix configure check for veracity of compiler error return codes
+- Fix CMake compilation of static lib for MSVC2010 x64
+- Remove unused variable in infback9.c
+- Fix argument checks in gzlog_compress() and gzlog_write()
+- Clean up the usage of z_const and respect const usage within zlib
+- Clean up examples/gzlog.[ch] comparisons of different types
+- Avoid shift equal to bits in type (caused endless loop)
+- Fix uninitialized value bug in gzputc() introduced by const patches
+- Fix memory allocation error in examples/zran.c [Nor]
+- Fix bug where gzopen(), gzclose() would write an empty file
+- Fix bug in gzclose() when gzwrite() runs out of memory
+- Check for input buffer malloc failure in examples/gzappend.c
+- Add note to contrib/blast to use binary mode in stdio
+- Fix comparisons of differently signed integers in contrib/blast
+- Check for invalid code length codes in contrib/puff
+- Fix serious but very rare decompression bug in inftrees.c
+- Update inflateBack() comments, since inflate() can be faster
+- Use underscored I/O function names for WINAPI_FAMILY
+- Add _tr_flush_bits to the external symbols prefixed by --zprefix
+- Add contrib/vstudio/vc10 pre-build step for static only
+- Quote --version-script argument in CMakeLists.txt
+- Don't specify --version-script on Apple platforms in CMakeLists.txt
+- Fix casting error in contrib/testzlib/testzlib.c
+- Fix types in contrib/minizip to match result of get_crc_table()
+- Simplify contrib/vstudio/vc10 with 'd' suffix
+- Add TOP support to win32/Makefile.msc
+- Support i686 and amd64 assembler builds in CMakeLists.txt
+- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h
+- Add vc11 and vc12 build files to contrib/vstudio
+- Add gzvprintf() as an undocumented function in zlib
+- Fix configure for Sun shell
+- Remove runtime check in configure for four-byte integer type
+- Add casts and consts to ease user conversion to C++
+- Add man pages for minizip and miniunzip
+- In Makefile uninstall, don't rm if preceding cd fails
+- Do not return Z_BUF_ERROR if deflateParam() has nothing to write
+
+Changes in 1.2.7 (2 May 2012)
+- Replace use of memmove() with a simple copy for portability
+- Test for existence of strerror
+- Restore gzgetc_ for backward compatibility with 1.2.6
+- Fix build with non-GNU make on Solaris
+- Require gcc 4.0 or later on Mac OS X to use the hidden attribute
+- Include unistd.h for Watcom C
+- Use __WATCOMC__ instead of __WATCOM__
+- Do not use the visibility attribute if NO_VIZ defined
+- Improve the detection of no hidden visibility attribute
+- Avoid using __int64 for gcc or solo compilation
+- Cast to char * in gzprintf to avoid warnings [Zinser]
+- Fix make_vms.com for VAX [Zinser]
+- Don't use library or built-in byte swaps
+- Simplify test and use of gcc hidden attribute
+- Fix bug in gzclose_w() when gzwrite() fails to allocate memory
+- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen()
+- Fix bug in test/minigzip.c for configure --solo
+- Fix contrib/vstudio project link errors [Mohanathas]
+- Add ability to choose the builder in make_vms.com [Schweda]
+- Add DESTDIR support to mingw32 win32/Makefile.gcc
+- Fix comments in win32/Makefile.gcc for proper usage
+- Allow overriding the default install locations for cmake
+- Generate and install the pkg-config file with cmake
+- Build both a static and a shared version of zlib with cmake
+- Include version symbols for cmake builds
+- If using cmake with MSVC, add the source directory to the includes
+- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta]
+- Move obsolete emx makefile to old [Truta]
+- Allow the use of -Wundef when compiling or using zlib
+- Avoid the use of the -u option with mktemp
+- Improve inflate() documentation on the use of Z_FINISH
+- Recognize clang as gcc
+- Add gzopen_w() in Windows for wide character path names
+- Rename zconf.h in CMakeLists.txt to move it out of the way
+- Add source directory in CMakeLists.txt for building examples
+- Look in build directory for zlib.pc in CMakeLists.txt
+- Remove gzflags from zlibvc.def in vc9 and vc10
+- Fix contrib/minizip compilation in the MinGW environment
+- Update ./configure for Solaris, support --64 [Mooney]
+- Remove -R. from Solaris shared build (possible security issue)
+- Avoid race condition for parallel make (-j) running example
+- Fix type mismatch between get_crc_table() and crc_table
+- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler]
+- Fix the path to zlib.map in CMakeLists.txt
+- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe]
+- Add instructions to win32/Makefile.gcc for shared install [Torri]
+
+Changes in 1.2.6.1 (12 Feb 2012)
+- Avoid the use of the Objective-C reserved name "id"
+- Include io.h in gzguts.h for Microsoft compilers
+- Fix problem with ./configure --prefix and gzgetc macro
+- Include gz_header definition when compiling zlib solo
+- Put gzflags() functionality back in zutil.c
+- Avoid library header include in crc32.c for Z_SOLO
+- Use name in GCC_CLASSIC as C compiler for coverage testing, if set
+- Minor cleanup in contrib/minizip/zip.c [Vollant]
+- Update make_vms.com [Zinser]
+- Remove unnecessary gzgetc_ function
+- Use optimized byte swap operations for Microsoft and GNU [Snyder]
+- Fix minor typo in zlib.h comments [Rzesniowiecki]
+
+Changes in 1.2.6 (29 Jan 2012)
+- Update the Pascal interface in contrib/pascal
+- Fix function numbers for gzgetc_ in zlibvc.def files
+- Fix configure.ac for contrib/minizip [Schiffer]
+- Fix large-entry detection in minizip on 64-bit systems [Schiffer]
+- Have ./configure use the compiler return code for error indication
+- Fix CMakeLists.txt for cross compilation [McClure]
+- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes]
+- Fix compilation of contrib/minizip on FreeBSD [Marquez]
+- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath]
+- Include io.h for Turbo C / Borland C on all platforms [Truta]
+- Make version explicit in contrib/minizip/configure.ac [Bosmans]
+- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant]
+- Minor cleanup up contrib/minizip/unzip.c [Vollant]
+- Fix bug when compiling minizip with C++ [Vollant]
+- Protect for long name and extra fields in contrib/minizip [Vollant]
+- Avoid some warnings in contrib/minizip [Vollant]
+- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip
+- Add missing libs to minizip linker command
+- Add support for VPATH builds in contrib/minizip
+- Add an --enable-demos option to contrib/minizip/configure
+- Add the generation of configure.log by ./configure
+- Exit when required parameters not provided to win32/Makefile.gcc
+- Have gzputc return the character written instead of the argument
+- Use the -m option on ldconfig for BSD systems [Tobias]
+- Correct in zlib.map when deflateResetKeep was added
+
+Changes in 1.2.5.3 (15 Jan 2012)
+- Restore gzgetc function for binary compatibility
+- Do not use _lseeki64 under Borland C++ [Truta]
+- Update win32/Makefile.msc to build test/*.c [Truta]
+- Remove old/visualc6 given CMakefile and other alternatives
+- Update AS400 build files and documentation [Monnerat]
+- Update win32/Makefile.gcc to build test/*.c [Truta]
+- Permit stronger flushes after Z_BLOCK flushes
+- Avoid extraneous empty blocks when doing empty flushes
+- Permit Z_NULL arguments to deflatePending
+- Allow deflatePrime() to insert bits in the middle of a stream
+- Remove second empty static block for Z_PARTIAL_FLUSH
+- Write out all of the available bits when using Z_BLOCK
+- Insert the first two strings in the hash table after a flush
+
+Changes in 1.2.5.2 (17 Dec 2011)
+- fix ld error: unable to find version dependency 'ZLIB_1.2.5'
+- use relative symlinks for shared libs
+- Avoid searching past window for Z_RLE strategy
+- Assure that high-water mark initialization is always applied in deflate
+- Add assertions to fill_window() in deflate.c to match comments
+- Update python link in README
+- Correct spelling error in gzread.c
+- Fix bug in gzgets() for a concatenated empty gzip stream
+- Correct error in comment for gz_make()
+- Change gzread() and related to ignore junk after gzip streams
+- Allow gzread() and related to continue after gzclearerr()
+- Allow gzrewind() and gzseek() after a premature end-of-file
+- Simplify gzseek() now that raw after gzip is ignored
+- Change gzgetc() to a macro for speed (~40% speedup in testing)
+- Fix gzclose() to return the actual error last encountered
+- Always add large file support for windows
+- Include zconf.h for windows large file support
+- Include zconf.h.cmakein for windows large file support
+- Update zconf.h.cmakein on make distclean
+- Merge vestigial vsnprintf determination from zutil.h to gzguts.h
+- Clarify how gzopen() appends in zlib.h comments
+- Correct documentation of gzdirect() since junk at end now ignored
+- Add a transparent write mode to gzopen() when 'T' is in the mode
+- Update python link in zlib man page
+- Get inffixed.h and MAKEFIXED result to match
+- Add a ./config --solo option to make zlib subset with no library use
+- Add undocumented inflateResetKeep() function for CAB file decoding
+- Add --cover option to ./configure for gcc coverage testing
+- Add #define ZLIB_CONST option to use const in the z_stream interface
+- Add comment to gzdopen() in zlib.h to use dup() when using fileno()
+- Note behavior of uncompress() to provide as much data as it can
+- Add files in contrib/minizip to aid in building libminizip
+- Split off AR options in Makefile.in and configure
+- Change ON macro to Z_ARG to avoid application conflicts
+- Facilitate compilation with Borland C++ for pragmas and vsnprintf
+- Include io.h for Turbo C / Borland C++
+- Move example.c and minigzip.c to test/
+- Simplify incomplete code table filling in inflate_table()
+- Remove code from inflate.c and infback.c that is impossible to execute
+- Test the inflate code with full coverage
+- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw)
+- Add deflateResetKeep and fix inflateResetKeep to retain dictionary
+- Fix gzwrite.c to accommodate reduced memory zlib compilation
+- Have inflate() with Z_FINISH avoid the allocation of a window
+- Do not set strm->adler when doing raw inflate
+- Fix gzeof() to behave just like feof() when read is not past end of file
+- Fix bug in gzread.c when end-of-file is reached
+- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF
+- Document gzread() capability to read concurrently written files
+- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo]
+
+Changes in 1.2.5.1 (10 Sep 2011)
+- Update FAQ entry on shared builds (#13)
+- Avoid symbolic argument to chmod in Makefile.in
+- Fix bug and add consts in contrib/puff [Oberhumer]
+- Update contrib/puff/zeros.raw test file to have all block types
+- Add full coverage test for puff in contrib/puff/Makefile
+- Fix static-only-build install in Makefile.in
+- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno]
+- Add libz.a dependency to shared in Makefile.in for parallel builds
+- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out
+- Replace $(...) with `...` in configure for non-bash sh [Bowler]
+- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen]
+- Add solaris* to Linux* in configure to allow gcc use [Groffen]
+- Add *bsd* to Linux* case in configure [Bar-Lev]
+- Add inffast.obj to dependencies in win32/Makefile.msc
+- Correct spelling error in deflate.h [Kohler]
+- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc
+- Add test to configure for GNU C looking for gcc in output of $cc -v
+- Add zlib.pc generation to win32/Makefile.gcc [Weigelt]
+- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not
+- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense
+- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser)
+- Make stronger test in zconf.h to include unistd.h for LFS
+- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack]
+- Fix zlib.h LFS support when Z_PREFIX used
+- Add updated as400 support (removed from old) [Monnerat]
+- Avoid deflate sensitivity to volatile input data
+- Avoid division in adler32_combine for NO_DIVIDE
+- Clarify the use of Z_FINISH with deflateBound() amount of space
+- Set binary for output file in puff.c
+- Use u4 type for crc_table to avoid conversion warnings
+- Apply casts in zlib.h to avoid conversion warnings
+- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller]
+- Improve inflateSync() documentation to note indeterminacy
+- Add deflatePending() function to return the amount of pending output
+- Correct the spelling of "specification" in FAQ [Randers-Pehrson]
+- Add a check in configure for stdarg.h, use for gzprintf()
+- Check that pointers fit in ints when gzprint() compiled old style
+- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler]
+- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt]
+- Add debug records in assembler code [Londer]
+- Update RFC references to use http://tools.ietf.org/html/... [Li]
+- Add --archs option, use of libtool to configure for Mac OS X [Borstel]
+
+Changes in 1.2.5 (19 Apr 2010)
+- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev]
+- Default to libdir as sharedlibdir in configure [Nieder]
+- Update copyright dates on modified source files
+- Update trees.c to be able to generate modified trees.h
+- Exit configure for MinGW, suggesting win32/Makefile.gcc
+- Check for NULL path in gz_open [Homurlu]
+
+Changes in 1.2.4.5 (18 Apr 2010)
+- Set sharedlibdir in configure [Torok]
+- Set LDFLAGS in Makefile.in [Bar-Lev]
+- Avoid mkdir objs race condition in Makefile.in [Bowler]
+- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays
+- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C
+- Don't use hidden attribute when it is a warning generator (e.g. Solaris)
+
+Changes in 1.2.4.4 (18 Apr 2010)
+- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok]
+- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty
+- Try to use bash or ksh regardless of functionality of /bin/sh
+- Fix configure incompatibility with NetBSD sh
+- Remove attempt to run under bash or ksh since have better NetBSD fix
+- Fix win32/Makefile.gcc for MinGW [Bar-Lev]
+- Add diagnostic messages when using CROSS_PREFIX in configure
+- Added --sharedlibdir option to configure [Weigelt]
+- Use hidden visibility attribute when available [Frysinger]
+
+Changes in 1.2.4.3 (10 Apr 2010)
+- Only use CROSS_PREFIX in configure for ar and ranlib if they exist
+- Use CROSS_PREFIX for nm [Bar-Lev]
+- Assume _LARGEFILE64_SOURCE defined is equivalent to true
+- Avoid use of undefined symbols in #if with && and ||
+- Make *64 prototypes in gzguts.h consistent with functions
+- Add -shared load option for MinGW in configure [Bowler]
+- Move z_off64_t to public interface, use instead of off64_t
+- Remove ! from shell test in configure (not portable to Solaris)
+- Change +0 macro tests to -0 for possibly increased portability
+
+Changes in 1.2.4.2 (9 Apr 2010)
+- Add consistent carriage returns to readme.txt's in masmx86 and masmx64
+- Really provide prototypes for *64 functions when building without LFS
+- Only define unlink() in minigzip.c if unistd.h not included
+- Update README to point to contrib/vstudio project files
+- Move projects/vc6 to old/ and remove projects/
+- Include stdlib.h in minigzip.c for setmode() definition under WinCE
+- Clean up assembler builds in win32/Makefile.msc [Rowe]
+- Include sys/types.h for Microsoft for off_t definition
+- Fix memory leak on error in gz_open()
+- Symbolize nm as $NM in configure [Weigelt]
+- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt]
+- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined
+- Fix bug in gzeof() to take into account unused input data
+- Avoid initialization of structures with variables in puff.c
+- Updated win32/README-WIN32.txt [Rowe]
+
+Changes in 1.2.4.1 (28 Mar 2010)
+- Remove the use of [a-z] constructs for sed in configure [gentoo 310225]
+- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech]
+- Restore "for debugging" comment on sprintf() in gzlib.c
+- Remove fdopen for MVS from gzguts.h
+- Put new README-WIN32.txt in win32 [Rowe]
+- Add check for shell to configure and invoke another shell if needed
+- Fix big fat stinking bug in gzseek() on uncompressed files
+- Remove vestigial F_OPEN64 define in zutil.h
+- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE
+- Avoid errors on non-LFS systems when applications define LFS macros
+- Set EXE to ".exe" in configure for MINGW [Kahle]
+- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill]
+- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev]
+- Add DLL install in win32/makefile.gcc [Bar-Lev]
+- Allow Linux* or linux* from uname in configure [Bar-Lev]
+- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev]
+- Add cross-compilation prefixes to configure [Bar-Lev]
+- Match type exactly in gz_load() invocation in gzread.c
+- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func
+- Provide prototypes for *64 functions when building zlib without LFS
+- Don't use -lc when linking shared library on MinGW
+- Remove errno.h check in configure and vestigial errno code in zutil.h
+
+Changes in 1.2.4 (14 Mar 2010)
+- Fix VER3 extraction in configure for no fourth subversion
+- Update zlib.3, add docs to Makefile.in to make .pdf out of it
+- Add zlib.3.pdf to distribution
+- Don't set error code in gzerror() if passed pointer is NULL
+- Apply destination directory fixes to CMakeLists.txt [Lowman]
+- Move #cmakedefine's to a new zconf.in.cmakein
+- Restore zconf.h for builds that don't use configure or cmake
+- Add distclean to dummy Makefile for convenience
+- Update and improve INDEX, README, and FAQ
+- Update CMakeLists.txt for the return of zconf.h [Lowman]
+- Update contrib/vstudio/vc9 and vc10 [Vollant]
+- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc
+- Apply license and readme changes to contrib/asm686 [Raiter]
+- Check file name lengths and add -c option in minigzip.c [Li]
+- Update contrib/amd64 and contrib/masmx86/ [Vollant]
+- Avoid use of "eof" parameter in trees.c to not shadow library variable
+- Update make_vms.com for removal of zlibdefs.h [Zinser]
+- Update assembler code and vstudio projects in contrib [Vollant]
+- Remove outdated assembler code contrib/masm686 and contrib/asm586
+- Remove old vc7 and vc8 from contrib/vstudio
+- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe]
+- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open()
+- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant]
+- Remove *64 functions from win32/zlib.def (they're not 64-bit yet)
+- Fix bug in void-returning vsprintf() case in gzwrite.c
+- Fix name change from inflate.h in contrib/inflate86/inffas86.c
+- Check if temporary file exists before removing in make_vms.com [Zinser]
+- Fix make install and uninstall for --static option
+- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta]
+- Update readme.txt in contrib/masmx64 and masmx86 to assemble
+
+Changes in 1.2.3.9 (21 Feb 2010)
+- Expunge gzio.c
+- Move as400 build information to old
+- Fix updates in contrib/minizip and contrib/vstudio
+- Add const to vsnprintf test in configure to avoid warnings [Weigelt]
+- Delete zconf.h (made by configure) [Weigelt]
+- Change zconf.in.h to zconf.h.in per convention [Weigelt]
+- Check for NULL buf in gzgets()
+- Return empty string for gzgets() with len == 1 (like fgets())
+- Fix description of gzgets() in zlib.h for end-of-file, NULL return
+- Update minizip to 1.1 [Vollant]
+- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c
+- Note in zlib.h that gzerror() should be used to distinguish from EOF
+- Remove use of snprintf() from gzlib.c
+- Fix bug in gzseek()
+- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant]
+- Fix zconf.h generation in CMakeLists.txt [Lowman]
+- Improve comments in zconf.h where modified by configure
+
+Changes in 1.2.3.8 (13 Feb 2010)
+- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer]
+- Use z_off64_t in gz_zero() and gz_skip() to match state->skip
+- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t)
+- Revert to Makefile.in from 1.2.3.6 (live with the clutter)
+- Fix missing error return in gzflush(), add zlib.h note
+- Add *64 functions to zlib.map [Levin]
+- Fix signed/unsigned comparison in gz_comp()
+- Use SFLAGS when testing shared linking in configure
+- Add --64 option to ./configure to use -m64 with gcc
+- Fix ./configure --help to correctly name options
+- Have make fail if a test fails [Levin]
+- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson]
+- Remove assembler object files from contrib
+
+Changes in 1.2.3.7 (24 Jan 2010)
+- Always gzopen() with O_LARGEFILE if available
+- Fix gzdirect() to work immediately after gzopen() or gzdopen()
+- Make gzdirect() more precise when the state changes while reading
+- Improve zlib.h documentation in many places
+- Catch memory allocation failure in gz_open()
+- Complete close operation if seek forward in gzclose_w() fails
+- Return Z_ERRNO from gzclose_r() if close() fails
+- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL
+- Return zero for gzwrite() errors to match zlib.h description
+- Return -1 on gzputs() error to match zlib.h description
+- Add zconf.in.h to allow recovery from configure modification [Weigelt]
+- Fix static library permissions in Makefile.in [Weigelt]
+- Avoid warnings in configure tests that hide functionality [Weigelt]
+- Add *BSD and DragonFly to Linux case in configure [gentoo 123571]
+- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212]
+- Avoid access of uninitialized data for first inflateReset2 call [Gomes]
+- Keep object files in subdirectories to reduce the clutter somewhat
+- Remove default Makefile and zlibdefs.h, add dummy Makefile
+- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_
+- Remove zlibdefs.h completely -- modify zconf.h instead
+
+Changes in 1.2.3.6 (17 Jan 2010)
+- Avoid void * arithmetic in gzread.c and gzwrite.c
+- Make compilers happier with const char * for gz_error message
+- Avoid unused parameter warning in inflate.c
+- Avoid signed-unsigned comparison warning in inflate.c
+- Indent #pragma's for traditional C
+- Fix usage of strwinerror() in glib.c, change to gz_strwinerror()
+- Correct email address in configure for system options
+- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser]
+- Update zlib.map [Brown]
+- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok]
+- Apply various fixes to CMakeLists.txt [Lowman]
+- Add checks on len in gzread() and gzwrite()
+- Add error message for no more room for gzungetc()
+- Remove zlib version check in gzwrite()
+- Defer compression of gzprintf() result until need to
+- Use snprintf() in gzdopen() if available
+- Remove USE_MMAP configuration determination (only used by minigzip)
+- Remove examples/pigz.c (available separately)
+- Update examples/gun.c to 1.6
+
+Changes in 1.2.3.5 (8 Jan 2010)
+- Add space after #if in zutil.h for some compilers
+- Fix relatively harmless bug in deflate_fast() [Exarevsky]
+- Fix same problem in deflate_slow()
+- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown]
+- Add deflate_rle() for faster Z_RLE strategy run-length encoding
+- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding
+- Change name of "write" variable in inffast.c to avoid library collisions
+- Fix premature EOF from gzread() in gzio.c [Brown]
+- Use zlib header window size if windowBits is 0 in inflateInit2()
+- Remove compressBound() call in deflate.c to avoid linking compress.o
+- Replace use of errno in gz* with functions, support WinCE [Alves]
+- Provide alternative to perror() in minigzip.c for WinCE [Alves]
+- Don't use _vsnprintf on later versions of MSVC [Lowman]
+- Add CMake build script and input file [Lowman]
+- Update contrib/minizip to 1.1 [Svensson, Vollant]
+- Moved nintendods directory from contrib to root
+- Replace gzio.c with a new set of routines with the same functionality
+- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above
+- Update contrib/minizip to 1.1b
+- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h
+
+Changes in 1.2.3.4 (21 Dec 2009)
+- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility
+- Update comments in configure and Makefile.in for default --shared
+- Fix test -z's in configure [Marquess]
+- Build examplesh and minigzipsh when not testing
+- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h
+- Import LDFLAGS from the environment in configure
+- Fix configure to populate SFLAGS with discovered CFLAGS options
+- Adapt make_vms.com to the new Makefile.in [Zinser]
+- Add zlib2ansi script for C++ compilation [Marquess]
+- Add _FILE_OFFSET_BITS=64 test to make test (when applicable)
+- Add AMD64 assembler code for longest match to contrib [Teterin]
+- Include options from $SFLAGS when doing $LDSHARED
+- Simplify 64-bit file support by introducing z_off64_t type
+- Make shared object files in objs directory to work around old Sun cc
+- Use only three-part version number for Darwin shared compiles
+- Add rc option to ar in Makefile.in for when ./configure not run
+- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4*
+- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile
+- Protect against _FILE_OFFSET_BITS being defined when compiling zlib
+- Rename Makefile.in targets allstatic to static and allshared to shared
+- Fix static and shared Makefile.in targets to be independent
+- Correct error return bug in gz_open() by setting state [Brown]
+- Put spaces before ;;'s in configure for better sh compatibility
+- Add pigz.c (parallel implementation of gzip) to examples/
+- Correct constant in crc32.c to UL [Leventhal]
+- Reject negative lengths in crc32_combine()
+- Add inflateReset2() function to work like inflateEnd()/inflateInit2()
+- Include sys/types.h for _LARGEFILE64_SOURCE [Brown]
+- Correct typo in doc/algorithm.txt [Janik]
+- Fix bug in adler32_combine() [Zhu]
+- Catch missing-end-of-block-code error in all inflates and in puff
+ Assures that random input to inflate eventually results in an error
+- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/
+- Update ENOUGH and its usage to reflect discovered bounds
+- Fix gzerror() error report on empty input file [Brown]
+- Add ush casts in trees.c to avoid pedantic runtime errors
+- Fix typo in zlib.h uncompress() description [Reiss]
+- Correct inflate() comments with regard to automatic header detection
+- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays)
+- Put new version of gzlog (2.0) in examples with interruption recovery
+- Add puff compile option to permit invalid distance-too-far streams
+- Add puff TEST command options, ability to read piped input
+- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but
+ _LARGEFILE64_SOURCE not defined
+- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart
+- Fix deflateSetDictionary() to use all 32K for output consistency
+- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h)
+- Clear bytes after deflate lookahead to avoid use of uninitialized data
+- Change a limit in inftrees.c to be more transparent to Coverity Prevent
+- Update win32/zlib.def with exported symbols from zlib.h
+- Correct spelling errors in zlib.h [Willem, Sobrado]
+- Allow Z_BLOCK for deflate() to force a new block
+- Allow negative bits in inflatePrime() to delete existing bit buffer
+- Add Z_TREES flush option to inflate() to return at end of trees
+- Add inflateMark() to return current state information for random access
+- Add Makefile for NintendoDS to contrib [Costa]
+- Add -w in configure compile tests to avoid spurious warnings [Beucler]
+- Fix typos in zlib.h comments for deflateSetDictionary()
+- Fix EOF detection in transparent gzread() [Maier]
+
+Changes in 1.2.3.3 (2 October 2006)
+- Make --shared the default for configure, add a --static option
+- Add compile option to permit invalid distance-too-far streams
+- Add inflateUndermine() function which is required to enable above
+- Remove use of "this" variable name for C++ compatibility [Marquess]
+- Add testing of shared library in make test, if shared library built
+- Use ftello() and fseeko() if available instead of ftell() and fseek()
+- Provide two versions of all functions that use the z_off_t type for
+ binary compatibility -- a normal version and a 64-bit offset version,
+ per the Large File Support Extension when _LARGEFILE64_SOURCE is
+ defined; use the 64-bit versions by default when _FILE_OFFSET_BITS
+ is defined to be 64
+- Add a --uname= option to configure to perhaps help with cross-compiling
+
+Changes in 1.2.3.2 (3 September 2006)
+- Turn off silly Borland warnings [Hay]
+- Use off64_t and define _LARGEFILE64_SOURCE when present
+- Fix missing dependency on inffixed.h in Makefile.in
+- Rig configure --shared to build both shared and static [Teredesai, Truta]
+- Remove zconf.in.h and instead create a new zlibdefs.h file
+- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant]
+- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt]
+
+Changes in 1.2.3.1 (16 August 2006)
+- Add watcom directory with OpenWatcom make files [Daniel]
+- Remove #undef of FAR in zconf.in.h for MVS [Fedtke]
+- Update make_vms.com [Zinser]
+- Use -fPIC for shared build in configure [Teredesai, Nicholson]
+- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen]
+- Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck]
+- Add some FAQ entries about the contrib directory
+- Update the MVS question in the FAQ
+- Avoid extraneous reads after EOF in gzio.c [Brown]
+- Correct spelling of "successfully" in gzio.c [Randers-Pehrson]
+- Add comments to zlib.h about gzerror() usage [Brown]
+- Set extra flags in gzip header in gzopen() like deflate() does
+- Make configure options more compatible with double-dash conventions
+ [Weigelt]
+- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen]
+- Fix uninstall target in Makefile.in [Truta]
+- Add pkgconfig support [Weigelt]
+- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt]
+- Replace set_data_type() with a more accurate detect_data_type() in
+ trees.c, according to the txtvsbin.txt document [Truta]
+- Swap the order of #include and #include "zlib.h" in
+ gzio.c, example.c and minigzip.c [Truta]
+- Shut up annoying VS2005 warnings about standard C deprecation [Rowe,
+ Truta] (where?)
+- Fix target "clean" from win32/Makefile.bor [Truta]
+- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe]
+- Update zlib www home address in win32/DLL_FAQ.txt [Truta]
+- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove]
+- Enable browse info in the "Debug" and "ASM Debug" configurations in
+ the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta]
+- Add pkgconfig support [Weigelt]
+- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h,
+ for use in win32/zlib1.rc [Polushin, Rowe, Truta]
+- Add a document that explains the new text detection scheme to
+ doc/txtvsbin.txt [Truta]
+- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta]
+- Move algorithm.txt into doc/ [Truta]
+- Synchronize FAQ with website
+- Fix compressBound(), was low for some pathological cases [Fearnley]
+- Take into account wrapper variations in deflateBound()
+- Set examples/zpipe.c input and output to binary mode for Windows
+- Update examples/zlib_how.html with new zpipe.c (also web site)
+- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems
+ that gcc became pickier in 4.0)
+- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain
+ un-versioned, the patch adds versioning only for symbols introduced in
+ zlib-1.2.0 or later. It also declares as local those symbols which are
+ not designed to be exported." [Levin]
+- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure
+- Do not initialize global static by default in trees.c, add a response
+ NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess]
+- Don't use strerror() in gzio.c under WinCE [Yakimov]
+- Don't use errno.h in zutil.h under WinCE [Yakimov]
+- Move arguments for AR to its usage to allow replacing ar [Marot]
+- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson]
+- Improve inflateInit() and inflateInit2() documentation
+- Fix structure size comment in inflate.h
+- Change configure help option from --h* to --help [Santos]
+
+Changes in 1.2.3 (18 July 2005)
+- Apply security vulnerability fixes to contrib/infback9 as well
+- Clean up some text files (carriage returns, trailing space)
+- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant]
+
+Changes in 1.2.2.4 (11 July 2005)
+- Add inflatePrime() function for starting inflation at bit boundary
+- Avoid some Visual C warnings in deflate.c
+- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit
+ compile
+- Fix some spelling errors in comments [Betts]
+- Correct inflateInit2() error return documentation in zlib.h
+- Add zran.c example of compressed data random access to examples
+ directory, shows use of inflatePrime()
+- Fix cast for assignments to strm->state in inflate.c and infback.c
+- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
+- Move declarations of gf2 functions to right place in crc32.c [Oberhumer]
+- Add cast in trees.c t avoid a warning [Oberhumer]
+- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
+- Update make_vms.com [Zinser]
+- Initialize state->write in inflateReset() since copied in inflate_fast()
+- Be more strict on incomplete code sets in inflate_table() and increase
+ ENOUGH and MAXD -- this repairs a possible security vulnerability for
+ invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
+ discovering the vulnerability and providing test cases
+- Add ia64 support to configure for HP-UX [Smith]
+- Add error return to gzread() for format or i/o error [Levin]
+- Use malloc.h for OS/2 [Necasek]
+
+Changes in 1.2.2.3 (27 May 2005)
+- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
+- Typecast fread() return values in gzio.c [Vollant]
+- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
+- Fix crc check bug in gzread() after gzungetc() [Heiner]
+- Add the deflateTune() function to adjust internal compression parameters
+- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
+- Remove an incorrect assertion in examples/zpipe.c
+- Add C++ wrapper in infback9.h [Donais]
+- Fix bug in inflateCopy() when decoding fixed codes
+- Note in zlib.h how much deflateSetDictionary() actually uses
+- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
+- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
+- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
+- Add gzdirect() function to indicate transparent reads
+- Update contrib/minizip [Vollant]
+- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
+- Add casts in crc32.c to avoid warnings [Oberhumer]
+- Add contrib/masmx64 [Vollant]
+- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
+
+Changes in 1.2.2.2 (30 December 2004)
+- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
+ avoid implicit memcpy calls (portability for no-library compilation)
+- Increase sprintf() buffer size in gzdopen() to allow for large numbers
+- Add INFLATE_STRICT to check distances against zlib header
+- Improve WinCE errno handling and comments [Chang]
+- Remove comment about no gzip header processing in FAQ
+- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
+- Add updated make_vms.com [Coghlan], update README
+- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
+ fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html
+- Add FAQ entry and comments in deflate.c on uninitialized memory access
+- Add Solaris 9 make options in configure [Gilbert]
+- Allow strerror() usage in gzio.c for STDC
+- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
+- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
+- Use z_off_t for adler32_combine() and crc32_combine() lengths
+- Make adler32() much faster for small len
+- Use OS_CODE in deflate() default gzip header
+
+Changes in 1.2.2.1 (31 October 2004)
+- Allow inflateSetDictionary() call for raw inflate
+- Fix inflate header crc check bug for file names and comments
+- Add deflateSetHeader() and gz_header structure for custom gzip headers
+- Add inflateGetheader() to retrieve gzip headers
+- Add crc32_combine() and adler32_combine() functions
+- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list
+- Use zstreamp consistently in zlib.h (inflate_back functions)
+- Remove GUNZIP condition from definition of inflate_mode in inflate.h
+ and in contrib/inflate86/inffast.S [Truta, Anderson]
+- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson]
+- Update projects/README.projects and projects/visualc6 [Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta]
+- Deprecate Z_ASCII; use Z_TEXT instead [Truta]
+- Use a new algorithm for setting strm->data_type in trees.c [Truta]
+- Do not define an exit() prototype in zutil.c unless DEBUG defined
+- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
+- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
+- Fix Darwin build version identification [Peterson]
+
+Changes in 1.2.2 (3 October 2004)
+- Update zlib.h comments on gzip in-memory processing
+- Set adler to 1 in inflateReset() to support Java test suite [Walles]
+- Add contrib/dotzlib [Ravn]
+- Update win32/DLL_FAQ.txt [Truta]
+- Update contrib/minizip [Vollant]
+- Move contrib/visual-basic.txt to old/ [Truta]
+- Fix assembler builds in projects/visualc6/ [Truta]
+
+Changes in 1.2.1.2 (9 September 2004)
+- Update INDEX file
+- Fix trees.c to update strm->data_type (no one ever noticed!)
+- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown]
+- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE)
+- Add limited multitasking protection to DYNAMIC_CRC_TABLE
+- Add NO_vsnprintf for VMS in zutil.h [Mozilla]
+- Don't declare strerror() under VMS [Mozilla]
+- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize
+- Update contrib/ada [Anisimkov]
+- Update contrib/minizip [Vollant]
+- Fix configure to not hardcode directories for Darwin [Peterson]
+- Fix gzio.c to not return error on empty files [Brown]
+- Fix indentation; update version in contrib/delphi/ZLib.pas and
+ contrib/pascal/zlibpas.pas [Truta]
+- Update mkasm.bat in contrib/masmx86 [Truta]
+- Update contrib/untgz [Truta]
+- Add projects/README.projects [Truta]
+- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta]
+- Remove an unnecessary assignment to curr in inftrees.c [Truta]
+- Add OS/2 to exe builds in configure [Poltorak]
+- Remove err dummy parameter in zlib.h [Kientzle]
+
+Changes in 1.2.1.1 (9 January 2004)
+- Update email address in README
+- Several FAQ updates
+- Fix a big fat bug in inftrees.c that prevented decoding valid
+ dynamic blocks with only literals and no distance codes --
+ Thanks to "Hot Emu" for the bug report and sample file
+- Add a note to puff.c on no distance codes case
+
+Changes in 1.2.1 (17 November 2003)
+- Remove a tab in contrib/gzappend/gzappend.c
+- Update some interfaces in contrib for new zlib functions
+- Update zlib version number in some contrib entries
+- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta]
+- Support shared libraries on Hurd and KFreeBSD [Brown]
+- Fix error in NO_DIVIDE option of adler32.c
+
+Changes in 1.2.0.8 (4 November 2003)
+- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas
+- Add experimental NO_DIVIDE #define in adler32.c
+ - Possibly faster on some processors (let me know if it is)
+- Correct Z_BLOCK to not return on first inflate call if no wrap
+- Fix strm->data_type on inflate() return to correctly indicate EOB
+- Add deflatePrime() function for appending in the middle of a byte
+- Add contrib/gzappend for an example of appending to a stream
+- Update win32/DLL_FAQ.txt [Truta]
+- Delete Turbo C comment in README [Truta]
+- Improve some indentation in zconf.h [Truta]
+- Fix infinite loop on bad input in configure script [Church]
+- Fix gzeof() for concatenated gzip files [Johnson]
+- Add example to contrib/visual-basic.txt [Michael B.]
+- Add -p to mkdir's in Makefile.in [vda]
+- Fix configure to properly detect presence or lack of printf functions
+- Add AS400 support [Monnerat]
+- Add a little Cygwin support [Wilson]
+
+Changes in 1.2.0.7 (21 September 2003)
+- Correct some debug formats in contrib/infback9
+- Cast a type in a debug statement in trees.c
+- Change search and replace delimiter in configure from % to # [Beebe]
+- Update contrib/untgz to 0.2 with various fixes [Truta]
+- Add build support for Amiga [Nikl]
+- Remove some directories in old that have been updated to 1.2
+- Add dylib building for Mac OS X in configure and Makefile.in
+- Remove old distribution stuff from Makefile
+- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X
+- Update links in README
+
+Changes in 1.2.0.6 (13 September 2003)
+- Minor FAQ updates
+- Update contrib/minizip to 1.00 [Vollant]
+- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta]
+- Update POSTINC comment for 68060 [Nikl]
+- Add contrib/infback9 with deflate64 decoding (unsupported)
+- For MVS define NO_vsnprintf and undefine FAR [van Burik]
+- Add pragma for fdopen on MVS [van Burik]
+
+Changes in 1.2.0.5 (8 September 2003)
+- Add OF to inflateBackEnd() declaration in zlib.h
+- Remember start when using gzdopen in the middle of a file
+- Use internal off_t counters in gz* functions to properly handle seeks
+- Perform more rigorous check for distance-too-far in inffast.c
+- Add Z_BLOCK flush option to return from inflate at block boundary
+- Set strm->data_type on return from inflate
+ - Indicate bits unused, if at block boundary, and if in last block
+- Replace size_t with ptrdiff_t in crc32.c, and check for correct size
+- Add condition so old NO_DEFLATE define still works for compatibility
+- FAQ update regarding the Windows DLL [Truta]
+- INDEX update: add qnx entry, remove aix entry [Truta]
+- Install zlib.3 into mandir [Wilson]
+- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta]
+- Adapt the zlib interface to the new DLL convention guidelines [Truta]
+- Introduce ZLIB_WINAPI macro to allow the export of functions using
+ the WINAPI calling convention, for Visual Basic [Vollant, Truta]
+- Update msdos and win32 scripts and makefiles [Truta]
+- Export symbols by name, not by ordinal, in win32/zlib.def [Truta]
+- Add contrib/ada [Anisimkov]
+- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta]
+- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant]
+- Add contrib/masm686 [Truta]
+- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm
+ [Truta, Vollant]
+- Update contrib/delphi; rename to contrib/pascal; add example [Truta]
+- Remove contrib/delphi2; add a new contrib/delphi [Truta]
+- Avoid inclusion of the nonstandard in contrib/iostream,
+ and fix some method prototypes [Truta]
+- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip
+ [Truta]
+- Avoid the use of backslash (\) in contrib/minizip [Vollant]
+- Fix file time handling in contrib/untgz; update makefiles [Truta]
+- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines
+ [Vollant]
+- Remove contrib/vstudio/vc15_16 [Vollant]
+- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta]
+- Update README.contrib [Truta]
+- Invert the assignment order of match_head and s->prev[...] in
+ INSERT_STRING [Truta]
+- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings
+ [Truta]
+- Compare function pointers with 0, not with NULL or Z_NULL [Truta]
+- Fix prototype of syncsearch in inflate.c [Truta]
+- Introduce ASMINF macro to be enabled when using an ASM implementation
+ of inflate_fast [Truta]
+- Change NO_DEFLATE to NO_GZCOMPRESS [Truta]
+- Modify test_gzio in example.c to take a single file name as a
+ parameter [Truta]
+- Exit the example.c program if gzopen fails [Truta]
+- Add type casts around strlen in example.c [Truta]
+- Remove casting to sizeof in minigzip.c; give a proper type
+ to the variable compared with SUFFIX_LEN [Truta]
+- Update definitions of STDC and STDC99 in zconf.h [Truta]
+- Synchronize zconf.h with the new Windows DLL interface [Truta]
+- Use SYS16BIT instead of __32BIT__ to distinguish between
+ 16- and 32-bit platforms [Truta]
+- Use far memory allocators in small 16-bit memory models for
+ Turbo C [Truta]
+- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in
+ zlibCompileFlags [Truta]
+- Cygwin has vsnprintf [Wilson]
+- In Windows16, OS_CODE is 0, as in MSDOS [Truta]
+- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson]
+
+Changes in 1.2.0.4 (10 August 2003)
+- Minor FAQ updates
+- Be more strict when checking inflateInit2's windowBits parameter
+- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well
+- Add gzip wrapper option to deflateInit2 using windowBits
+- Add updated QNX rule in configure and qnx directory [Bonnefoy]
+- Make inflate distance-too-far checks more rigorous
+- Clean up FAR usage in inflate
+- Add casting to sizeof() in gzio.c and minigzip.c
+
+Changes in 1.2.0.3 (19 July 2003)
+- Fix silly error in gzungetc() implementation [Vollant]
+- Update contrib/minizip and contrib/vstudio [Vollant]
+- Fix printf format in example.c
+- Correct cdecl support in zconf.in.h [Anisimkov]
+- Minor FAQ updates
+
+Changes in 1.2.0.2 (13 July 2003)
+- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons
+- Attempt to avoid warnings in crc32.c for pointer-int conversion
+- Add AIX to configure, remove aix directory [Bakker]
+- Add some casts to minigzip.c
+- Improve checking after insecure sprintf() or vsprintf() calls
+- Remove #elif's from crc32.c
+- Change leave label to inf_leave in inflate.c and infback.c to avoid
+ library conflicts
+- Remove inflate gzip decoding by default--only enable gzip decoding by
+ special request for stricter backward compatibility
+- Add zlibCompileFlags() function to return compilation information
+- More typecasting in deflate.c to avoid warnings
+- Remove leading underscore from _Capital #defines [Truta]
+- Fix configure to link shared library when testing
+- Add some Windows CE target adjustments [Mai]
+- Remove #define ZLIB_DLL in zconf.h [Vollant]
+- Add zlib.3 [Rodgers]
+- Update RFC URL in deflate.c and algorithm.txt [Mai]
+- Add zlib_dll_FAQ.txt to contrib [Truta]
+- Add UL to some constants [Truta]
+- Update minizip and vstudio [Vollant]
+- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h
+- Expand use of NO_DUMMY_DECL to avoid all dummy structures
+- Added iostream3 to contrib [Schwardt]
+- Replace rewind() with fseek() for WinCE [Truta]
+- Improve setting of zlib format compression level flags
+ - Report 0 for huffman and rle strategies and for level == 0 or 1
+ - Report 2 only for level == 6
+- Only deal with 64K limit when necessary at compile time [Truta]
+- Allow TOO_FAR check to be turned off at compile time [Truta]
+- Add gzclearerr() function [Souza]
+- Add gzungetc() function
+
+Changes in 1.2.0.1 (17 March 2003)
+- Add Z_RLE strategy for run-length encoding [Truta]
+ - When Z_RLE requested, restrict matches to distance one
+ - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE
+- Correct FASTEST compilation to allow level == 0
+- Clean up what gets compiled for FASTEST
+- Incorporate changes to zconf.in.h [Vollant]
+ - Refine detection of Turbo C need for dummy returns
+ - Refine ZLIB_DLL compilation
+ - Include additional header file on VMS for off_t typedef
+- Try to use _vsnprintf where it supplants vsprintf [Vollant]
+- Add some casts in inffast.c
+- Enhance comments in zlib.h on what happens if gzprintf() tries to
+ write more than 4095 bytes before compression
+- Remove unused state from inflateBackEnd()
+- Remove exit(0) from minigzip.c, example.c
+- Get rid of all those darn tabs
+- Add "check" target to Makefile.in that does the same thing as "test"
+- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in
+- Update contrib/inflate86 [Anderson]
+- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant]
+- Add msdos and win32 directories with makefiles [Truta]
+- More additions and improvements to the FAQ
+
+Changes in 1.2.0 (9 March 2003)
+- New and improved inflate code
+ - About 20% faster
+ - Does not allocate 32K window unless and until needed
+ - Automatically detects and decompresses gzip streams
+ - Raw inflate no longer needs an extra dummy byte at end
+ - Added inflateBack functions using a callback interface--even faster
+ than inflate, useful for file utilities (gzip, zip)
+ - Added inflateCopy() function to record state for random access on
+ externally generated deflate streams (e.g. in gzip files)
+ - More readable code (I hope)
+- New and improved crc32()
+ - About 50% faster, thanks to suggestions from Rodney Brown
+- Add deflateBound() and compressBound() functions
+- Fix memory leak in deflateInit2()
+- Permit setting dictionary for raw deflate (for parallel deflate)
+- Fix const declaration for gzwrite()
+- Check for some malloc() failures in gzio.c
+- Fix bug in gzopen() on single-byte file 0x1f
+- Fix bug in gzread() on concatenated file with 0x1f at end of buffer
+ and next buffer doesn't start with 0x8b
+- Fix uncompress() to return Z_DATA_ERROR on truncated input
+- Free memory at end of example.c
+- Remove MAX #define in trees.c (conflicted with some libraries)
+- Fix static const's in deflate.c, gzio.c, and zutil.[ch]
+- Declare malloc() and free() in gzio.c if STDC not defined
+- Use malloc() instead of calloc() in zutil.c if int big enough
+- Define STDC for AIX
+- Add aix/ with approach for compiling shared library on AIX
+- Add HP-UX support for shared libraries in configure
+- Add OpenUNIX support for shared libraries in configure
+- Use $cc instead of gcc to build shared library
+- Make prefix directory if needed when installing
+- Correct Macintosh avoidance of typedef Byte in zconf.h
+- Correct Turbo C memory allocation when under Linux
+- Use libz.a instead of -lz in Makefile (assure use of compiled library)
+- Update configure to check for snprintf or vsnprintf functions and their
+ return value, warn during make if using an insecure function
+- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that
+ is lost when library is used--resolution is to build new zconf.h
+- Documentation improvements (in zlib.h):
+ - Document raw deflate and inflate
+ - Update RFCs URL
+ - Point out that zlib and gzip formats are different
+ - Note that Z_BUF_ERROR is not fatal
+ - Document string limit for gzprintf() and possible buffer overflow
+ - Note requirement on avail_out when flushing
+ - Note permitted values of flush parameter of inflate()
+- Add some FAQs (and even answers) to the FAQ
+- Add contrib/inflate86/ for x86 faster inflate
+- Add contrib/blast/ for PKWare Data Compression Library decompression
+- Add contrib/puff/ simple inflate for deflate format description
+
+Changes in 1.1.4 (11 March 2002)
+- ZFREE was repeated on same allocation on some error conditions
+ This creates a security problem described in
+ http://www.zlib.org/advisory-2002-03-11.txt
+- Returned incorrect error (Z_MEM_ERROR) on some invalid data
+- Avoid accesses before window for invalid distances with inflate window
+ less than 32K
+- force windowBits > 8 to avoid a bug in the encoder for a window size
+ of 256 bytes. (A complete fix will be available in 1.1.5)
+
+Changes in 1.1.3 (9 July 1998)
+- fix "an inflate input buffer bug that shows up on rare but persistent
+ occasions" (Mark)
+- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
+- fix gzseek(..., SEEK_SET) in write mode
+- fix crc check after a gzeek (Frank Faubert)
+- fix miniunzip when the last entry in a zip file is itself a zip file
+ (J Lillge)
+- add contrib/asm586 and contrib/asm686 (Brian Raiter)
+ See http://www.muppetlabs.com/~breadbox/software/assembly.html
+- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
+- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
+- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
+- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
+- added a FAQ file
+
+- Support gzdopen on Mac with Metrowerks (Jason Linhart)
+- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart)
+- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young)
+- avoid some warnings with Borland C (Tom Tanner)
+- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant)
+- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant)
+- allow several arguments to configure (Tim Mooney, Frodo Looijaard)
+- use libdir and includedir in Makefile.in (Tim Mooney)
+- support shared libraries on OSF1 V4 (Tim Mooney)
+- remove so_locations in "make clean" (Tim Mooney)
+- fix maketree.c compilation error (Glenn, Mark)
+- Python interface to zlib now in Python 1.5 (Jeremy Hylton)
+- new Makefile.riscos (Rich Walker)
+- initialize static descriptors in trees.c for embedded targets (Nick Smith)
+- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith)
+- add the OS/2 files in Makefile.in too (Andrew Zabolotny)
+- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane)
+- fix maketree.c to allow clean compilation of inffixed.h (Mark)
+- fix parameter check in deflateCopy (Gunther Nikl)
+- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler)
+- Many portability patches by Christian Spieler:
+ . zutil.c, zutil.h: added "const" for zmem*
+ . Make_vms.com: fixed some typos
+ . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists
+ . msdos/Makefile.msc: remove "default rtl link library" info from obj files
+ . msdos/Makefile.*: use model-dependent name for the built zlib library
+ . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc:
+ new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT)
+- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane)
+- replace __far with _far for better portability (Christian Spieler, Tom Lane)
+- fix test for errno.h in configure (Tim Newsham)
+
+Changes in 1.1.2 (19 March 98)
+- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
+ See http://www.winimage.com/zLibDll/unzip.html
+- preinitialize the inflate tables for fixed codes, to make the code
+ completely thread safe (Mark)
+- some simplifications and slight speed-up to the inflate code (Mark)
+- fix gzeof on non-compressed files (Allan Schrum)
+- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
+- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
+- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
+- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
+- do not wrap extern "C" around system includes (Tom Lane)
+- mention zlib binding for TCL in README (Andreas Kupries)
+- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
+- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
+- allow "configure --prefix $HOME" (Tim Mooney)
+- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
+- move Makefile.sas to amiga/Makefile.sas
+
+Changes in 1.1.1 (27 Feb 98)
+- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson)
+- remove block truncation heuristic which had very marginal effect for zlib
+ (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
+ compression ratio on some files. This also allows inlining _tr_tally for
+ matches in deflate_slow
+- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
+
+Changes in 1.1.0 (24 Feb 98)
+- do not return STREAM_END prematurely in inflate (John Bowler)
+- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
+- compile with -DFASTEST to get compression code optimized for speed only
+- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
+- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
+ on Sun but significant on HP)
+
+- add a pointer to experimental unzip library in README (Gilles Vollant)
+- initialize variable gcc in configure (Chris Herborth)
+
+Changes in 1.0.9 (17 Feb 1998)
+- added gzputs and gzgets functions
+- do not clear eof flag in gzseek (Mark Diekhans)
+- fix gzseek for files in transparent mode (Mark Diekhans)
+- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
+- replace EXPORT with ZEXPORT to avoid conflict with other programs
+- added compress2 in zconf.h, zlib.def, zlib.dnt
+- new asm code from Gilles Vollant in contrib/asm386
+- simplify the inflate code (Mark):
+ . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
+ . ZALLOC the length list in inflate_trees_fixed() instead of using stack
+ . ZALLOC the value area for huft_build() instead of using stack
+ . Simplify Z_FINISH check in inflate()
+
+- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
+- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
+- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
+ the declaration of FAR (Gilles Vollant)
+- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
+- read_buf buf parameter of type Bytef* instead of charf*
+- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
+- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
+- fix check for presence of directories in "make install" (Ian Willis)
+
+Changes in 1.0.8 (27 Jan 1998)
+- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
+- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
+- added compress2() to allow setting the compression level
+- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
+- use constant arrays for the static trees in trees.c instead of computing
+ them at run time (thanks to Ken Raeburn for this suggestion). To create
+ trees.h, compile with GEN_TREES_H and run "make test"
+- check return code of example in "make test" and display result
+- pass minigzip command line options to file_compress
+- simplifying code of inflateSync to avoid gcc 2.8 bug
+
+- support CC="gcc -Wall" in configure -s (QingLong)
+- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
+- fix test for shared library support to avoid compiler warnings
+- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
+- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
+- do not use fdopen for Metrowerks on Mac (Brad Pettit))
+- add checks for gzputc and gzputc in example.c
+- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
+- use const for the CRC table (Ken Raeburn)
+- fixed "make uninstall" for shared libraries
+- use Tracev instead of Trace in infblock.c
+- in example.c use correct compressed length for test_sync
+- suppress +vnocompatwarnings in configure for HPUX (not always supported)
+
+Changes in 1.0.7 (20 Jan 1998)
+- fix gzseek which was broken in write mode
+- return error for gzseek to negative absolute position
+- fix configure for Linux (Chun-Chung Chen)
+- increase stack space for MSC (Tim Wegner)
+- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
+- define EXPORTVA for gzprintf (Gilles Vollant)
+- added man page zlib.3 (Rick Rodgers)
+- for contrib/untgz, fix makedir() and improve Makefile
+
+- check gzseek in write mode in example.c
+- allocate extra buffer for seeks only if gzseek is actually called
+- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
+- add inflateSyncPoint in zconf.h
+- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
+
+Changes in 1.0.6 (19 Jan 1998)
+- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
+ gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
+- Fix a deflate bug occurring only with compression level 0 (thanks to
+ Andy Buckler for finding this one)
+- In minigzip, pass transparently also the first byte for .Z files
+- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
+- check Z_FINISH in inflate (thanks to Marc Schluper)
+- Implement deflateCopy (thanks to Adam Costello)
+- make static libraries by default in configure, add --shared option
+- move MSDOS or Windows specific files to directory msdos
+- suppress the notion of partial flush to simplify the interface
+ (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
+- suppress history buffer provided by application to simplify the interface
+ (this feature was not implemented anyway in 1.0.4)
+- next_in and avail_in must be initialized before calling inflateInit or
+ inflateInit2
+- add EXPORT in all exported functions (for Windows DLL)
+- added Makefile.nt (thanks to Stephen Williams)
+- added the unsupported "contrib" directory:
+ contrib/asm386/ by Gilles Vollant
+ 386 asm code replacing longest_match()
+ contrib/iostream/ by Kevin Ruland
+ A C++ I/O streams interface to the zlib gz* functions
+ contrib/iostream2/ by Tyge Løvset
+ Another C++ I/O streams interface
+ contrib/untgz/ by "Pedro A. Aranda Guti\irrez"
+ A very simple tar.gz file extractor using zlib
+ contrib/visual-basic.txt by Carlos Rios
+ How to use compress(), uncompress() and the gz* functions from VB
+- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
+ level) in minigzip (thanks to Tom Lane)
+
+- use const for rommable constants in deflate
+- added test for gzseek and gztell in example.c
+- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
+- add undocumented function zError to convert error code to string
+ (for Tim Smithers)
+- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code
+- Use default memcpy for Symantec MSDOS compiler
+- Add EXPORT keyword for check_func (needed for Windows DLL)
+- add current directory to LD_LIBRARY_PATH for "make test"
+- create also a link for libz.so.1
+- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
+- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
+- added -soname for Linux in configure (Chun-Chung Chen,
+- assign numbers to the exported functions in zlib.def (for Windows DLL)
+- add advice in zlib.h for best usage of deflateSetDictionary
+- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
+- allow compilation with ANSI keywords only enabled for TurboC in large model
+- avoid "versionString"[0] (Borland bug)
+- add NEED_DUMMY_RETURN for Borland
+- use variable z_verbose for tracing in debug mode (L. Peter Deutsch)
+- allow compilation with CC
+- defined STDC for OS/2 (David Charlap)
+- limit external names to 8 chars for MVS (Thomas Lund)
+- in minigzip.c, use static buffers only for 16-bit systems
+- fix suffix check for "minigzip -d foo.gz"
+- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
+- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
+- added makelcc.bat for lcc-win32 (Tom St Denis)
+- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
+- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion
+- check for unistd.h in configure (for off_t)
+- remove useless check parameter in inflate_blocks_free
+- avoid useless assignment of s->check to itself in inflate_blocks_new
+- do not flush twice in gzclose (thanks to Ken Raeburn)
+- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
+- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
+- work around buggy fclose on pipes for HP/UX
+- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
+- fix configure if CC is already equal to gcc
+
+Changes in 1.0.5 (3 Jan 98)
+- Fix inflate to terminate gracefully when fed corrupted or invalid data
+- Use const for rommable constants in inflate
+- Eliminate memory leaks on error conditions in inflate
+- Removed some vestigial code in inflate
+- Update web address in README
+
+Changes in 1.0.4 (24 Jul 96)
+- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
+ bit, so the decompressor could decompress all the correct data but went
+ on to attempt decompressing extra garbage data. This affected minigzip too
+- zlibVersion and gzerror return const char* (needed for DLL)
+- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
+- use z_error only for DEBUG (avoid problem with DLLs)
+
+Changes in 1.0.3 (2 Jul 96)
+- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
+ small and medium models; this makes the library incompatible with previous
+ versions for these models. (No effect in large model or on other systems.)
+- return OK instead of BUF_ERROR if previous deflate call returned with
+ avail_out as zero but there is nothing to do
+- added memcmp for non STDC compilers
+- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
+- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
+- better check for 16-bit mode MSC (avoids problem with Symantec)
+
+Changes in 1.0.2 (23 May 96)
+- added Windows DLL support
+- added a function zlibVersion (for the DLL support)
+- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
+- Bytef is define's instead of typedef'd only for Borland C
+- avoid reading uninitialized memory in example.c
+- mention in README that the zlib format is now RFC1950
+- updated Makefile.dj2
+- added algorithm.doc
+
+Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
+- fix array overlay in deflate.c which sometimes caused bad compressed data
+- fix inflate bug with empty stored block
+- fix MSDOS medium model which was broken in 0.99
+- fix deflateParams() which could generate bad compressed data
+- Bytef is define'd instead of typedef'ed (work around Borland bug)
+- added an INDEX file
+- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
+ Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
+- speed up adler32 for modern machines without auto-increment
+- added -ansi for IRIX in configure
+- static_init_done in trees.c is an int
+- define unlink as delete for VMS
+- fix configure for QNX
+- add configure branch for SCO and HPUX
+- avoid many warnings (unused variables, dead assignments, etc...)
+- no fdopen for BeOS
+- fix the Watcom fix for 32 bit mode (define FAR as empty)
+- removed redefinition of Byte for MKWERKS
+- work around an MWKERKS bug (incorrect merge of all .h files)
+
+Changes in 0.99 (27 Jan 96)
+- allow preset dictionary shared between compressor and decompressor
+- allow compression level 0 (no compression)
+- add deflateParams in zlib.h: allow dynamic change of compression level
+ and compression strategy
+- test large buffers and deflateParams in example.c
+- add optional "configure" to build zlib as a shared library
+- suppress Makefile.qnx, use configure instead
+- fixed deflate for 64-bit systems (detected on Cray)
+- fixed inflate_blocks for 64-bit systems (detected on Alpha)
+- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
+- always return Z_BUF_ERROR when deflate() has nothing to do
+- deflateInit and inflateInit are now macros to allow version checking
+- prefix all global functions and types with z_ with -DZ_PREFIX
+- make falloc completely reentrant (inftrees.c)
+- fixed very unlikely race condition in ct_static_init
+- free in reverse order of allocation to help memory manager
+- use zlib-1.0/* instead of zlib/* inside the tar.gz
+- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
+ -Wconversion -Wstrict-prototypes -Wmissing-prototypes"
+- allow gzread on concatenated .gz files
+- deflateEnd now returns Z_DATA_ERROR if it was premature
+- deflate is finally (?) fully deterministic (no matches beyond end of input)
+- Document Z_SYNC_FLUSH
+- add uninstall in Makefile
+- Check for __cpluplus in zlib.h
+- Better test in ct_align for partial flush
+- avoid harmless warnings for Borland C++
+- initialize hash_head in deflate.c
+- avoid warning on fdopen (gzio.c) for HP cc -Aa
+- include stdlib.h for STDC compilers
+- include errno.h for Cray
+- ignore error if ranlib doesn't exist
+- call ranlib twice for NeXTSTEP
+- use exec_prefix instead of prefix for libz.a
+- renamed ct_* as _tr_* to avoid conflict with applications
+- clear z->msg in inflateInit2 before any error return
+- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
+- fixed typo in zconf.h (_GNUC__ => __GNUC__)
+- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
+- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
+- in fcalloc, normalize pointer if size > 65520 bytes
+- don't use special fcalloc for 32 bit Borland C++
+- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc.
+- use Z_BINARY instead of BINARY
+- document that gzclose after gzdopen will close the file
+- allow "a" as mode in gzopen
+- fix error checking in gzread
+- allow skipping .gz extra-field on pipes
+- added reference to Perl interface in README
+- put the crc table in FAR data (I dislike more and more the medium model :)
+- added get_crc_table
+- added a dimension to all arrays (Borland C can't count)
+- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
+- guard against multiple inclusion of *.h (for precompiled header on Mac)
+- Watcom C pretends to be Microsoft C small model even in 32 bit mode
+- don't use unsized arrays to avoid silly warnings by Visual C++:
+ warning C4746: 'inflate_mask' : unsized array treated as '__far'
+ (what's wrong with far data in far model?)
+- define enum out of inflate_blocks_state to allow compilation with C++
+
+Changes in 0.95 (16 Aug 95)
+- fix MSDOS small and medium model (now easier to adapt to any compiler)
+- inlined send_bits
+- fix the final (:-) bug for deflate with flush (output was correct but
+ not completely flushed in rare occasions)
+- default window size is same for compression and decompression
+ (it's now sufficient to set MAX_WBITS in zconf.h)
+- voidp -> voidpf and voidnp -> voidp (for consistency with other
+ typedefs and because voidnp was not near in large model)
+
+Changes in 0.94 (13 Aug 95)
+- support MSDOS medium model
+- fix deflate with flush (could sometimes generate bad output)
+- fix deflateReset (zlib header was incorrectly suppressed)
+- added support for VMS
+- allow a compression level in gzopen()
+- gzflush now calls fflush
+- For deflate with flush, flush even if no more input is provided
+- rename libgz.a as libz.a
+- avoid complex expression in infcodes.c triggering Turbo C bug
+- work around a problem with gcc on Alpha (in INSERT_STRING)
+- don't use inline functions (problem with some gcc versions)
+- allow renaming of Byte, uInt, etc... with #define
+- avoid warning about (unused) pointer before start of array in deflate.c
+- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
+- avoid reserved word 'new' in trees.c
+
+Changes in 0.93 (25 June 95)
+- temporarily disable inline functions
+- make deflate deterministic
+- give enough lookahead for PARTIAL_FLUSH
+- Set binary mode for stdin/stdout in minigzip.c for OS/2
+- don't even use signed char in inflate (not portable enough)
+- fix inflate memory leak for segmented architectures
+
+Changes in 0.92 (3 May 95)
+- don't assume that char is signed (problem on SGI)
+- Clear bit buffer when starting a stored block
+- no memcpy on Pyramid
+- suppressed inftest.c
+- optimized fill_window, put longest_match inline for gcc
+- optimized inflate on stored blocks
+- untabify all sources to simplify patches
+
+Changes in 0.91 (2 May 95)
+- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
+- Document the memory requirements in zconf.h
+- added "make install"
+- fix sync search logic in inflateSync
+- deflate(Z_FULL_FLUSH) now works even if output buffer too short
+- after inflateSync, don't scare people with just "lo world"
+- added support for DJGPP
+
+Changes in 0.9 (1 May 95)
+- don't assume that zalloc clears the allocated memory (the TurboC bug
+ was Mark's bug after all :)
+- let again gzread copy uncompressed data unchanged (was working in 0.71)
+- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
+- added a test of inflateSync in example.c
+- moved MAX_WBITS to zconf.h because users might want to change that
+- document explicitly that zalloc(64K) on MSDOS must return a normalized
+ pointer (zero offset)
+- added Makefiles for Microsoft C, Turbo C, Borland C++
+- faster crc32()
+
+Changes in 0.8 (29 April 95)
+- added fast inflate (inffast.c)
+- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
+ is incompatible with previous versions of zlib which returned Z_OK
+- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
+ (actually that was not a compiler bug, see 0.81 above)
+- gzread no longer reads one extra byte in certain cases
+- In gzio destroy(), don't reference a freed structure
+- avoid many warnings for MSDOS
+- avoid the ERROR symbol which is used by MS Windows
+
+Changes in 0.71 (14 April 95)
+- Fixed more MSDOS compilation problems :( There is still a bug with
+ TurboC large model
+
+Changes in 0.7 (14 April 95)
+- Added full inflate support
+- Simplified the crc32() interface. The pre- and post-conditioning
+ (one's complement) is now done inside crc32(). WARNING: this is
+ incompatible with previous versions; see zlib.h for the new usage
+
+Changes in 0.61 (12 April 95)
+- workaround for a bug in TurboC. example and minigzip now work on MSDOS
+
+Changes in 0.6 (11 April 95)
+- added minigzip.c
+- added gzdopen to reopen a file descriptor as gzFile
+- added transparent reading of non-gziped files in gzread
+- fixed bug in gzread (don't read crc as data)
+- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose)
+- don't allocate big arrays in the stack (for MSDOS)
+- fix some MSDOS compilation problems
+
+Changes in 0.5:
+- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
+ not yet Z_FULL_FLUSH
+- support decompression but only in a single step (forced Z_FINISH)
+- added opaque object for zalloc and zfree
+- added deflateReset and inflateReset
+- added a variable zlib_version for consistency checking
+- renamed the 'filter' parameter of deflateInit2 as 'strategy'
+ Added Z_FILTERED and Z_HUFFMAN_ONLY constants
+
+Changes in 0.4:
+- avoid "zip" everywhere, use zlib instead of ziplib
+- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
+ if compression method == 8
+- added adler32 and crc32
+- renamed deflateOptions as deflateInit2, call one or the other but not both
+- added the method parameter for deflateInit2
+- added inflateInit2
+- simplified considerably deflateInit and inflateInit by not supporting
+ user-provided history buffer. This is supported only in deflateInit2
+ and inflateInit2
+
+Changes in 0.3:
+- prefix all macro names with Z_
+- use Z_FINISH instead of deflateEnd to finish compression
+- added Z_HUFFMAN_ONLY
+- added gzerror()
diff --git a/Sources/zlib-1.3.1/LICENSE b/Sources/zlib-1.3.1/LICENSE
new file mode 100644
index 00000000..ab8ee6f7
--- /dev/null
+++ b/Sources/zlib-1.3.1/LICENSE
@@ -0,0 +1,22 @@
+Copyright notice:
+
+ (C) 1995-2022 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
diff --git a/Sources/zlib-1.3.1/README b/Sources/zlib-1.3.1/README
new file mode 100644
index 00000000..c5f91754
--- /dev/null
+++ b/Sources/zlib-1.3.1/README
@@ -0,0 +1,117 @@
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.3.1 is a general purpose data compression library. All the code is
+thread safe. The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
+rfc1952 (gzip format).
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
+of the library is given in the file test/example.c which also tests that
+the library is working correctly. Another example is given in the file
+test/minigzip.c. The compression library itself is composed of all source
+files in the root directory.
+
+To compile all files and run the test program, follow the instructions given at
+the top of Makefile.in. In short "./configure; make test", and if that goes
+well, "make install" should work for most flavors of Unix. For Windows, use
+one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
+make_vms.com.
+
+Questions about zlib should be sent to , or to Gilles Vollant
+ for the Windows DLL version. The zlib home page is
+http://zlib.net/ . Before reporting a problem, please check this site to
+verify that you have the latest version of zlib; otherwise get the latest
+version and check whether the problem still exists or not.
+
+PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
+
+Mark Nelson wrote an article about zlib for the Jan. 1997
+issue of Dr. Dobb's Journal; a copy of the article is available at
+https://marknelson.us/posts/1997/01/01/zlib-engine.html .
+
+The changes made in version 1.3.1 are documented in the file ChangeLog.
+
+Unsupported third party contributions are provided in directory contrib/ .
+
+zlib is available in Java using the java.util.zip package. Follow the API
+Documentation link at: https://docs.oracle.com/search/?q=java.util.zip .
+
+A Perl interface to zlib and bzip2 written by Paul Marquess
+can be found at https://github.com/pmqs/IO-Compress .
+
+A Python interface to zlib written by A.M. Kuchling is
+available in Python 1.5 and later versions, see
+http://docs.python.org/library/zlib.html .
+
+zlib is built into tcl: http://wiki.tcl.tk/4610 .
+
+An experimental package to read and write files in .zip format, written on top
+of zlib by Gilles Vollant , is available in the
+contrib/minizip directory of zlib.
+
+
+Notes for some targets:
+
+- For Windows DLL versions, please see win32/DLL_FAQ.txt
+
+- For 64-bit Irix, deflate.c must be compiled without any optimization. With
+ -O, one libpng test fails. The test works in 32 bit mode (with the -n32
+ compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
+ when compiled with cc.
+
+- On Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1 is
+ necessary to get gzprintf working correctly. This is done by configure.
+
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
+ other compilers. Use "make test" to check your compiler.
+
+- gzdopen is not supported on RISCOS or BEOS.
+
+- For PalmOs, see http://palmzlib.sourceforge.net/
+
+
+Acknowledgments:
+
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+ zlib specifications were written by L. Peter Deutsch. Thanks to all the
+ people who reported problems and suggested various improvements in zlib; they
+ are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-2024 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code. We make all
+contributions to and distributions of this project solely in our personal
+capacity, and are not conveying any rights to any intellectual property of
+any third parties.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
diff --git a/Sources/zlib-1.3.1/adler32.c b/Sources/zlib-1.3.1/adler32.c
new file mode 100644
index 00000000..04b81d29
--- /dev/null
+++ b/Sources/zlib-1.3.1/adler32.c
@@ -0,0 +1,164 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2011, 2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#define BASE 65521U /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware --
+ try it both ways to see which is faster */
+#ifdef NO_DIVIDE
+/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
+ (thank you to John Reiser for pointing this out) */
+# define CHOP(a) \
+ do { \
+ unsigned long tmp = a >> 16; \
+ a &= 0xffffUL; \
+ a += (tmp << 4) - tmp; \
+ } while (0)
+# define MOD28(a) \
+ do { \
+ CHOP(a); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD(a) \
+ do { \
+ CHOP(a); \
+ MOD28(a); \
+ } while (0)
+# define MOD63(a) \
+ do { /* this assumes a is not negative */ \
+ z_off64_t tmp = a >> 32; \
+ a &= 0xffffffffL; \
+ a += (tmp << 8) - (tmp << 5) + tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD28(a) a %= BASE
+# define MOD63(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD28(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) {
+ return adler32_z(adler, buf, len);
+}
+
+/* ========================================================================= */
+local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* for negative len, return invalid adler32 as a clue for debugging */
+ if (len2 < 0)
+ return 0xffffffffUL;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ MOD63(len2); /* assumes len2 >= 0 */
+ rem = (unsigned)len2;
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
+ if (sum2 >= BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
+ return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
+ return adler32_combine_(adler1, adler2, len2);
+}
diff --git a/Sources/zlib-1.3.1/compress.c b/Sources/zlib-1.3.1/compress.c
new file mode 100644
index 00000000..f43bacf7
--- /dev/null
+++ b/Sources/zlib-1.3.1/compress.c
@@ -0,0 +1,75 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source,
+ uLong sourceLen, int level) {
+ z_stream stream;
+ int err;
+ const uInt max = (uInt)-1;
+ uLong left;
+
+ left = *destLen;
+ *destLen = 0;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ stream.next_out = dest;
+ stream.avail_out = 0;
+ stream.next_in = (z_const Bytef *)source;
+ stream.avail_in = 0;
+
+ do {
+ if (stream.avail_out == 0) {
+ stream.avail_out = left > (uLong)max ? max : (uInt)left;
+ left -= stream.avail_out;
+ }
+ if (stream.avail_in == 0) {
+ stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
+ sourceLen -= stream.avail_in;
+ }
+ err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
+ } while (err == Z_OK);
+
+ *destLen = stream.total_out;
+ deflateEnd(&stream);
+ return err == Z_STREAM_END ? Z_OK : err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source,
+ uLong sourceLen) {
+ return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+ If the default memLevel or windowBits for deflateInit() is changed, then
+ this function needs to be updated.
+ */
+uLong ZEXPORT compressBound(uLong sourceLen) {
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13;
+}
diff --git a/Sources/zlib-1.3.1/crc32.c b/Sources/zlib-1.3.1/crc32.c
new file mode 100644
index 00000000..6c38f5c0
--- /dev/null
+++ b/Sources/zlib-1.3.1/crc32.c
@@ -0,0 +1,1049 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * This interleaved implementation of a CRC makes use of pipelined multiple
+ * arithmetic-logic units, commonly found in modern CPU cores. It is due to
+ * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.
+ */
+
+/* @(#) $Id$ */
+
+/*
+ Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+ protection on the static variables used to control the first-use generation
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ first call get_crc_table() to initialize the tables before allowing more than
+ one thread to use crc32().
+
+ MAKECRCH can be #defined to write out crc32.h. A main() routine is also
+ produced, so that this one source file can be compiled to an executable.
+ */
+
+#ifdef MAKECRCH
+# include
+# ifndef DYNAMIC_CRC_TABLE
+# define DYNAMIC_CRC_TABLE
+# endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */
+
+ /*
+ A CRC of a message is computed on N braids of words in the message, where
+ each word consists of W bytes (4 or 8). If N is 3, for example, then three
+ running sparse CRCs are calculated respectively on each braid, at these
+ indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...
+ This is done starting at a word boundary, and continues until as many blocks
+ of N * W bytes as are available have been processed. The results are combined
+ into a single CRC at the end. For this code, N must be in the range 1..6 and
+ W must be 4 or 8. The upper limit on N can be increased if desired by adding
+ more #if blocks, extending the patterns apparent in the code. In addition,
+ crc32.h would need to be regenerated, if the maximum N value is increased.
+
+ N and W are chosen empirically by benchmarking the execution time on a given
+ processor. The choices for N and W below were based on testing on Intel Kaby
+ Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64
+ Octeon II processors. The Intel, AMD, and ARM processors were all fastest
+ with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.
+ They were all tested with either gcc or clang, all using the -O3 optimization
+ level. Your mileage may vary.
+ */
+
+/* Define N */
+#ifdef Z_TESTN
+# define N Z_TESTN
+#else
+# define N 5
+#endif
+#if N < 1 || N > 6
+# error N must be in 1..6
+#endif
+
+/*
+ z_crc_t must be at least 32 bits. z_word_t must be at least as long as
+ z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and
+ that bytes are eight bits.
+ */
+
+/*
+ Define W and the associated z_word_t type. If W is not defined, then a
+ braided calculation is not used, and the associated tables and code are not
+ compiled.
+ */
+#ifdef Z_TESTW
+# if Z_TESTW-1 != -1
+# define W Z_TESTW
+# endif
+#else
+# ifdef MAKECRCH
+# define W 8 /* required for MAKECRCH */
+# else
+# if defined(__x86_64__) || defined(__aarch64__)
+# define W 8
+# else
+# define W 4
+# endif
+# endif
+#endif
+#ifdef W
+# if W == 8 && defined(Z_U8)
+ typedef Z_U8 z_word_t;
+# elif defined(Z_U4)
+# undef W
+# define W 4
+ typedef Z_U4 z_word_t;
+# else
+# undef W
+# endif
+#endif
+
+/* If available, use the ARM processor CRC32 instruction. */
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
+# define ARMCRC32
+#endif
+
+#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
+/*
+ Swap the bytes in a z_word_t to convert between little and big endian. Any
+ self-respecting compiler will optimize this to a single machine byte-swap
+ instruction, if one is available. This assumes that word_t is either 32 bits
+ or 64 bits.
+ */
+local z_word_t byte_swap(z_word_t word) {
+# if W == 8
+ return
+ (word & 0xff00000000000000) >> 56 |
+ (word & 0xff000000000000) >> 40 |
+ (word & 0xff0000000000) >> 24 |
+ (word & 0xff00000000) >> 8 |
+ (word & 0xff000000) << 8 |
+ (word & 0xff0000) << 24 |
+ (word & 0xff00) << 40 |
+ (word & 0xff) << 56;
+# else /* W == 4 */
+ return
+ (word & 0xff000000) >> 24 |
+ (word & 0xff0000) >> 8 |
+ (word & 0xff00) << 8 |
+ (word & 0xff) << 24;
+# endif
+}
+#endif
+
+#ifdef DYNAMIC_CRC_TABLE
+/* =========================================================================
+ * Table of powers of x for combining CRC-32s, filled in by make_crc_table()
+ * below.
+ */
+ local z_crc_t FAR x2n_table[32];
+#else
+/* =========================================================================
+ * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
+ * of x for combining CRC-32s, all made by make_crc_table().
+ */
+# include "crc32.h"
+#endif
+
+/* CRC polynomial. */
+#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */
+
+/*
+ Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
+ reflected. For speed, this requires that a not be zero.
+ */
+local z_crc_t multmodp(z_crc_t a, z_crc_t b) {
+ z_crc_t m, p;
+
+ m = (z_crc_t)1 << 31;
+ p = 0;
+ for (;;) {
+ if (a & m) {
+ p ^= b;
+ if ((a & (m - 1)) == 0)
+ break;
+ }
+ m >>= 1;
+ b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
+ }
+ return p;
+}
+
+/*
+ Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
+ initialized.
+ */
+local z_crc_t x2nmodp(z_off64_t n, unsigned k) {
+ z_crc_t p;
+
+ p = (z_crc_t)1 << 31; /* x^0 == 1 */
+ while (n) {
+ if (n & 1)
+ p = multmodp(x2n_table[k & 31], p);
+ n >>= 1;
+ k++;
+ }
+ return p;
+}
+
+#ifdef DYNAMIC_CRC_TABLE
+/* =========================================================================
+ * Build the tables for byte-wise and braided CRC-32 calculations, and a table
+ * of powers of x for combining CRC-32s.
+ */
+local z_crc_t FAR crc_table[256];
+#ifdef W
+ local z_word_t FAR crc_big_table[256];
+ local z_crc_t FAR crc_braid_table[W][256];
+ local z_word_t FAR crc_braid_big_table[W][256];
+ local void braid(z_crc_t [][256], z_word_t [][256], int, int);
+#endif
+#ifdef MAKECRCH
+ local void write_table(FILE *, const z_crc_t FAR *, int);
+ local void write_table32hi(FILE *, const z_word_t FAR *, int);
+ local void write_table64(FILE *, const z_word_t FAR *, int);
+#endif /* MAKECRCH */
+
+/*
+ Define a once() function depending on the availability of atomics. If this is
+ compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in
+ multiple threads, and if atomics are not available, then get_crc_table() must
+ be called to initialize the tables and must return before any threads are
+ allowed to compute or combine CRCs.
+ */
+
+/* Definition of once functionality. */
+typedef struct once_s once_t;
+
+/* Check for the availability of atomics. */
+#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
+ !defined(__STDC_NO_ATOMICS__)
+
+#include
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ atomic_flag begun;
+ atomic_int done;
+};
+#define ONCE_INIT {ATOMIC_FLAG_INIT, 0}
+
+/*
+ Run the provided init() function exactly once, even if multiple threads
+ invoke once() at the same time. The state must be a once_t initialized with
+ ONCE_INIT.
+ */
+local void once(once_t *state, void (*init)(void)) {
+ if (!atomic_load(&state->done)) {
+ if (atomic_flag_test_and_set(&state->begun))
+ while (!atomic_load(&state->done))
+ ;
+ else {
+ init();
+ atomic_store(&state->done, 1);
+ }
+ }
+}
+
+#else /* no atomics */
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ volatile int begun;
+ volatile int done;
+};
+#define ONCE_INIT {0, 0}
+
+/* Test and set. Alas, not atomic, but tries to minimize the period of
+ vulnerability. */
+local int test_and_set(int volatile *flag) {
+ int was;
+
+ was = *flag;
+ *flag = 1;
+ return was;
+}
+
+/* Run the provided init() function once. This is not thread-safe. */
+local void once(once_t *state, void (*init)(void)) {
+ if (!state->done) {
+ if (test_and_set(&state->begun))
+ while (!state->done)
+ ;
+ else {
+ init();
+ state->done = 1;
+ }
+ }
+}
+
+#endif
+
+/* State for once(). */
+local once_t made = ONCE_INIT;
+
+/*
+ Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x
+ (which is shifting right by one and adding x^32 mod p if the bit shifted out
+ is a one). We start with the highest power (least significant bit) of q and
+ repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all the
+ information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+ */
+
+local void make_crc_table(void) {
+ unsigned i, j, n;
+ z_crc_t p;
+
+ /* initialize the CRC of bytes tables */
+ for (i = 0; i < 256; i++) {
+ p = i;
+ for (j = 0; j < 8; j++)
+ p = p & 1 ? (p >> 1) ^ POLY : p >> 1;
+ crc_table[i] = p;
+#ifdef W
+ crc_big_table[i] = byte_swap(p);
+#endif
+ }
+
+ /* initialize the x^2^n mod p(x) table */
+ p = (z_crc_t)1 << 30; /* x^1 */
+ x2n_table[0] = p;
+ for (n = 1; n < 32; n++)
+ x2n_table[n] = p = multmodp(p, p);
+
+#ifdef W
+ /* initialize the braiding tables -- needs x2n_table[] */
+ braid(crc_braid_table, crc_braid_big_table, N, W);
+#endif
+
+#ifdef MAKECRCH
+ {
+ /*
+ The crc32.h header file contains tables for both 32-bit and 64-bit
+ z_word_t's, and so requires a 64-bit type be available. In that case,
+ z_word_t must be defined to be 64-bits. This code then also generates
+ and writes out the tables for the case that z_word_t is 32 bits.
+ */
+#if !defined(W) || W != 8
+# error Need a 64-bit integer type in order to generate crc32.h.
+#endif
+ FILE *out;
+ int k, n;
+ z_crc_t ltl[8][256];
+ z_word_t big[8][256];
+
+ out = fopen("crc32.h", "w");
+ if (out == NULL) return;
+
+ /* write out little-endian CRC table to crc32.h */
+ fprintf(out,
+ "/* crc32.h -- tables for rapid CRC calculation\n"
+ " * Generated automatically by crc32.c\n */\n"
+ "\n"
+ "local const z_crc_t FAR crc_table[] = {\n"
+ " ");
+ write_table(out, crc_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#ifdef W\n"
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table64(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table32hi(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n");
+
+ /* write out braid tables for each value of N */
+ for (n = 1; n <= 6; n++) {
+ fprintf(out,
+ "\n"
+ "#if N == %d\n", n);
+
+ /* compute braid tables for this N and 64-bit word_t */
+ braid(ltl, big, n, 8);
+
+ /* write out braid tables for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table64(out, big[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n");
+
+ /* compute braid tables for this N and 32-bit word_t */
+ braid(ltl, big, n, 4);
+
+ /* write out braid tables for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table32hi(out, big[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n"
+ "\n"
+ "#endif\n");
+ }
+ fprintf(out,
+ "\n"
+ "#endif\n");
+
+ /* write out zeros operator table to crc32.h */
+ fprintf(out,
+ "\n"
+ "local const z_crc_t FAR x2n_table[] = {\n"
+ " ");
+ write_table(out, x2n_table, 32);
+ fprintf(out,
+ "};\n");
+ fclose(out);
+ }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+
+/*
+ Write the 32-bit values in table[0..k-1] to out, five per line in
+ hexadecimal separated by commas.
+ */
+local void write_table(FILE *out, const z_crc_t FAR *table, int k) {
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n]),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the high 32-bits of each value in table[0..k-1] to out, five per line
+ in hexadecimal separated by commas.
+ */
+local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) {
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n] >> 32),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the 64-bit values in table[0..k-1] to out, three per line in
+ hexadecimal separated by commas. This assumes that if there is a 64-bit
+ type, then there is also a long long integer type, and it is at least 64
+ bits. If not, then the type cast and format string can be adjusted
+ accordingly.
+ */
+local void write_table64(FILE *out, const z_word_t FAR *table, int k) {
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ",
+ (unsigned long long)(table[n]),
+ n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", "));
+}
+
+/* Actually do the deed. */
+int main(void) {
+ make_crc_table();
+ return 0;
+}
+
+#endif /* MAKECRCH */
+
+#ifdef W
+/*
+ Generate the little and big-endian braid tables for the given n and z_word_t
+ size w. Each array must have room for w blocks of 256 elements.
+ */
+local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) {
+ int k;
+ z_crc_t i, p, q;
+ for (k = 0; k < w; k++) {
+ p = x2nmodp((n * w + 3 - k) << 3, 0);
+ ltl[k][0] = 0;
+ big[w - 1 - k][0] = 0;
+ for (i = 1; i < 256; i++) {
+ ltl[k][i] = q = multmodp(i << 24, p);
+ big[w - 1 - k][i] = byte_swap(q);
+ }
+ }
+}
+#endif
+
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32(), and to force the
+ * generation of the CRC tables in a threaded application.
+ */
+const z_crc_t FAR * ZEXPORT get_crc_table(void) {
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return (const z_crc_t FAR *)crc_table;
+}
+
+/* =========================================================================
+ * Use ARM machine instructions if available. This will compute the CRC about
+ * ten times faster than the braided calculation. This code does not check for
+ * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will
+ * only be defined if the compilation specifies an ARM processor architecture
+ * that has the instructions. For example, compiling with -march=armv8.1-a or
+ * -march=armv8-a+crc, or -march=native if the compile machine has the crc32
+ * instructions.
+ */
+#ifdef ARMCRC32
+
+/*
+ Constants empirically determined to maximize speed. These values are from
+ measurements on a Cortex-A57. Your mileage may vary.
+ */
+#define Z_BATCH 3990 /* number of words in a batch */
+#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */
+#define Z_BATCH_MIN 800 /* fewest words in a final batch */
+
+unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
+ z_size_t len) {
+ z_crc_t val;
+ z_word_t crc1, crc2;
+ const z_word_t *word;
+ z_word_t val0, val1, val2;
+ z_size_t last, last2, i;
+ z_size_t num;
+
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+
+ /* Pre-condition the CRC */
+ crc = (~crc) & 0xffffffff;
+
+ /* Compute the CRC up to a word boundary. */
+ while (len && ((z_size_t)buf & 7) != 0) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */
+ word = (z_word_t const *)buf;
+ num = len >> 3;
+ len &= 7;
+
+ /* Do three interleaved CRCs to realize the throughput of one crc32x
+ instruction per cycle. Each CRC is calculated on Z_BATCH words. The
+ three CRCs are combined into a single CRC after each set of batches. */
+ while (num >= 3 * Z_BATCH) {
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < Z_BATCH; i++) {
+ val0 = word[i];
+ val1 = word[i + Z_BATCH];
+ val2 = word[i + 2 * Z_BATCH];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * Z_BATCH;
+ num -= 3 * Z_BATCH;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;
+ }
+
+ /* Do one last smaller batch with the remaining words, if there are enough
+ to pay for the combination of CRCs. */
+ last = num / 3;
+ if (last >= Z_BATCH_MIN) {
+ last2 = last << 1;
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < last; i++) {
+ val0 = word[i];
+ val1 = word[i + last];
+ val2 = word[i + last2];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * last;
+ num -= 3 * last;
+ val = x2nmodp(last, 6);
+ crc = multmodp(val, crc) ^ crc1;
+ crc = multmodp(val, crc) ^ crc2;
+ }
+
+ /* Compute the CRC on any remaining words. */
+ for (i = 0; i < num; i++) {
+ val0 = word[i];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ }
+ word += num;
+
+ /* Complete the CRC on any remaining bytes. */
+ buf = (const unsigned char FAR *)word;
+ while (len) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
+}
+
+#else
+
+#ifdef W
+
+/*
+ Return the CRC of the W bytes in the word_t data, taking the
+ least-significant byte of the word as the first byte of data, without any pre
+ or post conditioning. This is used to combine the CRCs of each braid.
+ */
+local z_crc_t crc_word(z_word_t data) {
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data >> 8) ^ crc_table[data & 0xff];
+ return (z_crc_t)data;
+}
+
+local z_word_t crc_word_big(z_word_t data) {
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data << 8) ^
+ crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
+ return data;
+}
+
+#endif
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
+ z_size_t len) {
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+
+ /* Pre-condition the CRC */
+ crc = (~crc) & 0xffffffff;
+
+#ifdef W
+
+ /* If provided enough bytes, do a braided CRC calculation. */
+ if (len >= N * W + W - 1) {
+ z_size_t blks;
+ z_word_t const *words;
+ unsigned endian;
+ int k;
+
+ /* Compute the CRC up to a z_word_t boundary. */
+ while (len && ((z_size_t)buf & (W - 1)) != 0) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+
+ /* Compute the CRC on as many N z_word_t blocks as are available. */
+ blks = len / (N * W);
+ len -= blks * N * W;
+ words = (z_word_t const *)buf;
+
+ /* Do endian check at execution time instead of compile time, since ARM
+ processors can change the endianness at execution time. If the
+ compiler knows what the endianness will be, it can optimize out the
+ check and the unused branch. */
+ endian = 1;
+ if (*(unsigned char *)&endian) {
+ /* Little endian. */
+
+ z_crc_t crc0;
+ z_word_t word0;
+#if N > 1
+ z_crc_t crc1;
+ z_word_t word1;
+#if N > 2
+ z_crc_t crc2;
+ z_word_t word2;
+#if N > 3
+ z_crc_t crc3;
+ z_word_t word3;
+#if N > 4
+ z_crc_t crc4;
+ z_word_t word4;
+#if N > 5
+ z_crc_t crc5;
+ z_word_t word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = crc;
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ crc = crc_word(crc0 ^ words[0]);
+#if N > 1
+ crc = crc_word(crc1 ^ words[1] ^ crc);
+#if N > 2
+ crc = crc_word(crc2 ^ words[2] ^ crc);
+#if N > 3
+ crc = crc_word(crc3 ^ words[3] ^ crc);
+#if N > 4
+ crc = crc_word(crc4 ^ words[4] ^ crc);
+#if N > 5
+ crc = crc_word(crc5 ^ words[5] ^ crc);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ }
+ else {
+ /* Big endian. */
+
+ z_word_t crc0, word0, comb;
+#if N > 1
+ z_word_t crc1, word1;
+#if N > 2
+ z_word_t crc2, word2;
+#if N > 3
+ z_word_t crc3, word3;
+#if N > 4
+ z_word_t crc4, word4;
+#if N > 5
+ z_word_t crc5, word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = byte_swap(crc);
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_big_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_big_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_big_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_big_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_big_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_big_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ comb = crc_word_big(crc0 ^ words[0]);
+#if N > 1
+ comb = crc_word_big(crc1 ^ words[1] ^ comb);
+#if N > 2
+ comb = crc_word_big(crc2 ^ words[2] ^ comb);
+#if N > 3
+ comb = crc_word_big(crc3 ^ words[3] ^ comb);
+#if N > 4
+ comb = crc_word_big(crc4 ^ words[4] ^ comb);
+#if N > 5
+ comb = crc_word_big(crc5 ^ words[5] ^ comb);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ crc = byte_swap(comb);
+ }
+
+ /*
+ Update the pointer to the remaining bytes to process.
+ */
+ buf = (unsigned char const *)words;
+ }
+
+#endif /* W */
+
+ /* Complete the computation of the CRC on any remaining bytes. */
+ while (len >= 8) {
+ len -= 8;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+ while (len) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
+}
+
+#endif
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf,
+ uInt len) {
+ return crc32_z(crc, buf, len);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) {
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) {
+ return crc32_combine64(crc1, crc2, (z_off64_t)len2);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) {
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return x2nmodp(len2, 3);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen(z_off_t len2) {
+ return crc32_combine_gen64((z_off64_t)len2);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) {
+ return multmodp(op, crc1) ^ (crc2 & 0xffffffff);
+}
diff --git a/Sources/zlib-1.3.1/crc32.h b/Sources/zlib-1.3.1/crc32.h
new file mode 100644
index 00000000..137df68d
--- /dev/null
+++ b/Sources/zlib-1.3.1/crc32.h
@@ -0,0 +1,9446 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const z_crc_t FAR crc_table[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d};
+
+#ifdef W
+
+#if W == 8
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000};
+
+#else /* W == 4 */
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d};
+
+#endif
+
+#if N == 1
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c},
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000},
+ {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000,
+ 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000,
+ 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000,
+ 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000,
+ 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000,
+ 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000,
+ 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000,
+ 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000,
+ 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000,
+ 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000,
+ 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000,
+ 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000,
+ 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000,
+ 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000,
+ 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000,
+ 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000,
+ 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000,
+ 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000,
+ 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000,
+ 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000,
+ 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000,
+ 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000,
+ 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000,
+ 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000,
+ 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000,
+ 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000,
+ 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000,
+ 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000,
+ 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000,
+ 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000,
+ 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000,
+ 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000,
+ 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000,
+ 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000,
+ 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000,
+ 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000,
+ 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000,
+ 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000,
+ 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000,
+ 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000,
+ 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000,
+ 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000,
+ 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000,
+ 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000,
+ 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000,
+ 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000,
+ 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000,
+ 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000,
+ 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000,
+ 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000,
+ 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000,
+ 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000,
+ 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000,
+ 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000,
+ 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000,
+ 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000,
+ 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000,
+ 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000,
+ 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000,
+ 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000,
+ 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000,
+ 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000,
+ 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000,
+ 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000,
+ 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000,
+ 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000,
+ 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000,
+ 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000,
+ 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000,
+ 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000,
+ 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000,
+ 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000,
+ 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000,
+ 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000,
+ 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000,
+ 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000,
+ 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000,
+ 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000,
+ 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000,
+ 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000,
+ 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000,
+ 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000,
+ 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000,
+ 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000,
+ 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000,
+ 0x72fd249300000000},
+ {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000,
+ 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000,
+ 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000,
+ 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000,
+ 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000,
+ 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000,
+ 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000,
+ 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000,
+ 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000,
+ 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000,
+ 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000,
+ 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000,
+ 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000,
+ 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000,
+ 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000,
+ 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000,
+ 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000,
+ 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000,
+ 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000,
+ 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000,
+ 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000,
+ 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000,
+ 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000,
+ 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000,
+ 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000,
+ 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000,
+ 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000,
+ 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000,
+ 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000,
+ 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000,
+ 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000,
+ 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000,
+ 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000,
+ 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000,
+ 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000,
+ 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000,
+ 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000,
+ 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000,
+ 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000,
+ 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000,
+ 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000,
+ 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000,
+ 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000,
+ 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000,
+ 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000,
+ 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000,
+ 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000,
+ 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000,
+ 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000,
+ 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000,
+ 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000,
+ 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000,
+ 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000,
+ 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000,
+ 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000,
+ 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000,
+ 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000,
+ 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000,
+ 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000,
+ 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000,
+ 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000,
+ 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000,
+ 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000,
+ 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000,
+ 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000,
+ 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000,
+ 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000,
+ 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000,
+ 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000,
+ 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000,
+ 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000,
+ 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000,
+ 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000,
+ 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000,
+ 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000,
+ 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000,
+ 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000,
+ 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000,
+ 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000,
+ 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000,
+ 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000,
+ 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000,
+ 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000,
+ 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000,
+ 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000,
+ 0xed3498be00000000},
+ {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000,
+ 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000,
+ 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000,
+ 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000,
+ 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000,
+ 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000,
+ 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000,
+ 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000,
+ 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000,
+ 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000,
+ 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000,
+ 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000,
+ 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000,
+ 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000,
+ 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000,
+ 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000,
+ 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000,
+ 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000,
+ 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000,
+ 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000,
+ 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000,
+ 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000,
+ 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000,
+ 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000,
+ 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000,
+ 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000,
+ 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000,
+ 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000,
+ 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000,
+ 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000,
+ 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000,
+ 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000,
+ 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000,
+ 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000,
+ 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000,
+ 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000,
+ 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000,
+ 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000,
+ 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000,
+ 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000,
+ 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000,
+ 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000,
+ 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000,
+ 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000,
+ 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000,
+ 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000,
+ 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000,
+ 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000,
+ 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000,
+ 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000,
+ 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000,
+ 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000,
+ 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000,
+ 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000,
+ 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000,
+ 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000,
+ 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000,
+ 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000,
+ 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000,
+ 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000,
+ 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000,
+ 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000,
+ 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000,
+ 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000,
+ 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000,
+ 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000,
+ 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000,
+ 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000,
+ 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000,
+ 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000,
+ 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000,
+ 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000,
+ 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000,
+ 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000,
+ 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000,
+ 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000,
+ 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000,
+ 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000,
+ 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000,
+ 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000,
+ 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000,
+ 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000,
+ 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000,
+ 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000,
+ 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000,
+ 0xf10605de00000000},
+ {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000,
+ 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000,
+ 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000,
+ 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000,
+ 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000,
+ 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000,
+ 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000,
+ 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000,
+ 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000,
+ 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000,
+ 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000,
+ 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000,
+ 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000,
+ 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000,
+ 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000,
+ 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000,
+ 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000,
+ 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000,
+ 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000,
+ 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000,
+ 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000,
+ 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000,
+ 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000,
+ 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000,
+ 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000,
+ 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000,
+ 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000,
+ 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000,
+ 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000,
+ 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000,
+ 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000,
+ 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000,
+ 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000,
+ 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000,
+ 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000,
+ 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000,
+ 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000,
+ 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000,
+ 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000,
+ 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000,
+ 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000,
+ 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000,
+ 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000,
+ 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000,
+ 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000,
+ 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000,
+ 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000,
+ 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000,
+ 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000,
+ 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000,
+ 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000,
+ 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000,
+ 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000,
+ 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000,
+ 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000,
+ 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000,
+ 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000,
+ 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000,
+ 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000,
+ 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000,
+ 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000,
+ 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000,
+ 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000,
+ 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000,
+ 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000,
+ 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000,
+ 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000,
+ 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000,
+ 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000,
+ 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000,
+ 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000,
+ 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000,
+ 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000,
+ 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000,
+ 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000,
+ 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000,
+ 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000,
+ 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000,
+ 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000,
+ 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000,
+ 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000,
+ 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000,
+ 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000,
+ 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000,
+ 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000,
+ 0x8cc764ca00000000},
+ {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000,
+ 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000,
+ 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000,
+ 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000,
+ 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000,
+ 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000,
+ 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000,
+ 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000,
+ 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000,
+ 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000,
+ 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000,
+ 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000,
+ 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000,
+ 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000,
+ 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000,
+ 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000,
+ 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000,
+ 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000,
+ 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000,
+ 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000,
+ 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000,
+ 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000,
+ 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000,
+ 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000,
+ 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000,
+ 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000,
+ 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000,
+ 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000,
+ 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000,
+ 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000,
+ 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000,
+ 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000,
+ 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000,
+ 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000,
+ 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000,
+ 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000,
+ 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000,
+ 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000,
+ 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000,
+ 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000,
+ 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000,
+ 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000,
+ 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000,
+ 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000,
+ 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000,
+ 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000,
+ 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000,
+ 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000,
+ 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000,
+ 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000,
+ 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000,
+ 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000,
+ 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000,
+ 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000,
+ 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000,
+ 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000,
+ 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000,
+ 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000,
+ 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000,
+ 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000,
+ 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000,
+ 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000,
+ 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000,
+ 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000,
+ 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000,
+ 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000,
+ 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000,
+ 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000,
+ 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000,
+ 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000,
+ 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000,
+ 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000,
+ 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000,
+ 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000,
+ 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000,
+ 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000,
+ 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000,
+ 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000,
+ 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000,
+ 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000,
+ 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000,
+ 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000,
+ 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000,
+ 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000,
+ 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000,
+ 0xccabc4e400000000},
+ {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000,
+ 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000,
+ 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000,
+ 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000,
+ 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000,
+ 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000,
+ 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000,
+ 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000,
+ 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000,
+ 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000,
+ 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000,
+ 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000,
+ 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000,
+ 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000,
+ 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000,
+ 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000,
+ 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000,
+ 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000,
+ 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000,
+ 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000,
+ 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000,
+ 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000,
+ 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000,
+ 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000,
+ 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000,
+ 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000,
+ 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000,
+ 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000,
+ 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000,
+ 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000,
+ 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000,
+ 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000,
+ 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000,
+ 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000,
+ 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000,
+ 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000,
+ 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000,
+ 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000,
+ 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000,
+ 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000,
+ 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000,
+ 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000,
+ 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000,
+ 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000,
+ 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000,
+ 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000,
+ 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000,
+ 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000,
+ 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000,
+ 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000,
+ 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000,
+ 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000,
+ 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000,
+ 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000,
+ 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000,
+ 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000,
+ 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000,
+ 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000,
+ 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000,
+ 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000,
+ 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000,
+ 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000,
+ 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000,
+ 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000,
+ 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000,
+ 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000,
+ 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000,
+ 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000,
+ 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000,
+ 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000,
+ 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000,
+ 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000,
+ 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000,
+ 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000,
+ 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000,
+ 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000,
+ 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000,
+ 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000,
+ 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000,
+ 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000,
+ 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000,
+ 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000,
+ 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000,
+ 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000,
+ 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000,
+ 0x304a369200000000},
+ {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000,
+ 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000,
+ 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000,
+ 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000,
+ 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000,
+ 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000,
+ 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000,
+ 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000,
+ 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000,
+ 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000,
+ 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000,
+ 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000,
+ 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000,
+ 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000,
+ 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000,
+ 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000,
+ 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000,
+ 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000,
+ 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000,
+ 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000,
+ 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000,
+ 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000,
+ 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000,
+ 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000,
+ 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000,
+ 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000,
+ 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000,
+ 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000,
+ 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000,
+ 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000,
+ 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000,
+ 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000,
+ 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000,
+ 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000,
+ 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000,
+ 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000,
+ 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000,
+ 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000,
+ 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000,
+ 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000,
+ 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000,
+ 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000,
+ 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000,
+ 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000,
+ 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000,
+ 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000,
+ 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000,
+ 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000,
+ 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000,
+ 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000,
+ 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000,
+ 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000,
+ 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000,
+ 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000,
+ 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000,
+ 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000,
+ 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000,
+ 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000,
+ 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000,
+ 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000,
+ 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000,
+ 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000,
+ 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000,
+ 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000,
+ 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000,
+ 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000,
+ 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000,
+ 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000,
+ 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000,
+ 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000,
+ 0x6171384400000000, 0xff71928800000000, 0xe678578200000000,
+ 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000,
+ 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000,
+ 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000,
+ 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000,
+ 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000,
+ 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000,
+ 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000,
+ 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000,
+ 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000,
+ 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000,
+ 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000,
+ 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000,
+ 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000,
+ 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000,
+ 0xe6064b2600000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d},
+ {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64,
+ 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1,
+ 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e,
+ 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61,
+ 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82,
+ 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff,
+ 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7,
+ 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da,
+ 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139,
+ 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6,
+ 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89,
+ 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c,
+ 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0,
+ 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d,
+ 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a,
+ 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177,
+ 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de,
+ 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b,
+ 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824,
+ 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e,
+ 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad,
+ 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0,
+ 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d,
+ 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60,
+ 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83,
+ 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822,
+ 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d,
+ 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8,
+ 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171,
+ 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c,
+ 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b,
+ 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6,
+ 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca,
+ 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f,
+ 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430,
+ 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf,
+ 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c,
+ 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51,
+ 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9,
+ 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84,
+ 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67,
+ 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398,
+ 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7,
+ 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62,
+ 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e,
+ 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923,
+ 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4,
+ 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9,
+ 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070,
+ 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5,
+ 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a,
+ 0x72fd2493},
+ {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907,
+ 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f,
+ 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a,
+ 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e,
+ 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512,
+ 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14,
+ 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b,
+ 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d,
+ 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731,
+ 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925,
+ 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620,
+ 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28,
+ 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70,
+ 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176,
+ 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d,
+ 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b,
+ 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b,
+ 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63,
+ 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266,
+ 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a,
+ 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446,
+ 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40,
+ 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557,
+ 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51,
+ 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d,
+ 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0,
+ 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5,
+ 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed,
+ 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd,
+ 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb,
+ 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0,
+ 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6,
+ 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de,
+ 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6,
+ 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3,
+ 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7,
+ 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb,
+ 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd,
+ 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92,
+ 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094,
+ 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598,
+ 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c,
+ 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489,
+ 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81,
+ 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9,
+ 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af,
+ 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4,
+ 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2,
+ 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2,
+ 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba,
+ 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf,
+ 0xed3498be},
+ {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f,
+ 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d,
+ 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0,
+ 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42,
+ 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95,
+ 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2,
+ 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a,
+ 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d,
+ 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea,
+ 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748,
+ 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5,
+ 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27,
+ 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b,
+ 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac,
+ 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4,
+ 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3,
+ 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44,
+ 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6,
+ 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b,
+ 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329,
+ 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe,
+ 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9,
+ 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1,
+ 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6,
+ 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921,
+ 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555,
+ 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8,
+ 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a,
+ 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd,
+ 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a,
+ 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2,
+ 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5,
+ 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2,
+ 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330,
+ 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad,
+ 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f,
+ 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8,
+ 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef,
+ 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc,
+ 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb,
+ 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c,
+ 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e,
+ 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03,
+ 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1,
+ 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6,
+ 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1,
+ 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9,
+ 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e,
+ 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409,
+ 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb,
+ 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966,
+ 0xf10605de}};
+
+#endif
+
+#endif
+
+#if N == 2
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6},
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000,
+ 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000,
+ 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000,
+ 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000,
+ 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000,
+ 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000,
+ 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000,
+ 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000,
+ 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000,
+ 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000,
+ 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000,
+ 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000,
+ 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000,
+ 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000,
+ 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000,
+ 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000,
+ 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000,
+ 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000,
+ 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000,
+ 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000,
+ 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000,
+ 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000,
+ 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000,
+ 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000,
+ 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000,
+ 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000,
+ 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000,
+ 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000,
+ 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000,
+ 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000,
+ 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000,
+ 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000,
+ 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000,
+ 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000,
+ 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000,
+ 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000,
+ 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000,
+ 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000,
+ 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000,
+ 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000,
+ 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000,
+ 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000,
+ 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000,
+ 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000,
+ 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000,
+ 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000,
+ 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000,
+ 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000,
+ 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000,
+ 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000,
+ 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000,
+ 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000,
+ 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000,
+ 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000,
+ 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000,
+ 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000,
+ 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000,
+ 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000,
+ 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000,
+ 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000,
+ 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000,
+ 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000,
+ 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000,
+ 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000,
+ 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000,
+ 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000,
+ 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000,
+ 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000,
+ 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000,
+ 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000,
+ 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000,
+ 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000,
+ 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000,
+ 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000,
+ 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000,
+ 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000,
+ 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000,
+ 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000,
+ 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000,
+ 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000,
+ 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000,
+ 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000,
+ 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000,
+ 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000,
+ 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000,
+ 0x4b0c4f4900000000},
+ {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000,
+ 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000,
+ 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000,
+ 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000,
+ 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000,
+ 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000,
+ 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000,
+ 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000,
+ 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000,
+ 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000,
+ 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000,
+ 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000,
+ 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000,
+ 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000,
+ 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000,
+ 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000,
+ 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000,
+ 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000,
+ 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000,
+ 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000,
+ 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000,
+ 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000,
+ 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000,
+ 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000,
+ 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000,
+ 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000,
+ 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000,
+ 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000,
+ 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000,
+ 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000,
+ 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000,
+ 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000,
+ 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000,
+ 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000,
+ 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000,
+ 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000,
+ 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000,
+ 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000,
+ 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000,
+ 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000,
+ 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000,
+ 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000,
+ 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000,
+ 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000,
+ 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000,
+ 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000,
+ 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000,
+ 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000,
+ 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000,
+ 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000,
+ 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000,
+ 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000,
+ 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000,
+ 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000,
+ 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000,
+ 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000,
+ 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000,
+ 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000,
+ 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000,
+ 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000,
+ 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000,
+ 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000,
+ 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000,
+ 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000,
+ 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000,
+ 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000,
+ 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000,
+ 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000,
+ 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000,
+ 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000,
+ 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000,
+ 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000,
+ 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000,
+ 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000,
+ 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000,
+ 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000,
+ 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000,
+ 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000,
+ 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000,
+ 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000,
+ 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000,
+ 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000,
+ 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000,
+ 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000,
+ 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000,
+ 0x14d747e100000000},
+ {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000,
+ 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000,
+ 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000,
+ 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000,
+ 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000,
+ 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000,
+ 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000,
+ 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000,
+ 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000,
+ 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000,
+ 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000,
+ 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000,
+ 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000,
+ 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000,
+ 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000,
+ 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000,
+ 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000,
+ 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000,
+ 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000,
+ 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000,
+ 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000,
+ 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000,
+ 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000,
+ 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000,
+ 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000,
+ 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000,
+ 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000,
+ 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000,
+ 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000,
+ 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000,
+ 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000,
+ 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000,
+ 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000,
+ 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000,
+ 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000,
+ 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000,
+ 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000,
+ 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000,
+ 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000,
+ 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000,
+ 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000,
+ 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000,
+ 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000,
+ 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000,
+ 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000,
+ 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000,
+ 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000,
+ 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000,
+ 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000,
+ 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000,
+ 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000,
+ 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000,
+ 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000,
+ 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000,
+ 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000,
+ 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000,
+ 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000,
+ 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000,
+ 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000,
+ 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000,
+ 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000,
+ 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000,
+ 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000,
+ 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000,
+ 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000,
+ 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000,
+ 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000,
+ 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000,
+ 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000,
+ 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000,
+ 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000,
+ 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000,
+ 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000,
+ 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000,
+ 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000,
+ 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000,
+ 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000,
+ 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000,
+ 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000,
+ 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000,
+ 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000,
+ 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000,
+ 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000,
+ 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000,
+ 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000,
+ 0xaa933b1a00000000},
+ {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000,
+ 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000,
+ 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000,
+ 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000,
+ 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000,
+ 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000,
+ 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000,
+ 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000,
+ 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000,
+ 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000,
+ 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000,
+ 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000,
+ 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000,
+ 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000,
+ 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000,
+ 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000,
+ 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000,
+ 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000,
+ 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000,
+ 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000,
+ 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000,
+ 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000,
+ 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000,
+ 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000,
+ 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000,
+ 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000,
+ 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000,
+ 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000,
+ 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000,
+ 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000,
+ 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000,
+ 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000,
+ 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000,
+ 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000,
+ 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000,
+ 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000,
+ 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000,
+ 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000,
+ 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000,
+ 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000,
+ 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000,
+ 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000,
+ 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000,
+ 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000,
+ 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000,
+ 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000,
+ 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000,
+ 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000,
+ 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000,
+ 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000,
+ 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000,
+ 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000,
+ 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000,
+ 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000,
+ 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000,
+ 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000,
+ 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000,
+ 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000,
+ 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000,
+ 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000,
+ 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000,
+ 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000,
+ 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000,
+ 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000,
+ 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000,
+ 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000,
+ 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000,
+ 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000,
+ 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000,
+ 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000,
+ 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000,
+ 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000,
+ 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000,
+ 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000,
+ 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000,
+ 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000,
+ 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000,
+ 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000,
+ 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000,
+ 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000,
+ 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000,
+ 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000,
+ 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000,
+ 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000,
+ 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000,
+ 0x6571193600000000},
+ {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000,
+ 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000,
+ 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000,
+ 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000,
+ 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000,
+ 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000,
+ 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000,
+ 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000,
+ 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000,
+ 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000,
+ 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000,
+ 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000,
+ 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000,
+ 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000,
+ 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000,
+ 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000,
+ 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000,
+ 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000,
+ 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000,
+ 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000,
+ 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000,
+ 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000,
+ 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000,
+ 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000,
+ 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000,
+ 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000,
+ 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000,
+ 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000,
+ 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000,
+ 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000,
+ 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000,
+ 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000,
+ 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000,
+ 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000,
+ 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000,
+ 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000,
+ 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000,
+ 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000,
+ 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000,
+ 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000,
+ 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000,
+ 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000,
+ 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000,
+ 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000,
+ 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000,
+ 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000,
+ 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000,
+ 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000,
+ 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000,
+ 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000,
+ 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000,
+ 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000,
+ 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000,
+ 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000,
+ 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000,
+ 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000,
+ 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000,
+ 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000,
+ 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000,
+ 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000,
+ 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000,
+ 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000,
+ 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000,
+ 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000,
+ 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000,
+ 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000,
+ 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000,
+ 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000,
+ 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000,
+ 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000,
+ 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000,
+ 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000,
+ 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000,
+ 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000,
+ 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000,
+ 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000,
+ 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000,
+ 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000,
+ 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000,
+ 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000,
+ 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000,
+ 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000,
+ 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000,
+ 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000,
+ 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000,
+ 0xa68cee3d00000000},
+ {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000,
+ 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000,
+ 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000,
+ 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000,
+ 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000,
+ 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000,
+ 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000,
+ 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000,
+ 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000,
+ 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000,
+ 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000,
+ 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000,
+ 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000,
+ 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000,
+ 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000,
+ 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000,
+ 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000,
+ 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000,
+ 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000,
+ 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000,
+ 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000,
+ 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000,
+ 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000,
+ 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000,
+ 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000,
+ 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000,
+ 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000,
+ 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000,
+ 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000,
+ 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000,
+ 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000,
+ 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000,
+ 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000,
+ 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000,
+ 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000,
+ 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000,
+ 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000,
+ 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000,
+ 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000,
+ 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000,
+ 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000,
+ 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000,
+ 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000,
+ 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000,
+ 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000,
+ 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000,
+ 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000,
+ 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000,
+ 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000,
+ 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000,
+ 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000,
+ 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000,
+ 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000,
+ 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000,
+ 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000,
+ 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000,
+ 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000,
+ 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000,
+ 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000,
+ 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000,
+ 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000,
+ 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000,
+ 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000,
+ 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000,
+ 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000,
+ 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000,
+ 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000,
+ 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000,
+ 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000,
+ 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000,
+ 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000,
+ 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000,
+ 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000,
+ 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000,
+ 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000,
+ 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000,
+ 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000,
+ 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000,
+ 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000,
+ 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000,
+ 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000,
+ 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000,
+ 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000,
+ 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000,
+ 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000,
+ 0x51e8883f00000000},
+ {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000,
+ 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000,
+ 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000,
+ 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000,
+ 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000,
+ 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000,
+ 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000,
+ 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000,
+ 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000,
+ 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000,
+ 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000,
+ 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000,
+ 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000,
+ 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000,
+ 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000,
+ 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000,
+ 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000,
+ 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000,
+ 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000,
+ 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000,
+ 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000,
+ 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000,
+ 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000,
+ 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000,
+ 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000,
+ 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000,
+ 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000,
+ 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000,
+ 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000,
+ 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000,
+ 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000,
+ 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000,
+ 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000,
+ 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000,
+ 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000,
+ 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000,
+ 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000,
+ 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000,
+ 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000,
+ 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000,
+ 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000,
+ 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000,
+ 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000,
+ 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000,
+ 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000,
+ 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000,
+ 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000,
+ 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000,
+ 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000,
+ 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000,
+ 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000,
+ 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000,
+ 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000,
+ 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000,
+ 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000,
+ 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000,
+ 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000,
+ 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000,
+ 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000,
+ 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000,
+ 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000,
+ 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000,
+ 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000,
+ 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000,
+ 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000,
+ 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000,
+ 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000,
+ 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000,
+ 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000,
+ 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000,
+ 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000,
+ 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000,
+ 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000,
+ 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000,
+ 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000,
+ 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000,
+ 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000,
+ 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000,
+ 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000,
+ 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000,
+ 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000,
+ 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000,
+ 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000,
+ 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000,
+ 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000,
+ 0x8ae9531c00000000},
+ {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000,
+ 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000,
+ 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000,
+ 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000,
+ 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000,
+ 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000,
+ 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000,
+ 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000,
+ 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000,
+ 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000,
+ 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000,
+ 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000,
+ 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000,
+ 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000,
+ 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000,
+ 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000,
+ 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000,
+ 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000,
+ 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000,
+ 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000,
+ 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000,
+ 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000,
+ 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000,
+ 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000,
+ 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000,
+ 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000,
+ 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000,
+ 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000,
+ 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000,
+ 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000,
+ 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000,
+ 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000,
+ 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000,
+ 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000,
+ 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000,
+ 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000,
+ 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000,
+ 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000,
+ 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000,
+ 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000,
+ 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000,
+ 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000,
+ 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000,
+ 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000,
+ 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000,
+ 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000,
+ 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000,
+ 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000,
+ 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000,
+ 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000,
+ 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000,
+ 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000,
+ 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000,
+ 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000,
+ 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000,
+ 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000,
+ 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000,
+ 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000,
+ 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000,
+ 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000,
+ 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000,
+ 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000,
+ 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000,
+ 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000,
+ 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000,
+ 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000,
+ 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000,
+ 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000,
+ 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000,
+ 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000,
+ 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000,
+ 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000,
+ 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000,
+ 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000,
+ 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000,
+ 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000,
+ 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000,
+ 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000,
+ 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000,
+ 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000,
+ 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000,
+ 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000,
+ 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000,
+ 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000,
+ 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000,
+ 0xd739710d00000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5,
+ 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d,
+ 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf,
+ 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027,
+ 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050,
+ 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098,
+ 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb,
+ 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173,
+ 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104,
+ 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c,
+ 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e,
+ 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6,
+ 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358,
+ 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390,
+ 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312,
+ 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da,
+ 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd,
+ 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335,
+ 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387,
+ 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de,
+ 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9,
+ 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261,
+ 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283,
+ 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b,
+ 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c,
+ 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c,
+ 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e,
+ 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6,
+ 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1,
+ 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619,
+ 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b,
+ 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653,
+ 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785,
+ 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d,
+ 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf,
+ 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757,
+ 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720,
+ 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8,
+ 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593,
+ 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b,
+ 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c,
+ 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4,
+ 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506,
+ 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe,
+ 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428,
+ 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0,
+ 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462,
+ 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa,
+ 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd,
+ 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445,
+ 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7,
+ 0x8cc764ca},
+ {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b,
+ 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27,
+ 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a,
+ 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285,
+ 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef,
+ 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf,
+ 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a,
+ 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a,
+ 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70,
+ 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf,
+ 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2,
+ 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e,
+ 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f,
+ 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f,
+ 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae,
+ 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe,
+ 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97,
+ 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b,
+ 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436,
+ 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e,
+ 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4,
+ 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4,
+ 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46,
+ 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716,
+ 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c,
+ 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5,
+ 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8,
+ 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774,
+ 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d,
+ 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d,
+ 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc,
+ 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec,
+ 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82,
+ 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e,
+ 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623,
+ 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c,
+ 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6,
+ 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6,
+ 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c,
+ 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c,
+ 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66,
+ 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9,
+ 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4,
+ 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978,
+ 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416,
+ 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946,
+ 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7,
+ 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7,
+ 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e,
+ 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32,
+ 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f,
+ 0xccabc4e4},
+ {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4,
+ 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895,
+ 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50,
+ 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656,
+ 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154,
+ 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906,
+ 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258,
+ 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a,
+ 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08,
+ 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e,
+ 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb,
+ 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa,
+ 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44,
+ 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316,
+ 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0,
+ 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2,
+ 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7,
+ 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6,
+ 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73,
+ 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba,
+ 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8,
+ 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea,
+ 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b,
+ 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29,
+ 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b,
+ 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e,
+ 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb,
+ 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a,
+ 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef,
+ 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd,
+ 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b,
+ 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019,
+ 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3,
+ 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2,
+ 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417,
+ 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11,
+ 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13,
+ 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241,
+ 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b,
+ 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09,
+ 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b,
+ 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d,
+ 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8,
+ 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9,
+ 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003,
+ 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851,
+ 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7,
+ 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5,
+ 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190,
+ 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1,
+ 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134,
+ 0x304a3692},
+ {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84,
+ 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f,
+ 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15,
+ 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2,
+ 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf,
+ 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7,
+ 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb,
+ 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3,
+ 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae,
+ 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749,
+ 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243,
+ 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8,
+ 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29,
+ 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61,
+ 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8,
+ 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0,
+ 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1,
+ 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a,
+ 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40,
+ 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e,
+ 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03,
+ 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b,
+ 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee,
+ 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6,
+ 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb,
+ 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f,
+ 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495,
+ 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e,
+ 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f,
+ 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067,
+ 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be,
+ 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6,
+ 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e,
+ 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5,
+ 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf,
+ 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958,
+ 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305,
+ 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d,
+ 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338,
+ 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370,
+ 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d,
+ 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca,
+ 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0,
+ 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b,
+ 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083,
+ 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb,
+ 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012,
+ 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a,
+ 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b,
+ 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0,
+ 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea,
+ 0xe6064b26}};
+
+#endif
+
+#endif
+
+#if N == 3
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848},
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000,
+ 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000,
+ 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000,
+ 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000,
+ 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000,
+ 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000,
+ 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000,
+ 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000,
+ 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000,
+ 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000,
+ 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000,
+ 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000,
+ 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000,
+ 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000,
+ 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000,
+ 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000,
+ 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000,
+ 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000,
+ 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000,
+ 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000,
+ 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000,
+ 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000,
+ 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000,
+ 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000,
+ 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000,
+ 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000,
+ 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000,
+ 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000,
+ 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000,
+ 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000,
+ 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000,
+ 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000,
+ 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000,
+ 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000,
+ 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000,
+ 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000,
+ 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000,
+ 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000,
+ 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000,
+ 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000,
+ 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000,
+ 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000,
+ 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000,
+ 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000,
+ 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000,
+ 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000,
+ 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000,
+ 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000,
+ 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000,
+ 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000,
+ 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000,
+ 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000,
+ 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000,
+ 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000,
+ 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000,
+ 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000,
+ 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000,
+ 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000,
+ 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000,
+ 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000,
+ 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000,
+ 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000,
+ 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000,
+ 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000,
+ 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000,
+ 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000,
+ 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000,
+ 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000,
+ 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000,
+ 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000,
+ 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000,
+ 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000,
+ 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000,
+ 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000,
+ 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000,
+ 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000,
+ 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000,
+ 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000,
+ 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000,
+ 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000,
+ 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000,
+ 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000,
+ 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000,
+ 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000,
+ 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000,
+ 0x4e36ba1800000000},
+ {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000,
+ 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000,
+ 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000,
+ 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000,
+ 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000,
+ 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000,
+ 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000,
+ 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000,
+ 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000,
+ 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000,
+ 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000,
+ 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000,
+ 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000,
+ 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000,
+ 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000,
+ 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000,
+ 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000,
+ 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000,
+ 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000,
+ 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000,
+ 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000,
+ 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000,
+ 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000,
+ 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000,
+ 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000,
+ 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000,
+ 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000,
+ 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000,
+ 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000,
+ 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000,
+ 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000,
+ 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000,
+ 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000,
+ 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000,
+ 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000,
+ 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000,
+ 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000,
+ 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000,
+ 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000,
+ 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000,
+ 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000,
+ 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000,
+ 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000,
+ 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000,
+ 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000,
+ 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000,
+ 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000,
+ 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000,
+ 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000,
+ 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000,
+ 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000,
+ 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000,
+ 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000,
+ 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000,
+ 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000,
+ 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000,
+ 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000,
+ 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000,
+ 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000,
+ 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000,
+ 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000,
+ 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000,
+ 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000,
+ 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000,
+ 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000,
+ 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000,
+ 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000,
+ 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000,
+ 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000,
+ 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000,
+ 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000,
+ 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000,
+ 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000,
+ 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000,
+ 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000,
+ 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000,
+ 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000,
+ 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000,
+ 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000,
+ 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000,
+ 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000,
+ 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000,
+ 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000,
+ 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000,
+ 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000,
+ 0xa1d67c9100000000},
+ {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000,
+ 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000,
+ 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000,
+ 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000,
+ 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000,
+ 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000,
+ 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000,
+ 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000,
+ 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000,
+ 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000,
+ 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000,
+ 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000,
+ 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000,
+ 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000,
+ 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000,
+ 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000,
+ 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000,
+ 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000,
+ 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000,
+ 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000,
+ 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000,
+ 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000,
+ 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000,
+ 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000,
+ 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000,
+ 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000,
+ 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000,
+ 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000,
+ 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000,
+ 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000,
+ 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000,
+ 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000,
+ 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000,
+ 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000,
+ 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000,
+ 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000,
+ 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000,
+ 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000,
+ 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000,
+ 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000,
+ 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000,
+ 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000,
+ 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000,
+ 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000,
+ 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000,
+ 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000,
+ 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000,
+ 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000,
+ 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000,
+ 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000,
+ 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000,
+ 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000,
+ 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000,
+ 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000,
+ 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000,
+ 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000,
+ 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000,
+ 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000,
+ 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000,
+ 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000,
+ 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000,
+ 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000,
+ 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000,
+ 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000,
+ 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000,
+ 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000,
+ 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000,
+ 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000,
+ 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000,
+ 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000,
+ 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000,
+ 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000,
+ 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000,
+ 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000,
+ 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000,
+ 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000,
+ 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000,
+ 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000,
+ 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000,
+ 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000,
+ 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000,
+ 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000,
+ 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000,
+ 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000,
+ 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000,
+ 0xa8ef40a100000000},
+ {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000,
+ 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000,
+ 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000,
+ 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000,
+ 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000,
+ 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000,
+ 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000,
+ 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000,
+ 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000,
+ 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000,
+ 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000,
+ 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000,
+ 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000,
+ 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000,
+ 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000,
+ 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000,
+ 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000,
+ 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000,
+ 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000,
+ 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000,
+ 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000,
+ 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000,
+ 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000,
+ 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000,
+ 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000,
+ 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000,
+ 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000,
+ 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000,
+ 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000,
+ 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000,
+ 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000,
+ 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000,
+ 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000,
+ 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000,
+ 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000,
+ 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000,
+ 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000,
+ 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000,
+ 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000,
+ 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000,
+ 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000,
+ 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000,
+ 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000,
+ 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000,
+ 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000,
+ 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000,
+ 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000,
+ 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000,
+ 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000,
+ 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000,
+ 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000,
+ 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000,
+ 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000,
+ 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000,
+ 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000,
+ 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000,
+ 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000,
+ 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000,
+ 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000,
+ 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000,
+ 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000,
+ 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000,
+ 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000,
+ 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000,
+ 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000,
+ 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000,
+ 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000,
+ 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000,
+ 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000,
+ 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000,
+ 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000,
+ 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000,
+ 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000,
+ 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000,
+ 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000,
+ 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000,
+ 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000,
+ 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000,
+ 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000,
+ 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000,
+ 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000,
+ 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000,
+ 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000,
+ 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000,
+ 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000,
+ 0x356bacd800000000},
+ {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000,
+ 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000,
+ 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000,
+ 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000,
+ 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000,
+ 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000,
+ 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000,
+ 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000,
+ 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000,
+ 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000,
+ 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000,
+ 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000,
+ 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000,
+ 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000,
+ 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000,
+ 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000,
+ 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000,
+ 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000,
+ 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000,
+ 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000,
+ 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000,
+ 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000,
+ 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000,
+ 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000,
+ 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000,
+ 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000,
+ 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000,
+ 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000,
+ 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000,
+ 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000,
+ 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000,
+ 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000,
+ 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000,
+ 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000,
+ 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000,
+ 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000,
+ 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000,
+ 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000,
+ 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000,
+ 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000,
+ 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000,
+ 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000,
+ 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000,
+ 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000,
+ 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000,
+ 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000,
+ 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000,
+ 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000,
+ 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000,
+ 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000,
+ 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000,
+ 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000,
+ 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000,
+ 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000,
+ 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000,
+ 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000,
+ 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000,
+ 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000,
+ 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000,
+ 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000,
+ 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000,
+ 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000,
+ 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000,
+ 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000,
+ 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000,
+ 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000,
+ 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000,
+ 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000,
+ 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000,
+ 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000,
+ 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000,
+ 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000,
+ 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000,
+ 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000,
+ 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000,
+ 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000,
+ 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000,
+ 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000,
+ 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000,
+ 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000,
+ 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000,
+ 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000,
+ 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000,
+ 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000,
+ 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000,
+ 0x48686b5600000000},
+ {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000,
+ 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000,
+ 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000,
+ 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000,
+ 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000,
+ 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000,
+ 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000,
+ 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000,
+ 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000,
+ 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000,
+ 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000,
+ 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000,
+ 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000,
+ 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000,
+ 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000,
+ 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000,
+ 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000,
+ 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000,
+ 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000,
+ 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000,
+ 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000,
+ 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000,
+ 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000,
+ 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000,
+ 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000,
+ 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000,
+ 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000,
+ 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000,
+ 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000,
+ 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000,
+ 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000,
+ 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000,
+ 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000,
+ 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000,
+ 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000,
+ 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000,
+ 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000,
+ 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000,
+ 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000,
+ 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000,
+ 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000,
+ 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000,
+ 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000,
+ 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000,
+ 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000,
+ 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000,
+ 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000,
+ 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000,
+ 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000,
+ 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000,
+ 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000,
+ 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000,
+ 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000,
+ 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000,
+ 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000,
+ 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000,
+ 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000,
+ 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000,
+ 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000,
+ 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000,
+ 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000,
+ 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000,
+ 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000,
+ 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000,
+ 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000,
+ 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000,
+ 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000,
+ 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000,
+ 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000,
+ 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000,
+ 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000,
+ 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000,
+ 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000,
+ 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000,
+ 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000,
+ 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000,
+ 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000,
+ 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000,
+ 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000,
+ 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000,
+ 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000,
+ 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000,
+ 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000,
+ 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000,
+ 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000,
+ 0xcaa2517800000000},
+ {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000,
+ 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000,
+ 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000,
+ 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000,
+ 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000,
+ 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000,
+ 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000,
+ 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000,
+ 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000,
+ 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000,
+ 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000,
+ 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000,
+ 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000,
+ 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000,
+ 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000,
+ 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000,
+ 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000,
+ 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000,
+ 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000,
+ 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000,
+ 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000,
+ 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000,
+ 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000,
+ 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000,
+ 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000,
+ 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000,
+ 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000,
+ 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000,
+ 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000,
+ 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000,
+ 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000,
+ 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000,
+ 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000,
+ 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000,
+ 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000,
+ 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000,
+ 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000,
+ 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000,
+ 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000,
+ 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000,
+ 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000,
+ 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000,
+ 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000,
+ 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000,
+ 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000,
+ 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000,
+ 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000,
+ 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000,
+ 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000,
+ 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000,
+ 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000,
+ 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000,
+ 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000,
+ 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000,
+ 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000,
+ 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000,
+ 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000,
+ 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000,
+ 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000,
+ 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000,
+ 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000,
+ 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000,
+ 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000,
+ 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000,
+ 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000,
+ 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000,
+ 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000,
+ 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000,
+ 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000,
+ 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000,
+ 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000,
+ 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000,
+ 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000,
+ 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000,
+ 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000,
+ 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000,
+ 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000,
+ 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000,
+ 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000,
+ 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000,
+ 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000,
+ 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000,
+ 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000,
+ 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000,
+ 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000,
+ 0x0c7ac97b00000000},
+ {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000,
+ 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000,
+ 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000,
+ 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000,
+ 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000,
+ 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000,
+ 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000,
+ 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000,
+ 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000,
+ 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000,
+ 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000,
+ 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000,
+ 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000,
+ 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000,
+ 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000,
+ 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000,
+ 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000,
+ 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000,
+ 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000,
+ 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000,
+ 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000,
+ 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000,
+ 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000,
+ 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000,
+ 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000,
+ 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000,
+ 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000,
+ 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000,
+ 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000,
+ 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000,
+ 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000,
+ 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000,
+ 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000,
+ 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000,
+ 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000,
+ 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000,
+ 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000,
+ 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000,
+ 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000,
+ 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000,
+ 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000,
+ 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000,
+ 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000,
+ 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000,
+ 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000,
+ 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000,
+ 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000,
+ 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000,
+ 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000,
+ 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000,
+ 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000,
+ 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000,
+ 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000,
+ 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000,
+ 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000,
+ 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000,
+ 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000,
+ 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000,
+ 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000,
+ 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000,
+ 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000,
+ 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000,
+ 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000,
+ 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000,
+ 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000,
+ 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000,
+ 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000,
+ 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000,
+ 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000,
+ 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000,
+ 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000,
+ 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000,
+ 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000,
+ 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000,
+ 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000,
+ 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000,
+ 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000,
+ 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000,
+ 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000,
+ 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000,
+ 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000,
+ 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000,
+ 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000,
+ 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000,
+ 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000,
+ 0x5185cd0900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d,
+ 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac,
+ 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8,
+ 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95,
+ 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817,
+ 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d,
+ 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac,
+ 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6,
+ 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564,
+ 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39,
+ 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d,
+ 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac,
+ 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de,
+ 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594,
+ 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b,
+ 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01,
+ 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f,
+ 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de,
+ 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba,
+ 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65,
+ 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7,
+ 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad,
+ 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de,
+ 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294,
+ 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716,
+ 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71,
+ 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15,
+ 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4,
+ 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca,
+ 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280,
+ 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f,
+ 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15,
+ 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9,
+ 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748,
+ 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c,
+ 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971,
+ 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3,
+ 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9,
+ 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196,
+ 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc,
+ 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e,
+ 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03,
+ 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67,
+ 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296,
+ 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a,
+ 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170,
+ 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af,
+ 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5,
+ 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb,
+ 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a,
+ 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e,
+ 0x4b0c4f49},
+ {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09,
+ 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc,
+ 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e,
+ 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc,
+ 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934,
+ 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2,
+ 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b,
+ 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad,
+ 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155,
+ 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187,
+ 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65,
+ 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390,
+ 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e,
+ 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378,
+ 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889,
+ 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f,
+ 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0,
+ 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145,
+ 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7,
+ 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a,
+ 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2,
+ 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924,
+ 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2,
+ 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514,
+ 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec,
+ 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709,
+ 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb,
+ 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e,
+ 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1,
+ 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227,
+ 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6,
+ 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030,
+ 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0,
+ 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55,
+ 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7,
+ 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165,
+ 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d,
+ 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b,
+ 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c,
+ 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a,
+ 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362,
+ 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0,
+ 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52,
+ 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7,
+ 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237,
+ 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1,
+ 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020,
+ 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6,
+ 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719,
+ 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec,
+ 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e,
+ 0x14d747e1},
+ {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0,
+ 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b,
+ 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652,
+ 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437,
+ 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514,
+ 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265,
+ 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de,
+ 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af,
+ 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c,
+ 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9,
+ 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0,
+ 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b,
+ 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6,
+ 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7,
+ 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734,
+ 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045,
+ 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8,
+ 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303,
+ 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a,
+ 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9,
+ 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea,
+ 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b,
+ 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6,
+ 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7,
+ 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4,
+ 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6,
+ 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f,
+ 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054,
+ 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9,
+ 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8,
+ 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b,
+ 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a,
+ 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441,
+ 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a,
+ 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3,
+ 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6,
+ 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5,
+ 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94,
+ 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9,
+ 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288,
+ 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab,
+ 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce,
+ 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7,
+ 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c,
+ 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527,
+ 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256,
+ 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5,
+ 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4,
+ 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39,
+ 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2,
+ 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db,
+ 0xaa933b1a},
+ {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603,
+ 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d,
+ 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9,
+ 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b,
+ 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a,
+ 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792,
+ 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4,
+ 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c,
+ 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d,
+ 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f,
+ 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb,
+ 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65,
+ 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330,
+ 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8,
+ 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da,
+ 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742,
+ 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f,
+ 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1,
+ 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5,
+ 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f,
+ 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e,
+ 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6,
+ 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8,
+ 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250,
+ 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021,
+ 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb,
+ 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f,
+ 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511,
+ 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c,
+ 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4,
+ 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886,
+ 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e,
+ 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b,
+ 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5,
+ 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791,
+ 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003,
+ 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272,
+ 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea,
+ 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc,
+ 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24,
+ 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55,
+ 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7,
+ 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3,
+ 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d,
+ 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548,
+ 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0,
+ 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2,
+ 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a,
+ 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47,
+ 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9,
+ 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad,
+ 0x65711936}};
+
+#endif
+
+#endif
+
+#if N == 4
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a,
+ 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe,
+ 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b,
+ 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656,
+ 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd,
+ 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d,
+ 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7,
+ 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47,
+ 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac,
+ 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691,
+ 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404,
+ 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0,
+ 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4,
+ 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424,
+ 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5,
+ 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65,
+ 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67,
+ 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3,
+ 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626,
+ 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9,
+ 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222,
+ 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2,
+ 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a,
+ 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a,
+ 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1,
+ 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2,
+ 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077,
+ 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3,
+ 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1,
+ 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621,
+ 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0,
+ 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60,
+ 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0,
+ 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64,
+ 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1,
+ 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc,
+ 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027,
+ 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7,
+ 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9,
+ 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79,
+ 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292,
+ 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af,
+ 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a,
+ 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee,
+ 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e,
+ 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe,
+ 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f,
+ 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff,
+ 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd,
+ 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29,
+ 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc,
+ 0xe3c45916},
+ {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344,
+ 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59,
+ 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e,
+ 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463,
+ 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98,
+ 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d,
+ 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3,
+ 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656,
+ 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad,
+ 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0,
+ 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397,
+ 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a,
+ 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2,
+ 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357,
+ 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8,
+ 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d,
+ 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696,
+ 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b,
+ 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc,
+ 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0,
+ 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b,
+ 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be,
+ 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811,
+ 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384,
+ 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f,
+ 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955,
+ 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362,
+ 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f,
+ 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94,
+ 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701,
+ 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe,
+ 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b,
+ 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1,
+ 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc,
+ 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b,
+ 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986,
+ 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d,
+ 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8,
+ 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4,
+ 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371,
+ 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a,
+ 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87,
+ 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0,
+ 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad,
+ 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527,
+ 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2,
+ 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d,
+ 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998,
+ 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73,
+ 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e,
+ 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59,
+ 0xa7520488},
+ {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20,
+ 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09,
+ 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431,
+ 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a,
+ 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203,
+ 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b,
+ 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14,
+ 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c,
+ 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25,
+ 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e,
+ 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36,
+ 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f,
+ 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649,
+ 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961,
+ 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58,
+ 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170,
+ 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b,
+ 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742,
+ 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a,
+ 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55,
+ 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c,
+ 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64,
+ 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f,
+ 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77,
+ 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e,
+ 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a,
+ 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2,
+ 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b,
+ 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090,
+ 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8,
+ 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881,
+ 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9,
+ 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6,
+ 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f,
+ 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7,
+ 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c,
+ 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695,
+ 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd,
+ 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb,
+ 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3,
+ 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa,
+ 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1,
+ 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9,
+ 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0,
+ 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df,
+ 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7,
+ 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace,
+ 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6,
+ 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd,
+ 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4,
+ 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec,
+ 0x3522e9e4},
+ {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1,
+ 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86,
+ 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b,
+ 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669,
+ 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7,
+ 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352,
+ 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03,
+ 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6,
+ 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38,
+ 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a,
+ 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7,
+ 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80,
+ 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7,
+ 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522,
+ 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d,
+ 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8,
+ 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103,
+ 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54,
+ 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9,
+ 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0,
+ 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e,
+ 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb,
+ 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1,
+ 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624,
+ 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea,
+ 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a,
+ 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37,
+ 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360,
+ 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab,
+ 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e,
+ 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741,
+ 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4,
+ 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334,
+ 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63,
+ 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de,
+ 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c,
+ 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942,
+ 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7,
+ 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131,
+ 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4,
+ 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a,
+ 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758,
+ 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5,
+ 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2,
+ 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32,
+ 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7,
+ 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8,
+ 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d,
+ 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6,
+ 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1,
+ 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c,
+ 0x97411e28},
+ {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474,
+ 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5,
+ 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6,
+ 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7,
+ 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938,
+ 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051,
+ 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a,
+ 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3,
+ 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c,
+ 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d,
+ 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e,
+ 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf,
+ 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740,
+ 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29,
+ 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592,
+ 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb,
+ 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4,
+ 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365,
+ 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036,
+ 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7,
+ 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08,
+ 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561,
+ 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a,
+ 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663,
+ 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac,
+ 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d,
+ 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce,
+ 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f,
+ 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50,
+ 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639,
+ 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82,
+ 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb,
+ 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954,
+ 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5,
+ 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86,
+ 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7,
+ 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418,
+ 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71,
+ 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa,
+ 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93,
+ 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c,
+ 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d,
+ 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e,
+ 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df,
+ 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60,
+ 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309,
+ 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2,
+ 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db,
+ 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4,
+ 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45,
+ 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16,
+ 0x93c7a00b},
+ {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45,
+ 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb,
+ 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d,
+ 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696,
+ 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf,
+ 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb,
+ 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028,
+ 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c,
+ 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65,
+ 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be,
+ 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038,
+ 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6,
+ 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15,
+ 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11,
+ 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d,
+ 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19,
+ 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05,
+ 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b,
+ 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d,
+ 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c,
+ 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35,
+ 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31,
+ 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068,
+ 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c,
+ 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25,
+ 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a,
+ 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac,
+ 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22,
+ 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e,
+ 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a,
+ 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36,
+ 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32,
+ 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84,
+ 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a,
+ 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c,
+ 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057,
+ 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e,
+ 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a,
+ 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc,
+ 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8,
+ 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1,
+ 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a,
+ 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec,
+ 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62,
+ 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4,
+ 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0,
+ 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc,
+ 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8,
+ 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4,
+ 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a,
+ 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc,
+ 0xce5f968d},
+ {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de,
+ 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b,
+ 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d,
+ 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680,
+ 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4,
+ 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d,
+ 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde,
+ 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97,
+ 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3,
+ 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e,
+ 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678,
+ 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d,
+ 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723,
+ 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a,
+ 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0,
+ 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9,
+ 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85,
+ 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770,
+ 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56,
+ 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a,
+ 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e,
+ 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67,
+ 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785,
+ 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc,
+ 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788,
+ 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90,
+ 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6,
+ 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843,
+ 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f,
+ 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336,
+ 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac,
+ 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5,
+ 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68,
+ 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d,
+ 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb,
+ 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36,
+ 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72,
+ 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b,
+ 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b,
+ 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402,
+ 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446,
+ 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb,
+ 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed,
+ 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418,
+ 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95,
+ 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc,
+ 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946,
+ 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f,
+ 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233,
+ 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6,
+ 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0,
+ 0x3e721277},
+ {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb,
+ 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9,
+ 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11,
+ 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d,
+ 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9,
+ 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c,
+ 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881,
+ 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274,
+ 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790,
+ 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc,
+ 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514,
+ 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56,
+ 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9,
+ 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c,
+ 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13,
+ 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6,
+ 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c,
+ 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e,
+ 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386,
+ 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376,
+ 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692,
+ 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67,
+ 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416,
+ 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3,
+ 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07,
+ 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd,
+ 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15,
+ 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457,
+ 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd,
+ 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28,
+ 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337,
+ 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2,
+ 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594,
+ 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6,
+ 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e,
+ 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52,
+ 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6,
+ 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143,
+ 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17,
+ 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2,
+ 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306,
+ 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a,
+ 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182,
+ 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0,
+ 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496,
+ 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63,
+ 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c,
+ 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89,
+ 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903,
+ 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041,
+ 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9,
+ 0x1c65ace7}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000,
+ 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000,
+ 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000,
+ 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000,
+ 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000,
+ 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000,
+ 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000,
+ 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000,
+ 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000,
+ 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000,
+ 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000,
+ 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000,
+ 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000,
+ 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000,
+ 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000,
+ 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000,
+ 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000,
+ 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000,
+ 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000,
+ 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000,
+ 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000,
+ 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000,
+ 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000,
+ 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000,
+ 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000,
+ 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000,
+ 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000,
+ 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000,
+ 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000,
+ 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000,
+ 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000,
+ 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000,
+ 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000,
+ 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000,
+ 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000,
+ 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000,
+ 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000,
+ 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000,
+ 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000,
+ 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000,
+ 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000,
+ 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000,
+ 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000,
+ 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000,
+ 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000,
+ 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000,
+ 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000,
+ 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000,
+ 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000,
+ 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000,
+ 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000,
+ 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000,
+ 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000,
+ 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000,
+ 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000,
+ 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000,
+ 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000,
+ 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000,
+ 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000,
+ 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000,
+ 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000,
+ 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000,
+ 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000,
+ 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000,
+ 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000,
+ 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000,
+ 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000,
+ 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000,
+ 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000,
+ 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000,
+ 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000,
+ 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000,
+ 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000,
+ 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000,
+ 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000,
+ 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000,
+ 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000,
+ 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000,
+ 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000,
+ 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000,
+ 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000,
+ 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000,
+ 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000,
+ 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000,
+ 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000,
+ 0xe7ac651c00000000},
+ {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000,
+ 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000,
+ 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000,
+ 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000,
+ 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000,
+ 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000,
+ 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000,
+ 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000,
+ 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000,
+ 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000,
+ 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000,
+ 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000,
+ 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000,
+ 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000,
+ 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000,
+ 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000,
+ 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000,
+ 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000,
+ 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000,
+ 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000,
+ 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000,
+ 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000,
+ 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000,
+ 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000,
+ 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000,
+ 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000,
+ 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000,
+ 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000,
+ 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000,
+ 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000,
+ 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000,
+ 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000,
+ 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000,
+ 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000,
+ 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000,
+ 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000,
+ 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000,
+ 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000,
+ 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000,
+ 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000,
+ 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000,
+ 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000,
+ 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000,
+ 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000,
+ 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000,
+ 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000,
+ 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000,
+ 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000,
+ 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000,
+ 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000,
+ 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000,
+ 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000,
+ 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000,
+ 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000,
+ 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000,
+ 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000,
+ 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000,
+ 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000,
+ 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000,
+ 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000,
+ 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000,
+ 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000,
+ 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000,
+ 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000,
+ 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000,
+ 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000,
+ 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000,
+ 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000,
+ 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000,
+ 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000,
+ 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000,
+ 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000,
+ 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000,
+ 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000,
+ 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000,
+ 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000,
+ 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000,
+ 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000,
+ 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000,
+ 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000,
+ 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000,
+ 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000,
+ 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000,
+ 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000,
+ 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000,
+ 0x7712723e00000000},
+ {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000,
+ 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000,
+ 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000,
+ 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000,
+ 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000,
+ 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000,
+ 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000,
+ 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000,
+ 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000,
+ 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000,
+ 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000,
+ 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000,
+ 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000,
+ 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000,
+ 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000,
+ 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000,
+ 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000,
+ 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000,
+ 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000,
+ 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000,
+ 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000,
+ 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000,
+ 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000,
+ 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000,
+ 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000,
+ 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000,
+ 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000,
+ 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000,
+ 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000,
+ 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000,
+ 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000,
+ 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000,
+ 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000,
+ 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000,
+ 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000,
+ 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000,
+ 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000,
+ 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000,
+ 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000,
+ 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000,
+ 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000,
+ 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000,
+ 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000,
+ 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000,
+ 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000,
+ 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000,
+ 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000,
+ 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000,
+ 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000,
+ 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000,
+ 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000,
+ 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000,
+ 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000,
+ 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000,
+ 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000,
+ 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000,
+ 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000,
+ 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000,
+ 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000,
+ 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000,
+ 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000,
+ 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000,
+ 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000,
+ 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000,
+ 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000,
+ 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000,
+ 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000,
+ 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000,
+ 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000,
+ 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000,
+ 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000,
+ 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000,
+ 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000,
+ 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000,
+ 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000,
+ 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000,
+ 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000,
+ 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000,
+ 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000,
+ 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000,
+ 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000,
+ 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000,
+ 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000,
+ 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000,
+ 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000,
+ 0x8d965fce00000000},
+ {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000,
+ 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000,
+ 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000,
+ 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000,
+ 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000,
+ 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000,
+ 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000,
+ 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000,
+ 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000,
+ 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000,
+ 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000,
+ 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000,
+ 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000,
+ 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000,
+ 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000,
+ 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000,
+ 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000,
+ 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000,
+ 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000,
+ 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000,
+ 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000,
+ 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000,
+ 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000,
+ 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000,
+ 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000,
+ 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000,
+ 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000,
+ 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000,
+ 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000,
+ 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000,
+ 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000,
+ 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000,
+ 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000,
+ 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000,
+ 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000,
+ 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000,
+ 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000,
+ 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000,
+ 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000,
+ 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000,
+ 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000,
+ 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000,
+ 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000,
+ 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000,
+ 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000,
+ 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000,
+ 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000,
+ 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000,
+ 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000,
+ 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000,
+ 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000,
+ 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000,
+ 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000,
+ 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000,
+ 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000,
+ 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000,
+ 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000,
+ 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000,
+ 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000,
+ 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000,
+ 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000,
+ 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000,
+ 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000,
+ 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000,
+ 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000,
+ 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000,
+ 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000,
+ 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000,
+ 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000,
+ 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000,
+ 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000,
+ 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000,
+ 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000,
+ 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000,
+ 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000,
+ 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000,
+ 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000,
+ 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000,
+ 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000,
+ 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000,
+ 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000,
+ 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000,
+ 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000,
+ 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000,
+ 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000,
+ 0x0ba0c79300000000},
+ {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000,
+ 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000,
+ 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000,
+ 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000,
+ 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000,
+ 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000,
+ 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000,
+ 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000,
+ 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000,
+ 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000,
+ 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000,
+ 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000,
+ 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000,
+ 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000,
+ 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000,
+ 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000,
+ 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000,
+ 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000,
+ 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000,
+ 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000,
+ 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000,
+ 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000,
+ 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000,
+ 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000,
+ 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000,
+ 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000,
+ 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000,
+ 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000,
+ 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000,
+ 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000,
+ 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000,
+ 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000,
+ 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000,
+ 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000,
+ 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000,
+ 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000,
+ 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000,
+ 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000,
+ 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000,
+ 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000,
+ 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000,
+ 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000,
+ 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000,
+ 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000,
+ 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000,
+ 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000,
+ 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000,
+ 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000,
+ 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000,
+ 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000,
+ 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000,
+ 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000,
+ 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000,
+ 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000,
+ 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000,
+ 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000,
+ 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000,
+ 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000,
+ 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000,
+ 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000,
+ 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000,
+ 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000,
+ 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000,
+ 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000,
+ 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000,
+ 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000,
+ 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000,
+ 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000,
+ 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000,
+ 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000,
+ 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000,
+ 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000,
+ 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000,
+ 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000,
+ 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000,
+ 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000,
+ 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000,
+ 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000,
+ 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000,
+ 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000,
+ 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000,
+ 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000,
+ 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000,
+ 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000,
+ 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000,
+ 0x281e419700000000},
+ {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000,
+ 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000,
+ 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000,
+ 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000,
+ 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000,
+ 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000,
+ 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000,
+ 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000,
+ 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000,
+ 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000,
+ 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000,
+ 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000,
+ 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000,
+ 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000,
+ 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000,
+ 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000,
+ 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000,
+ 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000,
+ 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000,
+ 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000,
+ 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000,
+ 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000,
+ 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000,
+ 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000,
+ 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000,
+ 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000,
+ 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000,
+ 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000,
+ 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000,
+ 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000,
+ 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000,
+ 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000,
+ 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000,
+ 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000,
+ 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000,
+ 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000,
+ 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000,
+ 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000,
+ 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000,
+ 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000,
+ 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000,
+ 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000,
+ 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000,
+ 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000,
+ 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000,
+ 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000,
+ 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000,
+ 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000,
+ 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000,
+ 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000,
+ 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000,
+ 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000,
+ 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000,
+ 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000,
+ 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000,
+ 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000,
+ 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000,
+ 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000,
+ 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000,
+ 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000,
+ 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000,
+ 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000,
+ 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000,
+ 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000,
+ 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000,
+ 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000,
+ 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000,
+ 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000,
+ 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000,
+ 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000,
+ 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000,
+ 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000,
+ 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000,
+ 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000,
+ 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000,
+ 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000,
+ 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000,
+ 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000,
+ 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000,
+ 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000,
+ 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000,
+ 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000,
+ 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000,
+ 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000,
+ 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000,
+ 0xe4e9223500000000},
+ {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000,
+ 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000,
+ 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000,
+ 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000,
+ 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000,
+ 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000,
+ 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000,
+ 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000,
+ 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000,
+ 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000,
+ 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000,
+ 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000,
+ 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000,
+ 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000,
+ 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000,
+ 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000,
+ 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000,
+ 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000,
+ 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000,
+ 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000,
+ 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000,
+ 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000,
+ 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000,
+ 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000,
+ 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000,
+ 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000,
+ 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000,
+ 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000,
+ 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000,
+ 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000,
+ 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000,
+ 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000,
+ 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000,
+ 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000,
+ 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000,
+ 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000,
+ 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000,
+ 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000,
+ 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000,
+ 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000,
+ 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000,
+ 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000,
+ 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000,
+ 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000,
+ 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000,
+ 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000,
+ 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000,
+ 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000,
+ 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000,
+ 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000,
+ 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000,
+ 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000,
+ 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000,
+ 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000,
+ 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000,
+ 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000,
+ 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000,
+ 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000,
+ 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000,
+ 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000,
+ 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000,
+ 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000,
+ 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000,
+ 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000,
+ 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000,
+ 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000,
+ 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000,
+ 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000,
+ 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000,
+ 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000,
+ 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000,
+ 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000,
+ 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000,
+ 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000,
+ 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000,
+ 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000,
+ 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000,
+ 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000,
+ 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000,
+ 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000,
+ 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000,
+ 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000,
+ 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000,
+ 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000,
+ 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000,
+ 0x880452a700000000},
+ {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000,
+ 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000,
+ 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000,
+ 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000,
+ 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000,
+ 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000,
+ 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000,
+ 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000,
+ 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000,
+ 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000,
+ 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000,
+ 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000,
+ 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000,
+ 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000,
+ 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000,
+ 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000,
+ 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000,
+ 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000,
+ 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000,
+ 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000,
+ 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000,
+ 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000,
+ 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000,
+ 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000,
+ 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000,
+ 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000,
+ 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000,
+ 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000,
+ 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000,
+ 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000,
+ 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000,
+ 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000,
+ 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000,
+ 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000,
+ 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000,
+ 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000,
+ 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000,
+ 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000,
+ 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000,
+ 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000,
+ 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000,
+ 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000,
+ 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000,
+ 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000,
+ 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000,
+ 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000,
+ 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000,
+ 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000,
+ 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000,
+ 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000,
+ 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000,
+ 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000,
+ 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000,
+ 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000,
+ 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000,
+ 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000,
+ 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000,
+ 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000,
+ 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000,
+ 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000,
+ 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000,
+ 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000,
+ 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000,
+ 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000,
+ 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000,
+ 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000,
+ 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000,
+ 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000,
+ 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000,
+ 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000,
+ 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000,
+ 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000,
+ 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000,
+ 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000,
+ 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000,
+ 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000,
+ 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000,
+ 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000,
+ 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000,
+ 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000,
+ 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000,
+ 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000,
+ 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000,
+ 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000,
+ 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000,
+ 0x1659c4e300000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0,
+ 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587,
+ 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa,
+ 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09,
+ 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee,
+ 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3,
+ 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3,
+ 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce,
+ 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429,
+ 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda,
+ 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7,
+ 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0,
+ 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd,
+ 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0,
+ 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287,
+ 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a,
+ 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9,
+ 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e,
+ 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3,
+ 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3,
+ 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054,
+ 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49,
+ 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da,
+ 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7,
+ 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20,
+ 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d,
+ 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00,
+ 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347,
+ 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14,
+ 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209,
+ 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e,
+ 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33,
+ 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3,
+ 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194,
+ 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9,
+ 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a,
+ 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd,
+ 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0,
+ 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d,
+ 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460,
+ 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87,
+ 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674,
+ 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509,
+ 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e,
+ 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae,
+ 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3,
+ 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694,
+ 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989,
+ 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da,
+ 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d,
+ 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0,
+ 0xa68cee3d},
+ {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19,
+ 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae,
+ 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb,
+ 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a,
+ 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55,
+ 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1,
+ 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c,
+ 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8,
+ 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7,
+ 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936,
+ 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453,
+ 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4,
+ 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941,
+ 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5,
+ 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93,
+ 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17,
+ 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e,
+ 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89,
+ 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec,
+ 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0,
+ 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf,
+ 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b,
+ 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b,
+ 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f,
+ 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0,
+ 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e,
+ 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b,
+ 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc,
+ 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5,
+ 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261,
+ 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637,
+ 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3,
+ 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57,
+ 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0,
+ 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85,
+ 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454,
+ 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b,
+ 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f,
+ 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423,
+ 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7,
+ 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8,
+ 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739,
+ 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c,
+ 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb,
+ 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f,
+ 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b,
+ 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd,
+ 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59,
+ 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070,
+ 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7,
+ 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2,
+ 0x51e8883f},
+ {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a,
+ 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276,
+ 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed,
+ 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55,
+ 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b,
+ 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8,
+ 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320,
+ 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413,
+ 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd,
+ 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75,
+ 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee,
+ 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312,
+ 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca,
+ 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9,
+ 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad,
+ 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e,
+ 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504,
+ 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8,
+ 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63,
+ 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353,
+ 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d,
+ 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be,
+ 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae,
+ 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d,
+ 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943,
+ 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7,
+ 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c,
+ 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390,
+ 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a,
+ 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239,
+ 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d,
+ 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e,
+ 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c,
+ 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0,
+ 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b,
+ 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93,
+ 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d,
+ 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e,
+ 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c,
+ 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f,
+ 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1,
+ 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579,
+ 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2,
+ 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e,
+ 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c,
+ 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f,
+ 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b,
+ 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158,
+ 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2,
+ 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e,
+ 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5,
+ 0x8ae9531c},
+ {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4,
+ 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd,
+ 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220,
+ 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf,
+ 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495,
+ 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def,
+ 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90,
+ 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea,
+ 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0,
+ 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f,
+ 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2,
+ 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab,
+ 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e,
+ 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754,
+ 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda,
+ 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0,
+ 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c,
+ 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215,
+ 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8,
+ 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910,
+ 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a,
+ 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30,
+ 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658,
+ 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22,
+ 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478,
+ 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2,
+ 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f,
+ 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606,
+ 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba,
+ 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0,
+ 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e,
+ 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034,
+ 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f,
+ 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996,
+ 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b,
+ 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84,
+ 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de,
+ 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4,
+ 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5,
+ 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f,
+ 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5,
+ 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a,
+ 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7,
+ 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce,
+ 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65,
+ 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f,
+ 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91,
+ 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb,
+ 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57,
+ 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e,
+ 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3,
+ 0xd739710d}};
+
+#endif
+
+#endif
+
+#if N == 5
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df,
+ 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8,
+ 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef,
+ 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376,
+ 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201,
+ 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399,
+ 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372,
+ 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea,
+ 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d,
+ 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004,
+ 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353,
+ 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334,
+ 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a,
+ 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2,
+ 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a,
+ 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2,
+ 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b,
+ 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c,
+ 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b,
+ 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f,
+ 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338,
+ 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0,
+ 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6,
+ 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e,
+ 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319,
+ 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3,
+ 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4,
+ 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783,
+ 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a,
+ 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492,
+ 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a,
+ 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2,
+ 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496,
+ 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1,
+ 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6,
+ 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f,
+ 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548,
+ 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0,
+ 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741,
+ 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9,
+ 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae,
+ 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437,
+ 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760,
+ 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707,
+ 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433,
+ 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab,
+ 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703,
+ 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b,
+ 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412,
+ 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475,
+ 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722,
+ 0xe9947565},
+ {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5,
+ 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22,
+ 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c,
+ 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed,
+ 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d,
+ 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1,
+ 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e,
+ 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32,
+ 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142,
+ 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93,
+ 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d,
+ 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a,
+ 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58,
+ 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14,
+ 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81,
+ 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd,
+ 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab,
+ 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c,
+ 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72,
+ 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f,
+ 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff,
+ 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3,
+ 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30,
+ 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c,
+ 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c,
+ 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558,
+ 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146,
+ 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581,
+ 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7,
+ 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab,
+ 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e,
+ 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272,
+ 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838,
+ 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff,
+ 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1,
+ 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330,
+ 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840,
+ 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c,
+ 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb,
+ 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7,
+ 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7,
+ 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616,
+ 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208,
+ 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf,
+ 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85,
+ 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9,
+ 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c,
+ 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10,
+ 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76,
+ 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1,
+ 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf,
+ 0xf7d05006},
+ {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b,
+ 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774,
+ 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58,
+ 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a,
+ 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb,
+ 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952,
+ 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e,
+ 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7,
+ 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746,
+ 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14,
+ 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338,
+ 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907,
+ 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777,
+ 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de,
+ 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064,
+ 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd,
+ 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951,
+ 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e,
+ 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42,
+ 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b,
+ 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a,
+ 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3,
+ 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904,
+ 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad,
+ 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c,
+ 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d,
+ 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861,
+ 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e,
+ 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2,
+ 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b,
+ 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1,
+ 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78,
+ 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f,
+ 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40,
+ 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c,
+ 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e,
+ 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf,
+ 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166,
+ 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d,
+ 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4,
+ 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805,
+ 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157,
+ 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b,
+ 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644,
+ 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43,
+ 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea,
+ 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850,
+ 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9,
+ 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165,
+ 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a,
+ 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676,
+ 0xb2075b94},
+ {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf,
+ 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61,
+ 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be,
+ 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd,
+ 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3,
+ 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063,
+ 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105,
+ 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5,
+ 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb,
+ 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8,
+ 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07,
+ 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9,
+ 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5,
+ 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515,
+ 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4,
+ 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014,
+ 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7,
+ 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269,
+ 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6,
+ 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af,
+ 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1,
+ 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111,
+ 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d,
+ 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad,
+ 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3,
+ 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75,
+ 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa,
+ 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74,
+ 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7,
+ 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477,
+ 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6,
+ 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176,
+ 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af,
+ 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71,
+ 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae,
+ 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd,
+ 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3,
+ 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073,
+ 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0,
+ 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400,
+ 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e,
+ 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d,
+ 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2,
+ 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c,
+ 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5,
+ 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505,
+ 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4,
+ 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004,
+ 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7,
+ 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279,
+ 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6,
+ 0xba50bcb9},
+ {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897,
+ 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb,
+ 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2,
+ 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2,
+ 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372,
+ 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70,
+ 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92,
+ 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190,
+ 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40,
+ 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430,
+ 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759,
+ 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75,
+ 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2,
+ 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0,
+ 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7,
+ 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5,
+ 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39,
+ 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215,
+ 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c,
+ 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5,
+ 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625,
+ 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27,
+ 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c,
+ 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e,
+ 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee,
+ 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71,
+ 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18,
+ 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134,
+ 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8,
+ 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba,
+ 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd,
+ 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff,
+ 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a,
+ 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6,
+ 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf,
+ 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf,
+ 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f,
+ 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d,
+ 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d,
+ 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f,
+ 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af,
+ 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df,
+ 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6,
+ 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a,
+ 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef,
+ 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed,
+ 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa,
+ 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8,
+ 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624,
+ 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08,
+ 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861,
+ 0x808abcf4},
+ {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2,
+ 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd,
+ 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76,
+ 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52,
+ 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e,
+ 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124,
+ 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147,
+ 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d,
+ 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31,
+ 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15,
+ 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae,
+ 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1,
+ 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d,
+ 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307,
+ 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9,
+ 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3,
+ 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084,
+ 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb,
+ 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850,
+ 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2,
+ 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe,
+ 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94,
+ 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261,
+ 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b,
+ 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917,
+ 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53,
+ 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8,
+ 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787,
+ 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0,
+ 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba,
+ 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404,
+ 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e,
+ 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af,
+ 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0,
+ 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b,
+ 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f,
+ 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543,
+ 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129,
+ 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627,
+ 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d,
+ 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51,
+ 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75,
+ 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce,
+ 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1,
+ 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760,
+ 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a,
+ 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4,
+ 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde,
+ 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089,
+ 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6,
+ 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d,
+ 0xefdb3f95},
+ {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8,
+ 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7,
+ 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945,
+ 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9,
+ 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652,
+ 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc,
+ 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a,
+ 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4,
+ 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f,
+ 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3,
+ 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51,
+ 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e,
+ 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c,
+ 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362,
+ 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11,
+ 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff,
+ 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7,
+ 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8,
+ 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a,
+ 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690,
+ 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b,
+ 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5,
+ 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05,
+ 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb,
+ 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740,
+ 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f,
+ 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded,
+ 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2,
+ 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa,
+ 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714,
+ 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67,
+ 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89,
+ 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7,
+ 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8,
+ 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a,
+ 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6,
+ 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d,
+ 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3,
+ 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9,
+ 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57,
+ 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc,
+ 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540,
+ 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2,
+ 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd,
+ 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93,
+ 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d,
+ 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e,
+ 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0,
+ 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8,
+ 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7,
+ 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75,
+ 0x0e2fbf43},
+ {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc,
+ 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a,
+ 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3,
+ 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7,
+ 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b,
+ 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154,
+ 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3,
+ 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc,
+ 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330,
+ 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264,
+ 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd,
+ 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b,
+ 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a,
+ 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175,
+ 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275,
+ 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a,
+ 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234,
+ 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2,
+ 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b,
+ 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a,
+ 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6,
+ 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189,
+ 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b,
+ 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204,
+ 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8,
+ 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226,
+ 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff,
+ 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219,
+ 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167,
+ 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258,
+ 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158,
+ 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267,
+ 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c,
+ 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da,
+ 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003,
+ 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157,
+ 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b,
+ 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4,
+ 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179,
+ 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246,
+ 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a,
+ 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de,
+ 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107,
+ 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1,
+ 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba,
+ 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285,
+ 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185,
+ 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba,
+ 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4,
+ 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322,
+ 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb,
+ 0xf4377108}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000,
+ 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000,
+ 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000,
+ 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000,
+ 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000,
+ 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000,
+ 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000,
+ 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000,
+ 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000,
+ 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000,
+ 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000,
+ 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000,
+ 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000,
+ 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000,
+ 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000,
+ 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000,
+ 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000,
+ 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000,
+ 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000,
+ 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000,
+ 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000,
+ 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000,
+ 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000,
+ 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000,
+ 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000,
+ 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000,
+ 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000,
+ 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000,
+ 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000,
+ 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000,
+ 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000,
+ 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000,
+ 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000,
+ 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000,
+ 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000,
+ 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000,
+ 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000,
+ 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000,
+ 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000,
+ 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000,
+ 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000,
+ 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000,
+ 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000,
+ 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000,
+ 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000,
+ 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000,
+ 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000,
+ 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000,
+ 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000,
+ 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000,
+ 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000,
+ 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000,
+ 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000,
+ 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000,
+ 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000,
+ 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000,
+ 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000,
+ 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000,
+ 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000,
+ 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000,
+ 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000,
+ 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000,
+ 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000,
+ 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000,
+ 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000,
+ 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000,
+ 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000,
+ 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000,
+ 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000,
+ 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000,
+ 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000,
+ 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000,
+ 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000,
+ 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000,
+ 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000,
+ 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000,
+ 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000,
+ 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000,
+ 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000,
+ 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000,
+ 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000,
+ 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000,
+ 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000,
+ 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000,
+ 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000,
+ 0x087137f400000000},
+ {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000,
+ 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000,
+ 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000,
+ 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000,
+ 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000,
+ 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000,
+ 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000,
+ 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000,
+ 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000,
+ 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000,
+ 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000,
+ 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000,
+ 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000,
+ 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000,
+ 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000,
+ 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000,
+ 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000,
+ 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000,
+ 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000,
+ 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000,
+ 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000,
+ 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000,
+ 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000,
+ 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000,
+ 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000,
+ 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000,
+ 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000,
+ 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000,
+ 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000,
+ 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000,
+ 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000,
+ 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000,
+ 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000,
+ 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000,
+ 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000,
+ 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000,
+ 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000,
+ 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000,
+ 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000,
+ 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000,
+ 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000,
+ 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000,
+ 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000,
+ 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000,
+ 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000,
+ 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000,
+ 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000,
+ 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000,
+ 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000,
+ 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000,
+ 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000,
+ 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000,
+ 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000,
+ 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000,
+ 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000,
+ 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000,
+ 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000,
+ 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000,
+ 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000,
+ 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000,
+ 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000,
+ 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000,
+ 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000,
+ 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000,
+ 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000,
+ 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000,
+ 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000,
+ 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000,
+ 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000,
+ 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000,
+ 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000,
+ 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000,
+ 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000,
+ 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000,
+ 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000,
+ 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000,
+ 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000,
+ 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000,
+ 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000,
+ 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000,
+ 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000,
+ 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000,
+ 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000,
+ 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000,
+ 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000,
+ 0x43bf2f0e00000000},
+ {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000,
+ 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000,
+ 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000,
+ 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000,
+ 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000,
+ 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000,
+ 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000,
+ 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000,
+ 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000,
+ 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000,
+ 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000,
+ 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000,
+ 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000,
+ 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000,
+ 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000,
+ 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000,
+ 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000,
+ 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000,
+ 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000,
+ 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000,
+ 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000,
+ 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000,
+ 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000,
+ 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000,
+ 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000,
+ 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000,
+ 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000,
+ 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000,
+ 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000,
+ 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000,
+ 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000,
+ 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000,
+ 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000,
+ 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000,
+ 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000,
+ 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000,
+ 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000,
+ 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000,
+ 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000,
+ 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000,
+ 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000,
+ 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000,
+ 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000,
+ 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000,
+ 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000,
+ 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000,
+ 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000,
+ 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000,
+ 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000,
+ 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000,
+ 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000,
+ 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000,
+ 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000,
+ 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000,
+ 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000,
+ 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000,
+ 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000,
+ 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000,
+ 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000,
+ 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000,
+ 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000,
+ 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000,
+ 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000,
+ 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000,
+ 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000,
+ 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000,
+ 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000,
+ 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000,
+ 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000,
+ 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000,
+ 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000,
+ 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000,
+ 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000,
+ 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000,
+ 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000,
+ 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000,
+ 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000,
+ 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000,
+ 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000,
+ 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000,
+ 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000,
+ 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000,
+ 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000,
+ 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000,
+ 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000,
+ 0x953fdbef00000000},
+ {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000,
+ 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000,
+ 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000,
+ 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000,
+ 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000,
+ 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000,
+ 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000,
+ 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000,
+ 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000,
+ 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000,
+ 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000,
+ 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000,
+ 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000,
+ 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000,
+ 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000,
+ 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000,
+ 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000,
+ 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000,
+ 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000,
+ 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000,
+ 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000,
+ 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000,
+ 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000,
+ 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000,
+ 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000,
+ 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000,
+ 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000,
+ 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000,
+ 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000,
+ 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000,
+ 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000,
+ 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000,
+ 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000,
+ 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000,
+ 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000,
+ 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000,
+ 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000,
+ 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000,
+ 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000,
+ 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000,
+ 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000,
+ 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000,
+ 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000,
+ 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000,
+ 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000,
+ 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000,
+ 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000,
+ 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000,
+ 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000,
+ 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000,
+ 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000,
+ 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000,
+ 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000,
+ 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000,
+ 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000,
+ 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000,
+ 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000,
+ 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000,
+ 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000,
+ 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000,
+ 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000,
+ 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000,
+ 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000,
+ 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000,
+ 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000,
+ 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000,
+ 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000,
+ 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000,
+ 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000,
+ 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000,
+ 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000,
+ 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000,
+ 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000,
+ 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000,
+ 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000,
+ 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000,
+ 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000,
+ 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000,
+ 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000,
+ 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000,
+ 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000,
+ 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000,
+ 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000,
+ 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000,
+ 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000,
+ 0xf4bc8a8000000000},
+ {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000,
+ 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000,
+ 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000,
+ 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000,
+ 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000,
+ 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000,
+ 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000,
+ 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000,
+ 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000,
+ 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000,
+ 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000,
+ 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000,
+ 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000,
+ 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000,
+ 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000,
+ 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000,
+ 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000,
+ 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000,
+ 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000,
+ 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000,
+ 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000,
+ 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000,
+ 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000,
+ 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000,
+ 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000,
+ 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000,
+ 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000,
+ 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000,
+ 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000,
+ 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000,
+ 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000,
+ 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000,
+ 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000,
+ 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000,
+ 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000,
+ 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000,
+ 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000,
+ 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000,
+ 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000,
+ 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000,
+ 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000,
+ 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000,
+ 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000,
+ 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000,
+ 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000,
+ 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000,
+ 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000,
+ 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000,
+ 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000,
+ 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000,
+ 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000,
+ 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000,
+ 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000,
+ 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000,
+ 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000,
+ 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000,
+ 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000,
+ 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000,
+ 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000,
+ 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000,
+ 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000,
+ 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000,
+ 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000,
+ 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000,
+ 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000,
+ 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000,
+ 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000,
+ 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000,
+ 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000,
+ 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000,
+ 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000,
+ 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000,
+ 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000,
+ 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000,
+ 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000,
+ 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000,
+ 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000,
+ 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000,
+ 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000,
+ 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000,
+ 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000,
+ 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000,
+ 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000,
+ 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000,
+ 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000,
+ 0xb9bc50ba00000000},
+ {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000,
+ 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000,
+ 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000,
+ 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000,
+ 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000,
+ 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000,
+ 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000,
+ 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000,
+ 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000,
+ 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000,
+ 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000,
+ 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000,
+ 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000,
+ 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000,
+ 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000,
+ 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000,
+ 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000,
+ 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000,
+ 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000,
+ 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000,
+ 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000,
+ 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000,
+ 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000,
+ 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000,
+ 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000,
+ 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000,
+ 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000,
+ 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000,
+ 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000,
+ 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000,
+ 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000,
+ 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000,
+ 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000,
+ 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000,
+ 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000,
+ 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000,
+ 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000,
+ 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000,
+ 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000,
+ 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000,
+ 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000,
+ 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000,
+ 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000,
+ 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000,
+ 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000,
+ 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000,
+ 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000,
+ 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000,
+ 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000,
+ 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000,
+ 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000,
+ 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000,
+ 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000,
+ 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000,
+ 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000,
+ 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000,
+ 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000,
+ 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000,
+ 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000,
+ 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000,
+ 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000,
+ 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000,
+ 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000,
+ 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000,
+ 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000,
+ 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000,
+ 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000,
+ 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000,
+ 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000,
+ 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000,
+ 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000,
+ 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000,
+ 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000,
+ 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000,
+ 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000,
+ 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000,
+ 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000,
+ 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000,
+ 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000,
+ 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000,
+ 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000,
+ 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000,
+ 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000,
+ 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000,
+ 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000,
+ 0x945b07b200000000},
+ {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000,
+ 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000,
+ 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000,
+ 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000,
+ 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000,
+ 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000,
+ 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000,
+ 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000,
+ 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000,
+ 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000,
+ 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000,
+ 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000,
+ 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000,
+ 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000,
+ 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000,
+ 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000,
+ 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000,
+ 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000,
+ 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000,
+ 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000,
+ 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000,
+ 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000,
+ 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000,
+ 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000,
+ 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000,
+ 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000,
+ 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000,
+ 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000,
+ 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000,
+ 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000,
+ 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000,
+ 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000,
+ 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000,
+ 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000,
+ 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000,
+ 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000,
+ 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000,
+ 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000,
+ 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000,
+ 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000,
+ 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000,
+ 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000,
+ 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000,
+ 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000,
+ 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000,
+ 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000,
+ 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000,
+ 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000,
+ 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000,
+ 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000,
+ 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000,
+ 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000,
+ 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000,
+ 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000,
+ 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000,
+ 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000,
+ 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000,
+ 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000,
+ 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000,
+ 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000,
+ 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000,
+ 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000,
+ 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000,
+ 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000,
+ 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000,
+ 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000,
+ 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000,
+ 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000,
+ 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000,
+ 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000,
+ 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000,
+ 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000,
+ 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000,
+ 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000,
+ 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000,
+ 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000,
+ 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000,
+ 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000,
+ 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000,
+ 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000,
+ 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000,
+ 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000,
+ 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000,
+ 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000,
+ 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000,
+ 0x0650d0f700000000},
+ {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000,
+ 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000,
+ 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000,
+ 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000,
+ 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000,
+ 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000,
+ 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000,
+ 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000,
+ 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000,
+ 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000,
+ 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000,
+ 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000,
+ 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000,
+ 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000,
+ 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000,
+ 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000,
+ 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000,
+ 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000,
+ 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000,
+ 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000,
+ 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000,
+ 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000,
+ 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000,
+ 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000,
+ 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000,
+ 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000,
+ 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000,
+ 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000,
+ 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000,
+ 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000,
+ 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000,
+ 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000,
+ 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000,
+ 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000,
+ 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000,
+ 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000,
+ 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000,
+ 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000,
+ 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000,
+ 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000,
+ 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000,
+ 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000,
+ 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000,
+ 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000,
+ 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000,
+ 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000,
+ 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000,
+ 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000,
+ 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000,
+ 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000,
+ 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000,
+ 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000,
+ 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000,
+ 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000,
+ 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000,
+ 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000,
+ 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000,
+ 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000,
+ 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000,
+ 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000,
+ 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000,
+ 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000,
+ 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000,
+ 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000,
+ 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000,
+ 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000,
+ 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000,
+ 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000,
+ 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000,
+ 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000,
+ 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000,
+ 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000,
+ 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000,
+ 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000,
+ 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000,
+ 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000,
+ 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000,
+ 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000,
+ 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000,
+ 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000,
+ 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000,
+ 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000,
+ 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000,
+ 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000,
+ 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000,
+ 0x657594e900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873,
+ 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661,
+ 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441,
+ 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44,
+ 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1,
+ 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05,
+ 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa,
+ 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e,
+ 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb,
+ 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be,
+ 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e,
+ 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c,
+ 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d,
+ 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9,
+ 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f,
+ 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b,
+ 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39,
+ 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b,
+ 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b,
+ 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20,
+ 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595,
+ 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61,
+ 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0,
+ 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644,
+ 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1,
+ 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d,
+ 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d,
+ 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f,
+ 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad,
+ 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359,
+ 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f,
+ 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b,
+ 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7,
+ 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5,
+ 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5,
+ 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0,
+ 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65,
+ 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091,
+ 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633,
+ 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7,
+ 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272,
+ 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77,
+ 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57,
+ 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145,
+ 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9,
+ 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d,
+ 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb,
+ 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f,
+ 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad,
+ 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf,
+ 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f,
+ 0x4e36ba18},
+ {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b,
+ 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8,
+ 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19,
+ 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4,
+ 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239,
+ 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd,
+ 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258,
+ 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc,
+ 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41,
+ 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c,
+ 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d,
+ 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e,
+ 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba,
+ 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e,
+ 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8,
+ 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c,
+ 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f,
+ 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c,
+ 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d,
+ 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d,
+ 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0,
+ 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014,
+ 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc,
+ 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628,
+ 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5,
+ 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941,
+ 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0,
+ 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53,
+ 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880,
+ 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264,
+ 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92,
+ 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776,
+ 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8,
+ 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b,
+ 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea,
+ 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837,
+ 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca,
+ 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e,
+ 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211,
+ 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5,
+ 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08,
+ 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5,
+ 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934,
+ 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7,
+ 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049,
+ 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad,
+ 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b,
+ 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf,
+ 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c,
+ 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f,
+ 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e,
+ 0xa1d67c91},
+ {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9,
+ 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de,
+ 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94,
+ 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0,
+ 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a,
+ 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924,
+ 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052,
+ 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c,
+ 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6,
+ 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2,
+ 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8,
+ 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f,
+ 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d,
+ 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273,
+ 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30,
+ 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e,
+ 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7,
+ 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980,
+ 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca,
+ 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8,
+ 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62,
+ 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c,
+ 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c,
+ 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032,
+ 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798,
+ 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d,
+ 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07,
+ 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630,
+ 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389,
+ 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7,
+ 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4,
+ 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca,
+ 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55,
+ 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662,
+ 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828,
+ 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c,
+ 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6,
+ 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98,
+ 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3,
+ 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d,
+ 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037,
+ 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913,
+ 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759,
+ 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e,
+ 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1,
+ 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf,
+ 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c,
+ 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2,
+ 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b,
+ 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c,
+ 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276,
+ 0xa8ef40a1},
+ {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e,
+ 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8,
+ 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819,
+ 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f,
+ 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d,
+ 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756,
+ 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0,
+ 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb,
+ 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9,
+ 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f,
+ 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e,
+ 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8,
+ 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835,
+ 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e,
+ 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62,
+ 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749,
+ 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b,
+ 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d,
+ 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc,
+ 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80,
+ 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2,
+ 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599,
+ 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05,
+ 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e,
+ 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c,
+ 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e,
+ 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef,
+ 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359,
+ 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b,
+ 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0,
+ 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc,
+ 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7,
+ 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f,
+ 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189,
+ 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568,
+ 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e,
+ 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c,
+ 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27,
+ 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794,
+ 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf,
+ 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d,
+ 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db,
+ 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a,
+ 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c,
+ 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544,
+ 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f,
+ 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013,
+ 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38,
+ 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea,
+ 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c,
+ 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd,
+ 0x356bacd8}};
+
+#endif
+
+#endif
+
+#if N == 6
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370,
+ 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d,
+ 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69,
+ 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426,
+ 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3,
+ 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f,
+ 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c,
+ 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490,
+ 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155,
+ 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a,
+ 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e,
+ 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603,
+ 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349,
+ 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5,
+ 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50,
+ 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc,
+ 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b,
+ 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76,
+ 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862,
+ 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9,
+ 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c,
+ 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0,
+ 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937,
+ 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b,
+ 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e,
+ 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e,
+ 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a,
+ 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357,
+ 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0,
+ 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c,
+ 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9,
+ 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165,
+ 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766,
+ 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b,
+ 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f,
+ 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030,
+ 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5,
+ 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59,
+ 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63,
+ 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf,
+ 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a,
+ 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845,
+ 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51,
+ 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c,
+ 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f,
+ 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3,
+ 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46,
+ 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea,
+ 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d,
+ 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60,
+ 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74,
+ 0x8568a0a8},
+ {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5,
+ 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf,
+ 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5,
+ 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba,
+ 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf,
+ 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f,
+ 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0,
+ 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450,
+ 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55,
+ 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a,
+ 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620,
+ 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a,
+ 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454,
+ 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4,
+ 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534,
+ 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584,
+ 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694,
+ 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e,
+ 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4,
+ 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1,
+ 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4,
+ 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164,
+ 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1,
+ 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911,
+ 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314,
+ 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c,
+ 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6,
+ 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec,
+ 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc,
+ 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c,
+ 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c,
+ 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c,
+ 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716,
+ 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c,
+ 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676,
+ 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879,
+ 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c,
+ 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc,
+ 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77,
+ 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7,
+ 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2,
+ 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd,
+ 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7,
+ 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad,
+ 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897,
+ 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827,
+ 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7,
+ 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947,
+ 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57,
+ 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d,
+ 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37,
+ 0x0d907052},
+ {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d,
+ 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89,
+ 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31,
+ 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81,
+ 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e,
+ 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0,
+ 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f,
+ 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291,
+ 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e,
+ 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e,
+ 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936,
+ 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2,
+ 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13,
+ 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d,
+ 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f,
+ 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1,
+ 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a,
+ 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae,
+ 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516,
+ 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f,
+ 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20,
+ 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe,
+ 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28,
+ 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6,
+ 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419,
+ 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5,
+ 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d,
+ 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889,
+ 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412,
+ 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c,
+ 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e,
+ 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0,
+ 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02,
+ 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986,
+ 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e,
+ 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e,
+ 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221,
+ 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf,
+ 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913,
+ 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d,
+ 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622,
+ 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592,
+ 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a,
+ 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae,
+ 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c,
+ 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82,
+ 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20,
+ 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe,
+ 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025,
+ 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1,
+ 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719,
+ 0xfd1a6c8a},
+ {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3,
+ 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb,
+ 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d,
+ 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb,
+ 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9,
+ 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156,
+ 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045,
+ 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa,
+ 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8,
+ 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e,
+ 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8,
+ 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0,
+ 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38,
+ 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87,
+ 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46,
+ 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9,
+ 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585,
+ 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d,
+ 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb,
+ 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531,
+ 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03,
+ 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc,
+ 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33,
+ 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c,
+ 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be,
+ 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d,
+ 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b,
+ 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303,
+ 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f,
+ 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0,
+ 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801,
+ 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe,
+ 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e,
+ 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346,
+ 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620,
+ 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776,
+ 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844,
+ 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb,
+ 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0,
+ 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f,
+ 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d,
+ 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b,
+ 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d,
+ 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75,
+ 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795,
+ 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a,
+ 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb,
+ 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354,
+ 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28,
+ 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30,
+ 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856,
+ 0x7895f01a},
+ {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188,
+ 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33,
+ 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d,
+ 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445,
+ 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2,
+ 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058,
+ 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43,
+ 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9,
+ 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e,
+ 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06,
+ 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228,
+ 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93,
+ 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e,
+ 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4,
+ 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b,
+ 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371,
+ 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265,
+ 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede,
+ 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0,
+ 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f,
+ 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8,
+ 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32,
+ 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae,
+ 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544,
+ 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3,
+ 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f,
+ 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911,
+ 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa,
+ 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be,
+ 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54,
+ 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b,
+ 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1,
+ 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652,
+ 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9,
+ 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7,
+ 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f,
+ 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68,
+ 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782,
+ 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797,
+ 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d,
+ 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a,
+ 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2,
+ 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc,
+ 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647,
+ 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4,
+ 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e,
+ 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41,
+ 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab,
+ 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf,
+ 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904,
+ 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a,
+ 0x9239b848},
+ {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad,
+ 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0,
+ 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40,
+ 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b,
+ 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d,
+ 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b,
+ 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb,
+ 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d,
+ 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b,
+ 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0,
+ 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840,
+ 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d,
+ 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b,
+ 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d,
+ 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6,
+ 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0,
+ 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580,
+ 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd,
+ 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d,
+ 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b,
+ 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d,
+ 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b,
+ 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6,
+ 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0,
+ 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6,
+ 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c,
+ 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c,
+ 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461,
+ 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841,
+ 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317,
+ 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac,
+ 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa,
+ 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7,
+ 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba,
+ 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a,
+ 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161,
+ 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777,
+ 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21,
+ 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a,
+ 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc,
+ 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da,
+ 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1,
+ 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01,
+ 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c,
+ 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241,
+ 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917,
+ 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac,
+ 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa,
+ 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da,
+ 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397,
+ 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537,
+ 0xeb36d3cc},
+ {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b,
+ 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059,
+ 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251,
+ 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d,
+ 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9,
+ 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c,
+ 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41,
+ 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4,
+ 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10,
+ 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c,
+ 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54,
+ 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476,
+ 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8,
+ 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d,
+ 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92,
+ 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307,
+ 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad,
+ 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f,
+ 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87,
+ 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17,
+ 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3,
+ 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46,
+ 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197,
+ 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02,
+ 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6,
+ 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e,
+ 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96,
+ 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4,
+ 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e,
+ 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b,
+ 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934,
+ 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1,
+ 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7,
+ 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5,
+ 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd,
+ 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1,
+ 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475,
+ 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0,
+ 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155,
+ 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0,
+ 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304,
+ 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348,
+ 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140,
+ 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862,
+ 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14,
+ 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181,
+ 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e,
+ 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab,
+ 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01,
+ 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523,
+ 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b,
+ 0x38e5f3c5},
+ {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06,
+ 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad,
+ 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509,
+ 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba,
+ 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414,
+ 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3,
+ 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733,
+ 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994,
+ 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a,
+ 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889,
+ 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d,
+ 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386,
+ 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621,
+ 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886,
+ 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e,
+ 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389,
+ 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f,
+ 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294,
+ 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30,
+ 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3,
+ 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d,
+ 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba,
+ 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a,
+ 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad,
+ 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03,
+ 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2,
+ 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306,
+ 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad,
+ 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b,
+ 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc,
+ 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914,
+ 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3,
+ 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435,
+ 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e,
+ 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a,
+ 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589,
+ 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27,
+ 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080,
+ 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21,
+ 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586,
+ 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28,
+ 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b,
+ 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f,
+ 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94,
+ 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12,
+ 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5,
+ 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d,
+ 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba,
+ 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c,
+ 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7,
+ 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103,
+ 0x3d3101a2}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000,
+ 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000,
+ 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000,
+ 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000,
+ 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000,
+ 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000,
+ 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000,
+ 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000,
+ 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000,
+ 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000,
+ 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000,
+ 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000,
+ 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000,
+ 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000,
+ 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000,
+ 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000,
+ 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000,
+ 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000,
+ 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000,
+ 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000,
+ 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000,
+ 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000,
+ 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000,
+ 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000,
+ 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000,
+ 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000,
+ 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000,
+ 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000,
+ 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000,
+ 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000,
+ 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000,
+ 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000,
+ 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000,
+ 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000,
+ 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000,
+ 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000,
+ 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000,
+ 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000,
+ 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000,
+ 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000,
+ 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000,
+ 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000,
+ 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000,
+ 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000,
+ 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000,
+ 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000,
+ 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000,
+ 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000,
+ 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000,
+ 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000,
+ 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000,
+ 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000,
+ 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000,
+ 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000,
+ 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000,
+ 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000,
+ 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000,
+ 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000,
+ 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000,
+ 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000,
+ 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000,
+ 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000,
+ 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000,
+ 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000,
+ 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000,
+ 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000,
+ 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000,
+ 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000,
+ 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000,
+ 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000,
+ 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000,
+ 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000,
+ 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000,
+ 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000,
+ 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000,
+ 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000,
+ 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000,
+ 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000,
+ 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000,
+ 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000,
+ 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000,
+ 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000,
+ 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000,
+ 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000,
+ 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000,
+ 0xa201313d00000000},
+ {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000,
+ 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000,
+ 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000,
+ 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000,
+ 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000,
+ 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000,
+ 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000,
+ 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000,
+ 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000,
+ 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000,
+ 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000,
+ 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000,
+ 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000,
+ 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000,
+ 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000,
+ 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000,
+ 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000,
+ 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000,
+ 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000,
+ 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000,
+ 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000,
+ 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000,
+ 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000,
+ 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000,
+ 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000,
+ 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000,
+ 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000,
+ 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000,
+ 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000,
+ 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000,
+ 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000,
+ 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000,
+ 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000,
+ 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000,
+ 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000,
+ 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000,
+ 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000,
+ 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000,
+ 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000,
+ 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000,
+ 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000,
+ 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000,
+ 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000,
+ 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000,
+ 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000,
+ 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000,
+ 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000,
+ 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000,
+ 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000,
+ 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000,
+ 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000,
+ 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000,
+ 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000,
+ 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000,
+ 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000,
+ 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000,
+ 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000,
+ 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000,
+ 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000,
+ 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000,
+ 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000,
+ 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000,
+ 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000,
+ 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000,
+ 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000,
+ 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000,
+ 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000,
+ 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000,
+ 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000,
+ 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000,
+ 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000,
+ 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000,
+ 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000,
+ 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000,
+ 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000,
+ 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000,
+ 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000,
+ 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000,
+ 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000,
+ 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000,
+ 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000,
+ 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000,
+ 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000,
+ 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000,
+ 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000,
+ 0xc5f3e53800000000},
+ {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000,
+ 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000,
+ 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000,
+ 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000,
+ 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000,
+ 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000,
+ 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000,
+ 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000,
+ 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000,
+ 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000,
+ 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000,
+ 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000,
+ 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000,
+ 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000,
+ 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000,
+ 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000,
+ 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000,
+ 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000,
+ 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000,
+ 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000,
+ 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000,
+ 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000,
+ 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000,
+ 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000,
+ 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000,
+ 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000,
+ 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000,
+ 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000,
+ 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000,
+ 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000,
+ 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000,
+ 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000,
+ 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000,
+ 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000,
+ 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000,
+ 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000,
+ 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000,
+ 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000,
+ 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000,
+ 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000,
+ 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000,
+ 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000,
+ 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000,
+ 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000,
+ 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000,
+ 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000,
+ 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000,
+ 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000,
+ 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000,
+ 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000,
+ 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000,
+ 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000,
+ 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000,
+ 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000,
+ 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000,
+ 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000,
+ 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000,
+ 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000,
+ 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000,
+ 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000,
+ 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000,
+ 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000,
+ 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000,
+ 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000,
+ 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000,
+ 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000,
+ 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000,
+ 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000,
+ 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000,
+ 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000,
+ 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000,
+ 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000,
+ 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000,
+ 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000,
+ 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000,
+ 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000,
+ 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000,
+ 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000,
+ 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000,
+ 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000,
+ 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000,
+ 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000,
+ 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000,
+ 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000,
+ 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000,
+ 0xccd336eb00000000},
+ {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000,
+ 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000,
+ 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000,
+ 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000,
+ 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000,
+ 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000,
+ 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000,
+ 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000,
+ 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000,
+ 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000,
+ 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000,
+ 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000,
+ 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000,
+ 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000,
+ 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000,
+ 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000,
+ 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000,
+ 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000,
+ 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000,
+ 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000,
+ 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000,
+ 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000,
+ 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000,
+ 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000,
+ 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000,
+ 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000,
+ 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000,
+ 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000,
+ 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000,
+ 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000,
+ 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000,
+ 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000,
+ 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000,
+ 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000,
+ 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000,
+ 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000,
+ 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000,
+ 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000,
+ 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000,
+ 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000,
+ 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000,
+ 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000,
+ 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000,
+ 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000,
+ 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000,
+ 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000,
+ 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000,
+ 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000,
+ 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000,
+ 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000,
+ 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000,
+ 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000,
+ 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000,
+ 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000,
+ 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000,
+ 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000,
+ 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000,
+ 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000,
+ 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000,
+ 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000,
+ 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000,
+ 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000,
+ 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000,
+ 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000,
+ 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000,
+ 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000,
+ 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000,
+ 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000,
+ 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000,
+ 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000,
+ 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000,
+ 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000,
+ 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000,
+ 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000,
+ 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000,
+ 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000,
+ 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000,
+ 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000,
+ 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000,
+ 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000,
+ 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000,
+ 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000,
+ 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000,
+ 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000,
+ 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000,
+ 0x48b8399200000000},
+ {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000,
+ 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000,
+ 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000,
+ 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000,
+ 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000,
+ 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000,
+ 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000,
+ 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000,
+ 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000,
+ 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000,
+ 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000,
+ 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000,
+ 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000,
+ 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000,
+ 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000,
+ 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000,
+ 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000,
+ 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000,
+ 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000,
+ 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000,
+ 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000,
+ 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000,
+ 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000,
+ 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000,
+ 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000,
+ 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000,
+ 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000,
+ 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000,
+ 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000,
+ 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000,
+ 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000,
+ 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000,
+ 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000,
+ 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000,
+ 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000,
+ 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000,
+ 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000,
+ 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000,
+ 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000,
+ 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000,
+ 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000,
+ 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000,
+ 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000,
+ 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000,
+ 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000,
+ 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000,
+ 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000,
+ 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000,
+ 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000,
+ 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000,
+ 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000,
+ 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000,
+ 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000,
+ 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000,
+ 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000,
+ 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000,
+ 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000,
+ 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000,
+ 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000,
+ 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000,
+ 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000,
+ 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000,
+ 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000,
+ 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000,
+ 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000,
+ 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000,
+ 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000,
+ 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000,
+ 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000,
+ 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000,
+ 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000,
+ 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000,
+ 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000,
+ 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000,
+ 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000,
+ 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000,
+ 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000,
+ 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000,
+ 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000,
+ 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000,
+ 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000,
+ 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000,
+ 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000,
+ 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000,
+ 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000,
+ 0x1af0957800000000},
+ {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000,
+ 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000,
+ 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000,
+ 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000,
+ 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000,
+ 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000,
+ 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000,
+ 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000,
+ 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000,
+ 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000,
+ 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000,
+ 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000,
+ 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000,
+ 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000,
+ 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000,
+ 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000,
+ 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000,
+ 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000,
+ 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000,
+ 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000,
+ 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000,
+ 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000,
+ 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000,
+ 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000,
+ 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000,
+ 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000,
+ 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000,
+ 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000,
+ 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000,
+ 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000,
+ 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000,
+ 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000,
+ 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000,
+ 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000,
+ 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000,
+ 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000,
+ 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000,
+ 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000,
+ 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000,
+ 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000,
+ 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000,
+ 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000,
+ 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000,
+ 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000,
+ 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000,
+ 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000,
+ 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000,
+ 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000,
+ 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000,
+ 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000,
+ 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000,
+ 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000,
+ 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000,
+ 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000,
+ 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000,
+ 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000,
+ 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000,
+ 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000,
+ 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000,
+ 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000,
+ 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000,
+ 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000,
+ 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000,
+ 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000,
+ 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000,
+ 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000,
+ 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000,
+ 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000,
+ 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000,
+ 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000,
+ 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000,
+ 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000,
+ 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000,
+ 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000,
+ 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000,
+ 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000,
+ 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000,
+ 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000,
+ 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000,
+ 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000,
+ 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000,
+ 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000,
+ 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000,
+ 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000,
+ 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000,
+ 0x8a6c1afd00000000},
+ {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000,
+ 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000,
+ 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000,
+ 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000,
+ 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000,
+ 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000,
+ 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000,
+ 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000,
+ 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000,
+ 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000,
+ 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000,
+ 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000,
+ 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000,
+ 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000,
+ 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000,
+ 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000,
+ 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000,
+ 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000,
+ 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000,
+ 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000,
+ 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000,
+ 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000,
+ 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000,
+ 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000,
+ 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000,
+ 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000,
+ 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000,
+ 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000,
+ 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000,
+ 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000,
+ 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000,
+ 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000,
+ 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000,
+ 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000,
+ 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000,
+ 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000,
+ 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000,
+ 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000,
+ 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000,
+ 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000,
+ 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000,
+ 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000,
+ 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000,
+ 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000,
+ 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000,
+ 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000,
+ 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000,
+ 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000,
+ 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000,
+ 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000,
+ 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000,
+ 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000,
+ 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000,
+ 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000,
+ 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000,
+ 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000,
+ 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000,
+ 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000,
+ 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000,
+ 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000,
+ 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000,
+ 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000,
+ 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000,
+ 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000,
+ 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000,
+ 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000,
+ 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000,
+ 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000,
+ 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000,
+ 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000,
+ 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000,
+ 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000,
+ 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000,
+ 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000,
+ 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000,
+ 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000,
+ 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000,
+ 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000,
+ 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000,
+ 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000,
+ 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000,
+ 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000,
+ 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000,
+ 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000,
+ 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000,
+ 0x5270900d00000000},
+ {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000,
+ 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000,
+ 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000,
+ 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000,
+ 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000,
+ 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000,
+ 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000,
+ 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000,
+ 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000,
+ 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000,
+ 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000,
+ 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000,
+ 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000,
+ 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000,
+ 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000,
+ 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000,
+ 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000,
+ 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000,
+ 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000,
+ 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000,
+ 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000,
+ 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000,
+ 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000,
+ 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000,
+ 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000,
+ 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000,
+ 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000,
+ 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000,
+ 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000,
+ 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000,
+ 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000,
+ 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000,
+ 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000,
+ 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000,
+ 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000,
+ 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000,
+ 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000,
+ 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000,
+ 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000,
+ 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000,
+ 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000,
+ 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000,
+ 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000,
+ 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000,
+ 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000,
+ 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000,
+ 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000,
+ 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000,
+ 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000,
+ 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000,
+ 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000,
+ 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000,
+ 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000,
+ 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000,
+ 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000,
+ 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000,
+ 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000,
+ 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000,
+ 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000,
+ 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000,
+ 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000,
+ 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000,
+ 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000,
+ 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000,
+ 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000,
+ 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000,
+ 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000,
+ 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000,
+ 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000,
+ 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000,
+ 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000,
+ 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000,
+ 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000,
+ 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000,
+ 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000,
+ 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000,
+ 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000,
+ 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000,
+ 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000,
+ 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000,
+ 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000,
+ 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000,
+ 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000,
+ 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000,
+ 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000,
+ 0xa8a0688500000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912,
+ 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba,
+ 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3,
+ 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30,
+ 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e,
+ 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3,
+ 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73,
+ 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe,
+ 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0,
+ 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643,
+ 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a,
+ 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082,
+ 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4,
+ 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279,
+ 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735,
+ 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8,
+ 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad,
+ 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05,
+ 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c,
+ 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718,
+ 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46,
+ 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb,
+ 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc,
+ 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41,
+ 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f,
+ 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad,
+ 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4,
+ 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c,
+ 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779,
+ 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4,
+ 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8,
+ 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235,
+ 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7,
+ 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f,
+ 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476,
+ 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195,
+ 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb,
+ 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46,
+ 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622,
+ 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af,
+ 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1,
+ 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12,
+ 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b,
+ 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3,
+ 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51,
+ 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc,
+ 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90,
+ 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d,
+ 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708,
+ 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0,
+ 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9,
+ 0x48686b56},
+ {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c,
+ 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae,
+ 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb,
+ 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90,
+ 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410,
+ 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b,
+ 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6,
+ 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed,
+ 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d,
+ 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036,
+ 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953,
+ 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1,
+ 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca,
+ 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781,
+ 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d,
+ 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416,
+ 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f,
+ 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd,
+ 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8,
+ 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b,
+ 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb,
+ 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0,
+ 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5,
+ 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e,
+ 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e,
+ 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558,
+ 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d,
+ 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf,
+ 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6,
+ 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad,
+ 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971,
+ 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a,
+ 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b,
+ 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969,
+ 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c,
+ 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57,
+ 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7,
+ 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c,
+ 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab,
+ 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0,
+ 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160,
+ 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b,
+ 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e,
+ 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac,
+ 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d,
+ 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546,
+ 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a,
+ 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1,
+ 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8,
+ 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a,
+ 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f,
+ 0xcaa25178},
+ {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00,
+ 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b,
+ 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed,
+ 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777,
+ 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01,
+ 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a,
+ 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef,
+ 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74,
+ 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002,
+ 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498,
+ 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee,
+ 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75,
+ 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05,
+ 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e,
+ 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8,
+ 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73,
+ 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404,
+ 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f,
+ 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9,
+ 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71,
+ 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607,
+ 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c,
+ 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb,
+ 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470,
+ 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806,
+ 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790,
+ 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6,
+ 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d,
+ 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a,
+ 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991,
+ 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7,
+ 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c,
+ 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09,
+ 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92,
+ 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4,
+ 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e,
+ 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08,
+ 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593,
+ 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3,
+ 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778,
+ 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e,
+ 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94,
+ 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2,
+ 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079,
+ 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c,
+ 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497,
+ 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1,
+ 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a,
+ 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d,
+ 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396,
+ 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0,
+ 0x0c7ac97b},
+ {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669,
+ 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853,
+ 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062,
+ 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527,
+ 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad,
+ 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545,
+ 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27,
+ 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf,
+ 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45,
+ 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800,
+ 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031,
+ 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b,
+ 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26,
+ 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce,
+ 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d,
+ 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5,
+ 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130,
+ 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a,
+ 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b,
+ 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480,
+ 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a,
+ 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2,
+ 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e,
+ 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996,
+ 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c,
+ 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc,
+ 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd,
+ 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7,
+ 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232,
+ 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da,
+ 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439,
+ 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1,
+ 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da,
+ 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0,
+ 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1,
+ 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94,
+ 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e,
+ 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6,
+ 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2,
+ 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a,
+ 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0,
+ 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95,
+ 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4,
+ 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e,
+ 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395,
+ 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d,
+ 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e,
+ 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676,
+ 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83,
+ 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9,
+ 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888,
+ 0x5185cd09}};
+
+#endif
+
+#endif
+
+#endif
+
+local const z_crc_t FAR x2n_table[] = {
+ 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000,
+ 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467,
+ 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0,
+ 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169,
+ 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37,
+ 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a,
+ 0xc40ba6d0, 0xc4e22c3c};
diff --git a/Sources/zlib-1.3.1/deflate.c b/Sources/zlib-1.3.1/deflate.c
new file mode 100644
index 00000000..012ea814
--- /dev/null
+++ b/Sources/zlib-1.3.1/deflate.c
@@ -0,0 +1,2139 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in http://tools.ietf.org/html/rfc1951
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+ " deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func)(deflate_state *s, int flush);
+/* Compression function. Returns the block state after the call. */
+
+local block_state deflate_stored(deflate_state *s, int flush);
+local block_state deflate_fast(deflate_state *s, int flush);
+#ifndef FASTEST
+local block_state deflate_slow(deflate_state *s, int flush);
+#endif
+local block_state deflate_rle(deflate_state *s, int flush);
+local block_state deflate_huff(deflate_state *s, int flush);
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
+#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0))
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to UPDATE_HASH are made with consecutive input
+ * characters, so that a running hash key can be computed from the previous
+ * key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to INSERT_STRING are made with consecutive input
+ * characters and the first MIN_MATCH bytes of str are valid (except for
+ * the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ do { \
+ s->head[s->hash_size - 1] = NIL; \
+ zmemzero((Bytef *)s->head, \
+ (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \
+ } while (0)
+
+/* ===========================================================================
+ * Slide the hash table when sliding the window down (could be avoided with 32
+ * bit values at the expense of memory usage). We slide even when level == 0 to
+ * keep the hash table consistent if we switch back to level > 0 later.
+ */
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+ __attribute__((no_sanitize("memory")))
+# endif
+#endif
+local void slide_hash(deflate_state *s) {
+ unsigned n, m;
+ Posf *p;
+ uInt wsize = s->w_size;
+
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m - wsize : NIL);
+ } while (--n);
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m - wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) {
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ zmemcpy(buf, strm->next_in, len);
+ if (strm->state->wrap == 1) {
+ strm->adler = adler32(strm->adler, buf, len);
+ }
+#ifdef GZIP
+ else if (strm->state->wrap == 2) {
+ strm->adler = crc32(strm->adler, buf, len);
+ }
+#endif
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return len;
+}
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(deflate_state *s) {
+ unsigned n;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (sizeof(int) <= 2) {
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if
+ * strstart == 0 && lookahead == 1 (input done a byte at time)
+ */
+ more--;
+ }
+ }
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s->strstart >= wsize + MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
+ slide_hash(s);
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) break;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead + s->insert >= MIN_MATCH) {
+ uInt str = s->strstart - s->insert;
+ s->ins_h = s->window[str];
+ UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ while (s->insert) {
+ UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+ s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+ s->head[s->ins_h] = (Pos)str;
+ str++;
+ s->insert--;
+ if (s->lookahead + s->insert < MIN_MATCH)
+ break;
+ }
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+ /* If the WIN_INIT bytes after the end of the current data have never been
+ * written, then zero those bytes in order to avoid memory check reports of
+ * the use of uninitialized (or uninitialised as Julian writes) bytes by
+ * the longest match routines. Update the high water mark for the next
+ * time through here. WIN_INIT is set to MAX_MATCH since the longest match
+ * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+ */
+ if (s->high_water < s->window_size) {
+ ulg curr = s->strstart + (ulg)(s->lookahead);
+ ulg init;
+
+ if (s->high_water < curr) {
+ /* Previous high water mark below current data -- zero WIN_INIT
+ * bytes or up to end of window, whichever is less.
+ */
+ init = s->window_size - curr;
+ if (init > WIN_INIT)
+ init = WIN_INIT;
+ zmemzero(s->window + curr, (unsigned)init);
+ s->high_water = curr + init;
+ }
+ else if (s->high_water < (ulg)curr + WIN_INIT) {
+ /* High water mark at or above current data, but below current data
+ * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+ * to end of window, whichever is less.
+ */
+ init = (ulg)curr + WIN_INIT - s->high_water;
+ if (init > s->window_size - s->high_water)
+ init = s->window_size - s->high_water;
+ zmemzero(s->window + s->high_water, (unsigned)init);
+ s->high_water += init;
+ }
+ }
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "not enough room for search");
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version,
+ int stream_size) {
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
+ int windowBits, int memLevel, int strategy,
+ const char *version, int stream_size) {
+ deflate_state *s;
+ int wrap = 1;
+ static const char my_version[] = ZLIB_VERSION;
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ if (windowBits < -15)
+ return Z_STREAM_ERROR;
+ windowBits = -windowBits;
+ }
+#ifdef GZIP
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+#endif
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) {
+ return Z_STREAM_ERROR;
+ }
+ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+ s->status = INIT_STATE; /* to pass state test in deflateReset() */
+
+ s->wrap = wrap;
+ s->gzhead = Z_NULL;
+ s->w_bits = (uInt)windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = (uInt)memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->high_water = 0; /* nothing written to s->window yet */
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ /* We overlay pending_buf and sym_buf. This works since the average size
+ * for length/distance pairs over any compressed block is assured to be 31
+ * bits or less.
+ *
+ * Analysis: The longest fixed codes are a length code of 8 bits plus 5
+ * extra bits, for lengths 131 to 257. The longest fixed distance codes are
+ * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
+ * possible fixed-codes length/distance pair is then 31 bits total.
+ *
+ * sym_buf starts one-fourth of the way into pending_buf. So there are
+ * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
+ * in sym_buf is three bytes -- two for the distance and one for the
+ * literal/length. As each symbol is consumed, the pointer to the next
+ * sym_buf value to read moves forward three bytes. From that symbol, up to
+ * 31 bits are written to pending_buf. The closest the written pending_buf
+ * bits gets to the next sym_buf symbol to read is just before the last
+ * code is written. At that time, 31*(n - 2) bits have been written, just
+ * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at
+ * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1
+ * symbols are written.) The closest the writing gets to what is unread is
+ * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and
+ * can range from 128 to 32768.
+ *
+ * Therefore, at a minimum, there are 142 bits of space between what is
+ * written and what is read in the overlain buffers, so the symbols cannot
+ * be overwritten by the compressed data. That space is actually 139 bits,
+ * due to the three-bit fixed-code block header.
+ *
+ * That covers the case where either Z_FIXED is specified, forcing fixed
+ * codes, or when the use of fixed codes is chosen, because that choice
+ * results in a smaller compressed block than dynamic codes. That latter
+ * condition then assures that the above analysis also covers all dynamic
+ * blocks. A dynamic-code block will only be chosen to be emitted if it has
+ * fewer bits than a fixed-code block would for the same set of symbols.
+ * Therefore its average symbol length is assured to be less than 31. So
+ * the compressed data for a dynamic block also cannot overwrite the
+ * symbols from which it is being constructed.
+ */
+
+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS);
+ s->pending_buf_size = (ulg)s->lit_bufsize * 4;
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ s->status = FINISH_STATE;
+ strm->msg = ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+#ifdef LIT_MEM
+ s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1));
+ s->l_buf = s->pending_buf + (s->lit_bufsize << 2);
+ s->sym_end = s->lit_bufsize - 1;
+#else
+ s->sym_buf = s->pending_buf + s->lit_bufsize;
+ s->sym_end = (s->lit_bufsize - 1) * 3;
+#endif
+ /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* =========================================================================
+ * Check for a valid deflate stream state. Return 0 if ok, 1 if not.
+ */
+local int deflateStateCheck(z_streamp strm) {
+ deflate_state *s;
+ if (strm == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+ return 1;
+ s = strm->state;
+ if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE &&
+#ifdef GZIP
+ s->status != GZIP_STATE &&
+#endif
+ s->status != EXTRA_STATE &&
+ s->status != NAME_STATE &&
+ s->status != COMMENT_STATE &&
+ s->status != HCRC_STATE &&
+ s->status != BUSY_STATE &&
+ s->status != FINISH_STATE))
+ return 1;
+ return 0;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary,
+ uInt dictLength) {
+ deflate_state *s;
+ uInt str, n;
+ int wrap;
+ unsigned avail;
+ z_const unsigned char *next;
+
+ if (deflateStateCheck(strm) || dictionary == Z_NULL)
+ return Z_STREAM_ERROR;
+ s = strm->state;
+ wrap = s->wrap;
+ if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
+ return Z_STREAM_ERROR;
+
+ /* when using zlib wrappers, compute Adler-32 for provided dictionary */
+ if (wrap == 1)
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+ s->wrap = 0; /* avoid computing Adler-32 in read_buf */
+
+ /* if dictionary would fill window, just replace the history */
+ if (dictLength >= s->w_size) {
+ if (wrap == 0) { /* already empty otherwise */
+ CLEAR_HASH(s);
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->insert = 0;
+ }
+ dictionary += dictLength - s->w_size; /* use the tail */
+ dictLength = s->w_size;
+ }
+
+ /* insert dictionary into window and hash */
+ avail = strm->avail_in;
+ next = strm->next_in;
+ strm->avail_in = dictLength;
+ strm->next_in = (z_const Bytef *)dictionary;
+ fill_window(s);
+ while (s->lookahead >= MIN_MATCH) {
+ str = s->strstart;
+ n = s->lookahead - (MIN_MATCH-1);
+ do {
+ UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+ s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+ s->head[s->ins_h] = (Pos)str;
+ str++;
+ } while (--n);
+ s->strstart = str;
+ s->lookahead = MIN_MATCH-1;
+ fill_window(s);
+ }
+ s->strstart += s->lookahead;
+ s->block_start = (long)s->strstart;
+ s->insert = s->lookahead;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ strm->next_in = next;
+ strm->avail_in = avail;
+ s->wrap = wrap;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary,
+ uInt *dictLength) {
+ deflate_state *s;
+ uInt len;
+
+ if (deflateStateCheck(strm))
+ return Z_STREAM_ERROR;
+ s = strm->state;
+ len = s->strstart + s->lookahead;
+ if (len > s->w_size)
+ len = s->w_size;
+ if (dictionary != Z_NULL && len)
+ zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len);
+ if (dictLength != Z_NULL)
+ *dictLength = len;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateResetKeep(z_streamp strm) {
+ deflate_state *s;
+
+ if (deflateStateCheck(strm)) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->wrap < 0) {
+ s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s->status =
+#ifdef GZIP
+ s->wrap == 2 ? GZIP_STATE :
+#endif
+ INIT_STATE;
+ strm->adler =
+#ifdef GZIP
+ s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+ adler32(0L, Z_NULL, 0);
+ s->last_flush = -2;
+
+ _tr_init(s);
+
+ return Z_OK;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init(deflate_state *s) {
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->insert = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset(z_streamp strm) {
+ int ret;
+
+ ret = deflateResetKeep(strm);
+ if (ret == Z_OK)
+ lm_init(strm->state);
+ return ret;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) {
+ if (deflateStateCheck(strm) || strm->state->wrap != 2)
+ return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) {
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ if (pending != Z_NULL)
+ *pending = strm->state->pending;
+ if (bits != Z_NULL)
+ *bits = strm->state->bi_valid;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) {
+ deflate_state *s;
+ int put;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ s = strm->state;
+#ifdef LIT_MEM
+ if (bits < 0 || bits > 16 ||
+ (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3))
+ return Z_BUF_ERROR;
+#else
+ if (bits < 0 || bits > 16 ||
+ s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
+ return Z_BUF_ERROR;
+#endif
+ do {
+ put = Buf_size - s->bi_valid;
+ if (put > bits)
+ put = bits;
+ s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
+ s->bi_valid += put;
+ _tr_flush_bits(s);
+ value >>= put;
+ bits -= put;
+ } while (bits);
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) {
+ deflate_state *s;
+ compress_func func;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ s = strm->state;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if ((strategy != s->strategy || func != configuration_table[level].func) &&
+ s->last_flush != -2) {
+ /* Flush the last buffer: */
+ int err = deflate(strm, Z_BLOCK);
+ if (err == Z_STREAM_ERROR)
+ return err;
+ if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
+ return Z_BUF_ERROR;
+ }
+ if (s->level != level) {
+ if (s->level == 0 && s->matches != 0) {
+ if (s->matches == 1)
+ slide_hash(s);
+ else
+ CLEAR_HASH(s);
+ s->matches = 0;
+ }
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy,
+ int nice_length, int max_chain) {
+ deflate_state *s;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = (uInt)good_length;
+ s->max_lazy_match = (uInt)max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = (uInt)max_chain;
+ return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns a
+ * close to exact, as well as small, upper bound on the compressed size. This
+ * is an expansion of ~0.03%, plus a small constant.
+ *
+ * For any setting other than those defaults for windowBits and memLevel, one
+ * of two worst case bounds is returned. This is at most an expansion of ~4% or
+ * ~13%, plus a small constant.
+ *
+ * Both the 0.03% and 4% derive from the overhead of stored blocks. The first
+ * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second
+ * is for stored blocks of 127 bytes (the worst case memLevel == 1). The
+ * expansion results from five bytes of header for each stored block.
+ *
+ * The larger expansion of 13% results from a window size less than or equal to
+ * the symbols buffer size (windowBits <= memLevel + 7). In that case some of
+ * the data being compressed may have slid out of the sliding window, impeding
+ * a stored block from being emitted. Then the only choice is a fixed or
+ * dynamic block, where a fixed block limits the maximum expansion to 9 bits
+ * per 8-bit byte, plus 10 bits for every block. The smallest block size for
+ * which this can occur is 255 (memLevel == 2).
+ *
+ * Shifts are used to approximate divisions, for speed.
+ */
+uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) {
+ deflate_state *s;
+ uLong fixedlen, storelen, wraplen;
+
+ /* upper bound for fixed blocks with 9-bit literals and length 255
+ (memLevel == 2, which is the lowest that may not use stored blocks) --
+ ~13% overhead plus a small constant */
+ fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +
+ (sourceLen >> 9) + 4;
+
+ /* upper bound for stored blocks with length 127 (memLevel == 1) --
+ ~4% overhead plus a small constant */
+ storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) +
+ (sourceLen >> 11) + 7;
+
+ /* if can't get parameters, return larger bound plus a zlib wrapper */
+ if (deflateStateCheck(strm))
+ return (fixedlen > storelen ? fixedlen : storelen) + 6;
+
+ /* compute wrapper length */
+ s = strm->state;
+ switch (s->wrap) {
+ case 0: /* raw deflate */
+ wraplen = 0;
+ break;
+ case 1: /* zlib wrapper */
+ wraplen = 6 + (s->strstart ? 4 : 0);
+ break;
+#ifdef GZIP
+ case 2: /* gzip wrapper */
+ wraplen = 18;
+ if (s->gzhead != Z_NULL) { /* user-supplied gzip header */
+ Bytef *str;
+ if (s->gzhead->extra != Z_NULL)
+ wraplen += 2 + s->gzhead->extra_len;
+ str = s->gzhead->name;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ str = s->gzhead->comment;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ if (s->gzhead->hcrc)
+ wraplen += 2;
+ }
+ break;
+#endif
+ default: /* for compiler happiness */
+ wraplen = 6;
+ }
+
+ /* if not default parameters, return one of the conservative bounds */
+ if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+ return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) +
+ wraplen;
+
+ /* default settings: return tight bound for that case -- ~0.03% overhead
+ plus a small constant */
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13 - 6 + wraplen;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB(deflate_state *s, uInt b) {
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output, except for
+ * some deflate_stored() output, goes through this function so some
+ * applications may wish to modify it to avoid allocating a large
+ * strm->next_out buffer and copying into it. (See also read_buf()).
+ */
+local void flush_pending(z_streamp strm) {
+ unsigned len;
+ deflate_state *s = strm->state;
+
+ _tr_flush_bits(s);
+ len = s->pending;
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, s->pending_out, len);
+ strm->next_out += len;
+ s->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ s->pending -= len;
+ if (s->pending == 0) {
+ s->pending_out = s->pending_buf;
+ }
+}
+
+/* ===========================================================================
+ * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1].
+ */
+#define HCRC_UPDATE(beg) \
+ do { \
+ if (s->gzhead->hcrc && s->pending > (beg)) \
+ strm->adler = crc32(strm->adler, s->pending_buf + (beg), \
+ s->pending - (beg)); \
+ } while (0)
+
+/* ========================================================================= */
+int ZEXPORT deflate(z_streamp strm, int flush) {
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->avail_in != 0 && strm->next_in == Z_NULL) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Write the header */
+ if (s->status == INIT_STATE && s->wrap == 0)
+ s->status = BUSY_STATE;
+ if (s->status == INIT_STATE) {
+ /* zlib header */
+ uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8;
+ uInt level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+#ifdef GZIP
+ if (s->status == GZIP_STATE) {
+ /* gzip header */
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == Z_NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != Z_NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex;
+ while (s->pending + left > s->pending_buf_size) {
+ uInt copy = s->pending_buf_size - s->pending;
+ zmemcpy(s->pending_buf + s->pending,
+ s->gzhead->extra + s->gzindex, copy);
+ s->pending = s->pending_buf_size;
+ HCRC_UPDATE(beg);
+ s->gzindex += copy;
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ left -= copy;
+ }
+ zmemcpy(s->pending_buf + s->pending,
+ s->gzhead->extra + s->gzindex, left);
+ s->pending += left;
+ HCRC_UPDATE(beg);
+ s->gzindex = 0;
+ }
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ int val;
+ do {
+ if (s->pending == s->pending_buf_size) {
+ HCRC_UPDATE(beg);
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ HCRC_UPDATE(beg);
+ s->gzindex = 0;
+ }
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ int val;
+ do {
+ if (s->pending == s->pending_buf_size) {
+ HCRC_UPDATE(beg);
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ HCRC_UPDATE(beg);
+ }
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size) {
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ }
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+#endif
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = s->level == 0 ? deflate_stored(s, flush) :
+ s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+ s->strategy == Z_RLE ? deflate_rle(s, flush) :
+ (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ if (s->lookahead == 0) {
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->insert = 0;
+ }
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+ put_byte(s, (Byte)(strm->total_in & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd(z_streamp strm) {
+ int status;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
+#ifdef MAXSEG_64K
+ (void)dest;
+ (void)source;
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+
+
+ if (deflateStateCheck(source) || dest == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS);
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+#ifdef LIT_MEM
+ ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1));
+ ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2);
+#else
+ ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
+#endif
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+local uInt longest_match(deflate_state *s, IPos cur_match) {
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = (int)s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan + best_len - 1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len - 1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match + best_len - 1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart + 3, + 5, up to strstart + 257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window + strstart + 257 */
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1),
+ "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend - scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len - 1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len - 1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart + 258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1),
+ "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan + best_len - 1);
+#else
+ scan_end1 = scan[best_len - 1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+
+#else /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for FASTEST only
+ */
+local uInt longest_match(deflate_state *s, IPos cur_match) {
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len - 1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart + 258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#endif /* FASTEST */
+
+#ifdef ZLIB_DEBUG
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(deflate_state *s, IPos start, IPos match, int length) {
+ /* check that the match is indeed a match */
+ Bytef *back = s->window + (int)match, *here = s->window + start;
+ IPos len = length;
+ if (match == (IPos)-1) {
+ /* match starts one byte before the current window -- just compare the
+ subsequent length-1 bytes */
+ back++;
+ here++;
+ len--;
+ }
+ if (zmemcmp(back, here, len) != EQUAL) {
+ fprintf(stderr, " start %u, match %d, length %d\n",
+ start, (int)match, length);
+ do {
+ fprintf(stderr, "(%02x %02x)", *back++, *here++);
+ } while (--len != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start - match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif /* ZLIB_DEBUG */
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, last) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (last)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, last) { \
+ FLUSH_BLOCK_ONLY(s, last); \
+ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
+}
+
+/* Maximum stored block length in deflate format (not including header). */
+#define MAX_STORED 65535
+
+/* Minimum of a and b. */
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ *
+ * In case deflateParams() is used to later switch to a non-zero compression
+ * level, s->matches (otherwise unused when storing) keeps track of the number
+ * of hash table slides to perform. If s->matches is 1, then one hash table
+ * slide will be done when switching. If s->matches is 2, the maximum value
+ * allowed here, then the hash table will be cleared, since two or more slides
+ * is the same as a clear.
+ *
+ * deflate_stored() is written to minimize the number of times an input byte is
+ * copied. It is most efficient with large input and output buffers, which
+ * maximizes the opportunities to have a single copy from next_in to next_out.
+ */
+local block_state deflate_stored(deflate_state *s, int flush) {
+ /* Smallest worthy block size when not flushing or finishing. By default
+ * this is 32K. This can be as small as 507 bytes for memLevel == 1. For
+ * large input and output buffers, the stored block size will be larger.
+ */
+ unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size);
+
+ /* Copy as many min_block or larger stored blocks directly to next_out as
+ * possible. If flushing, copy the remaining available input to next_out as
+ * stored blocks, if there is enough space.
+ */
+ unsigned len, left, have, last = 0;
+ unsigned used = s->strm->avail_in;
+ do {
+ /* Set len to the maximum size block that we can copy directly with the
+ * available input data and output space. Set left to how much of that
+ * would be copied from what's left in the window.
+ */
+ len = MAX_STORED; /* maximum deflate stored block length */
+ have = (s->bi_valid + 42) >> 3; /* number of header bytes */
+ if (s->strm->avail_out < have) /* need room for header */
+ break;
+ /* maximum stored block length that will fit in avail_out: */
+ have = s->strm->avail_out - have;
+ left = s->strstart - s->block_start; /* bytes left in window */
+ if (len > (ulg)left + s->strm->avail_in)
+ len = left + s->strm->avail_in; /* limit len to the input */
+ if (len > have)
+ len = have; /* limit len to the output */
+
+ /* If the stored block would be less than min_block in length, or if
+ * unable to copy all of the available input when flushing, then try
+ * copying to the window and the pending buffer instead. Also don't
+ * write an empty block when flushing -- deflate() does that.
+ */
+ if (len < min_block && ((len == 0 && flush != Z_FINISH) ||
+ flush == Z_NO_FLUSH ||
+ len != left + s->strm->avail_in))
+ break;
+
+ /* Make a dummy stored block in pending to get the header bytes,
+ * including any pending bits. This also updates the debugging counts.
+ */
+ last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0;
+ _tr_stored_block(s, (char *)0, 0L, last);
+
+ /* Replace the lengths in the dummy stored block with len. */
+ s->pending_buf[s->pending - 4] = len;
+ s->pending_buf[s->pending - 3] = len >> 8;
+ s->pending_buf[s->pending - 2] = ~len;
+ s->pending_buf[s->pending - 1] = ~len >> 8;
+
+ /* Write the stored block header bytes. */
+ flush_pending(s->strm);
+
+#ifdef ZLIB_DEBUG
+ /* Update debugging counts for the data about to be copied. */
+ s->compressed_len += len << 3;
+ s->bits_sent += len << 3;
+#endif
+
+ /* Copy uncompressed bytes from the window to next_out. */
+ if (left) {
+ if (left > len)
+ left = len;
+ zmemcpy(s->strm->next_out, s->window + s->block_start, left);
+ s->strm->next_out += left;
+ s->strm->avail_out -= left;
+ s->strm->total_out += left;
+ s->block_start += left;
+ len -= left;
+ }
+
+ /* Copy uncompressed bytes directly from next_in to next_out, updating
+ * the check value.
+ */
+ if (len) {
+ read_buf(s->strm, s->strm->next_out, len);
+ s->strm->next_out += len;
+ s->strm->avail_out -= len;
+ s->strm->total_out += len;
+ }
+ } while (last == 0);
+
+ /* Update the sliding window with the last s->w_size bytes of the copied
+ * data, or append all of the copied data to the existing window if less
+ * than s->w_size bytes were copied. Also update the number of bytes to
+ * insert in the hash tables, in the event that deflateParams() switches to
+ * a non-zero compression level.
+ */
+ used -= s->strm->avail_in; /* number of input bytes directly copied */
+ if (used) {
+ /* If any input was used, then no unused input remains in the window,
+ * therefore s->block_start == s->strstart.
+ */
+ if (used >= s->w_size) { /* supplant the previous history */
+ s->matches = 2; /* clear hash */
+ zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
+ s->strstart = s->w_size;
+ s->insert = s->strstart;
+ }
+ else {
+ if (s->window_size - s->strstart <= used) {
+ /* Slide the window down. */
+ s->strstart -= s->w_size;
+ zmemcpy(s->window, s->window + s->w_size, s->strstart);
+ if (s->matches < 2)
+ s->matches++; /* add a pending slide_hash() */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
+ }
+ zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
+ s->strstart += used;
+ s->insert += MIN(used, s->w_size - s->insert);
+ }
+ s->block_start = s->strstart;
+ }
+ if (s->high_water < s->strstart)
+ s->high_water = s->strstart;
+
+ /* If the last block was written to next_out, then done. */
+ if (last)
+ return finish_done;
+
+ /* If flushing and all input has been consumed, then done. */
+ if (flush != Z_NO_FLUSH && flush != Z_FINISH &&
+ s->strm->avail_in == 0 && (long)s->strstart == s->block_start)
+ return block_done;
+
+ /* Fill the window with any remaining input. */
+ have = s->window_size - s->strstart;
+ if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
+ /* Slide the window down. */
+ s->block_start -= s->w_size;
+ s->strstart -= s->w_size;
+ zmemcpy(s->window, s->window + s->w_size, s->strstart);
+ if (s->matches < 2)
+ s->matches++; /* add a pending slide_hash() */
+ have += s->w_size; /* more space now */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
+ }
+ if (have > s->strm->avail_in)
+ have = s->strm->avail_in;
+ if (have) {
+ read_buf(s->strm, s->window + s->strstart, have);
+ s->strstart += have;
+ s->insert += MIN(have, s->w_size - s->insert);
+ }
+ if (s->high_water < s->strstart)
+ s->high_water = s->strstart;
+
+ /* There was not enough avail_out to write a complete worthy or flushed
+ * stored block to next_out. Write a stored block to pending instead, if we
+ * have enough input for a worthy block, or if flushing and there is enough
+ * room for the remaining input as a stored block in the pending buffer.
+ */
+ have = (s->bi_valid + 42) >> 3; /* number of header bytes */
+ /* maximum stored block length that will fit in pending: */
+ have = MIN(s->pending_buf_size - have, MAX_STORED);
+ min_block = MIN(have, s->w_size);
+ left = s->strstart - s->block_start;
+ if (left >= min_block ||
+ ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH &&
+ s->strm->avail_in == 0 && left <= have)) {
+ len = MIN(left, have);
+ last = flush == Z_FINISH && s->strm->avail_in == 0 &&
+ len == left ? 1 : 0;
+ _tr_stored_block(s, (charf *)s->window + s->block_start, len, last);
+ s->block_start += len;
+ flush_pending(s->strm);
+ }
+
+ /* We've done all we can with the available input and output. */
+ return last ? finish_started : need_more;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(deflate_state *s, int flush) {
+ IPos hash_head; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart + 2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(deflate_state *s, int flush) {
+ IPos hash_head; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart + 2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+ || (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR)
+#endif
+ )) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart - 1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart - 1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart - 1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length - 1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart - 1]));
+ _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart - 1]));
+ _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
+ s->match_available = 0;
+ }
+ s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+#endif /* FASTEST */
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(deflate_state *s, int flush) {
+ int bflush; /* set if current block must be flushed */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan, *strend; /* scan goes up to strend for length of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest run, plus one for the unrolled loop.
+ */
+ if (s->lookahead <= MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ s->match_length = 0;
+ if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
+ scan = s->window + s->strstart - 1;
+ prev = *scan;
+ if (prev == *++scan && prev == *++scan && prev == *++scan) {
+ strend = s->window + s->strstart + MAX_MATCH;
+ do {
+ } while (prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ scan < strend);
+ s->match_length = MAX_MATCH - (uInt)(strend - scan);
+ if (s->match_length > s->lookahead)
+ s->match_length = s->lookahead;
+ }
+ Assert(scan <= s->window + (uInt)(s->window_size - 1),
+ "wild scan");
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+ _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = 0;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(deflate_state *s, int flush) {
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we have a literal to write. */
+ if (s->lookahead == 0) {
+ fill_window(s);
+ if (s->lookahead == 0) {
+ if (flush == Z_NO_FLUSH)
+ return need_more;
+ break; /* flush the current block */
+ }
+ }
+
+ /* Output a literal byte */
+ s->match_length = 0;
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = 0;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
diff --git a/Sources/zlib-1.3.1/deflate.h b/Sources/zlib-1.3.1/deflate.h
new file mode 100644
index 00000000..300c6ada
--- /dev/null
+++ b/Sources/zlib-1.3.1/deflate.h
@@ -0,0 +1,377 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2024 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer creation by deflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip encoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GZIP
+#endif
+
+/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at
+ the cost of a larger memory footprint */
+/* #define LIT_MEM */
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define Buf_size 16
+/* size of bit buffer in bi_buf */
+
+#define INIT_STATE 42 /* zlib header -> BUSY_STATE */
+#ifdef GZIP
+# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */
+#endif
+#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */
+#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */
+#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */
+#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */
+#define BUSY_STATE 113 /* deflate -> FINISH_STATE */
+#define FINISH_STATE 666 /* stream complete */
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ const static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ ulg pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ ulg gzindex; /* where in extra, name, or comment */
+ Byte method; /* can only be DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to suppress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+#ifdef LIT_MEM
+# define LIT_BUFS 5
+ ushf *d_buf; /* buffer for distances */
+ uchf *l_buf; /* buffer for literals/lengths */
+#else
+# define LIT_BUFS 4
+ uchf *sym_buf; /* buffer for distances and literals/lengths */
+#endif
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt sym_next; /* running index in symbol buffer */
+ uInt sym_end; /* symbol table full when sym_next reaches this */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ uInt insert; /* bytes at end of window left to insert */
+
+#ifdef ZLIB_DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+ ulg high_water;
+ /* High water mark offset in window for initialized bytes -- bytes above
+ * this are set to zero in order to avoid memory check warnings when
+ * longest match routines access bytes past the input. This is then
+ * updated to the new high water mark.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+ memory checker errors from longest match routines */
+
+ /* in trees.c */
+void ZLIB_INTERNAL _tr_init(deflate_state *s);
+int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc);
+void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
+ ulg stored_len, int last);
+void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s);
+void ZLIB_INTERNAL _tr_align(deflate_state *s);
+void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
+ ulg stored_len, int last);
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef ZLIB_DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch ZLIB_INTERNAL _length_code[];
+ extern uch ZLIB_INTERNAL _dist_code[];
+#else
+ extern const uch ZLIB_INTERNAL _length_code[];
+ extern const uch ZLIB_INTERNAL _dist_code[];
+#endif
+
+#ifdef LIT_MEM
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->sym_next] = 0; \
+ s->l_buf[s->sym_next++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (uch)(length); \
+ ush dist = (ush)(distance); \
+ s->d_buf[s->sym_next] = dist; \
+ s->l_buf[s->sym_next++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (uch)(length); \
+ ush dist = (ush)(distance); \
+ s->sym_buf[s->sym_next++] = (uch)dist; \
+ s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \
+ s->sym_buf[s->sym_next++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+#endif
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/Sources/zlib-1.3.1/gzclose.c b/Sources/zlib-1.3.1/gzclose.c
new file mode 100644
index 00000000..48d6a86f
--- /dev/null
+++ b/Sources/zlib-1.3.1/gzclose.c
@@ -0,0 +1,23 @@
+/* gzclose.c -- zlib gzclose() function
+ * Copyright (C) 2004, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* gzclose() is in a separate file so that it is linked in only if it is used.
+ That way the other gzclose functions can be used instead to avoid linking in
+ unneeded compression or decompression routines. */
+int ZEXPORT gzclose(gzFile file) {
+#ifndef NO_GZCOMPRESS
+ gz_statep state;
+
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
+#else
+ return gzclose_r(file);
+#endif
+}
diff --git a/Sources/zlib-1.3.1/gzguts.h b/Sources/zlib-1.3.1/gzguts.h
new file mode 100644
index 00000000..eba72085
--- /dev/null
+++ b/Sources/zlib-1.3.1/gzguts.h
@@ -0,0 +1,214 @@
+/* gzguts.h -- zlib internal header definitions for gz* operations
+ * Copyright (C) 2004-2024 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifdef _LARGEFILE64_SOURCE
+# ifndef _LARGEFILE_SOURCE
+# define _LARGEFILE_SOURCE 1
+# endif
+# undef _FILE_OFFSET_BITS
+# undef _TIME_BITS
+#endif
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
+
+#include
+#include "zlib.h"
+#ifdef STDC
+# include
+# include
+# include
+#endif
+
+#ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE
+#endif
+#include
+
+#ifdef _WIN32
+# include
+#endif
+
+#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
+# include
+#endif
+
+#if defined(_WIN32)
+# define WIDECHAR
+#endif
+
+#ifdef WINAPI_FAMILY
+# define open _open
+# define read _read
+# define write _write
+# define close _close
+#endif
+
+#ifdef NO_DEFLATE /* for compatibility with old definition */
+# define NO_GZCOMPRESS
+#endif
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+# ifdef VMS
+# define NO_vsnprintf
+# endif
+# ifdef __OS400__
+# define NO_vsnprintf
+# endif
+# ifdef __MVS__
+# define NO_vsnprintf
+# endif
+#endif
+
+/* unlike snprintf (which is required in C99), _snprintf does not guarantee
+ null termination of the result -- however this is only used in gzlib.c where
+ the result is assured to fit in the space provided */
+#if defined(_MSC_VER) && _MSC_VER < 1900
+# define snprintf _snprintf
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* since "static" is used to mean two completely different things in C, we
+ define "local" for the non-static meaning of "static", for readability
+ (compile with -Dlocal if your debugger can't find static symbols) */
+
+/* gz* functions always use library allocation functions */
+#ifndef STDC
+ extern voidp malloc(uInt size);
+ extern void free(voidpf ptr);
+#endif
+
+/* get errno and strerror definition */
+#if defined UNDER_CE
+# include
+# define zstrerror() gz_strwinerror((DWORD)GetLastError())
+#else
+# ifndef NO_STRERROR
+# include
+# define zstrerror() strerror(errno)
+# else
+# define zstrerror() "stdio error (consult errno)"
+# endif
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+ ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+ ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
+ ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
+ ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
+#endif
+
+/* default memLevel */
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+
+/* default i/o buffer size -- double this for output when reading (this and
+ twice this must be able to fit in an unsigned type) */
+#define GZBUFSIZE 8192
+
+/* gzip modes, also provide a little integrity check on the passed structure */
+#define GZ_NONE 0
+#define GZ_READ 7247
+#define GZ_WRITE 31153
+#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
+
+/* values for gz_state how */
+#define LOOK 0 /* look for a gzip header */
+#define COPY 1 /* copy input directly */
+#define GZIP 2 /* decompress a gzip stream */
+
+/* internal gzip file state data structure */
+typedef struct {
+ /* exposed contents for gzgetc() macro */
+ struct gzFile_s x; /* "x" for exposed */
+ /* x.have: number of bytes available at x.next */
+ /* x.next: next output data to deliver or write */
+ /* x.pos: current position in uncompressed data */
+ /* used for both reading and writing */
+ int mode; /* see gzip modes above */
+ int fd; /* file descriptor */
+ char *path; /* path or fd for error messages */
+ unsigned size; /* buffer size, zero if not allocated yet */
+ unsigned want; /* requested buffer size, default is GZBUFSIZE */
+ unsigned char *in; /* input buffer (double-sized when writing) */
+ unsigned char *out; /* output buffer (double-sized when reading) */
+ int direct; /* 0 if processing gzip, 1 if transparent */
+ /* just for reading */
+ int how; /* 0: get header, 1: copy, 2: decompress */
+ z_off64_t start; /* where the gzip data started, for rewinding */
+ int eof; /* true if end of input file reached */
+ int past; /* true if read requested past end */
+ /* just for writing */
+ int level; /* compression level */
+ int strategy; /* compression strategy */
+ int reset; /* true if a reset is pending after a Z_FINISH */
+ /* seek request */
+ z_off64_t skip; /* amount to skip (already rewound if backwards) */
+ int seek; /* true if seek request pending */
+ /* error information */
+ int err; /* error code */
+ char *msg; /* error message */
+ /* zlib inflate or deflate stream */
+ z_stream strm; /* stream structure in-place (not a pointer) */
+} gz_state;
+typedef gz_state FAR *gz_statep;
+
+/* shared functions */
+void ZLIB_INTERNAL gz_error(gz_statep, int, const char *);
+#if defined UNDER_CE
+char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
+#endif
+
+/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
+ value -- needed when comparing unsigned to z_off64_t, which is signed
+ (possible z_off64_t types off_t, off64_t, and long are all signed) */
+unsigned ZLIB_INTERNAL gz_intmax(void);
+#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
diff --git a/Sources/zlib-1.3.1/gzlib.c b/Sources/zlib-1.3.1/gzlib.c
new file mode 100644
index 00000000..983153cc
--- /dev/null
+++ b/Sources/zlib-1.3.1/gzlib.c
@@ -0,0 +1,582 @@
+/* gzlib.c -- zlib functions common to reading and writing gzip files
+ * Copyright (C) 2004-2024 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+#if defined(_WIN32) && !defined(__BORLANDC__)
+# define LSEEK _lseeki64
+#else
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+# define LSEEK lseek64
+#else
+# define LSEEK lseek
+#endif
+#endif
+
+#if defined UNDER_CE
+
+/* Map the Windows error number in ERROR to a locale-dependent error message
+ string and return a pointer to it. Typically, the values for ERROR come
+ from GetLastError.
+
+ The string pointed to shall not be modified by the application, but may be
+ overwritten by a subsequent call to gz_strwinerror
+
+ The gz_strwinerror function does not change the current setting of
+ GetLastError. */
+char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
+ static char buf[1024];
+
+ wchar_t *msgbuf;
+ DWORD lasterr = GetLastError();
+ DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL,
+ error,
+ 0, /* Default language */
+ (LPVOID)&msgbuf,
+ 0,
+ NULL);
+ if (chars != 0) {
+ /* If there is an \r\n appended, zap it. */
+ if (chars >= 2
+ && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
+ chars -= 2;
+ msgbuf[chars] = 0;
+ }
+
+ if (chars > sizeof (buf) - 1) {
+ chars = sizeof (buf) - 1;
+ msgbuf[chars] = 0;
+ }
+
+ wcstombs(buf, msgbuf, chars + 1);
+ LocalFree(msgbuf);
+ }
+ else {
+ sprintf(buf, "unknown win32 error (%ld)", error);
+ }
+
+ SetLastError(lasterr);
+ return buf;
+}
+
+#endif /* UNDER_CE */
+
+/* Reset gzip file state */
+local void gz_reset(gz_statep state) {
+ state->x.have = 0; /* no output data available */
+ if (state->mode == GZ_READ) { /* for reading ... */
+ state->eof = 0; /* not at end of file */
+ state->past = 0; /* have not read past end yet */
+ state->how = LOOK; /* look for gzip header */
+ }
+ else /* for writing ... */
+ state->reset = 0; /* no deflateReset pending */
+ state->seek = 0; /* no seek request pending */
+ gz_error(state, Z_OK, NULL); /* clear error */
+ state->x.pos = 0; /* no uncompressed data yet */
+ state->strm.avail_in = 0; /* no input data yet */
+}
+
+/* Open a gzip file either by name or file descriptor. */
+local gzFile gz_open(const void *path, int fd, const char *mode) {
+ gz_statep state;
+ z_size_t len;
+ int oflag;
+#ifdef O_CLOEXEC
+ int cloexec = 0;
+#endif
+#ifdef O_EXCL
+ int exclusive = 0;
+#endif
+
+ /* check input */
+ if (path == NULL)
+ return NULL;
+
+ /* allocate gzFile structure to return */
+ state = (gz_statep)malloc(sizeof(gz_state));
+ if (state == NULL)
+ return NULL;
+ state->size = 0; /* no buffers allocated yet */
+ state->want = GZBUFSIZE; /* requested buffer size */
+ state->msg = NULL; /* no error message yet */
+
+ /* interpret mode */
+ state->mode = GZ_NONE;
+ state->level = Z_DEFAULT_COMPRESSION;
+ state->strategy = Z_DEFAULT_STRATEGY;
+ state->direct = 0;
+ while (*mode) {
+ if (*mode >= '0' && *mode <= '9')
+ state->level = *mode - '0';
+ else
+ switch (*mode) {
+ case 'r':
+ state->mode = GZ_READ;
+ break;
+#ifndef NO_GZCOMPRESS
+ case 'w':
+ state->mode = GZ_WRITE;
+ break;
+ case 'a':
+ state->mode = GZ_APPEND;
+ break;
+#endif
+ case '+': /* can't read and write at the same time */
+ free(state);
+ return NULL;
+ case 'b': /* ignore -- will request binary anyway */
+ break;
+#ifdef O_CLOEXEC
+ case 'e':
+ cloexec = 1;
+ break;
+#endif
+#ifdef O_EXCL
+ case 'x':
+ exclusive = 1;
+ break;
+#endif
+ case 'f':
+ state->strategy = Z_FILTERED;
+ break;
+ case 'h':
+ state->strategy = Z_HUFFMAN_ONLY;
+ break;
+ case 'R':
+ state->strategy = Z_RLE;
+ break;
+ case 'F':
+ state->strategy = Z_FIXED;
+ break;
+ case 'T':
+ state->direct = 1;
+ break;
+ default: /* could consider as an error, but just ignore */
+ ;
+ }
+ mode++;
+ }
+
+ /* must provide an "r", "w", or "a" */
+ if (state->mode == GZ_NONE) {
+ free(state);
+ return NULL;
+ }
+
+ /* can't force transparent read */
+ if (state->mode == GZ_READ) {
+ if (state->direct) {
+ free(state);
+ return NULL;
+ }
+ state->direct = 1; /* for empty file */
+ }
+
+ /* save the path name for error messages */
+#ifdef WIDECHAR
+ if (fd == -2) {
+ len = wcstombs(NULL, path, 0);
+ if (len == (z_size_t)-1)
+ len = 0;
+ }
+ else
+#endif
+ len = strlen((const char *)path);
+ state->path = (char *)malloc(len + 1);
+ if (state->path == NULL) {
+ free(state);
+ return NULL;
+ }
+#ifdef WIDECHAR
+ if (fd == -2)
+ if (len)
+ wcstombs(state->path, path, len + 1);
+ else
+ *(state->path) = 0;
+ else
+#endif
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+ (void)snprintf(state->path, len + 1, "%s", (const char *)path);
+#else
+ strcpy(state->path, path);
+#endif
+
+ /* compute the flags for open() */
+ oflag =
+#ifdef O_LARGEFILE
+ O_LARGEFILE |
+#endif
+#ifdef O_BINARY
+ O_BINARY |
+#endif
+#ifdef O_CLOEXEC
+ (cloexec ? O_CLOEXEC : 0) |
+#endif
+ (state->mode == GZ_READ ?
+ O_RDONLY :
+ (O_WRONLY | O_CREAT |
+#ifdef O_EXCL
+ (exclusive ? O_EXCL : 0) |
+#endif
+ (state->mode == GZ_WRITE ?
+ O_TRUNC :
+ O_APPEND)));
+
+ /* open the file with the appropriate flags (or just use fd) */
+ state->fd = fd > -1 ? fd : (
+#ifdef WIDECHAR
+ fd == -2 ? _wopen(path, oflag, 0666) :
+#endif
+ open((const char *)path, oflag, 0666));
+ if (state->fd == -1) {
+ free(state->path);
+ free(state);
+ return NULL;
+ }
+ if (state->mode == GZ_APPEND) {
+ LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
+ state->mode = GZ_WRITE; /* simplify later checks */
+ }
+
+ /* save the current position for rewinding (only if reading) */
+ if (state->mode == GZ_READ) {
+ state->start = LSEEK(state->fd, 0, SEEK_CUR);
+ if (state->start == -1) state->start = 0;
+ }
+
+ /* initialize stream */
+ gz_reset(state);
+
+ /* return stream */
+ return (gzFile)state;
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen(const char *path, const char *mode) {
+ return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
+ return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzdopen(int fd, const char *mode) {
+ char *path; /* identifier for error messages */
+ gzFile gz;
+
+ if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
+ return NULL;
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+ (void)snprintf(path, 7 + 3 * sizeof(int), "", fd);
+#else
+ sprintf(path, "", fd); /* for debugging */
+#endif
+ gz = gz_open(path, fd, mode);
+ free(path);
+ return gz;
+}
+
+/* -- see zlib.h -- */
+#ifdef WIDECHAR
+gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
+ return gz_open(path, -2, mode);
+}
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzbuffer(gzFile file, unsigned size) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* make sure we haven't already allocated memory */
+ if (state->size != 0)
+ return -1;
+
+ /* check and set requested size */
+ if ((size << 1) < size)
+ return -1; /* need to be able to double it */
+ if (size < 8)
+ size = 8; /* needed to behave well with flushing */
+ state->want = size;
+ return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzrewind(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* back up and start over */
+ if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
+ return -1;
+ gz_reset(state);
+ return 0;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
+ unsigned n;
+ z_off64_t ret;
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* check that there's no error */
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+
+ /* can only seek from start or relative to current position */
+ if (whence != SEEK_SET && whence != SEEK_CUR)
+ return -1;
+
+ /* normalize offset to a SEEK_CUR specification */
+ if (whence == SEEK_SET)
+ offset -= state->x.pos;
+ else if (state->seek)
+ offset += state->skip;
+ state->seek = 0;
+
+ /* if within raw area while reading, just go there */
+ if (state->mode == GZ_READ && state->how == COPY &&
+ state->x.pos + offset >= 0) {
+ ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
+ if (ret == -1)
+ return -1;
+ state->x.have = 0;
+ state->eof = 0;
+ state->past = 0;
+ state->seek = 0;
+ gz_error(state, Z_OK, NULL);
+ state->strm.avail_in = 0;
+ state->x.pos += offset;
+ return state->x.pos;
+ }
+
+ /* calculate skip amount, rewinding if needed for back seek when reading */
+ if (offset < 0) {
+ if (state->mode != GZ_READ) /* writing -- can't go backwards */
+ return -1;
+ offset += state->x.pos;
+ if (offset < 0) /* before start of file! */
+ return -1;
+ if (gzrewind(file) == -1) /* rewind, then skip to offset */
+ return -1;
+ }
+
+ /* if reading, skip what's in output buffer (one less gzgetc() check) */
+ if (state->mode == GZ_READ) {
+ n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
+ (unsigned)offset : state->x.have;
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ offset -= n;
+ }
+
+ /* request skip (if not zero) */
+ if (offset) {
+ state->seek = 1;
+ state->skip = offset;
+ }
+ return state->x.pos + offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
+ z_off64_t ret;
+
+ ret = gzseek64(file, (z_off64_t)offset, whence);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gztell64(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* return position */
+ return state->x.pos + (state->seek ? state->skip : 0);
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gztell(gzFile file) {
+ z_off64_t ret;
+
+ ret = gztell64(file);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzoffset64(gzFile file) {
+ z_off64_t offset;
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* compute and return effective offset in file */
+ offset = LSEEK(state->fd, 0, SEEK_CUR);
+ if (offset == -1)
+ return -1;
+ if (state->mode == GZ_READ) /* reading */
+ offset -= state->strm.avail_in; /* don't count buffered input */
+ return offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzoffset(gzFile file) {
+ z_off64_t ret;
+
+ ret = gzoffset64(file);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzeof(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return 0;
+
+ /* return end-of-file state */
+ return state->mode == GZ_READ ? state->past : 0;
+}
+
+/* -- see zlib.h -- */
+const char * ZEXPORT gzerror(gzFile file, int *errnum) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return NULL;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return NULL;
+
+ /* return error information */
+ if (errnum != NULL)
+ *errnum = state->err;
+ return state->err == Z_MEM_ERROR ? "out of memory" :
+ (state->msg == NULL ? "" : state->msg);
+}
+
+/* -- see zlib.h -- */
+void ZEXPORT gzclearerr(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return;
+
+ /* clear error and end-of-file */
+ if (state->mode == GZ_READ) {
+ state->eof = 0;
+ state->past = 0;
+ }
+ gz_error(state, Z_OK, NULL);
+}
+
+/* Create an error message in allocated memory and set state->err and
+ state->msg accordingly. Free any previous error message already there. Do
+ not try to free or allocate space if the error is Z_MEM_ERROR (out of
+ memory). Simply save the error message as a static string. If there is an
+ allocation failure constructing the error message, then convert the error to
+ out of memory. */
+void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
+ /* free previously allocated message and clear */
+ if (state->msg != NULL) {
+ if (state->err != Z_MEM_ERROR)
+ free(state->msg);
+ state->msg = NULL;
+ }
+
+ /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
+ if (err != Z_OK && err != Z_BUF_ERROR)
+ state->x.have = 0;
+
+ /* set error code, and if no message, then done */
+ state->err = err;
+ if (msg == NULL)
+ return;
+
+ /* for an out of memory error, return literal string when requested */
+ if (err == Z_MEM_ERROR)
+ return;
+
+ /* construct error message with path */
+ if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
+ NULL) {
+ state->err = Z_MEM_ERROR;
+ return;
+ }
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+ (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
+ "%s%s%s", state->path, ": ", msg);
+#else
+ strcpy(state->msg, state->path);
+ strcat(state->msg, ": ");
+ strcat(state->msg, msg);
+#endif
+}
+
+/* portably return maximum value for an int (when limits.h presumed not
+ available) -- we need to do this to cover cases where 2's complement not
+ used, since C standard permits 1's complement and sign-bit representations,
+ otherwise we could just use ((unsigned)-1) >> 1 */
+unsigned ZLIB_INTERNAL gz_intmax(void) {
+#ifdef INT_MAX
+ return INT_MAX;
+#else
+ unsigned p = 1, q;
+ do {
+ q = p;
+ p <<= 1;
+ p++;
+ } while (p > q);
+ return q >> 1;
+#endif
+}
diff --git a/Sources/zlib-1.3.1/gzread.c b/Sources/zlib-1.3.1/gzread.c
new file mode 100644
index 00000000..4168cbc8
--- /dev/null
+++ b/Sources/zlib-1.3.1/gzread.c
@@ -0,0 +1,602 @@
+/* gzread.c -- zlib functions for reading gzip files
+ * Copyright (C) 2004-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
+ state->fd, and update state->eof, state->err, and state->msg as appropriate.
+ This function needs to loop on read(), since read() is not guaranteed to
+ read the number of bytes requested, depending on the type of descriptor. */
+local int gz_load(gz_statep state, unsigned char *buf, unsigned len,
+ unsigned *have) {
+ int ret;
+ unsigned get, max = ((unsigned)-1 >> 2) + 1;
+
+ *have = 0;
+ do {
+ get = len - *have;
+ if (get > max)
+ get = max;
+ ret = read(state->fd, buf + *have, get);
+ if (ret <= 0)
+ break;
+ *have += (unsigned)ret;
+ } while (*have < len);
+ if (ret < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ if (ret == 0)
+ state->eof = 1;
+ return 0;
+}
+
+/* Load up input buffer and set eof flag if last data loaded -- return -1 on
+ error, 0 otherwise. Note that the eof flag is set when the end of the input
+ file is reached, even though there may be unused data in the buffer. Once
+ that data has been used, no more attempts will be made to read the file.
+ If strm->avail_in != 0, then the current data is moved to the beginning of
+ the input buffer, and then the remainder of the buffer is loaded with the
+ available data from the input file. */
+local int gz_avail(gz_statep state) {
+ unsigned got;
+ z_streamp strm = &(state->strm);
+
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+ if (state->eof == 0) {
+ if (strm->avail_in) { /* copy what's there to the start */
+ unsigned char *p = state->in;
+ unsigned const char *q = strm->next_in;
+ unsigned n = strm->avail_in;
+ do {
+ *p++ = *q++;
+ } while (--n);
+ }
+ if (gz_load(state, state->in + strm->avail_in,
+ state->size - strm->avail_in, &got) == -1)
+ return -1;
+ strm->avail_in += got;
+ strm->next_in = state->in;
+ }
+ return 0;
+}
+
+/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
+ If this is the first time in, allocate required memory. state->how will be
+ left unchanged if there is no more input data available, will be set to COPY
+ if there is no gzip header and direct copying will be performed, or it will
+ be set to GZIP for decompression. If direct copying, then leftover input
+ data from the input buffer will be copied to the output buffer. In that
+ case, all further file reads will be directly to either the output buffer or
+ a user buffer. If decompressing, the inflate state will be initialized.
+ gz_look() will return 0 on success or -1 on failure. */
+local int gz_look(gz_statep state) {
+ z_streamp strm = &(state->strm);
+
+ /* allocate read buffers and inflate memory */
+ if (state->size == 0) {
+ /* allocate buffers */
+ state->in = (unsigned char *)malloc(state->want);
+ state->out = (unsigned char *)malloc(state->want << 1);
+ if (state->in == NULL || state->out == NULL) {
+ free(state->out);
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ state->size = state->want;
+
+ /* allocate inflate memory */
+ state->strm.zalloc = Z_NULL;
+ state->strm.zfree = Z_NULL;
+ state->strm.opaque = Z_NULL;
+ state->strm.avail_in = 0;
+ state->strm.next_in = Z_NULL;
+ if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
+ free(state->out);
+ free(state->in);
+ state->size = 0;
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ }
+
+ /* get at least the magic bytes in the input buffer */
+ if (strm->avail_in < 2) {
+ if (gz_avail(state) == -1)
+ return -1;
+ if (strm->avail_in == 0)
+ return 0;
+ }
+
+ /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
+ a logical dilemma here when considering the case of a partially written
+ gzip file, to wit, if a single 31 byte is written, then we cannot tell
+ whether this is a single-byte file, or just a partially written gzip
+ file -- for here we assume that if a gzip file is being written, then
+ the header will be written in a single operation, so that reading a
+ single byte is sufficient indication that it is not a gzip file) */
+ if (strm->avail_in > 1 &&
+ strm->next_in[0] == 31 && strm->next_in[1] == 139) {
+ inflateReset(strm);
+ state->how = GZIP;
+ state->direct = 0;
+ return 0;
+ }
+
+ /* no gzip header -- if we were decoding gzip before, then this is trailing
+ garbage. Ignore the trailing garbage and finish. */
+ if (state->direct == 0) {
+ strm->avail_in = 0;
+ state->eof = 1;
+ state->x.have = 0;
+ return 0;
+ }
+
+ /* doing raw i/o, copy any leftover input to output -- this assumes that
+ the output buffer is larger than the input buffer, which also assures
+ space for gzungetc() */
+ state->x.next = state->out;
+ memcpy(state->x.next, strm->next_in, strm->avail_in);
+ state->x.have = strm->avail_in;
+ strm->avail_in = 0;
+ state->how = COPY;
+ state->direct = 1;
+ return 0;
+}
+
+/* Decompress from input to the provided next_out and avail_out in the state.
+ On return, state->x.have and state->x.next point to the just decompressed
+ data. If the gzip stream completes, state->how is reset to LOOK to look for
+ the next gzip stream or raw data, once state->x.have is depleted. Returns 0
+ on success, -1 on failure. */
+local int gz_decomp(gz_statep state) {
+ int ret = Z_OK;
+ unsigned had;
+ z_streamp strm = &(state->strm);
+
+ /* fill output buffer up to end of deflate stream */
+ had = strm->avail_out;
+ do {
+ /* get more input for inflate() */
+ if (strm->avail_in == 0 && gz_avail(state) == -1)
+ return -1;
+ if (strm->avail_in == 0) {
+ gz_error(state, Z_BUF_ERROR, "unexpected end of file");
+ break;
+ }
+
+ /* decompress and handle errors */
+ ret = inflate(strm, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
+ gz_error(state, Z_STREAM_ERROR,
+ "internal error: inflate stream corrupt");
+ return -1;
+ }
+ if (ret == Z_MEM_ERROR) {
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
+ gz_error(state, Z_DATA_ERROR,
+ strm->msg == NULL ? "compressed data error" : strm->msg);
+ return -1;
+ }
+ } while (strm->avail_out && ret != Z_STREAM_END);
+
+ /* update available output */
+ state->x.have = had - strm->avail_out;
+ state->x.next = strm->next_out - state->x.have;
+
+ /* if the gzip stream completed successfully, look for another */
+ if (ret == Z_STREAM_END)
+ state->how = LOOK;
+
+ /* good decompression */
+ return 0;
+}
+
+/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
+ Data is either copied from the input file or decompressed from the input
+ file depending on state->how. If state->how is LOOK, then a gzip header is
+ looked for to determine whether to copy or decompress. Returns -1 on error,
+ otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
+ end of the input file has been reached and all data has been processed. */
+local int gz_fetch(gz_statep state) {
+ z_streamp strm = &(state->strm);
+
+ do {
+ switch(state->how) {
+ case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
+ if (gz_look(state) == -1)
+ return -1;
+ if (state->how == LOOK)
+ return 0;
+ break;
+ case COPY: /* -> COPY */
+ if (gz_load(state, state->out, state->size << 1, &(state->x.have))
+ == -1)
+ return -1;
+ state->x.next = state->out;
+ return 0;
+ case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
+ strm->avail_out = state->size << 1;
+ strm->next_out = state->out;
+ if (gz_decomp(state) == -1)
+ return -1;
+ }
+ } while (state->x.have == 0 && (!state->eof || strm->avail_in));
+ return 0;
+}
+
+/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
+local int gz_skip(gz_statep state, z_off64_t len) {
+ unsigned n;
+
+ /* skip over len bytes or reach end-of-file, whichever comes first */
+ while (len)
+ /* skip over whatever is in output buffer */
+ if (state->x.have) {
+ n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
+ (unsigned)len : state->x.have;
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ len -= n;
+ }
+
+ /* output buffer empty -- return if we're at the end of the input */
+ else if (state->eof && state->strm.avail_in == 0)
+ break;
+
+ /* need more data to skip -- load up output buffer */
+ else {
+ /* get more output, looking for header if required */
+ if (gz_fetch(state) == -1)
+ return -1;
+ }
+ return 0;
+}
+
+/* Read len bytes into buf from file, or less than len up to the end of the
+ input. Return the number of bytes read. If zero is returned, either the
+ end of file was reached, or there was an error. state->err must be
+ consulted in that case to determine which. */
+local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
+ z_size_t got;
+ unsigned n;
+
+ /* if len is zero, avoid unnecessary operations */
+ if (len == 0)
+ return 0;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return 0;
+ }
+
+ /* get len bytes to buf, or less than len if at the end */
+ got = 0;
+ do {
+ /* set n to the maximum amount of len that fits in an unsigned int */
+ n = (unsigned)-1;
+ if (n > len)
+ n = (unsigned)len;
+
+ /* first just try copying data from the output buffer */
+ if (state->x.have) {
+ if (state->x.have < n)
+ n = state->x.have;
+ memcpy(buf, state->x.next, n);
+ state->x.next += n;
+ state->x.have -= n;
+ }
+
+ /* output buffer empty -- return if we're at the end of the input */
+ else if (state->eof && state->strm.avail_in == 0) {
+ state->past = 1; /* tried to read past end */
+ break;
+ }
+
+ /* need output data -- for small len or new stream load up our output
+ buffer */
+ else if (state->how == LOOK || n < (state->size << 1)) {
+ /* get more output, looking for header if required */
+ if (gz_fetch(state) == -1)
+ return 0;
+ continue; /* no progress yet -- go back to copy above */
+ /* the copy above assures that we will leave with space in the
+ output buffer, allowing at least one gzungetc() to succeed */
+ }
+
+ /* large len -- read directly into user buffer */
+ else if (state->how == COPY) { /* read directly */
+ if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
+ return 0;
+ }
+
+ /* large len -- decompress directly into user buffer */
+ else { /* state->how == GZIP */
+ state->strm.avail_out = n;
+ state->strm.next_out = (unsigned char *)buf;
+ if (gz_decomp(state) == -1)
+ return 0;
+ n = state->x.have;
+ state->x.have = 0;
+ }
+
+ /* update progress */
+ len -= n;
+ buf = (char *)buf + n;
+ got += n;
+ state->x.pos += n;
+ } while (len);
+
+ /* return number of bytes read into user buffer */
+ return got;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* since an int is returned, make sure len fits in one, otherwise return
+ with an error (this avoids a flaw in the interface) */
+ if ((int)len < 0) {
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
+ return -1;
+ }
+
+ /* read len or fewer bytes to buf */
+ len = (unsigned)gz_read(state, buf, len);
+
+ /* check for an error */
+ if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+
+ /* return the number of bytes read (this is assured to fit in an int) */
+ return (int)len;
+}
+
+/* -- see zlib.h -- */
+z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) {
+ z_size_t len;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return 0;
+
+ /* compute bytes to read -- error on overflow */
+ len = nitems * size;
+ if (size && len / size != nitems) {
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
+ return 0;
+ }
+
+ /* read len or fewer bytes to buf, return the number of full items read */
+ return len ? gz_read(state, buf, len) / size : 0;
+}
+
+/* -- see zlib.h -- */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+#else
+# undef gzgetc
+#endif
+int ZEXPORT gzgetc(gzFile file) {
+ unsigned char buf[1];
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* try output buffer (no need to check for skip request) */
+ if (state->x.have) {
+ state->x.have--;
+ state->x.pos++;
+ return *(state->x.next)++;
+ }
+
+ /* nothing there -- try gz_read() */
+ return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
+}
+
+int ZEXPORT gzgetc_(gzFile file) {
+ return gzgetc(file);
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzungetc(int c, gzFile file) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* in case this was just opened, set up the input buffer */
+ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
+ (void)gz_look(state);
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* can't push EOF */
+ if (c < 0)
+ return -1;
+
+ /* if output buffer empty, put byte at end (allows more pushing) */
+ if (state->x.have == 0) {
+ state->x.have = 1;
+ state->x.next = state->out + (state->size << 1) - 1;
+ state->x.next[0] = (unsigned char)c;
+ state->x.pos--;
+ state->past = 0;
+ return c;
+ }
+
+ /* if no room, give up (must have already done a gzungetc()) */
+ if (state->x.have == (state->size << 1)) {
+ gz_error(state, Z_DATA_ERROR, "out of room to push characters");
+ return -1;
+ }
+
+ /* slide output data if needed and insert byte before existing data */
+ if (state->x.next == state->out) {
+ unsigned char *src = state->out + state->x.have;
+ unsigned char *dest = state->out + (state->size << 1);
+ while (src > state->out)
+ *--dest = *--src;
+ state->x.next = dest;
+ }
+ state->x.have++;
+ state->x.next--;
+ state->x.next[0] = (unsigned char)c;
+ state->x.pos--;
+ state->past = 0;
+ return c;
+}
+
+/* -- see zlib.h -- */
+char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
+ unsigned left, n;
+ char *str;
+ unsigned char *eol;
+ gz_statep state;
+
+ /* check parameters and get internal structure */
+ if (file == NULL || buf == NULL || len < 1)
+ return NULL;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return NULL;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return NULL;
+ }
+
+ /* copy output bytes up to new line or len - 1, whichever comes first --
+ append a terminating zero to the string (we don't check for a zero in
+ the contents, let the user worry about that) */
+ str = buf;
+ left = (unsigned)len - 1;
+ if (left) do {
+ /* assure that something is in the output buffer */
+ if (state->x.have == 0 && gz_fetch(state) == -1)
+ return NULL; /* error */
+ if (state->x.have == 0) { /* end of file */
+ state->past = 1; /* read past end */
+ break; /* return what we have */
+ }
+
+ /* look for end-of-line in current output buffer */
+ n = state->x.have > left ? left : state->x.have;
+ eol = (unsigned char *)memchr(state->x.next, '\n', n);
+ if (eol != NULL)
+ n = (unsigned)(eol - state->x.next) + 1;
+
+ /* copy through end-of-line, or remainder if not found */
+ memcpy(buf, state->x.next, n);
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ left -= n;
+ buf += n;
+ } while (left && eol == NULL);
+
+ /* return terminated string, or if nothing, end of file */
+ if (buf == str)
+ return NULL;
+ buf[0] = 0;
+ return str;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzdirect(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* if the state is not known, but we can find out, then do so (this is
+ mainly for right after a gzopen() or gzdopen()) */
+ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
+ (void)gz_look(state);
+
+ /* return 1 if transparent, 0 if processing a gzip stream */
+ return state->direct;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_r(gzFile file) {
+ int ret, err;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're reading */
+ if (state->mode != GZ_READ)
+ return Z_STREAM_ERROR;
+
+ /* free memory and close file */
+ if (state->size) {
+ inflateEnd(&(state->strm));
+ free(state->out);
+ free(state->in);
+ }
+ err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
+ gz_error(state, Z_OK, NULL);
+ free(state->path);
+ ret = close(state->fd);
+ free(state);
+ return ret ? Z_ERRNO : err;
+}
diff --git a/Sources/zlib-1.3.1/gzwrite.c b/Sources/zlib-1.3.1/gzwrite.c
new file mode 100644
index 00000000..435b4621
--- /dev/null
+++ b/Sources/zlib-1.3.1/gzwrite.c
@@ -0,0 +1,631 @@
+/* gzwrite.c -- zlib functions for writing gzip files
+ * Copyright (C) 2004-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Initialize state for writing a gzip file. Mark initialization by setting
+ state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
+ success. */
+local int gz_init(gz_statep state) {
+ int ret;
+ z_streamp strm = &(state->strm);
+
+ /* allocate input buffer (double size for gzprintf) */
+ state->in = (unsigned char *)malloc(state->want << 1);
+ if (state->in == NULL) {
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+
+ /* only need output buffer and deflate state if compressing */
+ if (!state->direct) {
+ /* allocate output buffer */
+ state->out = (unsigned char *)malloc(state->want);
+ if (state->out == NULL) {
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+
+ /* allocate deflate memory, set up for gzip compression */
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ ret = deflateInit2(strm, state->level, Z_DEFLATED,
+ MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
+ if (ret != Z_OK) {
+ free(state->out);
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ strm->next_in = NULL;
+ }
+
+ /* mark state as initialized */
+ state->size = state->want;
+
+ /* initialize write buffer if compressing */
+ if (!state->direct) {
+ strm->avail_out = state->size;
+ strm->next_out = state->out;
+ state->x.next = strm->next_out;
+ }
+ return 0;
+}
+
+/* Compress whatever is at avail_in and next_in and write to the output file.
+ Return -1 if there is an error writing to the output file or if gz_init()
+ fails to allocate memory, otherwise 0. flush is assumed to be a valid
+ deflate() flush value. If flush is Z_FINISH, then the deflate() state is
+ reset to start a new gzip stream. If gz->direct is true, then simply write
+ to the output file without compressing, and ignore flush. */
+local int gz_comp(gz_statep state, int flush) {
+ int ret, writ;
+ unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
+ z_streamp strm = &(state->strm);
+
+ /* allocate memory if this is the first time through */
+ if (state->size == 0 && gz_init(state) == -1)
+ return -1;
+
+ /* write directly if requested */
+ if (state->direct) {
+ while (strm->avail_in) {
+ put = strm->avail_in > max ? max : strm->avail_in;
+ writ = write(state->fd, strm->next_in, put);
+ if (writ < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ strm->avail_in -= (unsigned)writ;
+ strm->next_in += writ;
+ }
+ return 0;
+ }
+
+ /* check for a pending reset */
+ if (state->reset) {
+ /* don't start a new gzip member unless there is data to write */
+ if (strm->avail_in == 0)
+ return 0;
+ deflateReset(strm);
+ state->reset = 0;
+ }
+
+ /* run deflate() on provided input until it produces no more output */
+ ret = Z_OK;
+ do {
+ /* write out current buffer contents if full, or if flushing, but if
+ doing Z_FINISH then don't write until we get to Z_STREAM_END */
+ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
+ (flush != Z_FINISH || ret == Z_STREAM_END))) {
+ while (strm->next_out > state->x.next) {
+ put = strm->next_out - state->x.next > (int)max ? max :
+ (unsigned)(strm->next_out - state->x.next);
+ writ = write(state->fd, state->x.next, put);
+ if (writ < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ state->x.next += writ;
+ }
+ if (strm->avail_out == 0) {
+ strm->avail_out = state->size;
+ strm->next_out = state->out;
+ state->x.next = state->out;
+ }
+ }
+
+ /* compress */
+ have = strm->avail_out;
+ ret = deflate(strm, flush);
+ if (ret == Z_STREAM_ERROR) {
+ gz_error(state, Z_STREAM_ERROR,
+ "internal error: deflate stream corrupt");
+ return -1;
+ }
+ have -= strm->avail_out;
+ } while (have);
+
+ /* if that completed a deflate stream, allow another to start */
+ if (flush == Z_FINISH)
+ state->reset = 1;
+
+ /* all done, no errors */
+ return 0;
+}
+
+/* Compress len zeros to output. Return -1 on a write error or memory
+ allocation failure by gz_comp(), or 0 on success. */
+local int gz_zero(gz_statep state, z_off64_t len) {
+ int first;
+ unsigned n;
+ z_streamp strm = &(state->strm);
+
+ /* consume whatever's left in the input buffer */
+ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return -1;
+
+ /* compress len zeros (len guaranteed > 0) */
+ first = 1;
+ while (len) {
+ n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
+ (unsigned)len : state->size;
+ if (first) {
+ memset(state->in, 0, n);
+ first = 0;
+ }
+ strm->avail_in = n;
+ strm->next_in = state->in;
+ state->x.pos += n;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return -1;
+ len -= n;
+ }
+ return 0;
+}
+
+/* Write len bytes from buf to file. Return the number of bytes written. If
+ the returned value is less than len, then there was an error. */
+local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
+ z_size_t put = len;
+
+ /* if len is zero, avoid unnecessary operations */
+ if (len == 0)
+ return 0;
+
+ /* allocate memory if this is the first time through */
+ if (state->size == 0 && gz_init(state) == -1)
+ return 0;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return 0;
+ }
+
+ /* for small len, copy to input buffer, otherwise compress directly */
+ if (len < state->size) {
+ /* copy to input buffer, compress when full */
+ do {
+ unsigned have, copy;
+
+ if (state->strm.avail_in == 0)
+ state->strm.next_in = state->in;
+ have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
+ state->in);
+ copy = state->size - have;
+ if (copy > len)
+ copy = (unsigned)len;
+ memcpy(state->in + have, buf, copy);
+ state->strm.avail_in += copy;
+ state->x.pos += copy;
+ buf = (const char *)buf + copy;
+ len -= copy;
+ if (len && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+ } while (len);
+ }
+ else {
+ /* consume whatever's left in the input buffer */
+ if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+
+ /* directly compress user buffer to file */
+ state->strm.next_in = (z_const Bytef *)buf;
+ do {
+ unsigned n = (unsigned)-1;
+ if (n > len)
+ n = (unsigned)len;
+ state->strm.avail_in = n;
+ state->x.pos += n;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+ len -= n;
+ } while (len);
+ }
+
+ /* input was all buffered or compressed */
+ return put;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return 0;
+
+ /* since an int is returned, make sure len fits in one, otherwise return
+ with an error (this avoids a flaw in the interface) */
+ if ((int)len < 0) {
+ gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
+ return 0;
+ }
+
+ /* write len bytes from buf (the return value will fit in an int) */
+ return (int)gz_write(state, buf, len);
+}
+
+/* -- see zlib.h -- */
+z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
+ gzFile file) {
+ z_size_t len;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return 0;
+
+ /* compute bytes to read -- error on overflow */
+ len = nitems * size;
+ if (size && len / size != nitems) {
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
+ return 0;
+ }
+
+ /* write len bytes to buf, return the number of full items written */
+ return len ? gz_write(state, buf, len) / size : 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputc(gzFile file, int c) {
+ unsigned have;
+ unsigned char buf[1];
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return -1;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* try writing to input buffer for speed (state->size == 0 if buffer not
+ initialized) */
+ if (state->size) {
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
+ if (have < state->size) {
+ state->in[have] = (unsigned char)c;
+ strm->avail_in++;
+ state->x.pos++;
+ return c & 0xff;
+ }
+ }
+
+ /* no room in buffer or not initialized, use gz_write() */
+ buf[0] = (unsigned char)c;
+ if (gz_write(state, buf, 1) != 1)
+ return -1;
+ return c & 0xff;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputs(gzFile file, const char *s) {
+ z_size_t len, put;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return -1;
+
+ /* write string */
+ len = strlen(s);
+ if ((int)len < 0 || (unsigned)len != len) {
+ gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
+ return -1;
+ }
+ put = gz_write(state, s, len);
+ return put < len ? -1 : (int)len;
+}
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#include
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
+ int len;
+ unsigned left;
+ char *next;
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* make sure we have some buffer space */
+ if (state->size == 0 && gz_init(state) == -1)
+ return state->err;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->err;
+ }
+
+ /* do the printf() into the input buffer, put length in len -- the input
+ buffer is double-sized just for this function, so there is guaranteed to
+ be state->size bytes available after the current contents */
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
+ next[state->size - 1] = 0;
+#ifdef NO_vsnprintf
+# ifdef HAS_vsprintf_void
+ (void)vsprintf(next, format, va);
+ for (len = 0; len < state->size; len++)
+ if (next[len] == 0) break;
+# else
+ len = vsprintf(next, format, va);
+# endif
+#else
+# ifdef HAS_vsnprintf_void
+ (void)vsnprintf(next, state->size, format, va);
+ len = strlen(next);
+# else
+ len = vsnprintf(next, state->size, format, va);
+# endif
+#endif
+
+ /* check that printf() results fit in buffer */
+ if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
+ return 0;
+
+ /* update buffer and position, compress first half if past that */
+ strm->avail_in += (unsigned)len;
+ state->x.pos += len;
+ if (strm->avail_in >= state->size) {
+ left = strm->avail_in - state->size;
+ strm->avail_in = state->size;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return state->err;
+ memmove(state->in, state->in + state->size, left);
+ strm->next_in = state->in;
+ strm->avail_in = left;
+ }
+ return len;
+}
+
+int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
+ va_list va;
+ int ret;
+
+ va_start(va, format);
+ ret = gzvprintf(file, format, va);
+ va_end(va);
+ return ret;
+}
+
+#else /* !STDC && !Z_HAVE_STDARG_H */
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
+ int a4, int a5, int a6, int a7, int a8, int a9, int a10,
+ int a11, int a12, int a13, int a14, int a15, int a16,
+ int a17, int a18, int a19, int a20) {
+ unsigned len, left;
+ char *next;
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that can really pass pointer in ints */
+ if (sizeof(int) != sizeof(void *))
+ return Z_STREAM_ERROR;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* make sure we have some buffer space */
+ if (state->size == 0 && gz_init(state) == -1)
+ return state->error;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->error;
+ }
+
+ /* do the printf() into the input buffer, put length in len -- the input
+ buffer is double-sized just for this function, so there is guaranteed to
+ be state->size bytes available after the current contents */
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ next = (char *)(strm->next_in + strm->avail_in);
+ next[state->size - 1] = 0;
+#ifdef NO_snprintf
+# ifdef HAS_sprintf_void
+ sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
+ a13, a14, a15, a16, a17, a18, a19, a20);
+ for (len = 0; len < size; len++)
+ if (next[len] == 0)
+ break;
+# else
+ len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
+ a12, a13, a14, a15, a16, a17, a18, a19, a20);
+# endif
+#else
+# ifdef HAS_snprintf_void
+ snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+ len = strlen(next);
+# else
+ len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+# endif
+#endif
+
+ /* check that printf() results fit in buffer */
+ if (len == 0 || len >= state->size || next[state->size - 1] != 0)
+ return 0;
+
+ /* update buffer and position, compress first half if past that */
+ strm->avail_in += len;
+ state->x.pos += len;
+ if (strm->avail_in >= state->size) {
+ left = strm->avail_in - state->size;
+ strm->avail_in = state->size;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return state->err;
+ memmove(state->in, state->in + state->size, left);
+ strm->next_in = state->in;
+ strm->avail_in = left;
+ }
+ return (int)len;
+}
+
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzflush(gzFile file, int flush) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* check flush parameter */
+ if (flush < 0 || flush > Z_FINISH)
+ return Z_STREAM_ERROR;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->err;
+ }
+
+ /* compress remaining data with requested flush */
+ (void)gz_comp(state, flush);
+ return state->err;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
+ return Z_STREAM_ERROR;
+
+ /* if no change is requested, then do nothing */
+ if (level == state->level && strategy == state->strategy)
+ return Z_OK;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->err;
+ }
+
+ /* change compression parameters for subsequent input */
+ if (state->size) {
+ /* flush previous input with previous parameters before changing */
+ if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
+ return state->err;
+ deflateParams(strm, level, strategy);
+ }
+ state->level = level;
+ state->strategy = strategy;
+ return Z_OK;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_w(gzFile file) {
+ int ret = Z_OK;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're writing */
+ if (state->mode != GZ_WRITE)
+ return Z_STREAM_ERROR;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ ret = state->err;
+ }
+
+ /* flush, free memory, and close file */
+ if (gz_comp(state, Z_FINISH) == -1)
+ ret = state->err;
+ if (state->size) {
+ if (!state->direct) {
+ (void)deflateEnd(&(state->strm));
+ free(state->out);
+ }
+ free(state->in);
+ }
+ gz_error(state, Z_OK, NULL);
+ free(state->path);
+ if (close(state->fd) == -1)
+ ret = Z_ERRNO;
+ free(state);
+ return ret;
+}
diff --git a/Sources/zlib-1.3.1/include/zconf.h b/Sources/zlib-1.3.1/include/zconf.h
new file mode 100644
index 00000000..62adc8d8
--- /dev/null
+++ b/Sources/zlib-1.3.1/include/zconf.h
@@ -0,0 +1,543 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+# define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+# define _dist_code z__dist_code
+# define _length_code z__length_code
+# define _tr_align z__tr_align
+# define _tr_flush_bits z__tr_flush_bits
+# define _tr_flush_block z__tr_flush_block
+# define _tr_init z__tr_init
+# define _tr_stored_block z__tr_stored_block
+# define _tr_tally z__tr_tally
+# define adler32 z_adler32
+# define adler32_combine z_adler32_combine
+# define adler32_combine64 z_adler32_combine64
+# define adler32_z z_adler32_z
+# ifndef Z_SOLO
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# endif
+# define crc32 z_crc32
+# define crc32_combine z_crc32_combine
+# define crc32_combine64 z_crc32_combine64
+# define crc32_combine_gen z_crc32_combine_gen
+# define crc32_combine_gen64 z_crc32_combine_gen64
+# define crc32_combine_op z_crc32_combine_op
+# define crc32_z z_crc32_z
+# define deflate z_deflate
+# define deflateBound z_deflateBound
+# define deflateCopy z_deflateCopy
+# define deflateEnd z_deflateEnd
+# define deflateGetDictionary z_deflateGetDictionary
+# define deflateInit z_deflateInit
+# define deflateInit2 z_deflateInit2
+# define deflateInit2_ z_deflateInit2_
+# define deflateInit_ z_deflateInit_
+# define deflateParams z_deflateParams
+# define deflatePending z_deflatePending
+# define deflatePrime z_deflatePrime
+# define deflateReset z_deflateReset
+# define deflateResetKeep z_deflateResetKeep
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateSetHeader z_deflateSetHeader
+# define deflateTune z_deflateTune
+# define deflate_copyright z_deflate_copyright
+# define get_crc_table z_get_crc_table
+# ifndef Z_SOLO
+# define gz_error z_gz_error
+# define gz_intmax z_gz_intmax
+# define gz_strwinerror z_gz_strwinerror
+# define gzbuffer z_gzbuffer
+# define gzclearerr z_gzclearerr
+# define gzclose z_gzclose
+# define gzclose_r z_gzclose_r
+# define gzclose_w z_gzclose_w
+# define gzdirect z_gzdirect
+# define gzdopen z_gzdopen
+# define gzeof z_gzeof
+# define gzerror z_gzerror
+# define gzflush z_gzflush
+# define gzfread z_gzfread
+# define gzfwrite z_gzfwrite
+# define gzgetc z_gzgetc
+# define gzgetc_ z_gzgetc_
+# define gzgets z_gzgets
+# define gzoffset z_gzoffset
+# define gzoffset64 z_gzoffset64
+# define gzopen z_gzopen
+# define gzopen64 z_gzopen64
+# ifdef _WIN32
+# define gzopen_w z_gzopen_w
+# endif
+# define gzprintf z_gzprintf
+# define gzputc z_gzputc
+# define gzputs z_gzputs
+# define gzread z_gzread
+# define gzrewind z_gzrewind
+# define gzseek z_gzseek
+# define gzseek64 z_gzseek64
+# define gzsetparams z_gzsetparams
+# define gztell z_gztell
+# define gztell64 z_gztell64
+# define gzungetc z_gzungetc
+# define gzvprintf z_gzvprintf
+# define gzwrite z_gzwrite
+# endif
+# define inflate z_inflate
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define inflateBackInit z_inflateBackInit
+# define inflateBackInit_ z_inflateBackInit_
+# define inflateCodesUsed z_inflateCodesUsed
+# define inflateCopy z_inflateCopy
+# define inflateEnd z_inflateEnd
+# define inflateGetDictionary z_inflateGetDictionary
+# define inflateGetHeader z_inflateGetHeader
+# define inflateInit z_inflateInit
+# define inflateInit2 z_inflateInit2
+# define inflateInit2_ z_inflateInit2_
+# define inflateInit_ z_inflateInit_
+# define inflateMark z_inflateMark
+# define inflatePrime z_inflatePrime
+# define inflateReset z_inflateReset
+# define inflateReset2 z_inflateReset2
+# define inflateResetKeep z_inflateResetKeep
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateUndermine z_inflateUndermine
+# define inflateValidate z_inflateValidate
+# define inflate_copyright z_inflate_copyright
+# define inflate_fast z_inflate_fast
+# define inflate_table z_inflate_table
+# ifndef Z_SOLO
+# define uncompress z_uncompress
+# define uncompress2 z_uncompress2
+# endif
+# define zError z_zError
+# ifndef Z_SOLO
+# define zcalloc z_zcalloc
+# define zcfree z_zcfree
+# endif
+# define zlibCompileFlags z_zlibCompileFlags
+# define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+# define Byte z_Byte
+# define Bytef z_Bytef
+# define alloc_func z_alloc_func
+# define charf z_charf
+# define free_func z_free_func
+# ifndef Z_SOLO
+# define gzFile z_gzFile
+# endif
+# define gz_header z_gz_header
+# define gz_headerp z_gz_headerp
+# define in_func z_in_func
+# define intf z_intf
+# define out_func z_out_func
+# define uInt z_uInt
+# define uIntf z_uIntf
+# define uLong z_uLong
+# define uLongf z_uLongf
+# define voidp z_voidp
+# define voidpc z_voidpc
+# define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+# define gz_header_s z_gz_header_s
+# define internal_state z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+# define z_const const
+#else
+# define z_const
+#endif
+
+#ifdef Z_SOLO
+# ifdef _WIN64
+ typedef unsigned long long z_size_t;
+# else
+ typedef unsigned long z_size_t;
+# endif
+#else
+# define z_longlong long long
+# if defined(NO_SIZE_T)
+ typedef unsigned NO_SIZE_T z_size_t;
+# elif defined(STDC)
+# include
+ typedef size_t z_size_t;
+# else
+ typedef unsigned long z_size_t;
+# endif
+# undef z_longlong
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+# include
+# if (UINT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned
+# elif (ULONG_MAX == 0xffffffffUL)
+# define Z_U4 unsigned long
+# elif (USHRT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned short
+# endif
+#endif
+
+#ifdef Z_U4
+ typedef Z_U4 z_crc_t;
+#else
+ typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+# ifndef Z_SOLO
+# include /* for off_t */
+# endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+# include /* for va_list */
+# endif
+#endif
+
+#ifdef _WIN32
+# ifndef Z_SOLO
+# include /* for wchar_t */
+# endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#ifndef Z_HAVE_UNISTD_H
+# ifdef __WATCOMC__
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_HAVE_UNISTD_H
+# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_SOLO
+# if defined(Z_HAVE_UNISTD_H)
+# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+# ifdef VMS
+# include /* for off_t */
+# endif
+# ifndef z_off_t
+# define z_off_t off_t
+# endif
+# endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+# define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+# define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+# define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+# define z_off64_t off64_t
+#else
+# if defined(_WIN32) && !defined(__GNUC__)
+# define z_off64_t __int64
+# else
+# define z_off64_t z_off_t
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+ #pragma map(deflateInit_,"DEIN")
+ #pragma map(deflateInit2_,"DEIN2")
+ #pragma map(deflateEnd,"DEEND")
+ #pragma map(deflateBound,"DEBND")
+ #pragma map(inflateInit_,"ININ")
+ #pragma map(inflateInit2_,"ININ2")
+ #pragma map(inflateEnd,"INEND")
+ #pragma map(inflateSync,"INSY")
+ #pragma map(inflateSetDictionary,"INSEDI")
+ #pragma map(compressBound,"CMBND")
+ #pragma map(inflate_table,"INTABL")
+ #pragma map(inflate_fast,"INFA")
+ #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/Sources/zlib-1.3.1/include/zlib.h b/Sources/zlib-1.3.1/include/zlib.h
new file mode 100644
index 00000000..8d4b932e
--- /dev/null
+++ b/Sources/zlib-1.3.1/include/zlib.h
@@ -0,0 +1,1938 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.3.1, January 22nd, 2024
+
+ Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+ (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.3.1"
+#define ZLIB_VERNUM 0x1310
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 3
+#define ZLIB_VER_REVISION 1
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed data.
+ This version of the library supports only one compression method (deflation)
+ but other algorithms will be added later and will have the same stream
+ interface.
+
+ Compression can be done in a single step if the buffers are large enough,
+ or can be done by repeated calls of the compression function. In the latter
+ case, the application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip and raw deflate streams in
+ memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never crash
+ even in the case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size);
+typedef void (*free_func)(voidpf opaque, voidpf address);
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ z_const Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total number of input bytes read so far */
+
+ Bytef *next_out; /* next output byte will go here */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total number of bytes output so far */
+
+ z_const char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text
+ for deflate, or the decoding state for inflate */
+ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has dropped
+ to zero. It must update next_out and avail_out when avail_out has dropped
+ to zero. The application must initialize zalloc, zfree and opaque before
+ calling the init function. All other fields are set by the compression
+ library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe. In that case, zlib is thread-safe. When zalloc and zfree are
+ Z_NULL on entry to the initialization function, they are set to internal
+ routines that use the standard library functions malloc() and free().
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this if
+ the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers
+ returned by zalloc for objects of exactly 65536 bytes *must* have their
+ offset normalized to zero. The default allocation function provided by this
+ library ensures this (see zutil.c). To reduce memory requirements and avoid
+ any allocation of 64K objects, at the expense of compression ratio, compile
+ the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or progress
+ reports. After compression, total_in holds the total size of the
+ uncompressed data and may be saved for use by the decompressor (particularly
+ if the decompressor wants to decompress everything in a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+#define Z_TREES 6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field for deflate() */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion(void);
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is not
+ compatible with the zlib.h header file used by the application. This check
+ is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level);
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+ allocation functions. total_in, total_out, adler, and msg are initialized.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at all
+ (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION
+ requests a default compromise between speed and compression (currently
+ equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if level is not a valid compression level, or
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION). msg is set to null
+ if there is no error message. deflateInit does not perform any compression:
+ this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush);
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary. Some output may be provided even if
+ flush is zero.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating avail_in or avail_out accordingly; avail_out should
+ never be zero before the call. The application can consume the compressed
+ output when it wants, for example when the output buffer is full (avail_out
+ == 0), or after each call of deflate(). If deflate returns Z_OK and with
+ zero avail_out, it must be called again after making room in the output
+ buffer because there might be more output pending. See deflatePending(),
+ which can be used if desired to determine whether or not there is more output
+ in that case.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumulate before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In
+ particular avail_in is zero after the call if enough output space has been
+ provided before the call.) Flushing may degrade compression for some
+ compression algorithms and so it should be used only when necessary. This
+ completes the current deflate block and follows it with an empty stored block
+ that is three bits plus filler bits to the next byte, followed by four bytes
+ (00 00 ff ff).
+
+ If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+ output buffer, but the output is not aligned to a byte boundary. All of the
+ input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+ This completes the current deflate block and follows it with an empty fixed
+ codes block that is 10 bits long. This assures that enough bytes are output
+ in order for the decompressor to finish the block before the empty fixed
+ codes block.
+
+ If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+ for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+ seven bits of the current block are held to be written as the next byte after
+ the next deflate block is completed. In this case, the decompressor may not
+ be provided enough bits at this point in order to complete decompression of
+ the data provided so far to the compressor. It may need to wait for the next
+ block to be emitted. This is for advanced applications that need to control
+ the emission of deflate blocks.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six when the flush marker begins, in order to avoid
+ repeated flush markers upon calling deflate() again when avail_out == 0.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there was
+ enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this
+ function must be called again with Z_FINISH and more output space (updated
+ avail_out) but no more input data, until it returns with Z_STREAM_END or an
+ error. After deflate has returned Z_STREAM_END, the only possible operations
+ on the stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used in the first deflate call after deflateInit if all the
+ compression is to be done in a single step. In order to complete in one
+ call, avail_out must be at least the value returned by deflateBound (see
+ below). Then deflate is guaranteed to return Z_STREAM_END. If not enough
+ output space is provided, deflate will not return Z_STREAM_END, and it must
+ be called again as described above.
+
+ deflate() sets strm->adler to the Adler-32 checksum of all input read
+ so far (that is, total_in bytes). If a gzip stream is being generated, then
+ strm->adler will be the CRC-32 checksum of the input read so far. (See
+ deflateInit2 below.)
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is
+ considered binary. This field is only for information purposes and does not
+ affect the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was Z_NULL or the state was inadvertently written over
+ by the application), or Z_BUF_ERROR if no progress is possible (for example
+ avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and
+ deflate() can be called again with more input and more output space to
+ continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd(z_streamp strm);
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case, msg
+ may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit(z_streamp strm);
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. In the current version of inflate, the provided input is not
+ read or consumed. The allocation of a sliding window will be deferred to
+ the first call of inflate (if the decompression does not complete on the
+ first call). If zalloc and zfree are set to Z_NULL, inflateInit updates
+ them to use default allocation functions. total_in, total_out, adler, and
+ msg are initialized.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit does not perform any decompression.
+ Actual decompression will be done by inflate(). So next_in, and avail_in,
+ next_out, and avail_out are unused and unchanged. The current
+ implementation of inflateInit() does not process any header information --
+ that is deferred until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush);
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), then next_in and avail_in are updated
+ accordingly, and processing will resume at this point for the next call of
+ inflate().
+
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there is
+ no more input data or no more space in the output buffer (see below about
+ the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating the next_* and avail_* values accordingly. If the
+ caller of inflate() does not provide both available input and available
+ output space, it is possible that there will be no progress made. The
+ application can consume the uncompressed output when it wants, for example
+ when the output buffer is full (avail_out == 0), or after each call of
+ inflate(). If inflate returns Z_OK and with zero avail_out, it must be
+ called again after making room in the output buffer because there might be
+ more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+ Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate()
+ stop if and when it gets to the next deflate block boundary. When decoding
+ the zlib or gzip format, this will cause inflate() to return immediately
+ after the header and before the first block. When doing a raw inflate,
+ inflate() will go ahead and process the first block, and will return when it
+ gets to the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ To assist in this, on return inflate() always sets strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64 if
+ inflate() is currently decoding the last block in the deflate stream, plus
+ 128 if inflate() returned immediately after decoding an end-of-block code or
+ decoding the complete header up to just before the first byte of the deflate
+ stream. The end-of-block will not be indicated until all of the uncompressed
+ data from that block has been written to strm->next_out. The number of
+ unused bits may in general be greater than seven, except when bit 7 of
+ data_type is set, in which case the number of unused bits will be less than
+ eight. data_type is set as noted here every time inflate() returns for all
+ flush options, and so can be used to determine the amount of currently
+ consumed input in bits.
+
+ The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+ end of each deflate block header is reached, before any actual data in that
+ block is decoded. This allows the caller to determine the length of the
+ deflate block header for later use in random access within a deflate block.
+ 256 is added to the value of strm->data_type when inflate() returns
+ immediately after reaching the end of the deflate block header.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step (a
+ single call of inflate), the parameter flush should be set to Z_FINISH. In
+ this case all pending input is processed and all pending output is flushed;
+ avail_out must be large enough to hold all of the uncompressed data for the
+ operation to complete. (The size of the uncompressed data may have been
+ saved by the compressor for this purpose.) The use of Z_FINISH is not
+ required to perform an inflation in one step. However it may be used to
+ inform inflate that a faster approach can be used for the single inflate()
+ call. Z_FINISH also informs inflate to not maintain a sliding window if the
+ stream completes, which reduces inflate's memory footprint. If the stream
+ does not complete, either because not all of the stream is provided or not
+ enough output space is provided, then a sliding window will be allocated and
+ inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+ been used.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the effects of the flush parameter in this implementation are
+ on the return value of inflate() as noted below, when inflate() returns early
+ when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+ memory for a sliding window when Z_FINISH is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the Adler-32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed Adler-32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically, if requested when
+ initializing with inflateInit2(). Any information contained in the gzip
+ header is not retained unless inflateGetHeader() is used. When processing
+ gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+ produced so far. The CRC-32 is checked against the gzip trailer, as is the
+ uncompressed length, modulo 2^32.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value, in which case strm->msg points to a string with a more specific
+ error), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ next_in or next_out was Z_NULL, or the state was inadvertently written over
+ by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR
+ if no progress was possible or if there was not enough room in the output
+ buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may
+ then call inflateSync() to look for a good compression block if a partial
+ recovery of the data is to be attempted.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd(z_streamp strm);
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state
+ was inconsistent.
+*/
+
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2(z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy);
+
+ This is another version of deflateInit with more compression options. The
+ fields zalloc, zfree and opaque must be initialized before by the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ For the current implementation of deflate(), a windowBits value of 8 (a
+ window size of 256 bytes) is not supported. As a result, a request for 8
+ will result in 9 (a 512-byte window). In that case, providing 8 to
+ inflateInit2() will result in an error when the zlib header with 9 is
+ checked against the initialization of inflate(). The remedy is to not use 8
+ with deflateInit2() with this initialization, or at least in that case use 9
+ with inflateInit2().
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute a check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero), no
+ header crc, and the operating system will be set to the appropriate value,
+ if the operating system was determined at compile time. If a gzip stream is
+ being written, strm->adler is a CRC-32 instead of an Adler-32.
+
+ For raw deflate or gzip encoding, a request for a 256-byte window is
+ rejected as invalid, since only the zlib header provides a means of
+ transmitting the window size to the decompressor.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but is
+ slow and reduces compression ratio; memLevel=9 uses maximum memory for
+ optimal speed. The default value is 8. See zconf.h for total memory usage
+ as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as
+ fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The
+ strategy parameter only affects the compression ratio but not the
+ correctness of the compressed output even if it is not set appropriately.
+ Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+ decoder for special applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+ method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+ incompatible with the version assumed by the caller (ZLIB_VERSION). msg is
+ set to null if there is no error message. deflateInit2 does not perform any
+ compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. When using the zlib format, this
+ function must be called immediately after deflateInit, deflateInit2 or
+ deflateReset, and before any call of deflate. When doing raw deflate, this
+ function must be called either before any call of deflate, or immediately
+ after the completion of a deflate block, i.e. after all input has been
+ consumed and all output has been delivered when using any of the flush
+ options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
+ compressor and decompressor must use exactly the same dictionary (see
+ inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size
+ provided in deflateInit or deflateInit2. Thus the strings most likely to be
+ useful should be put at the end of the dictionary, not at the front. In
+ addition, the current implementation of deflate will use at most the window
+ size minus 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the Adler-32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler-32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ Adler-32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if not at a block boundary for raw deflate). deflateSetDictionary does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength);
+/*
+ Returns the sliding dictionary being maintained by deflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If deflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similarly, if dictLength is Z_NULL, then it is not set.
+
+ deflateGetDictionary() may return a length less than the window size, even
+ when more than the window size in input has been provided. It may return up
+ to 258 bytes less in that case, due to how zlib's implementation of deflate
+ manages the sliding window and lookahead for matches, where matches can be
+ up to 258 bytes long. If the application needs the last window-size bytes of
+ input, then that would need to be saved by the application outside of zlib.
+
+ deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateCopy(z_streamp dest,
+ z_streamp source);
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and can
+ consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset(z_streamp strm);
+/*
+ This function is equivalent to deflateEnd followed by deflateInit, but
+ does not free and reallocate the internal compression state. The stream
+ will leave the compression level and any other attributes that may have been
+ set unchanged. total_in, total_out, adler, and msg are initialized.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams(z_streamp strm,
+ int level,
+ int strategy);
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2(). This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different strategy.
+ If the compression approach (which is a function of the level) or the
+ strategy is changed, and if there have been any deflate() calls since the
+ state was initialized or reset, then the input available so far is
+ compressed with the old level and strategy using deflate(strm, Z_BLOCK).
+ There are three approaches for the compression levels 0, 1..3, and 4..9
+ respectively. The new level and strategy will take effect at the next call
+ of deflate().
+
+ If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
+ not have enough output space to complete, then the parameter change will not
+ take effect. In this case, deflateParams() can be called again with the
+ same parameters and more output space to try again.
+
+ In order to assure a change in the parameters on the first try, the
+ deflate stream should be flushed using deflate() with Z_BLOCK or other flush
+ request until strm.avail_out is not zero, before calling deflateParams().
+ Then no more input data should be provided before the deflateParams() call.
+ If this is done, the old level and strategy will be applied to the data
+ compressed before deflateParams(), and the new level and strategy will be
+ applied to the data compressed after deflateParams().
+
+ deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
+ state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
+ there was not enough output space to complete the compression of the
+ available input data before a change in the strategy or approach. Note that
+ in the case of a Z_BUF_ERROR, the parameters are not changed. A return
+ value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be
+ retried with more output space.
+*/
+
+ZEXTERN int ZEXPORT deflateTune(z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain);
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm,
+ uLong sourceLen);
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit() or
+ deflateInit2(), and after deflateSetHeader(), if used. This would be used
+ to allocate an output buffer for deflation in a single pass, and so would be
+ called before deflate(). If that first deflate() call is provided the
+ sourceLen input bytes, an output buffer allocated to the size returned by
+ deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+ to return Z_STREAM_END. Note that it is possible for the compressed size to
+ be larger than the value returned by deflateBound() if flush options other
+ than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending(z_streamp strm,
+ unsigned *pending,
+ int *bits);
+/*
+ deflatePending() returns the number of bytes and bits of output that have
+ been generated, but not yet provided in the available output. The bytes not
+ provided would be due to the available output space having being consumed.
+ The number of bits of output not provided are between 0 and 7, where they
+ await more bits to join them in order to fill out a full byte. If pending
+ or bits are Z_NULL, then those values are not set.
+
+ deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime(z_streamp strm,
+ int bits,
+ int value);
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the bits
+ leftover from a previous deflate stream when appending to it. As such, this
+ function can only be used for raw deflate, and must be used before the first
+ deflate() call after a deflateInit2() or deflateReset(). bits must be less
+ than or equal to 16, and that many of the least significant bits of value
+ will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+ room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm,
+ gz_headerp head);
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to the current operating system, with no
+ extra, name, or comment fields. The gzip header is returned to the default
+ state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2(z_streamp strm,
+ int windowBits);
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be zero to request that inflate use the window size in
+ the zlib header of the compressed stream.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an Adler-32 or a CRC-32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
+ CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
+ below), inflate() will *not* automatically decode concatenated gzip members.
+ inflate() will return Z_STREAM_END at the end of the gzip member. The state
+ would need to be reset to continue decoding a subsequent gzip member. This
+ *must* be done if there is more data after a gzip member, in order for the
+ decompression to be compliant with the gzip standard (RFC 1952).
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit2 does not perform any decompression
+ apart from possibly reading the zlib header if present: actual decompression
+ will be done by inflate(). (So next_in and avail_in may be modified, but
+ next_out and avail_out are unused and unchanged.) The current implementation
+ of inflateInit2() does not process any header information -- that is
+ deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler-32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called at any
+ time to set the dictionary. If the provided dictionary is smaller than the
+ window and there is already data in the window, then the provided dictionary
+ will amend what's there. The application must insure that the dictionary
+ that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler-32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength);
+/*
+ Returns the sliding dictionary being maintained by inflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If inflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similarly, if dictLength is Z_NULL, then it is not set.
+
+ inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateSync(z_streamp strm);
+/*
+ Skips invalid compressed data until a possible full flush point (see above
+ for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+ All full flush points have this pattern, but not all occurrences of this
+ pattern are full flush points.
+
+ inflateSync returns Z_OK if a possible full flush point has been found,
+ Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+ has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+ In the success case, the application may save the current value of total_in
+ which indicates where valid compressed data was found. In the error case,
+ the application may repeatedly call inflateSync, providing more input each
+ time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
+ z_streamp source);
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset(z_streamp strm);
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate the internal decompression state. The
+ stream will keep attributes that may have been set by inflateInit2.
+ total_in, total_out, adler, and msg are initialized.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2(z_streamp strm,
+ int windowBits);
+/*
+ This function is the same as inflateReset, but it also permits changing
+ the wrap and window size requests. The windowBits parameter is interpreted
+ the same as it is for inflateInit2. If the window size is changed, then the
+ memory allocated for the window is freed, and the window will be reallocated
+ by inflate() if needed.
+
+ inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+ the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime(z_streamp strm,
+ int bits,
+ int value);
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ If bits is negative, then the input stream bit buffer is emptied. Then
+ inflatePrime() can be called again to put bits in the buffer. This is used
+ to clear out bits leftover after feeding inflate a block description prior
+ to feeding inflate codes.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark(z_streamp strm);
+/*
+ This function returns two values, one in the lower 16 bits of the return
+ value, and the other in the remaining upper bits, obtained by shifting the
+ return value down 16 bits. If the upper value is -1 and the lower value is
+ zero, then inflate() is currently decoding information outside of a block.
+ If the upper value is -1 and the lower value is non-zero, then inflate is in
+ the middle of a stored block, with the lower value equaling the number of
+ bytes from the input remaining to copy. If the upper value is not -1, then
+ it is the number of bits back from the current bit position in the input of
+ the code (literal or length/distance pair) currently being processed. In
+ that case the lower value is the number of bytes already emitted for that
+ code.
+
+ A code is being processed if inflate is waiting for more input to complete
+ decoding of the code, or if it has completed decoding but is waiting for
+ more output space to write the literal or match data.
+
+ inflateMark() is used to mark locations in the input data for random
+ access, which may be at bit positions, and to note those cases where the
+ output of a code may span boundaries of random access blocks. The current
+ location in the input stream can be determined from avail_in and data_type
+ as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+ inflateMark returns the value noted above, or -65536 if the provided
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm,
+ gz_headerp head);
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be
+ used to force inflate() to return immediately after header processing is
+ complete and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When any
+ of extra, name, or comment are not Z_NULL and the respective field is not
+ present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits,
+ unsigned char FAR *window);
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+ allocated, or Z_VERSION_ERROR if the version of the library does not match
+ the version of the header file.
+*/
+
+typedef unsigned (*in_func)(void FAR *,
+ z_const unsigned char FAR * FAR *);
+typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned);
+
+ZEXTERN int ZEXPORT inflateBack(z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc);
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is potentially more efficient than
+ inflate() for file i/o applications, in that it avoids copying between the
+ output and the sliding window by simply making the window itself the output
+ buffer. inflate() can be faster on modern CPUs when used with large
+ buffers. inflateBack() trusts the application to not change the output
+ buffer passed by the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free the
+ allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects only
+ the raw deflate stream to decompress. This is different from the default
+ behavior of inflate(), which expects a zlib header and trailer around the
+ deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero -- buf is ignored in that
+ case -- and inflateBack() will return a buffer error. inflateBack() will
+ call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].
+ out() should return zero on success, or non-zero on failure. If out()
+ returns non-zero, inflateBack() will return with an error. Neither in() nor
+ out() are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+ in the deflate stream (in which case strm->msg is set to indicate the nature
+ of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+ In the case of Z_BUF_ERROR, an input or output error can be distinguished
+ using strm->next_in which will be Z_NULL only if in() returned an error. If
+ strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+ non-zero. (in() will always be called before out(), so strm->next_in is
+ assured to be defined if out() returns non-zero.) Note that inflateBack()
+ cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm);
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags(void);
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: ZLIB_DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the basic
+ stream-oriented functions. To simplify the interface, some default options
+ are assumed (compression level and memory usage, standard memory allocation
+ functions). The source code of these utility functions can be modified if
+ you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data. compress() is equivalent to compress2() with a level
+ parameter of Z_DEFAULT_COMPRESSION.
+
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level);
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen);
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before a
+ compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit, destLen
+ is the actual size of the uncompressed data.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
+ the case where there is not enough room, uncompress() will fill the output
+ buffer with the uncompressed data up to that point.
+*/
+
+ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong *sourceLen);
+/*
+ Same as uncompress, except that sourceLen is a pointer, where the
+ length of the source is *sourceLen. On return, *sourceLen is the number of
+ source bytes consumed.
+*/
+
+ /* gzip file access functions */
+
+/*
+ This library supports reading and writing files in gzip (.gz) format with
+ an interface similar to that of stdio, using the functions that start with
+ "gz". The gzip format is different from the zlib format. gzip is a gzip
+ wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode);
+
+ Open the gzip (.gz) file at path for reading and decompressing, or
+ compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
+ but can also include a compression level ("wb9") or a strategy: 'f' for
+ filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
+ 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
+ as in "wb9F". (See the description of deflateInit2 for more information
+ about the strategy parameter.) 'T' will request transparent writing or
+ appending with no compression and not using the gzip format.
+
+ "a" can be used instead of "w" to request that the gzip stream that will
+ be written be appended to the file. "+" will result in an error, since
+ reading and writing to the same gzip file is not supported. The addition of
+ "x" when writing will create the file exclusively, which fails if the file
+ already exists. On systems that support it, the addition of "e" when
+ reading or writing will set the flag to close the file on an execve() call.
+
+ These functions, as well as gzip, will read and decode a sequence of gzip
+ streams in a file. The append function of gzopen() can be used to create
+ such a file. (Also see gzflush() for another way to do this.) When
+ appending, gzopen does not test whether the file begins with a gzip stream,
+ nor does it look for the end of the gzip streams to begin appending. gzopen
+ will simply append a gzip stream to the existing file.
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression. When
+ reading, this will be detected automatically by looking for the magic two-
+ byte gzip header.
+
+ gzopen returns NULL if the file could not be opened, if there was
+ insufficient memory to allocate the gzFile state, or if an invalid mode was
+ specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+ errno can be checked to determine if the reason gzopen failed was that the
+ file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode);
+/*
+ Associate a gzFile with the file descriptor fd. File descriptors are
+ obtained from calls like open, dup, creat, pipe or fileno (if the file has
+ been previously opened with fopen). The mode parameter is as in gzopen.
+
+ The next call of gzclose on the returned gzFile will also close the file
+ descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+ fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+ mode);. The duplicated descriptor should be saved to avoid a leak, since
+ gzdopen does not close fd if it fails. If you are using fileno() to get the
+ file descriptor from a FILE *, then you will have to use dup() to avoid
+ double-close()ing the file descriptor. Both gzclose() and fclose() will
+ close the associated file descriptor, so they need to have different file
+ descriptors.
+
+ gzdopen returns NULL if there was insufficient memory to allocate the
+ gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+ provided, or '+' was provided), or if fd is -1. The file descriptor is not
+ used until the next gz* read, write, seek, or close operation, so gzdopen
+ will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size);
+/*
+ Set the internal buffer size used by this library's functions for file to
+ size. The default buffer size is 8192 bytes. This function must be called
+ after gzopen() or gzdopen(), and before any other calls that read or write
+ the file. The buffer memory allocation is always deferred to the first read
+ or write. Three times that size in buffer space is allocated. A larger
+ buffer size of, for example, 64K or 128K bytes will noticeably increase the
+ speed of decompression (reading).
+
+ The new buffer size also affects the maximum length for gzprintf().
+
+ gzbuffer() returns 0 on success, or -1 on failure, such as being called
+ too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy);
+/*
+ Dynamically update the compression level and strategy for file. See the
+ description of deflateInit2 for the meaning of these parameters. Previously
+ provided data is flushed before applying the parameter changes.
+
+ gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
+ opened for writing, Z_ERRNO if there is an error writing the flushed data,
+ or Z_MEM_ERROR if there is a memory allocation error.
+*/
+
+ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len);
+/*
+ Read and decompress up to len uncompressed bytes from file into buf. If
+ the input file is not in gzip format, gzread copies the given number of
+ bytes into the buffer directly from the file.
+
+ After reaching the end of a gzip stream in the input, gzread will continue
+ to read, looking for another gzip stream. Any number of gzip streams may be
+ concatenated in the input file, and will all be decompressed by gzread().
+ If something other than a gzip stream is encountered after a gzip stream,
+ that remaining trailing garbage is ignored (and no error is returned).
+
+ gzread can be used to read a gzip file that is being concurrently written.
+ Upon reaching the end of the input, gzread will return with the available
+ data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+ gzclearerr can be used to clear the end of file indicator in order to permit
+ gzread to be tried again. Z_OK indicates that a gzip stream was completed
+ on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
+ middle of a gzip stream. Note that gzread does not return -1 in the event
+ of an incomplete gzip stream. This error is deferred until gzclose(), which
+ will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+ stream. Alternatively, gzerror can be used before gzclose to detect this
+ case.
+
+ gzread returns the number of uncompressed bytes actually read, less than
+ len for end of file, or -1 for error. If len is too large to fit in an int,
+ then nothing is read, -1 is returned, and the error state is set to
+ Z_STREAM_ERROR.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems,
+ gzFile file);
+/*
+ Read and decompress up to nitems items of size size from file into buf,
+ otherwise operating as gzread() does. This duplicates the interface of
+ stdio's fread(), with size_t request and return types. If the library
+ defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
+ is an unsigned integer type that can contain a pointer.
+
+ gzfread() returns the number of full items read of size size, or zero if
+ the end of the file was reached and a full item could not be read, or if
+ there was an error. gzerror() must be consulted if zero is returned in
+ order to determine if there was an error. If the multiplication of size and
+ nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
+ is read, zero is returned, and the error state is set to Z_STREAM_ERROR.
+
+ In the event that the end of file is reached and only a partial item is
+ available at the end, i.e. the remaining uncompressed data length is not a
+ multiple of size, then the final partial item is nevertheless read into buf
+ and the end-of-file flag is set. The length of the partial item read is not
+ provided, but could be inferred from the result of gztell(). This behavior
+ is the same as the behavior of fread() implementations in common libraries,
+ but it prevents the direct use of gzfread() to read a concurrently written
+ file, resetting and retrying on end-of-file, when size is not 1.
+*/
+
+ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len);
+/*
+ Compress and write the len uncompressed bytes at buf to file. gzwrite
+ returns the number of uncompressed bytes written or 0 in case of error.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size,
+ z_size_t nitems, gzFile file);
+/*
+ Compress and write nitems items of size size from buf to file, duplicating
+ the interface of stdio's fwrite(), with size_t request and return types. If
+ the library defines size_t, then z_size_t is identical to size_t. If not,
+ then z_size_t is an unsigned integer type that can contain a pointer.
+
+ gzfwrite() returns the number of full items written of size size, or zero
+ if there was an error. If the multiplication of size and nitems overflows,
+ i.e. the product does not fit in a z_size_t, then nothing is written, zero
+ is returned, and the error state is set to Z_STREAM_ERROR.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...);
+/*
+ Convert, format, compress, and write the arguments (...) to file under
+ control of the string format, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written, or a negative zlib error code in case
+ of error. The number of uncompressed bytes written is limited to 8191, or
+ one less than the buffer size given to gzbuffer(). The caller should assure
+ that this limit is not exceeded. If it is exceeded, then gzprintf() will
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf(),
+ because the secure snprintf() or vsnprintf() functions were not available.
+ This can be determined using zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s);
+/*
+ Compress and write the given null-terminated string s to file, excluding
+ the terminating null character.
+
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len);
+/*
+ Read and decompress bytes from file into buf, until len-1 characters are
+ read, or until a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. If any characters are read or if len
+ is one, the string is terminated with a null character. If no characters
+ are read due to an end-of-file or len is less than one, then the buffer is
+ left untouched.
+
+ gzgets returns buf which is a null-terminated string, or it returns NULL
+ for end-of-file or in case of error. If there was an error, the contents at
+ buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc(gzFile file, int c);
+/*
+ Compress and write c, converted to an unsigned char, into file. gzputc
+ returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc(gzFile file);
+/*
+ Read and decompress one byte from file. gzgetc returns this byte or -1
+ in case of end of file or error. This is implemented as a macro for speed.
+ As such, it does not do all of the checking the other functions do. I.e.
+ it does not check to see if file is NULL, nor whether the structure file
+ points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc(int c, gzFile file);
+/*
+ Push c back onto the stream for file to be read as the first character on
+ the next read. At least one character of push-back is always allowed.
+ gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
+ fail if c is -1, and may fail if a character has been pushed but not read
+ yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
+ output buffer size of pushed characters is allowed. (See gzbuffer above.)
+ The pushed character will be discarded if the stream is repositioned with
+ gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush(gzFile file, int flush);
+/*
+ Flush all pending output to file. The parameter flush is as in the
+ deflate() function. The return value is the zlib error number (see function
+ gzerror below). gzflush is only permitted when writing.
+
+ If the flush parameter is Z_FINISH, the remaining data is written and the
+ gzip stream is completed in the output. If gzwrite() is called again, a new
+ gzip stream will be started in the output. gzread() is able to read such
+ concatenated gzip streams.
+
+ gzflush should be called only when strictly necessary because it will
+ degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek(gzFile file,
+ z_off_t offset, int whence);
+
+ Set the starting position to offset relative to whence for the next gzread
+ or gzwrite on file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind(gzFile file);
+/*
+ Rewind file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gztell(gzFile file);
+
+ Return the starting position for the next gzread or gzwrite on file.
+ This position represents a number of bytes in the uncompressed data stream,
+ and is zero when starting, even if appending or reading a gzip stream from
+ the middle of a file using gzdopen().
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file);
+
+ Return the current compressed (actual) read or write offset of file. This
+ offset includes the count of bytes that precede the gzip stream, for example
+ when appending or when using gzdopen() for reading. When reading, the
+ offset does not include as yet unused buffered input. This information can
+ be used for a progress indicator. On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof(gzFile file);
+/*
+ Return true (1) if the end-of-file indicator for file has been set while
+ reading, false (0) otherwise. Note that the end-of-file indicator is set
+ only if the read tried to go past the end of the input, but came up short.
+ Therefore, just like feof(), gzeof() may return false even if there is no
+ more data to read, in the event that the last read request was for the exact
+ number of bytes remaining in the input file. This will happen if the input
+ file size is an exact multiple of the buffer size.
+
+ If gzeof() returns true, then the read functions will return no more data,
+ unless the end-of-file indicator is reset by gzclearerr() and the input file
+ has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect(gzFile file);
+/*
+ Return true (1) if file is being copied directly while reading, or false
+ (0) if file is a gzip stream being decompressed.
+
+ If the input file is empty, gzdirect() will return true, since the input
+ does not contain a gzip stream.
+
+ If gzdirect() is used immediately after gzopen() or gzdopen() it will
+ cause buffers to be allocated to allow reading the file to determine if it
+ is a gzip file. Therefore if gzbuffer() is used, it should be called before
+ gzdirect().
+
+ When writing, gzdirect() returns true (1) if transparent writing was
+ requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
+ gzdirect() is not needed when writing. Transparent writing must be
+ explicitly requested, so the application already knows the answer. When
+ linking statically, using gzdirect() will include all of the zlib code for
+ gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT gzclose(gzFile file);
+/*
+ Flush all pending output for file, if necessary, close file and
+ deallocate the (de)compression state. Note that once file is closed, you
+ cannot call gzerror with file, since its structures have been deallocated.
+ gzclose must not be called more than once on the same file, just as free
+ must not be called more than once on the same allocation.
+
+ gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+ file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+ last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r(gzFile file);
+ZEXTERN int ZEXPORT gzclose_w(gzFile file);
+/*
+ Same as gzclose(), but gzclose_r() is only for use when reading, and
+ gzclose_w() is only for use when writing or appending. The advantage to
+ using these instead of gzclose() is that they avoid linking in zlib
+ compression or decompression code that is not used when only reading or only
+ writing respectively. If gzclose() is used, then both compression and
+ decompression code will be included the application when linking to a static
+ zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum);
+/*
+ Return the error message for the last error which occurred on file.
+ errnum is set to zlib error number. If an error occurred in the file system
+ and not in the compression library, errnum is set to Z_ERRNO and the
+ application may consult errno to get the exact error code.
+
+ The application must not modify the returned string. Future calls to
+ this function may invalidate the previously returned string. If file is
+ closed, then the string previously returned by gzerror will no longer be
+ available.
+
+ gzerror() should be used to distinguish errors from end-of-file for those
+ functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr(gzFile file);
+/*
+ Clear the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the compression
+ library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len);
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. An Adler-32 value is in the range of a 32-bit
+ unsigned integer. If buf is Z_NULL, this function returns the required
+ initial value for the checksum.
+
+ An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
+ much faster.
+
+ Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf,
+ z_size_t len);
+/*
+ Same as adler32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2,
+ z_off_t len2);
+
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
+ that the z_off_t type (like off_t) is a signed integer. If len2 is
+ negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len);
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
+ If buf is Z_NULL, this function returns the required initial value for the
+ crc. Pre- and post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the application.
+
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf,
+ z_size_t len);
+/*
+ Same as crc32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2);
+
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2. len2 must be non-negative.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
+
+ Return the operator corresponding to length len2, to be used with
+ crc32_combine_op(). len2 must be non-negative.
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
+/*
+ Give the same result as crc32_combine(), using op in place of len2. op is
+ is generated from len2 by crc32_combine_gen(). This will be faster than
+ crc32_combine() if the generated op is used more than once.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level,
+ const char *version, int stream_size);
+ZEXTERN int ZEXPORT inflateInit_(z_streamp strm,
+ const char *version, int stream_size);
+ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size);
+ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
+ const char *version, int stream_size);
+ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size);
+#ifdef Z_PREFIX_SET
+# define z_deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define z_inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#else
+# define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#endif
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure. Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro. The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously. They can
+ * only be used by the gzgetc() macro. You have been warned.
+ */
+struct gzFile_s {
+ unsigned have;
+ unsigned char *next;
+ z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+# define z_gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#else
+# define gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+ ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
+ ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
+ ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
+ ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t);
+ ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t);
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+# ifdef Z_PREFIX_SET
+# define z_gzopen z_gzopen64
+# define z_gzseek z_gzseek64
+# define z_gztell z_gztell64
+# define z_gzoffset z_gzoffset64
+# define z_adler32_combine z_adler32_combine64
+# define z_crc32_combine z_crc32_combine64
+# define z_crc32_combine_gen z_crc32_combine_gen64
+# else
+# define gzopen gzopen64
+# define gzseek gzseek64
+# define gztell gztell64
+# define gzoffset gzoffset64
+# define adler32_combine adler32_combine64
+# define crc32_combine crc32_combine64
+# define crc32_combine_gen crc32_combine_gen64
+# endif
+# ifndef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+ ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int);
+ ZEXTERN z_off_t ZEXPORT gztell64(gzFile);
+ ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile);
+ ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
+# endif
+#else
+ ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *);
+ ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int);
+ ZEXTERN z_off_t ZEXPORT gztell(gzFile);
+ ZEXTERN z_off_t ZEXPORT gzoffset(gzFile);
+ ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
+#endif
+
+#else /* Z_SOLO */
+
+ ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
+
+#endif /* !Z_SOLO */
+
+/* undocumented functions */
+ZEXTERN const char * ZEXPORT zError(int);
+ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp);
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void);
+ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int);
+ZEXTERN int ZEXPORT inflateValidate(z_streamp, int);
+ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp);
+ZEXTERN int ZEXPORT inflateResetKeep(z_streamp);
+ZEXTERN int ZEXPORT deflateResetKeep(z_streamp);
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path,
+ const char *mode);
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+ZEXTERN int ZEXPORTVA gzvprintf(gzFile file,
+ const char *format,
+ va_list va);
+# endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/Sources/zlib-1.3.1/infback.c b/Sources/zlib-1.3.1/infback.c
new file mode 100644
index 00000000..e7b25b30
--- /dev/null
+++ b/Sources/zlib-1.3.1/infback.c
@@ -0,0 +1,628 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ This code is largely copied from inflate.c. Normally either infback.o or
+ inflate.o would be linked into an application--not both. The interface
+ with inffast.c is retained so that optimized assembler-coded versions of
+ inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/*
+ strm provides memory allocation functions in zalloc and zfree, or
+ Z_NULL to use the library memory allocation functions.
+
+ windowBits is in the range 8..15, and window is a user-supplied
+ window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
+ unsigned char FAR *window, const char *version,
+ int stream_size) {
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL || window == Z_NULL ||
+ windowBits < 8 || windowBits > 15)
+ return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+ sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->dmax = 32768U;
+ state->wbits = (uInt)windowBits;
+ state->wsize = 1U << windowBits;
+ state->window = window;
+ state->wnext = 0;
+ state->whave = 0;
+ state->sane = 1;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(struct inflate_state FAR *state) {
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Assure that some input is available. If input is requested, but denied,
+ then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+ do { \
+ if (have == 0) { \
+ have = in(in_desc, &next); \
+ if (have == 0) { \
+ next = Z_NULL; \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+ with an error if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ PULL(); \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflateBack() with
+ an error. */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Assure that some output space is available, by writing out the window
+ if it's full. If the write fails, return from inflateBack() with a
+ Z_BUF_ERROR. */
+#define ROOM() \
+ do { \
+ if (left == 0) { \
+ put = state->window; \
+ left = state->wsize; \
+ state->whave = left; \
+ if (out(out_desc, put, left)) { \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/*
+ strm provides the memory allocation functions and window buffer on input,
+ and provides information on the unused input on return. For Z_DATA_ERROR
+ returns, strm will also provide an error message.
+
+ in() and out() are the call-back input and output functions. When
+ inflateBack() needs more input, it calls in(). When inflateBack() has
+ filled the window with output, or when it completes with data in the
+ window, it calls out() to write out the data. The application must not
+ change the provided input until in() is called again or inflateBack()
+ returns. The application must not change the window/output buffer until
+ inflateBack() returns.
+
+ in() and out() are called with a descriptor parameter provided in the
+ inflateBack() call. This parameter can be a structure that provides the
+ information required to do the read or write, as well as accumulated
+ information on the input and output such as totals and check values.
+
+ in() should return zero on failure. out() should return non-zero on
+ failure. If either in() or out() fails, than inflateBack() returns a
+ Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
+ was in() or out() that caused in the error. Otherwise, inflateBack()
+ returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+ error, or Z_MEM_ERROR if it could not allocate memory for the state.
+ inflateBack() can also return Z_STREAM_ERROR if the input parameters
+ are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc) {
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ /* Check that the strm exists and that the state was initialized */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* Reset the state */
+ strm->msg = Z_NULL;
+ state->mode = TYPE;
+ state->last = 0;
+ state->whave = 0;
+ next = strm->next_in;
+ have = next != Z_NULL ? strm->avail_in : 0;
+ hold = 0;
+ bits = 0;
+ put = state->window;
+ left = state->wsize;
+
+ /* Inflate until end of block marked as last */
+ for (;;)
+ switch (state->mode) {
+ case TYPE:
+ /* determine and dispatch block type */
+ if (state->last) {
+ BYTEBITS();
+ state->mode = DONE;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+
+ case STORED:
+ /* get and verify stored block length */
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+
+ /* copy stored block from input to output */
+ while (state->length != 0) {
+ copy = state->length;
+ PULL();
+ ROOM();
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+
+ case TABLE:
+ /* get dynamic table entries descriptor */
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+
+ /* get code length code lengths (not a typo) */
+ state->have = 0;
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+
+ /* get length and distance code code lengths */
+ state->have = 0;
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = (unsigned)(state->lens[state->have - 1]);
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ /* fallthrough */
+
+ case LEN:
+ /* use inflate_fast() if we have enough input and output */
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ if (state->whave < state->wsize)
+ state->whave = state->wsize - left;
+ inflate_fast(strm, state->wsize);
+ LOAD();
+ break;
+ }
+
+ /* get a literal, length, or end-of-block code */
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ state->length = (unsigned)here.val;
+
+ /* process literal */
+ if (here.op == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ ROOM();
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ }
+
+ /* process end of block */
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+
+ /* invalid code */
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+
+ /* length code -- get extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+
+ /* get distance code */
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+
+ /* get distance extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ if (state->offset > state->wsize - (state->whave < state->wsize ?
+ left : 0)) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+
+ /* copy match from window to output */
+ do {
+ ROOM();
+ copy = state->wsize - state->offset;
+ if (copy < left) {
+ from = put + copy;
+ copy = left - copy;
+ }
+ else {
+ from = put - state->offset;
+ copy = left;
+ }
+ if (copy > state->length) copy = state->length;
+ state->length -= copy;
+ left -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ } while (state->length != 0);
+ break;
+
+ case DONE:
+ /* inflate stream terminated properly */
+ ret = Z_STREAM_END;
+ goto inf_leave;
+
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+
+ default:
+ /* can't happen, but makes compilers happy */
+ ret = Z_STREAM_ERROR;
+ goto inf_leave;
+ }
+
+ /* Write leftover output and return unused input */
+ inf_leave:
+ if (left < state->wsize) {
+ if (out(out_desc, state->window, state->wsize - left) &&
+ ret == Z_STREAM_END)
+ ret = Z_BUF_ERROR;
+ }
+ strm->next_in = next;
+ strm->avail_in = have;
+ return ret;
+}
+
+int ZEXPORT inflateBackEnd(z_streamp strm) {
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
diff --git a/Sources/zlib-1.3.1/inffast.c b/Sources/zlib-1.3.1/inffast.c
new file mode 100644
index 00000000..9354676e
--- /dev/null
+++ b/Sources/zlib-1.3.1/inffast.c
@@ -0,0 +1,320 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef ASMINF
+# pragma message("Assembler code may have bugs -- use at your own risk")
+#else
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *in; /* local strm->next_in */
+ z_const unsigned char FAR *last; /* have enough input while in < last */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code const *here; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ wnext = state->wnext;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ here = lcode + (hold & lmask);
+ dolen:
+ op = (unsigned)(here->bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here->op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here->val));
+ *out++ = (unsigned char)(here->val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(here->val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ here = dcode + (hold & dmask);
+ dodist:
+ op = (unsigned)(here->bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here->op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(here->val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ if (state->sane) {
+ strm->msg =
+ (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ if (len <= op - whave) {
+ do {
+ *out++ = 0;
+ } while (--len);
+ continue;
+ }
+ len -= op - whave;
+ do {
+ *out++ = 0;
+ } while (--op > whave);
+ if (op == 0) {
+ from = out - dist;
+ do {
+ *out++ = *from++;
+ } while (--len);
+ continue;
+ }
+#endif
+ }
+ from = window;
+ if (wnext == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (wnext < op) { /* wrap around window */
+ from += wsize + wnext - op;
+ op -= wnext;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = window;
+ if (wnext < len) { /* some from start of window */
+ op = wnext;
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += wnext - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ *out++ = *from++;
+ *out++ = *from++;
+ *out++ = *from++;
+ len -= 3;
+ }
+ if (len) {
+ *out++ = *from++;
+ if (len > 1)
+ *out++ = *from++;
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ *out++ = *from++;
+ *out++ = *from++;
+ *out++ = *from++;
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ *out++ = *from++;
+ if (len > 1)
+ *out++ = *from++;
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ here = dcode + here->val + (hold & ((1U << op) - 1));
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ here = lcode + here->val + (hold & ((1U << op) - 1));
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in;
+ strm->next_out = out;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and wnext == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/Sources/zlib-1.3.1/inffast.h b/Sources/zlib-1.3.1/inffast.h
new file mode 100644
index 00000000..49c6d156
--- /dev/null
+++ b/Sources/zlib-1.3.1/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start);
diff --git a/Sources/zlib-1.3.1/inffixed.h b/Sources/zlib-1.3.1/inffixed.h
new file mode 100644
index 00000000..d6283277
--- /dev/null
+++ b/Sources/zlib-1.3.1/inffixed.h
@@ -0,0 +1,94 @@
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
+
+ /* WARNING: this file should *not* be used by applications.
+ It is part of the implementation of this library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/Sources/zlib-1.3.1/inflate.c b/Sources/zlib-1.3.1/inflate.c
new file mode 100644
index 00000000..94ecff01
--- /dev/null
+++ b/Sources/zlib-1.3.1/inflate.c
@@ -0,0 +1,1526 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0 24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ * creation of window when not needed, minimize use of window when it is
+ * needed, make inffast.c even faster, implement gzip decoding, and to
+ * improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1 25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2 4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ * to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3 22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ * buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4 1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ * source file infback.c to provide a call-back interface to inflate for
+ * programs like gzip and unzip -- uses window as output buffer to avoid
+ * window copying
+ *
+ * 1.2.beta5 1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ * input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6 4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ * make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7 27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0 9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ * for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ * and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+
+local int inflateStateCheck(z_streamp strm) {
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+ return 1;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state == Z_NULL || state->strm != strm ||
+ state->mode < HEAD || state->mode > SYNC)
+ return 1;
+ return 0;
+}
+
+int ZEXPORT inflateResetKeep(z_streamp strm) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ if (state->wrap) /* to support ill-conceived Java test suite */
+ strm->adler = state->wrap & 1;
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->flags = -1;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ state->sane = 1;
+ state->back = -1;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateReset(z_streamp strm) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ state->wsize = 0;
+ state->whave = 0;
+ state->wnext = 0;
+ return inflateResetKeep(strm);
+}
+
+int ZEXPORT inflateReset2(z_streamp strm, int windowBits) {
+ int wrap;
+ struct inflate_state FAR *state;
+
+ /* get the state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* extract wrap request from windowBits parameter */
+ if (windowBits < 0) {
+ if (windowBits < -15)
+ return Z_STREAM_ERROR;
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ wrap = (windowBits >> 4) + 5;
+#ifdef GUNZIP
+ if (windowBits < 48)
+ windowBits &= 15;
+#endif
+ }
+
+ /* set number of window bits, free window if different */
+ if (windowBits && (windowBits < 8 || windowBits > 15))
+ return Z_STREAM_ERROR;
+ if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+ ZFREE(strm, state->window);
+ state->window = Z_NULL;
+ }
+
+ /* update state and reset the rest of it */
+ state->wrap = wrap;
+ state->wbits = (unsigned)windowBits;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
+ const char *version, int stream_size) {
+ int ret;
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->strm = strm;
+ state->window = Z_NULL;
+ state->mode = HEAD; /* to pass state test in inflateReset2() */
+ ret = inflateReset2(strm, windowBits);
+ if (ret != Z_OK) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ }
+ return ret;
+}
+
+int ZEXPORT inflateInit_(z_streamp strm, const char *version,
+ int stream_size) {
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ if (bits == 0)
+ return Z_OK;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits < 0) {
+ state->hold = 0;
+ state->bits = 0;
+ return Z_OK;
+ }
+ if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += (unsigned)value << state->bits;
+ state->bits += (uInt)bits;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(struct inflate_state FAR *state) {
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include
+
+/*
+ Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
+ defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
+ those tables to stdout, which would be piped to inffixed.h. A small program
+ can simply call makefixed to do this:
+
+ void makefixed(void);
+
+ int main(void)
+ {
+ makefixed();
+ return 0;
+ }
+
+ Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+ a.out > inffixed.h
+ */
+void makefixed(void)
+{
+ unsigned low, size;
+ struct inflate_state state;
+
+ fixedtables(&state);
+ puts(" /* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts(" /* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf(" static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+ state.lencode[low].bits, state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+ size = 1U << 5;
+ printf("\n static const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+}
+#endif /* MAKEFIXED */
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) {
+ struct inflate_state FAR *state;
+ unsigned dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->wnext = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, end - state->wsize, state->wsize);
+ state->wnext = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->wnext;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->wnext, end - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, end - copy, copy);
+ state->wnext = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->wnext += dist;
+ if (state->wnext == state->wsize) state->wnext = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE_CHECK(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(z_streamp strm, int flush) {
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ if (state->wbits == 0)
+ state->wbits = 15;
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (state->wbits == 0)
+ state->wbits = len;
+ if (len > 15 || len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ state->flags = 0; /* indicate zlib header */
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ /* fallthrough */
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ /* fallthrough */
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ /* fallthrough */
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ /* fallthrough */
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL &&
+ (len = state->head->extra_len - state->length) <
+ state->head->extra_max) {
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ /* fallthrough */
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ /* fallthrough */
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ /* fallthrough */
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = ZSWAP32(hold);
+ INITBITS();
+ state->mode = DICT;
+ /* fallthrough */
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ /* fallthrough */
+ case TYPE:
+ if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN_; /* decode codes */
+ if (flush == Z_TREES) {
+ DROPBITS(2);
+ goto inf_leave;
+ }
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY_;
+ if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
+ case COPY_:
+ state->mode = COPY;
+ /* fallthrough */
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ /* fallthrough */
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (const code FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ /* fallthrough */
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (const code FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (const code FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN_;
+ if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
+ case LEN_:
+ state->mode = LEN;
+ /* fallthrough */
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ if (state->mode == TYPE)
+ state->back = -1;
+ break;
+ }
+ state->back = 0;
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ state->length = (unsigned)here.val;
+ if ((int)(here.op) == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ state->mode = LIT;
+ break;
+ }
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->back = -1;
+ state->mode = TYPE;
+ break;
+ }
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = LENEXT;
+ /* fallthrough */
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->was = state->length;
+ state->mode = DIST;
+ /* fallthrough */
+ case DIST:
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = DISTEXT;
+ /* fallthrough */
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ /* fallthrough */
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->whave) {
+ if (state->sane) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ Trace((stderr, "inflate.c too far\n"));
+ copy -= state->whave;
+ if (copy > state->length) copy = state->length;
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = 0;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+#endif
+ }
+ if (copy > state->wnext) {
+ copy -= state->wnext;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->wnext - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if ((state->wrap & 4) && out)
+ strm->adler = state->check =
+ UPDATE_CHECK(state->check, put - out, out);
+ out = left;
+ if ((state->wrap & 4) && (
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ ZSWAP32(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ /* fallthrough */
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ /* fallthrough */
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ /* fallthrough */
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+ (state->mode < CHECK || flush != Z_FINISH)))
+ if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if ((state->wrap & 4) && out)
+ strm->adler = state->check =
+ UPDATE_CHECK(state->check, strm->next_out - out, out);
+ strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0) +
+ (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(z_streamp strm) {
+ struct inflate_state FAR *state;
+ if (inflateStateCheck(strm))
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
+ uInt *dictLength) {
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* copy dictionary */
+ if (state->whave && dictionary != Z_NULL) {
+ zmemcpy(dictionary, state->window + state->wnext,
+ state->whave - state->wnext);
+ zmemcpy(dictionary + state->whave - state->wnext,
+ state->window, state->wnext);
+ }
+ if (dictLength != Z_NULL)
+ *dictLength = state->whave;
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
+ uInt dictLength) {
+ struct inflate_state FAR *state;
+ unsigned long dictid;
+ int ret;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary identifier */
+ if (state->mode == DICT) {
+ dictid = adler32(0L, Z_NULL, 0);
+ dictid = adler32(dictid, dictionary, dictLength);
+ if (dictid != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window using updatewindow(), which will amend the
+ existing dictionary if appropriate */
+ ret = updatewindow(strm, dictionary + dictLength, dictLength);
+ if (ret) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) {
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf,
+ unsigned len) {
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(z_streamp strm) {
+ unsigned len; /* number of bytes to look at or looked at */
+ int flags; /* temporary to save header status */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold >>= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ if (state->flags == -1)
+ state->wrap = 0; /* if no header yet, treat as raw */
+ else
+ state->wrap &= ~4; /* no point in computing a check value now */
+ flags = state->flags;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->flags = flags;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(z_streamp strm) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (inflateStateCheck(source) || dest == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+ zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+ copy->strm = dest;
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(z_streamp strm, int subvert) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ state->sane = !subvert;
+ return Z_OK;
+#else
+ (void)subvert;
+ state->sane = 1;
+ return Z_DATA_ERROR;
+#endif
+}
+
+int ZEXPORT inflateValidate(z_streamp strm, int check) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (check && state->wrap)
+ state->wrap |= 4;
+ else
+ state->wrap &= ~4;
+ return Z_OK;
+}
+
+long ZEXPORT inflateMark(z_streamp strm) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm))
+ return -(1L << 16);
+ state = (struct inflate_state FAR *)strm->state;
+ return (long)(((unsigned long)((long)state->back)) << 16) +
+ (state->mode == COPY ? state->length :
+ (state->mode == MATCH ? state->was - state->length : 0));
+}
+
+unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) {
+ struct inflate_state FAR *state;
+ if (inflateStateCheck(strm)) return (unsigned long)-1;
+ state = (struct inflate_state FAR *)strm->state;
+ return (unsigned long)(state->next - state->codes);
+}
diff --git a/Sources/zlib-1.3.1/inflate.h b/Sources/zlib-1.3.1/inflate.h
new file mode 100644
index 00000000..f127b6b1
--- /dev/null
+++ b/Sources/zlib-1.3.1/inflate.h
@@ -0,0 +1,126 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD = 16180, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY_, /* i/o: same as COPY below, but only first time in */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN_, /* i: same as LEN below, but only first time in */
+ LEN, /* i: waiting for length/lit/eob code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to BAD or MEM on error -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib) or (raw)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+ HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ (raw) -> TYPEDO
+ Read deflate blocks:
+ TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+ STORED -> COPY_ -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN_
+ LEN_ -> LEN
+ Read deflate codes in fixed or dynamic block:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* State maintained between inflate() calls -- approximately 7K bytes, not
+ including the allocated sliding window, which is up to 32K bytes. */
+struct inflate_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
+ bit 2 true to validate check value */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags, 0 if zlib, or
+ -1 if raw or no header yet */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+ int sane; /* if false, allow invalid distance too far */
+ int back; /* bits back of last unprocessed length/lit */
+ unsigned was; /* initial length of match */
+};
diff --git a/Sources/zlib-1.3.1/inftrees.c b/Sources/zlib-1.3.1/inftrees.c
new file mode 100644
index 00000000..98cfe164
--- /dev/null
+++ b/Sources/zlib-1.3.1/inftrees.c
@@ -0,0 +1,299 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2024 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work) {
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code here; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ unsigned match; /* use base and extra for symbol >= match */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)1;
+ here.val = (unsigned short)0;
+ *(*table)++ = here; /* make a table to force an error */
+ *(*table)++ = here;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min < max; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked for LENS and DIST tables against
+ the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+ the initial root table size constants. See the comments in inftrees.h
+ for more information.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ match = 20;
+ break;
+ case LENS:
+ base = lbase;
+ extra = lext;
+ match = 257;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ match = 0;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if ((type == LENS && used > ENOUGH_LENS) ||
+ (type == DISTS && used > ENOUGH_DISTS))
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ here.bits = (unsigned char)(len - drop);
+ if (work[sym] + 1U < match) {
+ here.op = (unsigned char)0;
+ here.val = work[sym];
+ }
+ else if (work[sym] >= match) {
+ here.op = (unsigned char)(extra[work[sym] - match]);
+ here.val = base[work[sym] - match];
+ }
+ else {
+ here.op = (unsigned char)(32 + 64); /* end of block */
+ here.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = here;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1U << curr;
+ if ((type == LENS && used > ENOUGH_LENS) ||
+ (type == DISTS && used > ENOUGH_DISTS))
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /* fill in remaining table entry if code is incomplete (guaranteed to have
+ at most one remaining entry, since if the code is incomplete, the
+ maximum code length that was allowed to get this far is one bit) */
+ if (huff != 0) {
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)(len - drop);
+ here.val = (unsigned short)0;
+ next[huff] = here;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
diff --git a/Sources/zlib-1.3.1/inftrees.h b/Sources/zlib-1.3.1/inftrees.h
new file mode 100644
index 00000000..396f74b5
--- /dev/null
+++ b/Sources/zlib-1.3.1/inftrees.h
@@ -0,0 +1,62 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of the dynamic table. The maximum number of code structures is
+ 1444, which is the sum of 852 for literal/length codes and 592 for distance
+ codes. These values were found by exhaustive searches using the program
+ examples/enough.c found in the zlib distribution. The arguments to that
+ program are the number of symbols, the initial root table size, and the
+ maximum bit length of a code. "enough 286 9 15" for literal/length codes
+ returns 852, and "enough 30 6 15" for distance codes returns 592. The
+ initial root table size (9 or 6) is found in the fifth argument of the
+ inflate_table() calls in inflate.c and infback.c. If the root table size is
+ changed, then these maximum sizes would be need to be recalculated and
+ updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
+
+/* Type of code to build for inflate_table() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work);
diff --git a/Sources/zlib-1.3.1/trees.c b/Sources/zlib-1.3.1/trees.c
new file mode 100644
index 00000000..6a523ef3
--- /dev/null
+++ b/Sources/zlib-1.3.1/trees.c
@@ -0,0 +1,1117 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2024 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef ZLIB_DEBUG
+# include
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+#ifdef NO_INIT_GLOBAL_POINTERS
+# define TCONST
+#else
+# define TCONST const
+#endif
+
+local TCONST static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local TCONST static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local TCONST static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(unsigned code, int len) {
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(deflate_state *s) {
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(deflate_state *s) {
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef ZLIB_DEBUG
+ s->bits_sent = (s->bits_sent + 7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) {
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ unsigned code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ code = (code + bl_count[bits - 1]) << 1;
+ next_code[bits] = (ush)code;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1));
+ }
+}
+
+#ifdef GEN_TREES_H
+local void gen_trees_header(void);
+#endif
+
+#ifndef ZLIB_DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* !ZLIB_DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef ZLIB_DEBUG
+local void send_bits(deflate_state *s, int value, int length) {
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !ZLIB_DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = (int)value;\
+ s->bi_buf |= (ush)val << s->bi_valid;\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (ush)(value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* ZLIB_DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init(void) {
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+#endif
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1 << extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length - 1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1 << extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256 + dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Generate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef ZLIB_DEBUG
+# include
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width) - 1 ? ",\n" : ", "))
+
+void gen_trees_header(void) {
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header,
+ "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(deflate_state *s) {
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->sym_next = s->matches = 0;
+}
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void ZLIB_INTERNAL _tr_init(deflate_state *s) {
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef ZLIB_DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(deflate_state *s, ct_data *tree, int k) {
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(deflate_state *s, tree_desc *desc) {
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max + 1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n - base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (unsigned)(bits + xbits);
+ if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Tracev((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length - 1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
+ Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+#ifdef DUMP_BL_TREE
+# include
+#endif
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(deflate_state *s, tree_desc *desc) {
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+ s->depth[n] : s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree(deflate_state *s, ct_data *tree, int max_code) {
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code + 1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n + 1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree(deflate_state *s, ct_data *tree, int max_code) {
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code + 1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n + 1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(deflate_state *s) {
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except the
+ * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(deflate_state *s, int lcodes, int dcodes,
+ int blcodes) {
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes - 1, 5);
+ send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
+ ulg stored_len, int last) {
+ send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */
+ bi_windup(s); /* align on byte boundary */
+ put_short(s, (ush)stored_len);
+ put_short(s, (ush)~stored_len);
+ if (stored_len)
+ zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
+ s->pending += stored_len;
+#ifdef ZLIB_DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+ s->bits_sent += 2*16;
+ s->bits_sent += stored_len << 3;
+#endif
+}
+
+/* ===========================================================================
+ * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
+ */
+void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) {
+ bi_flush(s);
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ */
+void ZLIB_INTERNAL _tr_align(deflate_state *s) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(deflate_state *s, const ct_data *ltree,
+ const ct_data *dtree) {
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned sx = 0; /* running index in symbol buffers */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->sym_next != 0) do {
+#ifdef LIT_MEM
+ dist = s->d_buf[sx];
+ lc = s->l_buf[sx++];
+#else
+ dist = s->sym_buf[sx++] & 0xff;
+ dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
+ lc = s->sym_buf[sx++];
+#endif
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code + LITERALS + 1, ltree); /* send length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= (unsigned)base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check for no overlay of pending_buf on needed symbols */
+#ifdef LIT_MEM
+ Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow");
+#else
+ Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
+#endif
+
+ } while (sx < s->sym_next);
+
+ send_code(s, END_BLOCK, ltree);
+}
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ * a) There are no non-portable control characters belonging to the
+ * "block list" (0..6, 14..25, 28..31).
+ * b) There is at least one printable character belonging to the
+ * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ * "gray list" that is ignored in this detection algorithm:
+ * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local int detect_data_type(deflate_state *s) {
+ /* block_mask is the bit mask of block-listed bytes
+ * set bits 0..6, 14..25, and 28..31
+ * 0xf3ffc07f = binary 11110011111111111100000001111111
+ */
+ unsigned long block_mask = 0xf3ffc07fUL;
+ int n;
+
+ /* Check for non-textual ("block-listed") bytes. */
+ for (n = 0; n <= 31; n++, block_mask >>= 1)
+ if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+ return Z_BINARY;
+
+ /* Check for textual ("allow-listed") bytes. */
+ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+ || s->dyn_ltree[13].Freq != 0)
+ return Z_TEXT;
+ for (n = 32; n < LITERALS; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ return Z_TEXT;
+
+ /* There are no "block-listed" or "allow-listed" bytes:
+ * this stream either is empty or has tolerated ("gray-listed") bytes only.
+ */
+ return Z_BINARY;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and write out the encoded block.
+ */
+void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
+ ulg stored_len, int last) {
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is binary or text */
+ if (s->strm->data_type == Z_UNKNOWN)
+ s->strm->data_type = detect_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s->opt_len + 3 + 7) >> 3;
+ static_lenb = (s->static_len + 3 + 7) >> 3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->sym_next / 3));
+
+#ifndef FORCE_STATIC
+ if (static_lenb <= opt_lenb || s->strategy == Z_FIXED)
+#endif
+ opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len + 4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, last);
+
+ } else if (static_lenb == opt_lenb) {
+ send_bits(s, (STATIC_TREES<<1) + last, 3);
+ compress_block(s, (const ct_data *)static_ltree,
+ (const ct_data *)static_dtree);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1) + last, 3);
+ send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1,
+ max_blindex + 1);
+ compress_block(s, (const ct_data *)s->dyn_ltree,
+ (const ct_data *)s->dyn_dtree);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (last) {
+ bi_windup(s);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3,
+ s->compressed_len - 7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
+#ifdef LIT_MEM
+ s->d_buf[s->sym_next] = (ush)dist;
+ s->l_buf[s->sym_next++] = (uch)lc;
+#else
+ s->sym_buf[s->sym_next++] = (uch)dist;
+ s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
+ s->sym_buf[s->sym_next++] = (uch)lc;
+#endif
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+ return (s->sym_next == s->sym_end);
+}
diff --git a/Sources/zlib-1.3.1/trees.h b/Sources/zlib-1.3.1/trees.h
new file mode 100644
index 00000000..d35639d8
--- /dev/null
+++ b/Sources/zlib-1.3.1/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
+
diff --git a/Sources/zlib-1.3.1/uncompr.c b/Sources/zlib-1.3.1/uncompr.c
new file mode 100644
index 00000000..5e256663
--- /dev/null
+++ b/Sources/zlib-1.3.1/uncompr.c
@@ -0,0 +1,85 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. *sourceLen is
+ the byte length of the source buffer. Upon entry, *destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit,
+ *destLen is the size of the decompressed data and *sourceLen is the number
+ of source bytes consumed. Upon return, source + *sourceLen points to the
+ first unused input byte.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
+ Z_DATA_ERROR if the input data was corrupted, including if the input data is
+ an incomplete zlib stream.
+*/
+int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source,
+ uLong *sourceLen) {
+ z_stream stream;
+ int err;
+ const uInt max = (uInt)-1;
+ uLong len, left;
+ Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
+
+ len = *sourceLen;
+ if (*destLen) {
+ left = *destLen;
+ *destLen = 0;
+ }
+ else {
+ left = 1;
+ dest = buf;
+ }
+
+ stream.next_in = (z_const Bytef *)source;
+ stream.avail_in = 0;
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ stream.next_out = dest;
+ stream.avail_out = 0;
+
+ do {
+ if (stream.avail_out == 0) {
+ stream.avail_out = left > (uLong)max ? max : (uInt)left;
+ left -= stream.avail_out;
+ }
+ if (stream.avail_in == 0) {
+ stream.avail_in = len > (uLong)max ? max : (uInt)len;
+ len -= stream.avail_in;
+ }
+ err = inflate(&stream, Z_NO_FLUSH);
+ } while (err == Z_OK);
+
+ *sourceLen -= len + stream.avail_in;
+ if (dest != buf)
+ *destLen = stream.total_out;
+ else if (stream.total_out && err == Z_BUF_ERROR)
+ left = 1;
+
+ inflateEnd(&stream);
+ return err == Z_STREAM_END ? Z_OK :
+ err == Z_NEED_DICT ? Z_DATA_ERROR :
+ err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
+ err;
+}
+
+int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
+ uLong sourceLen) {
+ return uncompress2(dest, destLen, source, &sourceLen);
+}
diff --git a/Sources/zlib-1.3.1/zconf.h b/Sources/zlib-1.3.1/zconf.h
new file mode 100644
index 00000000..62adc8d8
--- /dev/null
+++ b/Sources/zlib-1.3.1/zconf.h
@@ -0,0 +1,543 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+# define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+# define _dist_code z__dist_code
+# define _length_code z__length_code
+# define _tr_align z__tr_align
+# define _tr_flush_bits z__tr_flush_bits
+# define _tr_flush_block z__tr_flush_block
+# define _tr_init z__tr_init
+# define _tr_stored_block z__tr_stored_block
+# define _tr_tally z__tr_tally
+# define adler32 z_adler32
+# define adler32_combine z_adler32_combine
+# define adler32_combine64 z_adler32_combine64
+# define adler32_z z_adler32_z
+# ifndef Z_SOLO
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# endif
+# define crc32 z_crc32
+# define crc32_combine z_crc32_combine
+# define crc32_combine64 z_crc32_combine64
+# define crc32_combine_gen z_crc32_combine_gen
+# define crc32_combine_gen64 z_crc32_combine_gen64
+# define crc32_combine_op z_crc32_combine_op
+# define crc32_z z_crc32_z
+# define deflate z_deflate
+# define deflateBound z_deflateBound
+# define deflateCopy z_deflateCopy
+# define deflateEnd z_deflateEnd
+# define deflateGetDictionary z_deflateGetDictionary
+# define deflateInit z_deflateInit
+# define deflateInit2 z_deflateInit2
+# define deflateInit2_ z_deflateInit2_
+# define deflateInit_ z_deflateInit_
+# define deflateParams z_deflateParams
+# define deflatePending z_deflatePending
+# define deflatePrime z_deflatePrime
+# define deflateReset z_deflateReset
+# define deflateResetKeep z_deflateResetKeep
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateSetHeader z_deflateSetHeader
+# define deflateTune z_deflateTune
+# define deflate_copyright z_deflate_copyright
+# define get_crc_table z_get_crc_table
+# ifndef Z_SOLO
+# define gz_error z_gz_error
+# define gz_intmax z_gz_intmax
+# define gz_strwinerror z_gz_strwinerror
+# define gzbuffer z_gzbuffer
+# define gzclearerr z_gzclearerr
+# define gzclose z_gzclose
+# define gzclose_r z_gzclose_r
+# define gzclose_w z_gzclose_w
+# define gzdirect z_gzdirect
+# define gzdopen z_gzdopen
+# define gzeof z_gzeof
+# define gzerror z_gzerror
+# define gzflush z_gzflush
+# define gzfread z_gzfread
+# define gzfwrite z_gzfwrite
+# define gzgetc z_gzgetc
+# define gzgetc_ z_gzgetc_
+# define gzgets z_gzgets
+# define gzoffset z_gzoffset
+# define gzoffset64 z_gzoffset64
+# define gzopen z_gzopen
+# define gzopen64 z_gzopen64
+# ifdef _WIN32
+# define gzopen_w z_gzopen_w
+# endif
+# define gzprintf z_gzprintf
+# define gzputc z_gzputc
+# define gzputs z_gzputs
+# define gzread z_gzread
+# define gzrewind z_gzrewind
+# define gzseek z_gzseek
+# define gzseek64 z_gzseek64
+# define gzsetparams z_gzsetparams
+# define gztell z_gztell
+# define gztell64 z_gztell64
+# define gzungetc z_gzungetc
+# define gzvprintf z_gzvprintf
+# define gzwrite z_gzwrite
+# endif
+# define inflate z_inflate
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define inflateBackInit z_inflateBackInit
+# define inflateBackInit_ z_inflateBackInit_
+# define inflateCodesUsed z_inflateCodesUsed
+# define inflateCopy z_inflateCopy
+# define inflateEnd z_inflateEnd
+# define inflateGetDictionary z_inflateGetDictionary
+# define inflateGetHeader z_inflateGetHeader
+# define inflateInit z_inflateInit
+# define inflateInit2 z_inflateInit2
+# define inflateInit2_ z_inflateInit2_
+# define inflateInit_ z_inflateInit_
+# define inflateMark z_inflateMark
+# define inflatePrime z_inflatePrime
+# define inflateReset z_inflateReset
+# define inflateReset2 z_inflateReset2
+# define inflateResetKeep z_inflateResetKeep
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateUndermine z_inflateUndermine
+# define inflateValidate z_inflateValidate
+# define inflate_copyright z_inflate_copyright
+# define inflate_fast z_inflate_fast
+# define inflate_table z_inflate_table
+# ifndef Z_SOLO
+# define uncompress z_uncompress
+# define uncompress2 z_uncompress2
+# endif
+# define zError z_zError
+# ifndef Z_SOLO
+# define zcalloc z_zcalloc
+# define zcfree z_zcfree
+# endif
+# define zlibCompileFlags z_zlibCompileFlags
+# define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+# define Byte z_Byte
+# define Bytef z_Bytef
+# define alloc_func z_alloc_func
+# define charf z_charf
+# define free_func z_free_func
+# ifndef Z_SOLO
+# define gzFile z_gzFile
+# endif
+# define gz_header z_gz_header
+# define gz_headerp z_gz_headerp
+# define in_func z_in_func
+# define intf z_intf
+# define out_func z_out_func
+# define uInt z_uInt
+# define uIntf z_uIntf
+# define uLong z_uLong
+# define uLongf z_uLongf
+# define voidp z_voidp
+# define voidpc z_voidpc
+# define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+# define gz_header_s z_gz_header_s
+# define internal_state z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+# define z_const const
+#else
+# define z_const
+#endif
+
+#ifdef Z_SOLO
+# ifdef _WIN64
+ typedef unsigned long long z_size_t;
+# else
+ typedef unsigned long z_size_t;
+# endif
+#else
+# define z_longlong long long
+# if defined(NO_SIZE_T)
+ typedef unsigned NO_SIZE_T z_size_t;
+# elif defined(STDC)
+# include
+ typedef size_t z_size_t;
+# else
+ typedef unsigned long z_size_t;
+# endif
+# undef z_longlong
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+# include
+# if (UINT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned
+# elif (ULONG_MAX == 0xffffffffUL)
+# define Z_U4 unsigned long
+# elif (USHRT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned short
+# endif
+#endif
+
+#ifdef Z_U4
+ typedef Z_U4 z_crc_t;
+#else
+ typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+# ifndef Z_SOLO
+# include /* for off_t */
+# endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+# include /* for va_list */
+# endif
+#endif
+
+#ifdef _WIN32
+# ifndef Z_SOLO
+# include /* for wchar_t */
+# endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#ifndef Z_HAVE_UNISTD_H
+# ifdef __WATCOMC__
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_HAVE_UNISTD_H
+# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_SOLO
+# if defined(Z_HAVE_UNISTD_H)
+# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+# ifdef VMS
+# include /* for off_t */
+# endif
+# ifndef z_off_t
+# define z_off_t off_t
+# endif
+# endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+# define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+# define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+# define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+# define z_off64_t off64_t
+#else
+# if defined(_WIN32) && !defined(__GNUC__)
+# define z_off64_t __int64
+# else
+# define z_off64_t z_off_t
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+ #pragma map(deflateInit_,"DEIN")
+ #pragma map(deflateInit2_,"DEIN2")
+ #pragma map(deflateEnd,"DEEND")
+ #pragma map(deflateBound,"DEBND")
+ #pragma map(inflateInit_,"ININ")
+ #pragma map(inflateInit2_,"ININ2")
+ #pragma map(inflateEnd,"INEND")
+ #pragma map(inflateSync,"INSY")
+ #pragma map(inflateSetDictionary,"INSEDI")
+ #pragma map(compressBound,"CMBND")
+ #pragma map(inflate_table,"INTABL")
+ #pragma map(inflate_fast,"INFA")
+ #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/Sources/zlib-1.3.1/zlib.3 b/Sources/zlib-1.3.1/zlib.3
new file mode 100644
index 00000000..c716020e
--- /dev/null
+++ b/Sources/zlib-1.3.1/zlib.3
@@ -0,0 +1,149 @@
+.TH ZLIB 3 "22 Jan 2024"
+.SH NAME
+zlib \- compression/decompression library
+.SH SYNOPSIS
+[see
+.I zlib.h
+for full description]
+.SH DESCRIPTION
+The
+.I zlib
+library is a general purpose data compression library.
+The code is thread safe, assuming that the standard library functions
+used are thread safe, such as memory allocation routines.
+It provides in-memory compression and decompression functions,
+including integrity checks of the uncompressed data.
+This version of the library supports only one compression method (deflation)
+but other algorithms may be added later
+with the same stream interface.
+.LP
+Compression can be done in a single step if the buffers are large enough
+or can be done by repeated calls of the compression function.
+In the latter case,
+the application must provide more input and/or consume the output
+(providing more output space) before each call.
+.LP
+The library also supports reading and writing files in
+.IR gzip (1)
+(.gz) format
+with an interface similar to that of stdio.
+.LP
+The library does not install any signal handler.
+The decoder checks the consistency of the compressed data,
+so the library should never crash even in the case of corrupted input.
+.LP
+All functions of the compression library are documented in the file
+.IR zlib.h .
+The distribution source includes examples of use of the library
+in the files
+.I test/example.c
+and
+.IR test/minigzip.c,
+as well as other examples in the
+.IR examples/
+directory.
+.LP
+Changes to this version are documented in the file
+.I ChangeLog
+that accompanies the source.
+.LP
+.I zlib
+is built in to many languages and operating systems, including but not limited to
+Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go.
+.LP
+An experimental package to read and write files in the .zip format,
+written on top of
+.I zlib
+by Gilles Vollant (info@winimage.com),
+is available at:
+.IP
+http://www.winimage.com/zLibDll/minizip.html
+and also in the
+.I contrib/minizip
+directory of the main
+.I zlib
+source distribution.
+.SH "SEE ALSO"
+The
+.I zlib
+web site can be found at:
+.IP
+http://zlib.net/
+.LP
+The data format used by the
+.I zlib
+library is described by RFC
+(Request for Comments) 1950 to 1952 in the files:
+.IP
+http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format)
+.br
+http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format)
+.br
+http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format)
+.LP
+Mark Nelson wrote an article about
+.I zlib
+for the Jan. 1997 issue of Dr. Dobb's Journal;
+a copy of the article is available at:
+.IP
+http://marknelson.us/1997/01/01/zlib-engine/
+.SH "REPORTING PROBLEMS"
+Before reporting a problem,
+please check the
+.I zlib
+web site to verify that you have the latest version of
+.IR zlib ;
+otherwise,
+obtain the latest version and see if the problem still exists.
+Please read the
+.I zlib
+FAQ at:
+.IP
+http://zlib.net/zlib_faq.html
+.LP
+before asking for help.
+Send questions and/or comments to zlib@gzip.org,
+or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
+.SH AUTHORS AND LICENSE
+Version 1.3.1
+.LP
+Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
+.LP
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+.LP
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+.LP
+.nr step 1 1
+.IP \n[step]. 3
+The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+.IP \n+[step].
+Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+.IP \n+[step].
+This notice may not be removed or altered from any source distribution.
+.LP
+Jean-loup Gailly Mark Adler
+.br
+jloup@gzip.org madler@alumni.caltech.edu
+.LP
+The deflate format used by
+.I zlib
+was defined by Phil Katz.
+The deflate and
+.I zlib
+specifications were written by L. Peter Deutsch.
+Thanks to all the people who reported problems and suggested various
+improvements in
+.IR zlib ;
+who are too numerous to cite here.
+.LP
+UNIX manual page by R. P. C. Rodgers,
+U.S. National Library of Medicine (rodgers@nlm.nih.gov).
+.\" end of man page
diff --git a/Sources/zlib-1.3.1/zlib.h b/Sources/zlib-1.3.1/zlib.h
new file mode 100644
index 00000000..8d4b932e
--- /dev/null
+++ b/Sources/zlib-1.3.1/zlib.h
@@ -0,0 +1,1938 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.3.1, January 22nd, 2024
+
+ Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+ (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.3.1"
+#define ZLIB_VERNUM 0x1310
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 3
+#define ZLIB_VER_REVISION 1
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed data.
+ This version of the library supports only one compression method (deflation)
+ but other algorithms will be added later and will have the same stream
+ interface.
+
+ Compression can be done in a single step if the buffers are large enough,
+ or can be done by repeated calls of the compression function. In the latter
+ case, the application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip and raw deflate streams in
+ memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never crash
+ even in the case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size);
+typedef void (*free_func)(voidpf opaque, voidpf address);
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ z_const Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total number of input bytes read so far */
+
+ Bytef *next_out; /* next output byte will go here */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total number of bytes output so far */
+
+ z_const char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text
+ for deflate, or the decoding state for inflate */
+ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has dropped
+ to zero. It must update next_out and avail_out when avail_out has dropped
+ to zero. The application must initialize zalloc, zfree and opaque before
+ calling the init function. All other fields are set by the compression
+ library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe. In that case, zlib is thread-safe. When zalloc and zfree are
+ Z_NULL on entry to the initialization function, they are set to internal
+ routines that use the standard library functions malloc() and free().
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this if
+ the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers
+ returned by zalloc for objects of exactly 65536 bytes *must* have their
+ offset normalized to zero. The default allocation function provided by this
+ library ensures this (see zutil.c). To reduce memory requirements and avoid
+ any allocation of 64K objects, at the expense of compression ratio, compile
+ the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or progress
+ reports. After compression, total_in holds the total size of the
+ uncompressed data and may be saved for use by the decompressor (particularly
+ if the decompressor wants to decompress everything in a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+#define Z_TREES 6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field for deflate() */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion(void);
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is not
+ compatible with the zlib.h header file used by the application. This check
+ is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level);
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+ allocation functions. total_in, total_out, adler, and msg are initialized.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at all
+ (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION
+ requests a default compromise between speed and compression (currently
+ equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if level is not a valid compression level, or
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION). msg is set to null
+ if there is no error message. deflateInit does not perform any compression:
+ this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush);
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary. Some output may be provided even if
+ flush is zero.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating avail_in or avail_out accordingly; avail_out should
+ never be zero before the call. The application can consume the compressed
+ output when it wants, for example when the output buffer is full (avail_out
+ == 0), or after each call of deflate(). If deflate returns Z_OK and with
+ zero avail_out, it must be called again after making room in the output
+ buffer because there might be more output pending. See deflatePending(),
+ which can be used if desired to determine whether or not there is more output
+ in that case.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumulate before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In
+ particular avail_in is zero after the call if enough output space has been
+ provided before the call.) Flushing may degrade compression for some
+ compression algorithms and so it should be used only when necessary. This
+ completes the current deflate block and follows it with an empty stored block
+ that is three bits plus filler bits to the next byte, followed by four bytes
+ (00 00 ff ff).
+
+ If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+ output buffer, but the output is not aligned to a byte boundary. All of the
+ input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+ This completes the current deflate block and follows it with an empty fixed
+ codes block that is 10 bits long. This assures that enough bytes are output
+ in order for the decompressor to finish the block before the empty fixed
+ codes block.
+
+ If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+ for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+ seven bits of the current block are held to be written as the next byte after
+ the next deflate block is completed. In this case, the decompressor may not
+ be provided enough bits at this point in order to complete decompression of
+ the data provided so far to the compressor. It may need to wait for the next
+ block to be emitted. This is for advanced applications that need to control
+ the emission of deflate blocks.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six when the flush marker begins, in order to avoid
+ repeated flush markers upon calling deflate() again when avail_out == 0.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there was
+ enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this
+ function must be called again with Z_FINISH and more output space (updated
+ avail_out) but no more input data, until it returns with Z_STREAM_END or an
+ error. After deflate has returned Z_STREAM_END, the only possible operations
+ on the stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used in the first deflate call after deflateInit if all the
+ compression is to be done in a single step. In order to complete in one
+ call, avail_out must be at least the value returned by deflateBound (see
+ below). Then deflate is guaranteed to return Z_STREAM_END. If not enough
+ output space is provided, deflate will not return Z_STREAM_END, and it must
+ be called again as described above.
+
+ deflate() sets strm->adler to the Adler-32 checksum of all input read
+ so far (that is, total_in bytes). If a gzip stream is being generated, then
+ strm->adler will be the CRC-32 checksum of the input read so far. (See
+ deflateInit2 below.)
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is
+ considered binary. This field is only for information purposes and does not
+ affect the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was Z_NULL or the state was inadvertently written over
+ by the application), or Z_BUF_ERROR if no progress is possible (for example
+ avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and
+ deflate() can be called again with more input and more output space to
+ continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd(z_streamp strm);
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case, msg
+ may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit(z_streamp strm);
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. In the current version of inflate, the provided input is not
+ read or consumed. The allocation of a sliding window will be deferred to
+ the first call of inflate (if the decompression does not complete on the
+ first call). If zalloc and zfree are set to Z_NULL, inflateInit updates
+ them to use default allocation functions. total_in, total_out, adler, and
+ msg are initialized.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit does not perform any decompression.
+ Actual decompression will be done by inflate(). So next_in, and avail_in,
+ next_out, and avail_out are unused and unchanged. The current
+ implementation of inflateInit() does not process any header information --
+ that is deferred until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush);
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), then next_in and avail_in are updated
+ accordingly, and processing will resume at this point for the next call of
+ inflate().
+
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there is
+ no more input data or no more space in the output buffer (see below about
+ the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating the next_* and avail_* values accordingly. If the
+ caller of inflate() does not provide both available input and available
+ output space, it is possible that there will be no progress made. The
+ application can consume the uncompressed output when it wants, for example
+ when the output buffer is full (avail_out == 0), or after each call of
+ inflate(). If inflate returns Z_OK and with zero avail_out, it must be
+ called again after making room in the output buffer because there might be
+ more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+ Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate()
+ stop if and when it gets to the next deflate block boundary. When decoding
+ the zlib or gzip format, this will cause inflate() to return immediately
+ after the header and before the first block. When doing a raw inflate,
+ inflate() will go ahead and process the first block, and will return when it
+ gets to the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ To assist in this, on return inflate() always sets strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64 if
+ inflate() is currently decoding the last block in the deflate stream, plus
+ 128 if inflate() returned immediately after decoding an end-of-block code or
+ decoding the complete header up to just before the first byte of the deflate
+ stream. The end-of-block will not be indicated until all of the uncompressed
+ data from that block has been written to strm->next_out. The number of
+ unused bits may in general be greater than seven, except when bit 7 of
+ data_type is set, in which case the number of unused bits will be less than
+ eight. data_type is set as noted here every time inflate() returns for all
+ flush options, and so can be used to determine the amount of currently
+ consumed input in bits.
+
+ The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+ end of each deflate block header is reached, before any actual data in that
+ block is decoded. This allows the caller to determine the length of the
+ deflate block header for later use in random access within a deflate block.
+ 256 is added to the value of strm->data_type when inflate() returns
+ immediately after reaching the end of the deflate block header.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step (a
+ single call of inflate), the parameter flush should be set to Z_FINISH. In
+ this case all pending input is processed and all pending output is flushed;
+ avail_out must be large enough to hold all of the uncompressed data for the
+ operation to complete. (The size of the uncompressed data may have been
+ saved by the compressor for this purpose.) The use of Z_FINISH is not
+ required to perform an inflation in one step. However it may be used to
+ inform inflate that a faster approach can be used for the single inflate()
+ call. Z_FINISH also informs inflate to not maintain a sliding window if the
+ stream completes, which reduces inflate's memory footprint. If the stream
+ does not complete, either because not all of the stream is provided or not
+ enough output space is provided, then a sliding window will be allocated and
+ inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+ been used.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the effects of the flush parameter in this implementation are
+ on the return value of inflate() as noted below, when inflate() returns early
+ when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+ memory for a sliding window when Z_FINISH is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the Adler-32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed Adler-32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically, if requested when
+ initializing with inflateInit2(). Any information contained in the gzip
+ header is not retained unless inflateGetHeader() is used. When processing
+ gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+ produced so far. The CRC-32 is checked against the gzip trailer, as is the
+ uncompressed length, modulo 2^32.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value, in which case strm->msg points to a string with a more specific
+ error), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ next_in or next_out was Z_NULL, or the state was inadvertently written over
+ by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR
+ if no progress was possible or if there was not enough room in the output
+ buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may
+ then call inflateSync() to look for a good compression block if a partial
+ recovery of the data is to be attempted.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd(z_streamp strm);
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state
+ was inconsistent.
+*/
+
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2(z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy);
+
+ This is another version of deflateInit with more compression options. The
+ fields zalloc, zfree and opaque must be initialized before by the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ For the current implementation of deflate(), a windowBits value of 8 (a
+ window size of 256 bytes) is not supported. As a result, a request for 8
+ will result in 9 (a 512-byte window). In that case, providing 8 to
+ inflateInit2() will result in an error when the zlib header with 9 is
+ checked against the initialization of inflate(). The remedy is to not use 8
+ with deflateInit2() with this initialization, or at least in that case use 9
+ with inflateInit2().
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute a check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero), no
+ header crc, and the operating system will be set to the appropriate value,
+ if the operating system was determined at compile time. If a gzip stream is
+ being written, strm->adler is a CRC-32 instead of an Adler-32.
+
+ For raw deflate or gzip encoding, a request for a 256-byte window is
+ rejected as invalid, since only the zlib header provides a means of
+ transmitting the window size to the decompressor.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but is
+ slow and reduces compression ratio; memLevel=9 uses maximum memory for
+ optimal speed. The default value is 8. See zconf.h for total memory usage
+ as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as
+ fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The
+ strategy parameter only affects the compression ratio but not the
+ correctness of the compressed output even if it is not set appropriately.
+ Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+ decoder for special applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+ method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+ incompatible with the version assumed by the caller (ZLIB_VERSION). msg is
+ set to null if there is no error message. deflateInit2 does not perform any
+ compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. When using the zlib format, this
+ function must be called immediately after deflateInit, deflateInit2 or
+ deflateReset, and before any call of deflate. When doing raw deflate, this
+ function must be called either before any call of deflate, or immediately
+ after the completion of a deflate block, i.e. after all input has been
+ consumed and all output has been delivered when using any of the flush
+ options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
+ compressor and decompressor must use exactly the same dictionary (see
+ inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size
+ provided in deflateInit or deflateInit2. Thus the strings most likely to be
+ useful should be put at the end of the dictionary, not at the front. In
+ addition, the current implementation of deflate will use at most the window
+ size minus 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the Adler-32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler-32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ Adler-32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if not at a block boundary for raw deflate). deflateSetDictionary does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength);
+/*
+ Returns the sliding dictionary being maintained by deflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If deflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similarly, if dictLength is Z_NULL, then it is not set.
+
+ deflateGetDictionary() may return a length less than the window size, even
+ when more than the window size in input has been provided. It may return up
+ to 258 bytes less in that case, due to how zlib's implementation of deflate
+ manages the sliding window and lookahead for matches, where matches can be
+ up to 258 bytes long. If the application needs the last window-size bytes of
+ input, then that would need to be saved by the application outside of zlib.
+
+ deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateCopy(z_streamp dest,
+ z_streamp source);
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and can
+ consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset(z_streamp strm);
+/*
+ This function is equivalent to deflateEnd followed by deflateInit, but
+ does not free and reallocate the internal compression state. The stream
+ will leave the compression level and any other attributes that may have been
+ set unchanged. total_in, total_out, adler, and msg are initialized.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams(z_streamp strm,
+ int level,
+ int strategy);
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2(). This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different strategy.
+ If the compression approach (which is a function of the level) or the
+ strategy is changed, and if there have been any deflate() calls since the
+ state was initialized or reset, then the input available so far is
+ compressed with the old level and strategy using deflate(strm, Z_BLOCK).
+ There are three approaches for the compression levels 0, 1..3, and 4..9
+ respectively. The new level and strategy will take effect at the next call
+ of deflate().
+
+ If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
+ not have enough output space to complete, then the parameter change will not
+ take effect. In this case, deflateParams() can be called again with the
+ same parameters and more output space to try again.
+
+ In order to assure a change in the parameters on the first try, the
+ deflate stream should be flushed using deflate() with Z_BLOCK or other flush
+ request until strm.avail_out is not zero, before calling deflateParams().
+ Then no more input data should be provided before the deflateParams() call.
+ If this is done, the old level and strategy will be applied to the data
+ compressed before deflateParams(), and the new level and strategy will be
+ applied to the data compressed after deflateParams().
+
+ deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
+ state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
+ there was not enough output space to complete the compression of the
+ available input data before a change in the strategy or approach. Note that
+ in the case of a Z_BUF_ERROR, the parameters are not changed. A return
+ value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be
+ retried with more output space.
+*/
+
+ZEXTERN int ZEXPORT deflateTune(z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain);
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm,
+ uLong sourceLen);
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit() or
+ deflateInit2(), and after deflateSetHeader(), if used. This would be used
+ to allocate an output buffer for deflation in a single pass, and so would be
+ called before deflate(). If that first deflate() call is provided the
+ sourceLen input bytes, an output buffer allocated to the size returned by
+ deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+ to return Z_STREAM_END. Note that it is possible for the compressed size to
+ be larger than the value returned by deflateBound() if flush options other
+ than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending(z_streamp strm,
+ unsigned *pending,
+ int *bits);
+/*
+ deflatePending() returns the number of bytes and bits of output that have
+ been generated, but not yet provided in the available output. The bytes not
+ provided would be due to the available output space having being consumed.
+ The number of bits of output not provided are between 0 and 7, where they
+ await more bits to join them in order to fill out a full byte. If pending
+ or bits are Z_NULL, then those values are not set.
+
+ deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime(z_streamp strm,
+ int bits,
+ int value);
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the bits
+ leftover from a previous deflate stream when appending to it. As such, this
+ function can only be used for raw deflate, and must be used before the first
+ deflate() call after a deflateInit2() or deflateReset(). bits must be less
+ than or equal to 16, and that many of the least significant bits of value
+ will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+ room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm,
+ gz_headerp head);
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to the current operating system, with no
+ extra, name, or comment fields. The gzip header is returned to the default
+ state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2(z_streamp strm,
+ int windowBits);
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be zero to request that inflate use the window size in
+ the zlib header of the compressed stream.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an Adler-32 or a CRC-32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
+ CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
+ below), inflate() will *not* automatically decode concatenated gzip members.
+ inflate() will return Z_STREAM_END at the end of the gzip member. The state
+ would need to be reset to continue decoding a subsequent gzip member. This
+ *must* be done if there is more data after a gzip member, in order for the
+ decompression to be compliant with the gzip standard (RFC 1952).
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit2 does not perform any decompression
+ apart from possibly reading the zlib header if present: actual decompression
+ will be done by inflate(). (So next_in and avail_in may be modified, but
+ next_out and avail_out are unused and unchanged.) The current implementation
+ of inflateInit2() does not process any header information -- that is
+ deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler-32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called at any
+ time to set the dictionary. If the provided dictionary is smaller than the
+ window and there is already data in the window, then the provided dictionary
+ will amend what's there. The application must insure that the dictionary
+ that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler-32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength);
+/*
+ Returns the sliding dictionary being maintained by inflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If inflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similarly, if dictLength is Z_NULL, then it is not set.
+
+ inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateSync(z_streamp strm);
+/*
+ Skips invalid compressed data until a possible full flush point (see above
+ for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+ All full flush points have this pattern, but not all occurrences of this
+ pattern are full flush points.
+
+ inflateSync returns Z_OK if a possible full flush point has been found,
+ Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+ has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+ In the success case, the application may save the current value of total_in
+ which indicates where valid compressed data was found. In the error case,
+ the application may repeatedly call inflateSync, providing more input each
+ time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
+ z_streamp source);
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset(z_streamp strm);
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate the internal decompression state. The
+ stream will keep attributes that may have been set by inflateInit2.
+ total_in, total_out, adler, and msg are initialized.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2(z_streamp strm,
+ int windowBits);
+/*
+ This function is the same as inflateReset, but it also permits changing
+ the wrap and window size requests. The windowBits parameter is interpreted
+ the same as it is for inflateInit2. If the window size is changed, then the
+ memory allocated for the window is freed, and the window will be reallocated
+ by inflate() if needed.
+
+ inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+ the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime(z_streamp strm,
+ int bits,
+ int value);
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ If bits is negative, then the input stream bit buffer is emptied. Then
+ inflatePrime() can be called again to put bits in the buffer. This is used
+ to clear out bits leftover after feeding inflate a block description prior
+ to feeding inflate codes.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark(z_streamp strm);
+/*
+ This function returns two values, one in the lower 16 bits of the return
+ value, and the other in the remaining upper bits, obtained by shifting the
+ return value down 16 bits. If the upper value is -1 and the lower value is
+ zero, then inflate() is currently decoding information outside of a block.
+ If the upper value is -1 and the lower value is non-zero, then inflate is in
+ the middle of a stored block, with the lower value equaling the number of
+ bytes from the input remaining to copy. If the upper value is not -1, then
+ it is the number of bits back from the current bit position in the input of
+ the code (literal or length/distance pair) currently being processed. In
+ that case the lower value is the number of bytes already emitted for that
+ code.
+
+ A code is being processed if inflate is waiting for more input to complete
+ decoding of the code, or if it has completed decoding but is waiting for
+ more output space to write the literal or match data.
+
+ inflateMark() is used to mark locations in the input data for random
+ access, which may be at bit positions, and to note those cases where the
+ output of a code may span boundaries of random access blocks. The current
+ location in the input stream can be determined from avail_in and data_type
+ as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+ inflateMark returns the value noted above, or -65536 if the provided
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm,
+ gz_headerp head);
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be
+ used to force inflate() to return immediately after header processing is
+ complete and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When any
+ of extra, name, or comment are not Z_NULL and the respective field is not
+ present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits,
+ unsigned char FAR *window);
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+ allocated, or Z_VERSION_ERROR if the version of the library does not match
+ the version of the header file.
+*/
+
+typedef unsigned (*in_func)(void FAR *,
+ z_const unsigned char FAR * FAR *);
+typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned);
+
+ZEXTERN int ZEXPORT inflateBack(z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc);
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is potentially more efficient than
+ inflate() for file i/o applications, in that it avoids copying between the
+ output and the sliding window by simply making the window itself the output
+ buffer. inflate() can be faster on modern CPUs when used with large
+ buffers. inflateBack() trusts the application to not change the output
+ buffer passed by the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free the
+ allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects only
+ the raw deflate stream to decompress. This is different from the default
+ behavior of inflate(), which expects a zlib header and trailer around the
+ deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero -- buf is ignored in that
+ case -- and inflateBack() will return a buffer error. inflateBack() will
+ call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].
+ out() should return zero on success, or non-zero on failure. If out()
+ returns non-zero, inflateBack() will return with an error. Neither in() nor
+ out() are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+ in the deflate stream (in which case strm->msg is set to indicate the nature
+ of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+ In the case of Z_BUF_ERROR, an input or output error can be distinguished
+ using strm->next_in which will be Z_NULL only if in() returned an error. If
+ strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+ non-zero. (in() will always be called before out(), so strm->next_in is
+ assured to be defined if out() returns non-zero.) Note that inflateBack()
+ cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm);
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags(void);
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: ZLIB_DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the basic
+ stream-oriented functions. To simplify the interface, some default options
+ are assumed (compression level and memory usage, standard memory allocation
+ functions). The source code of these utility functions can be modified if
+ you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data. compress() is equivalent to compress2() with a level
+ parameter of Z_DEFAULT_COMPRESSION.
+
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level);
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen);
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before a
+ compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit, destLen
+ is the actual size of the uncompressed data.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
+ the case where there is not enough room, uncompress() will fill the output
+ buffer with the uncompressed data up to that point.
+*/
+
+ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong *sourceLen);
+/*
+ Same as uncompress, except that sourceLen is a pointer, where the
+ length of the source is *sourceLen. On return, *sourceLen is the number of
+ source bytes consumed.
+*/
+
+ /* gzip file access functions */
+
+/*
+ This library supports reading and writing files in gzip (.gz) format with
+ an interface similar to that of stdio, using the functions that start with
+ "gz". The gzip format is different from the zlib format. gzip is a gzip
+ wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode);
+
+ Open the gzip (.gz) file at path for reading and decompressing, or
+ compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
+ but can also include a compression level ("wb9") or a strategy: 'f' for
+ filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
+ 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
+ as in "wb9F". (See the description of deflateInit2 for more information
+ about the strategy parameter.) 'T' will request transparent writing or
+ appending with no compression and not using the gzip format.
+
+ "a" can be used instead of "w" to request that the gzip stream that will
+ be written be appended to the file. "+" will result in an error, since
+ reading and writing to the same gzip file is not supported. The addition of
+ "x" when writing will create the file exclusively, which fails if the file
+ already exists. On systems that support it, the addition of "e" when
+ reading or writing will set the flag to close the file on an execve() call.
+
+ These functions, as well as gzip, will read and decode a sequence of gzip
+ streams in a file. The append function of gzopen() can be used to create
+ such a file. (Also see gzflush() for another way to do this.) When
+ appending, gzopen does not test whether the file begins with a gzip stream,
+ nor does it look for the end of the gzip streams to begin appending. gzopen
+ will simply append a gzip stream to the existing file.
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression. When
+ reading, this will be detected automatically by looking for the magic two-
+ byte gzip header.
+
+ gzopen returns NULL if the file could not be opened, if there was
+ insufficient memory to allocate the gzFile state, or if an invalid mode was
+ specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+ errno can be checked to determine if the reason gzopen failed was that the
+ file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode);
+/*
+ Associate a gzFile with the file descriptor fd. File descriptors are
+ obtained from calls like open, dup, creat, pipe or fileno (if the file has
+ been previously opened with fopen). The mode parameter is as in gzopen.
+
+ The next call of gzclose on the returned gzFile will also close the file
+ descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+ fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+ mode);. The duplicated descriptor should be saved to avoid a leak, since
+ gzdopen does not close fd if it fails. If you are using fileno() to get the
+ file descriptor from a FILE *, then you will have to use dup() to avoid
+ double-close()ing the file descriptor. Both gzclose() and fclose() will
+ close the associated file descriptor, so they need to have different file
+ descriptors.
+
+ gzdopen returns NULL if there was insufficient memory to allocate the
+ gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+ provided, or '+' was provided), or if fd is -1. The file descriptor is not
+ used until the next gz* read, write, seek, or close operation, so gzdopen
+ will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size);
+/*
+ Set the internal buffer size used by this library's functions for file to
+ size. The default buffer size is 8192 bytes. This function must be called
+ after gzopen() or gzdopen(), and before any other calls that read or write
+ the file. The buffer memory allocation is always deferred to the first read
+ or write. Three times that size in buffer space is allocated. A larger
+ buffer size of, for example, 64K or 128K bytes will noticeably increase the
+ speed of decompression (reading).
+
+ The new buffer size also affects the maximum length for gzprintf().
+
+ gzbuffer() returns 0 on success, or -1 on failure, such as being called
+ too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy);
+/*
+ Dynamically update the compression level and strategy for file. See the
+ description of deflateInit2 for the meaning of these parameters. Previously
+ provided data is flushed before applying the parameter changes.
+
+ gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
+ opened for writing, Z_ERRNO if there is an error writing the flushed data,
+ or Z_MEM_ERROR if there is a memory allocation error.
+*/
+
+ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len);
+/*
+ Read and decompress up to len uncompressed bytes from file into buf. If
+ the input file is not in gzip format, gzread copies the given number of
+ bytes into the buffer directly from the file.
+
+ After reaching the end of a gzip stream in the input, gzread will continue
+ to read, looking for another gzip stream. Any number of gzip streams may be
+ concatenated in the input file, and will all be decompressed by gzread().
+ If something other than a gzip stream is encountered after a gzip stream,
+ that remaining trailing garbage is ignored (and no error is returned).
+
+ gzread can be used to read a gzip file that is being concurrently written.
+ Upon reaching the end of the input, gzread will return with the available
+ data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+ gzclearerr can be used to clear the end of file indicator in order to permit
+ gzread to be tried again. Z_OK indicates that a gzip stream was completed
+ on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
+ middle of a gzip stream. Note that gzread does not return -1 in the event
+ of an incomplete gzip stream. This error is deferred until gzclose(), which
+ will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+ stream. Alternatively, gzerror can be used before gzclose to detect this
+ case.
+
+ gzread returns the number of uncompressed bytes actually read, less than
+ len for end of file, or -1 for error. If len is too large to fit in an int,
+ then nothing is read, -1 is returned, and the error state is set to
+ Z_STREAM_ERROR.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems,
+ gzFile file);
+/*
+ Read and decompress up to nitems items of size size from file into buf,
+ otherwise operating as gzread() does. This duplicates the interface of
+ stdio's fread(), with size_t request and return types. If the library
+ defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
+ is an unsigned integer type that can contain a pointer.
+
+ gzfread() returns the number of full items read of size size, or zero if
+ the end of the file was reached and a full item could not be read, or if
+ there was an error. gzerror() must be consulted if zero is returned in
+ order to determine if there was an error. If the multiplication of size and
+ nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
+ is read, zero is returned, and the error state is set to Z_STREAM_ERROR.
+
+ In the event that the end of file is reached and only a partial item is
+ available at the end, i.e. the remaining uncompressed data length is not a
+ multiple of size, then the final partial item is nevertheless read into buf
+ and the end-of-file flag is set. The length of the partial item read is not
+ provided, but could be inferred from the result of gztell(). This behavior
+ is the same as the behavior of fread() implementations in common libraries,
+ but it prevents the direct use of gzfread() to read a concurrently written
+ file, resetting and retrying on end-of-file, when size is not 1.
+*/
+
+ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len);
+/*
+ Compress and write the len uncompressed bytes at buf to file. gzwrite
+ returns the number of uncompressed bytes written or 0 in case of error.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size,
+ z_size_t nitems, gzFile file);
+/*
+ Compress and write nitems items of size size from buf to file, duplicating
+ the interface of stdio's fwrite(), with size_t request and return types. If
+ the library defines size_t, then z_size_t is identical to size_t. If not,
+ then z_size_t is an unsigned integer type that can contain a pointer.
+
+ gzfwrite() returns the number of full items written of size size, or zero
+ if there was an error. If the multiplication of size and nitems overflows,
+ i.e. the product does not fit in a z_size_t, then nothing is written, zero
+ is returned, and the error state is set to Z_STREAM_ERROR.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...);
+/*
+ Convert, format, compress, and write the arguments (...) to file under
+ control of the string format, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written, or a negative zlib error code in case
+ of error. The number of uncompressed bytes written is limited to 8191, or
+ one less than the buffer size given to gzbuffer(). The caller should assure
+ that this limit is not exceeded. If it is exceeded, then gzprintf() will
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf(),
+ because the secure snprintf() or vsnprintf() functions were not available.
+ This can be determined using zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s);
+/*
+ Compress and write the given null-terminated string s to file, excluding
+ the terminating null character.
+
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len);
+/*
+ Read and decompress bytes from file into buf, until len-1 characters are
+ read, or until a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. If any characters are read or if len
+ is one, the string is terminated with a null character. If no characters
+ are read due to an end-of-file or len is less than one, then the buffer is
+ left untouched.
+
+ gzgets returns buf which is a null-terminated string, or it returns NULL
+ for end-of-file or in case of error. If there was an error, the contents at
+ buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc(gzFile file, int c);
+/*
+ Compress and write c, converted to an unsigned char, into file. gzputc
+ returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc(gzFile file);
+/*
+ Read and decompress one byte from file. gzgetc returns this byte or -1
+ in case of end of file or error. This is implemented as a macro for speed.
+ As such, it does not do all of the checking the other functions do. I.e.
+ it does not check to see if file is NULL, nor whether the structure file
+ points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc(int c, gzFile file);
+/*
+ Push c back onto the stream for file to be read as the first character on
+ the next read. At least one character of push-back is always allowed.
+ gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
+ fail if c is -1, and may fail if a character has been pushed but not read
+ yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
+ output buffer size of pushed characters is allowed. (See gzbuffer above.)
+ The pushed character will be discarded if the stream is repositioned with
+ gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush(gzFile file, int flush);
+/*
+ Flush all pending output to file. The parameter flush is as in the
+ deflate() function. The return value is the zlib error number (see function
+ gzerror below). gzflush is only permitted when writing.
+
+ If the flush parameter is Z_FINISH, the remaining data is written and the
+ gzip stream is completed in the output. If gzwrite() is called again, a new
+ gzip stream will be started in the output. gzread() is able to read such
+ concatenated gzip streams.
+
+ gzflush should be called only when strictly necessary because it will
+ degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek(gzFile file,
+ z_off_t offset, int whence);
+
+ Set the starting position to offset relative to whence for the next gzread
+ or gzwrite on file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind(gzFile file);
+/*
+ Rewind file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gztell(gzFile file);
+
+ Return the starting position for the next gzread or gzwrite on file.
+ This position represents a number of bytes in the uncompressed data stream,
+ and is zero when starting, even if appending or reading a gzip stream from
+ the middle of a file using gzdopen().
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file);
+
+ Return the current compressed (actual) read or write offset of file. This
+ offset includes the count of bytes that precede the gzip stream, for example
+ when appending or when using gzdopen() for reading. When reading, the
+ offset does not include as yet unused buffered input. This information can
+ be used for a progress indicator. On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof(gzFile file);
+/*
+ Return true (1) if the end-of-file indicator for file has been set while
+ reading, false (0) otherwise. Note that the end-of-file indicator is set
+ only if the read tried to go past the end of the input, but came up short.
+ Therefore, just like feof(), gzeof() may return false even if there is no
+ more data to read, in the event that the last read request was for the exact
+ number of bytes remaining in the input file. This will happen if the input
+ file size is an exact multiple of the buffer size.
+
+ If gzeof() returns true, then the read functions will return no more data,
+ unless the end-of-file indicator is reset by gzclearerr() and the input file
+ has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect(gzFile file);
+/*
+ Return true (1) if file is being copied directly while reading, or false
+ (0) if file is a gzip stream being decompressed.
+
+ If the input file is empty, gzdirect() will return true, since the input
+ does not contain a gzip stream.
+
+ If gzdirect() is used immediately after gzopen() or gzdopen() it will
+ cause buffers to be allocated to allow reading the file to determine if it
+ is a gzip file. Therefore if gzbuffer() is used, it should be called before
+ gzdirect().
+
+ When writing, gzdirect() returns true (1) if transparent writing was
+ requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
+ gzdirect() is not needed when writing. Transparent writing must be
+ explicitly requested, so the application already knows the answer. When
+ linking statically, using gzdirect() will include all of the zlib code for
+ gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT gzclose(gzFile file);
+/*
+ Flush all pending output for file, if necessary, close file and
+ deallocate the (de)compression state. Note that once file is closed, you
+ cannot call gzerror with file, since its structures have been deallocated.
+ gzclose must not be called more than once on the same file, just as free
+ must not be called more than once on the same allocation.
+
+ gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+ file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+ last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r(gzFile file);
+ZEXTERN int ZEXPORT gzclose_w(gzFile file);
+/*
+ Same as gzclose(), but gzclose_r() is only for use when reading, and
+ gzclose_w() is only for use when writing or appending. The advantage to
+ using these instead of gzclose() is that they avoid linking in zlib
+ compression or decompression code that is not used when only reading or only
+ writing respectively. If gzclose() is used, then both compression and
+ decompression code will be included the application when linking to a static
+ zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum);
+/*
+ Return the error message for the last error which occurred on file.
+ errnum is set to zlib error number. If an error occurred in the file system
+ and not in the compression library, errnum is set to Z_ERRNO and the
+ application may consult errno to get the exact error code.
+
+ The application must not modify the returned string. Future calls to
+ this function may invalidate the previously returned string. If file is
+ closed, then the string previously returned by gzerror will no longer be
+ available.
+
+ gzerror() should be used to distinguish errors from end-of-file for those
+ functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr(gzFile file);
+/*
+ Clear the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the compression
+ library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len);
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. An Adler-32 value is in the range of a 32-bit
+ unsigned integer. If buf is Z_NULL, this function returns the required
+ initial value for the checksum.
+
+ An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
+ much faster.
+
+ Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf,
+ z_size_t len);
+/*
+ Same as adler32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2,
+ z_off_t len2);
+
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
+ that the z_off_t type (like off_t) is a signed integer. If len2 is
+ negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len);
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
+ If buf is Z_NULL, this function returns the required initial value for the
+ crc. Pre- and post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the application.
+
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf,
+ z_size_t len);
+/*
+ Same as crc32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2);
+
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2. len2 must be non-negative.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
+
+ Return the operator corresponding to length len2, to be used with
+ crc32_combine_op(). len2 must be non-negative.
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
+/*
+ Give the same result as crc32_combine(), using op in place of len2. op is
+ is generated from len2 by crc32_combine_gen(). This will be faster than
+ crc32_combine() if the generated op is used more than once.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level,
+ const char *version, int stream_size);
+ZEXTERN int ZEXPORT inflateInit_(z_streamp strm,
+ const char *version, int stream_size);
+ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size);
+ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
+ const char *version, int stream_size);
+ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size);
+#ifdef Z_PREFIX_SET
+# define z_deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define z_inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#else
+# define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#endif
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure. Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro. The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously. They can
+ * only be used by the gzgetc() macro. You have been warned.
+ */
+struct gzFile_s {
+ unsigned have;
+ unsigned char *next;
+ z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+# define z_gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#else
+# define gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+ ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
+ ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
+ ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
+ ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t);
+ ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t);
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+# ifdef Z_PREFIX_SET
+# define z_gzopen z_gzopen64
+# define z_gzseek z_gzseek64
+# define z_gztell z_gztell64
+# define z_gzoffset z_gzoffset64
+# define z_adler32_combine z_adler32_combine64
+# define z_crc32_combine z_crc32_combine64
+# define z_crc32_combine_gen z_crc32_combine_gen64
+# else
+# define gzopen gzopen64
+# define gzseek gzseek64
+# define gztell gztell64
+# define gzoffset gzoffset64
+# define adler32_combine adler32_combine64
+# define crc32_combine crc32_combine64
+# define crc32_combine_gen crc32_combine_gen64
+# endif
+# ifndef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+ ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int);
+ ZEXTERN z_off_t ZEXPORT gztell64(gzFile);
+ ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile);
+ ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
+# endif
+#else
+ ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *);
+ ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int);
+ ZEXTERN z_off_t ZEXPORT gztell(gzFile);
+ ZEXTERN z_off_t ZEXPORT gzoffset(gzFile);
+ ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
+#endif
+
+#else /* Z_SOLO */
+
+ ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
+
+#endif /* !Z_SOLO */
+
+/* undocumented functions */
+ZEXTERN const char * ZEXPORT zError(int);
+ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp);
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void);
+ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int);
+ZEXTERN int ZEXPORT inflateValidate(z_streamp, int);
+ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp);
+ZEXTERN int ZEXPORT inflateResetKeep(z_streamp);
+ZEXTERN int ZEXPORT deflateResetKeep(z_streamp);
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path,
+ const char *mode);
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+ZEXTERN int ZEXPORTVA gzvprintf(gzFile file,
+ const char *format,
+ va_list va);
+# endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/Sources/zlib-1.3.1/zlib.map b/Sources/zlib-1.3.1/zlib.map
new file mode 100644
index 00000000..31544f2e
--- /dev/null
+++ b/Sources/zlib-1.3.1/zlib.map
@@ -0,0 +1,100 @@
+ZLIB_1.2.0 {
+ global:
+ compressBound;
+ deflateBound;
+ inflateBack;
+ inflateBackEnd;
+ inflateBackInit_;
+ inflateCopy;
+ local:
+ deflate_copyright;
+ inflate_copyright;
+ inflate_fast;
+ inflate_table;
+ zcalloc;
+ zcfree;
+ z_errmsg;
+ gz_error;
+ gz_intmax;
+ _*;
+};
+
+ZLIB_1.2.0.2 {
+ gzclearerr;
+ gzungetc;
+ zlibCompileFlags;
+} ZLIB_1.2.0;
+
+ZLIB_1.2.0.8 {
+ deflatePrime;
+} ZLIB_1.2.0.2;
+
+ZLIB_1.2.2 {
+ adler32_combine;
+ crc32_combine;
+ deflateSetHeader;
+ inflateGetHeader;
+} ZLIB_1.2.0.8;
+
+ZLIB_1.2.2.3 {
+ deflateTune;
+ gzdirect;
+} ZLIB_1.2.2;
+
+ZLIB_1.2.2.4 {
+ inflatePrime;
+} ZLIB_1.2.2.3;
+
+ZLIB_1.2.3.3 {
+ adler32_combine64;
+ crc32_combine64;
+ gzopen64;
+ gzseek64;
+ gztell64;
+ inflateUndermine;
+} ZLIB_1.2.2.4;
+
+ZLIB_1.2.3.4 {
+ inflateReset2;
+ inflateMark;
+} ZLIB_1.2.3.3;
+
+ZLIB_1.2.3.5 {
+ gzbuffer;
+ gzoffset;
+ gzoffset64;
+ gzclose_r;
+ gzclose_w;
+} ZLIB_1.2.3.4;
+
+ZLIB_1.2.5.1 {
+ deflatePending;
+} ZLIB_1.2.3.5;
+
+ZLIB_1.2.5.2 {
+ deflateResetKeep;
+ gzgetc_;
+ inflateResetKeep;
+} ZLIB_1.2.5.1;
+
+ZLIB_1.2.7.1 {
+ inflateGetDictionary;
+ gzvprintf;
+} ZLIB_1.2.5.2;
+
+ZLIB_1.2.9 {
+ inflateCodesUsed;
+ inflateValidate;
+ uncompress2;
+ gzfread;
+ gzfwrite;
+ deflateGetDictionary;
+ adler32_z;
+ crc32_z;
+} ZLIB_1.2.7.1;
+
+ZLIB_1.2.12 {
+ crc32_combine_gen;
+ crc32_combine_gen64;
+ crc32_combine_op;
+} ZLIB_1.2.9;
diff --git a/Sources/zlib-1.3.1/zutil.c b/Sources/zlib-1.3.1/zutil.c
new file mode 100644
index 00000000..b1c5d2d3
--- /dev/null
+++ b/Sources/zlib-1.3.1/zutil.c
@@ -0,0 +1,299 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2017 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+#ifndef Z_SOLO
+# include "gzguts.h"
+#endif
+
+z_const char * const z_errmsg[10] = {
+ (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */
+ (z_const char *)"stream end", /* Z_STREAM_END 1 */
+ (z_const char *)"", /* Z_OK 0 */
+ (z_const char *)"file error", /* Z_ERRNO (-1) */
+ (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */
+ (z_const char *)"data error", /* Z_DATA_ERROR (-3) */
+ (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */
+ (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */
+ (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
+ (z_const char *)""
+};
+
+
+const char * ZEXPORT zlibVersion(void) {
+ return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags(void) {
+ uLong flags;
+
+ flags = 0;
+ switch ((int)(sizeof(uInt))) {
+ case 2: break;
+ case 4: flags += 1; break;
+ case 8: flags += 2; break;
+ default: flags += 3;
+ }
+ switch ((int)(sizeof(uLong))) {
+ case 2: break;
+ case 4: flags += 1 << 2; break;
+ case 8: flags += 2 << 2; break;
+ default: flags += 3 << 2;
+ }
+ switch ((int)(sizeof(voidpf))) {
+ case 2: break;
+ case 4: flags += 1 << 4; break;
+ case 8: flags += 2 << 4; break;
+ default: flags += 3 << 4;
+ }
+ switch ((int)(sizeof(z_off_t))) {
+ case 2: break;
+ case 4: flags += 1 << 6; break;
+ case 8: flags += 2 << 6; break;
+ default: flags += 3 << 6;
+ }
+#ifdef ZLIB_DEBUG
+ flags += 1 << 8;
+#endif
+ /*
+#if defined(ASMV) || defined(ASMINF)
+ flags += 1 << 9;
+#endif
+ */
+#ifdef ZLIB_WINAPI
+ flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+ flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+ flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+ flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+ flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ flags += 1L << 20;
+#endif
+#ifdef FASTEST
+ flags += 1L << 21;
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifdef NO_vsnprintf
+ flags += 1L << 25;
+# ifdef HAS_vsprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_vsnprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#else
+ flags += 1L << 24;
+# ifdef NO_snprintf
+ flags += 1L << 25;
+# ifdef HAS_sprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_snprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#endif
+ return flags;
+}
+
+#ifdef ZLIB_DEBUG
+#include
+# ifndef verbose
+# define verbose 0
+# endif
+int ZLIB_INTERNAL z_verbose = verbose;
+
+void ZLIB_INTERNAL z_error(char *m) {
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(int err) {
+ return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
+ /* The older Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
+ int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) {
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) {
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) {
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+#ifndef Z_SOLO
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
+ voidpf buf;
+ ulg bsize = (ulg)items*size;
+
+ (void)opaque;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
+ int n;
+
+ (void)opaque;
+
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) {
+ (void)opaque;
+ return _halloc((long)items, size);
+}
+
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
+ (void)opaque;
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp malloc(uInt size);
+extern voidp calloc(uInt items, uInt size);
+extern void free(voidpf ptr);
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
+ (void)opaque;
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
+ (void)opaque;
+ free(ptr);
+}
+
+#endif /* MY_ZCALLOC */
+
+#endif /* !Z_SOLO */
diff --git a/Sources/zlib-1.3.1/zutil.h b/Sources/zlib-1.3.1/zutil.h
new file mode 100644
index 00000000..48dd7feb
--- /dev/null
+++ b/Sources/zlib-1.3.1/zutil.h
@@ -0,0 +1,254 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
+
+#include "zlib.h"
+
+#if defined(STDC) && !defined(Z_SOLO)
+# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
+# include
+# endif
+# include
+# include
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* since "static" is used to mean two completely different things in C, we
+ define "local" for the non-static meaning of "static", for readability
+ (compile with -Dlocal if your debugger can't find static symbols) */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
+# include
+# if (ULONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long
+# elif (ULLONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long long
+# elif (UINT_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned
+# endif
+#endif
+
+extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# ifndef Z_SOLO
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include
+# endif
+# else /* MSC or DJGPP */
+# include
+# endif
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 1
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 2
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef __370__
+# if __TARGET_LIB__ < 0x20000000
+# define OS_CODE 4
+# elif __TARGET_LIB__ < 0x40000000
+# define OS_CODE 11
+# else
+# define OS_CODE 8
+# endif
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 5
+#endif
+
+#ifdef OS2
+# define OS_CODE 6
+# if defined(M_I86) && !defined(Z_SOLO)
+# include
+# endif
+#endif
+
+#if defined(MACOS)
+# define OS_CODE 7
+#endif
+
+#ifdef __acorn
+# define OS_CODE 13
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+# define OS_CODE 10
+#endif
+
+#ifdef _BEOS_
+# define OS_CODE 16
+#endif
+
+#ifdef __TOS_OS400__
+# define OS_CODE 18
+#endif
+
+#ifdef __APPLE__
+# define OS_CODE 19
+#endif
+
+#if defined(__BORLANDC__) && !defined(MSDOS)
+ #pragma warn -8004
+ #pragma warn -8008
+ #pragma warn -8066
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_WIN32) && \
+ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
+ ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 3 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(pyr) || defined(Z_SOLO)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len);
+ int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len);
+ void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len);
+#endif
+
+/* Diagnostic functions */
+#ifdef ZLIB_DEBUG
+# include
+ extern int ZLIB_INTERNAL z_verbose;
+ extern void ZLIB_INTERNAL z_error(char *m);
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+#ifndef Z_SOLO
+ voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items,
+ unsigned size);
+ void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr);
+#endif
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+/* Reverse the bytes in a 32-bit value */
+#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+#endif /* ZUTIL_H */
diff --git a/USAGE.md b/USAGE.md
index 475185dc..2ec33d48 100644
--- a/USAGE.md
+++ b/USAGE.md
@@ -52,8 +52,9 @@ extension MyConnectionController: VNCConnectionDelegate {
}
func connection(_ connection: VNCConnection,
- framebuffer: VNCFramebuffer,
- didUpdateRegion updatedRegion: CGRect) {
+ didUpdateFramebuffer framebuffer: VNCFramebuffer,
+ x: UInt16, y: UInt16,
+ width: UInt16, height: UInt16) {
// TODO: Update the image in your framebuffer view
}
@@ -91,7 +92,7 @@ func connection(_ connection: VNCConnection,
}
```
- For a headless client, this is all that's needed to establish the connection and get notified about updates to it.
-- To send input to the remote host, use one of the `VNCConnection`'s input APIs like `keyDown(_:)`, `keyUp(_:)`, `mouseDown(_:)`, `mouseUp(_:)`, etc.
+- To send input to the remote host, use one of the `VNCConnection`'s input APIs like `keyDown(_:)`, `keyUp(_:)`, `mouseButtonDown(_:x:y:)`, `mouseButtonUp(_:x:y:)`, etc.
```swift
// Convert the string "abc" into VNCKeyCode's
let keyCodes = VNCKeyCode.keyCodesFrom(characters: "abc")
@@ -107,8 +108,8 @@ connection.keyDown(.return)
connection.keyUp(.return)
// Press Left Mouse Button at x: 10, y: 15
-connection.mouseDown(.init(x: 10, y: 15))
-connection.mouseUp(.init(x: 10, y: 15))
+connection.mouseButtonDown(.left, x: 10, y: 15)
+connection.mouseButtonUp(.left, x: 10, y: 15)
```
- If you want to close the connection, call `VNCConnection.disconnect()`. Note that this is a non-blocking/asynchronous method and likely will only complete some time after you call it. Don't assume the connection has been fully teared down immediately after the call to `disconnect()`. Instead, wait for `connection(_:stateDidChange:)` to be called with a status of `VNCConnection.Status.disconnected`. Once that has happened, you're not(!) supposed to (re-)use the connection anymore and discard your strong reference to it.
```swift
@@ -132,19 +133,20 @@ func connection(_ connection: VNCConnection,
## Handling framebuffer updates
- Now that you have a functioning headless VNC connection you will likely also want to allow the user to see and interact with the remote desktop.
-- To do so, you will have to implement additional `VNCConnectionDelegate` methods, namely `connection(_:didCreateFramebuffer:)`, `connection(_:didResizeFramebuffer:)`, `connection(_:framebuffer:didUpdateRegion:)` and `connection(_:didUpdateCursor:)`.
+- To do so, you will have to implement additional `VNCConnectionDelegate` methods, namely `connection(_:didCreateFramebuffer:)`, `connection(_:didResizeFramebuffer:)`, `connection(_:didUpdateFramebuffer:x:y:width:height:)` and `connection(_:didUpdateCursor:)`.
- `connection(_:didCreateFramebuffer:)` and `connection(_:didResizeFramebuffer:)` are called when a framebuffer has been created or resized respectively. In both cases, you will need to (re-)create a view for the framebuffer and present it.
-- `connection(_:framebuffer:didUpdateRegion:)` is called whenever a specific region of the framebuffer has been updated. This allows you to optimize updates to your framebuffer view so that you can only render a subset of the full framebuffer's bounds.
+- `connection(_:didUpdateFramebuffer:x:y:width:height:)` is called whenever a specific region of the framebuffer has been updated. This allows you to optimize updates to your framebuffer view so that you can only render a subset of the full framebuffer's bounds.
- Last but not least, `connection(_:didUpdateCursor:)` is called whenever the remote desktop requests that you show a local mouse cursor. Note that not all VNC servers support local cursors so in some cases this delegate method may never get called.
- To retrieve an image of the remote desktop's framebuffer, you use `VNCFramebuffer.ciImage` or `VNCFramebuffer.cgImage`, depending on the context you'll render the image in.
- Then it's up to you to display that image to the user. You can, for instance directly assign the `CGImage` to the `contents` property of an `CALayer` or use Metal to render the `CIImage`.
```swift
func connection(_ connection: VNCConnection,
- framebuffer: VNCFramebuffer,
- didUpdateRegion updatedRegion: CGRect) {
- // TODO: Only update updatedRegion part of the image
+ didUpdateFramebuffer framebuffer: VNCFramebuffer,
+ x: UInt16, y: UInt16,
+ width: UInt16, height: UInt16) {
+ // TODO: Only invalidate the part of the image that was updated, indicated by the x, y, width and height parameters
self.view.layer?.contents = framebuffer.cgImage
}
```
- RoyalVNCKit also provides some ready-to-use views that handle this for you (and more, including input handling). For instance, `VNCCAFramebufferView` is an `NSView` subclass for macOS.
- - Just initialize the view with a frame, framebuffer and connection, add it to your view hierarchy and then forward some of the connection's delegate methods to it, namely `connection(_:framebuffer:didUpdateRegion:)` and `connection(_:didUpdateCursor:)`.
+ - Just initialize the view with a frame, framebuffer and connection, add it to your view hierarchy and then forward some of the connection's delegate methods to it, namely `connection(_:didUpdateFramebuffer:x:y:width:height:)` and `connection(_:didUpdateCursor:)`.