This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,147 @@
name: Cross-platform tests
on:
pull_request:
push:
branches:
- 'master'
jobs:
test-with-setup-ocaml:
strategy:
fail-fast: false
matrix:
os:
- windows-latest
- ubuntu-latest
- macos-latest
ocaml-compiler:
- '4.13.x'
runs-on: ${{ matrix.os }}
name: test-ocaml / ${{ matrix.os }}-${{ matrix.ocaml-compiler }}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Hack Git CRLF for ocaml/setup-ocaml issue #529
if: ${{ startsWith(matrix.os, 'windows-') }}
run: |
& "C:\Program Files\Git\bin\git.exe" config --system core.autocrlf input
- name: OCaml ${{ matrix.ocaml-compiler }} with Dune cache
uses: ocaml/setup-ocaml@v2
if: ${{ !startsWith(matrix.os, 'windows-') }}
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
dune-cache: true
- name: OCaml ${{ matrix.ocaml-compiler }} without Dune cache
uses: ocaml/setup-ocaml@v2
if: ${{ startsWith(matrix.os, 'windows-') }}
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
dune-cache: false
- name: Install/build/test
run: |
opam install . --deps-only --with-test
opam exec -- dune build --display=short
opam exec -- dune runtest --display=short
setup-dkml:
uses: 'diskuv/dkml-workflows/.github/workflows/setup-dkml.yml@v0'
permissions: {} # remove all rights of GITHUB_TOKEN when it is passed to setup-dkml.yml
with:
ocaml-compiler: 4.12.1
test-with-setup-dkml:
needs: setup-dkml
strategy:
fail-fast: false
matrix:
include:
- os: windows-2019
abi-pattern: win32-windows_x86
dkml-host-abi: windows_x86
opam-root: D:/.opam
default_shell: msys2 {0}
msys2_system: MINGW32
msys2_packages: mingw-w64-i686-pkg-config
bits: "32"
- os: windows-2019
abi-pattern: win32-windows_x86_64
dkml-host-abi: windows_x86_64
opam-root: D:/.opam
default_shell: msys2 {0}
msys2_system: CLANG64
msys2_packages: mingw-w64-clang-x86_64-pkg-config
bits: "64"
- os: macos-latest
abi-pattern: macos-darwin_all
dkml-host-abi: darwin_x86_64
default_shell: sh
opam-root: /Users/runner/.opam
bits: "64"
- os: ubuntu-latest
abi-pattern: manylinux2014-linux_x86
bits: "32"
default_shell: sh
dkml-host-abi: linux_x86
opam-root: .ci/opamroot # local directory of $GITHUB_WORKSPACE so available to dockcross
- os: ubuntu-latest
abi-pattern: manylinux2014-linux_x86_64
bits: "64"
default_shell: sh
dkml-host-abi: linux_x86_64
opam-root: .ci/opamroot # local directory of $GITHUB_WORKSPACE so available to dockcross
runs-on: ${{ matrix.os }}
name: test-dkml / ${{ matrix.abi-pattern }}
defaults:
run:
shell: ${{ matrix.default_shell }}
env:
OPAMROOT: ${{ matrix.opam-root }}
COMPONENT: dkml-component-staging-opam${{ matrix.bits }}
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
path: .ci/dist
- name: Install MSYS2 (Windows)
if: startsWith(matrix.dkml-host-abi, 'windows_')
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msys2_system }}
update: true
install: >-
${{ matrix.msys2_packages }}
wget
make
rsync
diffutils
patch
unzip
git
tar
- name: Import build environments from setup-dkml
run: |
${{ needs.setup-dkml.outputs.import_func }}
import ${{ matrix.abi-pattern }}
- name: Cache Opam downloads by host
uses: actions/cache@v3
with:
path: ${{ matrix.opam-root }}/download-cache
key: ${{ matrix.dkml-host-abi }}
- name: Install/build/test
run: |
# Fix dependencies to work with MSVC
# - alcotest.1.4.0 works with MSVC; 1.5.0 does not
opamrun pin alcotest -k version 1.4.0 --no-action --yes
opamrun install . --deps-only --with-test --yes
opamrun exec -- dune build --display=short
opamrun exec -- dune runtest --display=short

17
unikernel/duniverse/digestif/.gitignore vendored Normal file
View file

@ -0,0 +1,17 @@
_build
setup.data
setup.log
doc/*.html
*.native
*.byte
*.so
lib/decompress_conf.ml
*.tar.gz
_tests
lib_test/files
zpipe
c/dpipe
*.install
*~
.merlin
_opam

View file

@ -0,0 +1,10 @@
version = 0.21.0
break-infix = fit-or-vertical
parse-docstrings = true
indicate-multiline-delimiters=no
nested-match=align
sequence-style=separator
break-before-in=auto
if-then-else=keyword-first
dock-collection-brackets=true
break-collection-expressions=wrap

View file

@ -0,0 +1,10 @@
#!/bin/sh
set -ex
opam install -y mirage
(cd mirage && mirage configure -t unix && make depends && mirage build && ./digestif_test && mirage clean && cd ..) || exit 1
(cd mirage && mirage configure -t hvt && make depends && mirage build && mirage clean && cd ..) || exit 1
if [ $(uname -m) = "amd64" ] || [ $(uname -m) = "x86_64" ]; then
(cd mirage && mirage configure -t xen && make depend && mirage build && mirage clean && cd ..) || exit 1
fi

View file

@ -0,0 +1,18 @@
language: c
install:
- wget https://raw.githubusercontent.com/ocaml/ocaml-travisci-skeleton/master/.travis-opam.sh
- wget https://raw.githubusercontent.com/dinosaure/ocaml-travisci-skeleton/master/.travis-docgen.sh
script: bash -ex .travis-opam.sh
sudo: true
env:
global:
- PACKAGE=digestif
matrix:
- OCAML_VERSION=4.03
- OCAML_VERSION=4.04
- OCAML_VERSION=4.05
- OCAML_VERSION=4.06
- OCAML_VERSION=4.07
- OCAML_VERSION=4.08 DEPOPTS="ocaml-freestanding"
- OCAML_VERSION=4.08
- OCAML_VERSION=4.09 TESTS=false POST_INSTALL_HOOK=./.test-mirage.sh

View file

@ -0,0 +1,169 @@
### v1.3.0 2025-04-14 Paris (France)
- Use `CAMLextern` rather than `extern` in `caml_*` forward declarations to
support bytecode linking on Windows (@jonahbeckford, #157)
- Add `x-maintenance-intent` into OPAM file (@hannesm, #158)
- Implement _feedable_ hmac (@reynir, #155)
### v1.2.0 2024-03-18 Paris (France)
- Update the description to include SHA3 (@Leonidas-from-XIV, #146)
- Add a new type `hash'`, a polymorphic variant (@reynir, @dinosaure, #150)
- Lint `fmt` dependency lower-bound (@reynir, #152)
- Add `get_into_bytes` function and a fuzzer about it (@reynir, @dinosaure, #149)
### v1.1.4 2023-03-23 Paris (France)
- Add a test about CVE-2022-37454 (@dinosaure, #143)
- Lint the distribution and delete the `pkg-config` dependency (@dinosuare, 1eff5c5)
- Fix primitives used for bytes and fix the support of `js_of_ocaml` 5 (@hhugo, #144)
### v1.1.3 2022-10-20 Paris (France)
- Support MSVC compiler (@jonahbeckford, #137)
- Fix CI on Windows (`test_conv.ml` requires `/dev/urandom`) (@dinosaure, #138)
- Fix threads support (@dinosaure, #140)
- Delete the META trick needed for MirageOS 3 when we install `digestif` (@dinosaure, #141)
This version of `digestif` breaks the compatibility with MirageOS 3
and `ocaml-freestanding`. This PR should unlock the ability to
use `dune-cache`.
### v1.1.2 2022-04-08 Paris (France)
- Minor update on the README.md (@punchagan, #133)
- Support only OCaml >= 4.08, update with `ocamlformat.0.21.0` and remove `bigarray-compat`
dependency (@hannesm, #134)
### v1.1.1 2022-03-28 Paradou (France)
- Hide C functions (`sha3_keccakf`) (@hannesm, #125)
- Use `ocaml` to run `install.ml` instead of a shebang (@Nymphium, #127)
- Use `command -v` instead of `which` (@Numphium, #126)
- Add `@since` meta-data in documentation (@c-cube, @dinosaure, #128)
- Update the README.md (@dinosaure, @mimoo, #130)
- `ocaml-solo5` provides `__ocaml_solo5__` instead of `__ocaml_freestanding__` (@dinosaure, #131)
### v1.1.0 2021-10-11 Paris (France)
- Add Keccak256 module (ethereum padding) (@maxtori, @dinosaure, #118)
- Update README.md to include the documentation (@mimoo, @dinosaure, 65a5c12)
- Remove deprecated function from `fmt` library (@dinosaure, #121)
- **NOTE**: This version lost the support of OCaml 4.03 and OCaml 4.04.
### v1.0.1 2020-02-08 Paris (France)
- Fix `esy` support (@dinosaure, #115)
- Fix big-endian support (@dinosaure, #113)
### v1.0.0 2020-11-02 Paris (France)
- **breaking changes** Upgrade the library with MirageOS 3.9 (new layout of artifacts)
Add tests about compilation of unikernels (execution and link)
(#105, @dinosaure, @hannesm)
- Fix `esy` installation (#104, @dinosaure)
- **breaking changes** Better GADT (#103, @dinosaure)
As far as I can tell, nobody really use this part of `digestif`.
The idea is to provide a GADT which contains the type of the hash.
From third-part libraries point-of-view, it's better to _pattern-match_ with
such information instead to use a polymorphic variant (as before).
- **breaking changes** key used for HMAC is a constant `string` (#101, @dinosaure, @hannesm)
The key should not follow the same type as the digest value (`string`, `bytes`, `bigstring`).
This update restricts the user to user only constant key (as a `string`).
### v0.9.0 2020-07-10 Paris (France)
- Add sha3 implementation (#98), @lyrm, @dinosaure, @hannesm and @cfcs
### v0.8.1 2020-06-15 Paris (France)
- Move to `dune.2.6.0` (#97)
- Apply `ocamlformat.0.14.2` (#97)
- Fix tests according `alcotest.1.0.0` (#95)
### v0.8.0 2019-20-09 Saint Louis (Sénégal)
- Fake version to prioritize dune's variants instead of
old linking trick
- Use `stdlib-shims` to keep compatibility with < ocaml.4.07.0
### v0.7.3 2019-07-09 Paris (France)
- Fix bug about specialization of BLAKE2{B,S} (#85, #86)
reported by @samoht, fixed by @dinosaure, reviewed by @hannes and @cfcs
### v0.7.2 2019-05-16 Paris (France)
- Add conflict with `< mirage-xen-posix.3.1.0` packages (@hannesm)
- Add a note on README.md about the linking-trick and order of dependencies (@rizo)
- Use experimental feature of variants with `dune` (@dinosaure, review @rgrinberg)
`digestif` requires at least `dune.1.9.2`
### v0.7.1 2018-11-15 Paris (France)
- Cross compilation adjustments (@hannesm) (# 76)
- Add the WHIRLPOOL hash algorithm (@clecat) (#77)
- Backport fix on opam file (@dinosaure, @kit-ty-kate)
### v0.7 2018-10-15 Paris (France)
- Fixed HMAC on BLAKE2{S,B} (@emillon) (#46, #51)
- Fixed `convenient_of_hex` (@dinosaure, @hannesm, @cfcs) (#55)
- Add `of_raw_string`/`to_raw_string` (@samoht) (#57)
- Test `digestif` on solo5 and xen backends (@samoht)
- *breaking change*, commont type `t` is an abstract type (#58, #56)
- Fixed META file (@dinosaure, @g2p) (#75)
- New dependency `eqaf` (@dinosaure, @cfcs, @hannesm) (constant-time equal function) (#33, #34, #48, #50, #52, #65)
- Remove `Obj.magic` in common implementation (@dinosaure, @samoht) (#61, #62)
- Add conveniences functions in common implementation (@hcarty) (#63)
- Add option-returning functions in common implementation (@harcty) (#63)
- Verify length of string on `of_raw_string` function (@hcarty) (#63)
- Release runtime lock (@andersfugmann, @dinosaure, @cfcs) (#69, #70)
- Bounds check (@cfcs, @dinosaure) (#71, #72)
- Fixed linking problem (@andersfugmann, @g2p, @dinosaure) (#49, #53, #73, #74)
- Update OPAM file (@dinosaure)
### v0.6.1 2018-07-24 Paris (France)
- *breaking change* API: Digestif implements a true linking trick. End-user need
to explicitely link with `digestif.{c,ocaml}` and it needs to be the first of
your dependencies.
- move to `jbuilder`/`dune`
### v0.6 2018-07-05 Paris (France)
- *breaking change* API:
From a consensus between people who use `digestif`, we decide to delete `*.Bytes.*` and `*.Bigstring.*` sub-modules.
We replace it by `feed_{bytes,string,bigstring}` (`digest_`, and `hmac_` too)
- *breaking change* semantic: streaming and referentially transparent
Add `feedi_{bytes,string,bigstring}`, `digesti_{bytes,string,bigstring}` and `hmaci_{bytes,string,bigstring}`
(@hannesm, @cfcs)
- Constant time for `eq`/`neq` functions
(@cfcs)
- *breaking change* semantic on `compare` and `unsafe_compare`:
`compare` is not a lexicographical comparison function (rename to `unsafe_compare`)
(@cfcs)
- Add `consistent_of_hex` (@hannesm, @cfcs)
### v0.4 2017-10-30 Mysore / ಮೈಸೂರು (India)
- Add an automatised test suit
- Add the RIPEMD160 hash algorithm
- Add the BLAKE2S hash algorithm
- Update authors
- Add `feed_bytes` and `feed_bigstring` for `Bytes` and `Bigstring`
### v0.3 2017-07-21 Phnom Penh (Cambodia)
- Fixed issue #6
- Make a new test suit
### v0.2 2017-07-05 Phnom Penh (Cambodia)
- Implementation of the hash function in pure OCaml
- Link improvement (à la `mtime`) to decide to use the C stub or the OCaml implementation
- Improvement of the common interface (pretty-print, type t, etc.)
### v0.1 2017-05-12 Rạch Giá (Vietnam)
- First release

View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2014 oklm-wsh
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,10 @@
.PHONY: all clean test
all:
dune build
test:
dune runtest
clean:
dune clean

View file

@ -0,0 +1,119 @@
Digestif - Hash algorithms in C and OCaml
=========================================
Digestif is a toolbox which implements hashes:
* MD5
* SHA1
* SHA2
* SHA3
* WHIRLPOOL
* BLAKE2B
* BLAKE2S
* RIPEMD160
Digestif uses a trick about linking and let the end-user to choose which
implementation he wants to use. We provide 2 implementations:
* C implementation with `digestif.c`
* OCaml implementation with `digestif.ocaml`
Both are well-tested. However, OCaml implementation is slower than the C
implementation.
**Note**: The linking trick requires `digestif.c` or `digestif.ocaml` to be the
first of your dependencies.
Documentation: https://mirage.github.io/digestif/
Contact: Romain Calascibetta `<romain.calascibet ta@gmail.com>`
## Install & Usage
The library is available on [OPAM](https://opam.ocaml.org/packages/digestif/). You can install it via:
```sh
$ opam install digestif
```
This is a simple program which implements `sha1sum`:
```sh
$ cat >sha1sum.ml <<EOF
let sum ic =
let tmp = Bytes.create 0x1000 in
let rec go ctx = match input ic tmp 0 0x1000 with
| 0 -> Digestif.SHA1.get ctx
| len ->
let ctx = Digestif.SHA1.feed_bytes ctx ~off:0 ~len tmp in
go ctx
| exception End_of_file -> Digestif.SHA1.get ctx in
go Digestif.SHA1.empty
let () = match Sys.argv with
| [| _; filename; |] when Sys.file_exists filename ->
let ic = open_in filename in
let hash = sum ic in
close_in ic ; print_endline (Digestif.SHA1.to_hex hash)
| [| _ |] ->
let hash = sum stdin in
print_endline (Digestif.SHA1.to_hex hash)
| _ -> Format.eprintf "%s [<filename>]\n%!" Sys.argv.(0)
EOF
$ cat >dune <<EOF
(executable
(name sha1sum)
(libraries digestif))
EOF
$ dune exec ./sha1sum.exe -- sha1sum.ml
fe6e6639a817c23857b507e2d833ec776f23f327
```
## API
For each hash, we implement the same API which is referentially transparent.
Then, on the top of these, we reflect functions (like `digesti` or `hmaci`) with
GADT - however, conversion from GADT to hash type is not possible (but you can
_destruct_ GADT with `to_raw_string`).
## Equal/Compare function
We deciced to protect users to timing-attack. In this case, `Digestif.equal` (by
[eqaf](https://github.com/mirage/eqaf.git) package) compares hashes in
constant-time.
However, we provide `unsafe_compare` function too which is __not__ a constant
time function. In some contexts, like `ocaml-git`, we don't care about timing
attack and we use `unsafe_compare` - then, we need to make a wrap where we
rename `unsafe_compare` to `compare` to be able to use it in some functors like
`Map.Make` or `Set.Make`.
It's little annoying to do that but it forces the user to get the right question
about security issues. So, please, don't ask to rename this function.
## MirageOS
Of course, this package is available to be used on MirageOS (both
implementations). User is able to compile `digestif.ocaml` with `js_of_ocaml`
and this package is platform agnostic.
## Build Requirements
* OCaml >= 4.03.0 (may be less but need test)
* `base-bytes` meta-package
* `base-bigarray` meta-package
* `dune` to build the project
If you want to compile the test program, you need:
* `alcotest`
## Credits
This work is from the [nocrypto](https://github.com/mirleft/nocrypto) library
and the Vincent hanquez's work in
[ocaml-sha](https://github.com/vincenthz/ocaml-sha).
All credits appear in the begin of files and this library is motivated by two
reasons:
* delete the dependancy with `nocrypto` if you don't use the encryption (and
common) part
* aggregate all hashes functions in one library

View file

@ -0,0 +1,61 @@
version: "1.3.0"
opam-version: "2.0"
name: "digestif"
maintainer: [ "Eyyüb Sari <eyyub.sari@epitech.eu>"
"Romain Calascibetta <romain.calascibetta@gmail.com>" ]
authors: [ "Eyyüb Sari <eyyub.sari@epitech.eu>"
"Romain Calascibetta <romain.calascibetta@gmail.com>" ]
homepage: "https://github.com/mirage/digestif"
bug-reports: "https://github.com/mirage/digestif/issues"
dev-repo: "git+https://github.com/mirage/digestif.git"
doc: "https://mirage.github.io/digestif/"
license: "MIT"
synopsis: "Hashes implementations (SHA*, RIPEMD160, BLAKE2* and MD5)"
description: """
Digestif is a toolbox to provide hashes implementations in C and OCaml.
It uses the linking trick and user can decide at the end to use the C implementation or the OCaml implementation.
We provides implementation of:
* MD5
* SHA1
* SHA224
* SHA256
* SHA384
* SHA512
* SHA3
* Keccak-256
* WHIRLPOOL
* BLAKE2B
* BLAKE2S
* RIPEMD160
"""
build: [
[ "dune" "build" "-p" name "-j" jobs ]
[ "dune" "runtest" "-p" name "-j" jobs ] {with-test}
]
install: [
[ "dune" "install" "-p" name ] {with-test}
[ "ocaml" "./test/test_runes.ml" ] {with-test}
]
depends: [
"ocaml" {>= "4.08.0"}
"dune" {>= "2.6.0"}
"eqaf"
"fmt" {with-test & >= "0.8.7"}
"alcotest" {with-test}
"bos" {with-test}
"astring" {with-test}
"fpath" {with-test}
"rresult" {with-test}
"ocamlfind" {with-test}
"crowbar" {with-test}
]
conflicts: [
"mirage-xen" {< "6.0.0"}
"ocaml-freestanding"
]
x-maintenance-intent: [ "(latest)" ]

View file

@ -0,0 +1,3 @@
(lang dune 2.6)
(name digestif)
(version v1.3.0)

View file

@ -0,0 +1,6 @@
(executable
(name fuzz)
(libraries digestif.c crowbar))
(rule
(copy# ../fuzz.ml fuzz.ml))

View file

@ -0,0 +1,25 @@
(rule
(copy# fuzz.ml fuzz_c.ml))
(rule
(copy# fuzz.ml fuzz_ocaml.ml))
(executable
(name fuzz_c)
(modules fuzz_c)
(libraries digestif.c crowbar))
(executable
(name fuzz_ocaml)
(modules fuzz_ocaml)
(libraries digestif.ocaml crowbar))
(rule
(alias runtest)
(action
(run ./fuzz_ocaml.exe)))
(rule
(alias runtest)
(action
(run ./fuzz_c.exe)))

View file

@ -0,0 +1,32 @@
open Crowbar
type pack = Pack : 'a Digestif.hash -> pack
let hash =
choose
[
const (Pack Digestif.sha1); const (Pack Digestif.sha256);
const (Pack Digestif.sha512);
]
let with_get_into_bytes off len (type ctx)
(module Hash : Digestif.S with type ctx = ctx) (ctx : ctx) =
let buf = Bytes.create len in
let () =
try Hash.get_into_bytes ctx ~off buf
with Invalid_argument e -> (
(* Skip if the invalid argument is valid; otherwise fail *)
match Bytes.sub buf off Hash.digest_size with
| _ -> failf "Hash.get_into_bytes: Invalid_argument %S" e
| exception Invalid_argument _ -> bad_test ()) in
Bytes.sub_string buf off Hash.digest_size
let () =
add_test ~name:"get_into_bytes" [ hash; int8; range 1024; bytes ]
@@ fun (Pack hash) off len bytes ->
let (module Hash) = Digestif.module_of hash in
let ctx = Hash.empty in
let ctx = Hash.feed_string ctx bytes in
let a = with_get_into_bytes off len (module Hash) ctx in
let b = Hash.(to_raw_string (get ctx)) in
check_eq ~eq:String.equal a b

View file

@ -0,0 +1,6 @@
(executable
(name fuzz)
(libraries digestif.ocaml crowbar))
(rule
(copy# ../fuzz.ml fuzz.ml))

View file

@ -0,0 +1 @@
true: package(digestif.c)

View file

@ -0,0 +1,5 @@
open Mirage
let main = foreign "Unikernel.Make" (console @-> job)
let packages = [ package "digestif" ]
let () = register ~packages "digestif-test" [ main $ default_console ]

View file

@ -0,0 +1,7 @@
module Make (Console : Mirage_console.S) = struct
let log console fmt = Format.kasprintf (Console.log console) fmt
let start console =
let hash = Digestif.SHA1.digest_string "Hello World!" in
log console "%a" Digestif.SHA1.pp hash
end

View file

@ -0,0 +1,777 @@
type bigstring =
(char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
type 'a iter = ('a -> unit) -> unit
type 'a compare = 'a -> 'a -> int
type 'a equal = 'a -> 'a -> bool
type 'a pp = Format.formatter -> 'a -> unit
module Native = Digestif_native
module By = Digestif_by
module Bi = Digestif_bi
module Eq = Digestif_eq
module Conv = Digestif_conv
let failwith fmt = Format.ksprintf failwith fmt
module type S = sig
val digest_size : int
type ctx
type hmac
type t
val empty : ctx
val init : unit -> ctx
val feed_bytes : ctx -> ?off:int -> ?len:int -> Bytes.t -> ctx
val feed_string : ctx -> ?off:int -> ?len:int -> String.t -> ctx
val feed_bigstring : ctx -> ?off:int -> ?len:int -> bigstring -> ctx
val feedi_bytes : ctx -> Bytes.t iter -> ctx
val feedi_string : ctx -> String.t iter -> ctx
val feedi_bigstring : ctx -> bigstring iter -> ctx
val get : ctx -> t
val hmac_init : key:string -> hmac
val hmac_feed_bytes : hmac -> ?off:int -> ?len:int -> Bytes.t -> hmac
val hmac_feed_string : hmac -> ?off:int -> ?len:int -> String.t -> hmac
val hmac_feed_bigstring : hmac -> ?off:int -> ?len:int -> bigstring -> hmac
val hmac_feedi_bytes : hmac -> Bytes.t iter -> hmac
val hmac_feedi_string : hmac -> String.t iter -> hmac
val hmac_feedi_bigstring : hmac -> bigstring iter -> hmac
val hmac_get : hmac -> t
val digest_bytes : ?off:int -> ?len:int -> Bytes.t -> t
val digest_string : ?off:int -> ?len:int -> String.t -> t
val digest_bigstring : ?off:int -> ?len:int -> bigstring -> t
val digesti_bytes : Bytes.t iter -> t
val digesti_string : String.t iter -> t
val digesti_bigstring : bigstring iter -> t
val digestv_bytes : Bytes.t list -> t
val digestv_string : String.t list -> t
val digestv_bigstring : bigstring list -> t
val hmac_bytes : key:string -> ?off:int -> ?len:int -> Bytes.t -> t
val hmac_string : key:string -> ?off:int -> ?len:int -> String.t -> t
val hmac_bigstring : key:string -> ?off:int -> ?len:int -> bigstring -> t
val hmaci_bytes : key:string -> Bytes.t iter -> t
val hmaci_string : key:string -> String.t iter -> t
val hmaci_bigstring : key:string -> bigstring iter -> t
val hmacv_bytes : key:string -> Bytes.t list -> t
val hmacv_string : key:string -> String.t list -> t
val hmacv_bigstring : key:string -> bigstring list -> t
val unsafe_compare : t compare
val equal : t equal
val pp : t pp
val of_hex : string -> t
val of_hex_opt : string -> t option
val consistent_of_hex : string -> t
val consistent_of_hex_opt : string -> t option
val to_hex : t -> string
val of_raw_string : string -> t
val of_raw_string_opt : string -> t option
val to_raw_string : t -> string
val get_into_bytes : ctx -> ?off:int -> bytes -> unit
end
module type MAC = sig
type t
val mac_bytes : key:string -> ?off:int -> ?len:int -> Bytes.t -> t
val mac_string : key:string -> ?off:int -> ?len:int -> String.t -> t
val mac_bigstring : key:string -> ?off:int -> ?len:int -> bigstring -> t
val maci_bytes : key:string -> Bytes.t iter -> t
val maci_string : key:string -> String.t iter -> t
val maci_bigstring : key:string -> bigstring iter -> t
val macv_bytes : key:string -> Bytes.t list -> t
val macv_string : key:string -> String.t list -> t
val macv_bigstring : key:string -> bigstring list -> t
end
module type Foreign = sig
open Native
module Bigstring : sig
val init : ctx -> unit
val update : ctx -> ba -> int -> int -> unit
val finalize : ctx -> ba -> int -> unit
end
module Bytes : sig
val init : ctx -> unit
val update : ctx -> st -> int -> int -> unit
val finalize : ctx -> st -> int -> unit
end
val ctx_size : unit -> int
end
module type Desc = sig
val block_size : int
val digest_size : int
end
module Unsafe (F : Foreign) (D : Desc) = struct
let block_size = D.block_size
and digest_size = D.digest_size
and ctx_size = F.ctx_size ()
let init () =
let t = By.create ctx_size in
F.Bytes.init t ;
t
let empty =
let buf = Bytes.create ctx_size in
F.Bytes.init buf ;
buf
let unsafe_feed_bytes t ?off ?len buf =
let off, len =
match (off, len) with
| Some off, Some len -> (off, len)
| Some off, None -> (off, By.length buf - off)
| None, Some len -> (0, len)
| None, None -> (0, By.length buf) in
if off < 0 || len < 0 || off > By.length buf - len
then invalid_arg "offset out of bounds"
else F.Bytes.update t buf off len
let unsafe_feed_string t ?off ?len buf =
unsafe_feed_bytes t ?off ?len (Bytes.unsafe_of_string buf)
let unsafe_feed_bigstring t ?off ?len buf =
let off, len =
match (off, len) with
| Some off, Some len -> (off, len)
| Some off, None -> (off, Bi.length buf - off)
| None, Some len -> (0, len)
| None, None -> (0, Bi.length buf) in
if off < 0 || len < 0 || off > Bi.length buf - len
then invalid_arg "offset out of bounds"
else F.Bigstring.update t buf off len
let unsafe_get t =
let res = By.create digest_size in
By.fill res 0 digest_size '\000' ;
F.Bytes.finalize t res 0 ;
res
let get_into_bytes t ?(off = 0) buf =
if off < 0 || off >= Bytes.length buf
then invalid_arg "offset out of bounds" ;
if Bytes.length buf - off < digest_size
then invalid_arg "destination too small" ;
F.Bytes.finalize (Native.dup t) buf off
end
module Core (F : Foreign) (D : Desc) = struct
type t = string
type ctx = Native.ctx
include Unsafe (F) (D)
include Conv.Make (D)
include Eq.Make (D)
let get t =
let t = Native.dup t in
unsafe_get t |> By.unsafe_to_string
let feed_bytes t ?off ?len buf =
let t = Native.dup t in
unsafe_feed_bytes t ?off ?len buf ;
t
let feed_string t ?off ?len buf =
let t = Native.dup t in
unsafe_feed_string t ?off ?len buf ;
t
let feed_bigstring t ?off ?len buf =
let t = Native.dup t in
unsafe_feed_bigstring t ?off ?len buf ;
t
let feedi_bytes t iter =
let t = Native.dup t in
let feed buf = unsafe_feed_bytes t buf in
iter feed ;
t
let feedi_string t iter =
let t = Native.dup t in
let feed buf = unsafe_feed_string t buf in
iter feed ;
t
let feedi_bigstring t iter =
let t = Native.dup t in
let feed buf = unsafe_feed_bigstring t buf in
iter feed ;
t
let digest_bytes ?off ?len buf = feed_bytes empty ?off ?len buf |> get
let digest_string ?off ?len buf = feed_string empty ?off ?len buf |> get
let digest_bigstring ?off ?len buf = feed_bigstring empty ?off ?len buf |> get
let digesti_bytes iter = feedi_bytes empty iter |> get
let digesti_string iter = feedi_string empty iter |> get
let digesti_bigstring iter = feedi_bigstring empty iter |> get
let digestv_bytes lst = digesti_bytes (fun f -> List.iter f lst)
let digestv_string lst = digesti_string (fun f -> List.iter f lst)
let digestv_bigstring lst = digesti_bigstring (fun f -> List.iter f lst)
end
module Make (F : Foreign) (D : Desc) = struct
include Core (F) (D)
type hmac = ctx * string
let bytes_opad = By.make block_size '\x5c'
let bytes_ipad = By.make block_size '\x36'
let rec norm_bytes key =
match Stdlib.compare (String.length key) block_size with
| 1 -> norm_bytes (digest_string key)
| -1 -> By.rpad (By.unsafe_of_string key) block_size '\000'
| _ -> By.of_string key
let hmac_init ~key =
let key = norm_bytes key in
let outer = Native.XOR.Bytes.xor key bytes_opad in
let inner = Native.XOR.Bytes.xor key bytes_ipad in
let ctx = feed_bytes empty inner in
(ctx, Bytes.unsafe_to_string outer)
let hmac_feed_bytes (t, outer) ?off ?len buf =
(feed_bytes t ?off ?len buf, outer)
let hmac_feed_string (t, outer) ?off ?len buf =
(feed_string t ?off ?len buf, outer)
let hmac_feed_bigstring (t, outer) ?off ?len buf =
(feed_bigstring t ?off ?len buf, outer)
let hmac_get (ctx, outer) =
feed_string (feed_string empty outer) (get ctx) |> get
let hmac_feedi_bytes (t, outer) iter = (feedi_bytes t iter, outer)
let hmac_feedi_string (t, outer) iter = (feedi_string t iter, outer)
let hmac_feedi_bigstring (t, outer) iter = (feedi_bigstring t iter, outer)
let hmaci_bytes ~key iter =
let t = hmac_init ~key in
hmac_feedi_bytes t iter |> hmac_get
let hmaci_string ~key iter =
let t = hmac_init ~key in
hmac_feedi_string t iter |> hmac_get
let hmaci_bigstring ~key iter =
let t = hmac_init ~key in
hmac_feedi_bigstring t iter |> hmac_get
let hmac_bytes ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> By.sub buf off len
| Some off, None -> By.sub buf off (By.length buf - off)
| None, Some len -> By.sub buf 0 len
| None, None -> buf in
hmaci_bytes ~key (fun f -> f buf)
let hmac_string ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> String.sub buf off len
| Some off, None -> String.sub buf off (String.length buf - off)
| None, Some len -> String.sub buf 0 len
| None, None -> buf in
hmaci_string ~key (fun f -> f buf)
let hmac_bigstring ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> Bi.sub buf off len
| Some off, None -> Bi.sub buf off (Bi.length buf - off)
| None, Some len -> Bi.sub buf 0 len
| None, None -> buf in
hmaci_bigstring ~key (fun f -> f buf)
let hmacv_bytes ~key bufs = hmaci_bytes ~key (fun f -> List.iter f bufs)
let hmacv_string ~key bufs = hmaci_string ~key (fun f -> List.iter f bufs)
let hmacv_bigstring ~key bufs =
hmaci_bigstring ~key (fun f -> List.iter f bufs)
end
(* XXX(dinosaure): this interface provide a new function to set digest size and
key. See #20. *)
module type Foreign_BLAKE2 = sig
open Native
module Bigstring : sig
val update : ctx -> ba -> int -> int -> unit
val finalize : ctx -> ba -> int -> unit
val with_outlen_and_key : ctx -> int -> ba -> int -> int -> unit
end
module Bytes : sig
val update : ctx -> st -> int -> int -> unit
val finalize : ctx -> st -> int -> unit
val with_outlen_and_key : ctx -> int -> st -> int -> int -> unit
end
val max_outlen : unit -> int
val ctx_size : unit -> int
val key_size : unit -> int
end
module Make_BLAKE2 (F : Foreign_BLAKE2) (D : Desc) = struct
let () =
if D.digest_size > F.max_outlen ()
then
failwith "Invalid digest_size:%d to make a BLAKE2{S,B} implementation"
D.digest_size
include
Make
(struct
module Bigstring = struct
let init ctx =
F.Bigstring.with_outlen_and_key ctx D.digest_size Bi.empty 0 0
let update = F.Bigstring.update
let finalize = F.Bigstring.finalize
end
module Bytes = struct
let init ctx =
F.Bytes.with_outlen_and_key ctx D.digest_size By.empty 0 0
let update = F.Bytes.update
let finalize = F.Bytes.finalize
end
let ctx_size () = F.ctx_size ()
end)
(D)
type outer = t
module Keyed = struct
type t = outer
let key_size = F.key_size ()
let maci_bytes ~key iter : t =
if String.length key > key_size
then invalid_arg "BLAKE2{S,B}.Keyed.maci_bytes: invalid key" ;
let ctx = By.create ctx_size in
F.Bytes.with_outlen_and_key ctx digest_size (By.unsafe_of_string key) 0
(String.length key) ;
feedi_bytes ctx iter |> get
let maci_string ~key iter =
if String.length key > key_size
then invalid_arg "BLAKE2{S,B}.Keyed.maci_string: invalid key" ;
let ctx = By.create ctx_size in
F.Bytes.with_outlen_and_key ctx digest_size (By.unsafe_of_string key) 0
(String.length key) ;
feedi_string ctx iter |> get
let maci_bigstring ~key iter =
if String.length key > key_size
then invalid_arg "BLAKE2{S,B}.Keyed.maci_bigstring: invalid key" ;
let ctx = By.create ctx_size in
F.Bytes.with_outlen_and_key ctx digest_size (By.unsafe_of_string key) 0
(String.length key) ;
feedi_bigstring ctx iter |> get
let mac_bytes ~key ?off ?len buf : t =
let buf =
match (off, len) with
| Some off, Some len -> By.sub buf off len
| Some off, None -> By.sub buf off (By.length buf - off)
| None, Some len -> By.sub buf 0 len
| None, None -> buf in
maci_bytes ~key (fun f -> f buf)
let mac_string ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> String.sub buf off len
| Some off, None -> String.sub buf off (String.length buf - off)
| None, Some len -> String.sub buf 0 len
| None, None -> buf in
maci_string ~key (fun f -> f buf)
let mac_bigstring ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> Bi.sub buf off len
| Some off, None -> Bi.sub buf off (Bi.length buf - off)
| None, Some len -> Bi.sub buf 0 len
| None, None -> buf in
maci_bigstring ~key (fun f -> f buf)
let macv_bytes ~key bufs = maci_bytes ~key (fun f -> List.iter f bufs)
let macv_string ~key bufs = maci_string ~key (fun f -> List.iter f bufs)
let macv_bigstring ~key bufs =
maci_bigstring ~key (fun f -> List.iter f bufs)
end
end
module MD5 : S =
Make
(Native.MD5)
(struct
let digest_size, block_size = (16, 64)
end)
module SHA1 : S =
Make
(Native.SHA1)
(struct
let digest_size, block_size = (20, 64)
end)
module SHA224 : S =
Make
(Native.SHA224)
(struct
let digest_size, block_size = (28, 64)
end)
module SHA256 : S =
Make
(Native.SHA256)
(struct
let digest_size, block_size = (32, 64)
end)
module SHA384 : S =
Make
(Native.SHA384)
(struct
let digest_size, block_size = (48, 128)
end)
module SHA512 : S =
Make
(Native.SHA512)
(struct
let digest_size, block_size = (64, 128)
end)
module SHA3_224 : S =
Make
(Native.SHA3_224)
(struct
let digest_size, block_size = (28, 144)
end)
module SHA3_256 : S =
Make
(Native.SHA3_256)
(struct
let digest_size, block_size = (32, 136)
end)
module KECCAK_256 : S =
Make
(Native.KECCAK_256)
(struct
let digest_size, block_size = (32, 136)
end)
module SHA3_384 : S =
Make
(Native.SHA3_384)
(struct
let digest_size, block_size = (48, 104)
end)
module SHA3_512 : S =
Make
(Native.SHA3_512)
(struct
let digest_size, block_size = (64, 72)
end)
module WHIRLPOOL : S =
Make
(Native.WHIRLPOOL)
(struct
let digest_size, block_size = (64, 64)
end)
module BLAKE2B : sig
include S
module Keyed : MAC with type t = t
end =
Make_BLAKE2
(Native.BLAKE2B)
(struct
let digest_size, block_size = (64, 128)
end)
module BLAKE2S : sig
include S
module Keyed : MAC with type t = t
end =
Make_BLAKE2
(Native.BLAKE2S)
(struct
let digest_size, block_size = (32, 64)
end)
module RMD160 : S =
Make
(Native.RMD160)
(struct
let digest_size, block_size = (20, 64)
end)
module Make_BLAKE2B (D : sig
val digest_size : int
end) : S = struct
include
Make_BLAKE2
(Native.BLAKE2B)
(struct
let digest_size, block_size = (D.digest_size, 128)
end)
end
module Make_BLAKE2S (D : sig
val digest_size : int
end) : S = struct
include
Make_BLAKE2
(Native.BLAKE2S)
(struct
let digest_size, block_size = (D.digest_size, 64)
end)
end
type 'k hash =
| MD5 : MD5.t hash
| SHA1 : SHA1.t hash
| RMD160 : RMD160.t hash
| SHA224 : SHA224.t hash
| SHA256 : SHA256.t hash
| SHA384 : SHA384.t hash
| SHA512 : SHA512.t hash
| SHA3_224 : SHA3_224.t hash
| SHA3_256 : SHA3_256.t hash
| KECCAK_256 : KECCAK_256.t hash
| SHA3_384 : SHA3_384.t hash
| SHA3_512 : SHA3_512.t hash
| WHIRLPOOL : WHIRLPOOL.t hash
| BLAKE2B : BLAKE2B.t hash
| BLAKE2S : BLAKE2S.t hash
let md5 = MD5
let sha1 = SHA1
let rmd160 = RMD160
let sha224 = SHA224
let sha256 = SHA256
let sha384 = SHA384
let sha512 = SHA512
let sha3_224 = SHA3_224
let sha3_256 = SHA3_256
let keccak_256 = KECCAK_256
let sha3_384 = SHA3_384
let sha3_512 = SHA3_512
let whirlpool = WHIRLPOOL
let blake2b = BLAKE2B
let blake2s = BLAKE2S
type hash' =
[ `MD5
| `SHA1
| `RMD160
| `SHA224
| `SHA256
| `SHA384
| `SHA512
| `SHA3_224
| `SHA3_256
| `KECCAK_256
| `SHA3_384
| `SHA3_512
| `WHIRLPOOL
| `BLAKE2B
| `BLAKE2S ]
let hash_to_hash' : type a. a hash -> hash' = function
| MD5 -> `MD5
| SHA1 -> `SHA1
| RMD160 -> `RMD160
| SHA224 -> `SHA224
| SHA256 -> `SHA256
| SHA384 -> `SHA384
| SHA512 -> `SHA512
| SHA3_224 -> `SHA3_224
| SHA3_256 -> `SHA3_256
| KECCAK_256 -> `KECCAK_256
| SHA3_384 -> `SHA3_384
| SHA3_512 -> `SHA3_512
| WHIRLPOOL -> `WHIRLPOOL
| BLAKE2B -> `BLAKE2B
| BLAKE2S -> `BLAKE2S
let module_of_hash' : hash' -> (module S) = function
| `MD5 -> (module MD5)
| `SHA1 -> (module SHA1)
| `RMD160 -> (module RMD160)
| `SHA224 -> (module SHA224)
| `SHA256 -> (module SHA256)
| `SHA384 -> (module SHA384)
| `SHA512 -> (module SHA512)
| `SHA3_224 -> (module SHA3_224)
| `SHA3_256 -> (module SHA3_256)
| `KECCAK_256 -> (module KECCAK_256)
| `SHA3_384 -> (module SHA3_384)
| `SHA3_512 -> (module SHA3_512)
| `WHIRLPOOL -> (module WHIRLPOOL)
| `BLAKE2B -> (module BLAKE2B)
| `BLAKE2S -> (module BLAKE2S)
let module_of : type k. k hash -> (module S with type t = k) = function
| MD5 -> (module MD5)
| SHA1 -> (module SHA1)
| RMD160 -> (module RMD160)
| SHA224 -> (module SHA224)
| SHA256 -> (module SHA256)
| SHA384 -> (module SHA384)
| SHA512 -> (module SHA512)
| SHA3_224 -> (module SHA3_224)
| SHA3_256 -> (module SHA3_256)
| KECCAK_256 -> (module KECCAK_256)
| SHA3_384 -> (module SHA3_384)
| SHA3_512 -> (module SHA3_512)
| WHIRLPOOL -> (module WHIRLPOOL)
| BLAKE2B -> (module BLAKE2B)
| BLAKE2S -> (module BLAKE2S)
type 'hash t = 'hash
let digest_bytes : type k. k hash -> Bytes.t -> k t =
fun hash buf ->
let module H = (val module_of hash) in
H.digest_bytes buf
let digest_string : type k. k hash -> String.t -> k t =
fun hash buf ->
let module H = (val module_of hash) in
H.digest_string buf
let digest_bigstring : type k. k hash -> bigstring -> k t =
fun hash buf ->
let module H = (val module_of hash) in
H.digest_bigstring buf
let digesti_bytes : type k. k hash -> Bytes.t iter -> k t =
fun hash iter ->
let module H = (val module_of hash) in
H.digesti_bytes iter
let digesti_string : type k. k hash -> String.t iter -> k t =
fun hash iter ->
let module H = (val module_of hash) in
H.digesti_string iter
let digesti_bigstring : type k. k hash -> bigstring iter -> k t =
fun hash iter ->
let module H = (val module_of hash) in
H.digesti_bigstring iter
let hmaci_bytes : type k. k hash -> key:string -> Bytes.t iter -> k t =
fun hash ~key iter ->
let module H = (val module_of hash) in
H.hmaci_bytes ~key iter
let hmaci_string : type k. k hash -> key:string -> String.t iter -> k t =
fun hash ~key iter ->
let module H = (val module_of hash) in
H.hmaci_string ~key iter
let hmaci_bigstring : type k. k hash -> key:string -> bigstring iter -> k t =
fun hash ~key iter ->
let module H = (val module_of hash) in
H.hmaci_bigstring ~key iter
(* XXX(dinosaure): unsafe part to avoid overhead. *)
let unsafe_compare : type k. k hash -> k t -> k t -> int =
fun hash a b ->
let module H = (val module_of hash) in
H.unsafe_compare a b
let equal : type k. k hash -> k t equal =
fun hash a b ->
let module H = (val module_of hash) in
H.equal a b
let pp : type k. k hash -> k t pp =
fun hash ppf t ->
let module H = (val module_of hash) in
H.pp ppf t
let consistent_of_hex : type k. k hash -> string -> k t =
fun hash hex ->
let module H = (val module_of hash) in
H.consistent_of_hex hex
let consistent_of_hex_opt : type k. k hash -> string -> k t option =
fun hash hex ->
let module H = (val module_of hash) in
H.consistent_of_hex_opt hex
let of_hex : type k. k hash -> string -> k t =
fun hash hex ->
let module H = (val module_of hash) in
H.of_hex hex
let of_hex_opt : type k. k hash -> string -> k t option =
fun hash hex ->
let module H = (val module_of hash) in
H.of_hex_opt hex
let to_hex : type k. k hash -> k t -> string =
fun hash t ->
let module H = (val module_of hash) in
H.to_hex t
let of_raw_string : type k. k hash -> string -> k t =
fun hash s ->
let module H = (val module_of hash) in
H.of_raw_string s
let of_raw_string_opt : type k. k hash -> string -> k t option =
fun hash s ->
let module H = (val module_of hash) in
H.of_raw_string_opt s
let to_raw_string : type k. k hash -> k t -> string =
fun hash t ->
let module H = (val module_of hash) in
H.to_raw_string t
let of_digest (type hash) (module H : S with type t = hash) (hash : H.t) :
hash t =
hash
let of_md5 hash = hash
let of_sha1 hash = hash
let of_rmd160 hash = hash
let of_sha224 hash = hash
let of_sha256 hash = hash
let of_sha384 hash = hash
let of_sha512 hash = hash
let of_sha3_224 hash = hash
let of_sha3_256 hash = hash
let of_keccak_256 hash = hash
let of_sha3_384 hash = hash
let of_sha3_512 hash = hash
let of_whirlpool hash = hash
let of_blake2b hash = hash
let of_blake2s hash = hash

View file

@ -0,0 +1,535 @@
(* Copyright (c) 2014-2016 David Kaloper Meršinjak
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *)
module By = Digestif_by
module Bi = Digestif_bi
type off = int
type size = int
type ba = Bi.t
type st = By.t
type ctx = By.t
let dup : ctx -> ctx = By.copy
module MD5 = struct
type kind = [ `MD5 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_md5_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_md5_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_md5_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_md5_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_md5_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_md5_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_md5_ctx_size" [@@noalloc]
end
module SHA1 = struct
type kind = [ `SHA1 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha1_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha1_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_sha1_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha1_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha1_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_sha1_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha1_ctx_size" [@@noalloc]
end
module SHA224 = struct
type kind = [ `SHA224 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha224_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha224_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_sha224_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha224_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha224_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_sha224_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha224_ctx_size" [@@noalloc]
end
module SHA256 = struct
type kind = [ `SHA256 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha256_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha256_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_sha256_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha256_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha256_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_sha256_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha256_ctx_size" [@@noalloc]
end
module SHA384 = struct
type kind = [ `SHA384 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha384_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha384_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_sha384_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha384_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha384_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_sha384_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha384_ctx_size" [@@noalloc]
end
module SHA512 = struct
type kind = [ `SHA512 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha512_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha512_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_sha512_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha512_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha512_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_sha512_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha512_ctx_size" [@@noalloc]
end
module SHA3_224 = struct
type kind = [ `SHA3_224 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha3_224_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha3_224_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_sha3_224_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha3_224_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha3_224_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_sha3_224_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha3_224_ctx_size"
[@@noalloc]
end
module SHA3_256 = struct
type kind = [ `SHA3_256 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha3_256_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha3_256_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_sha3_256_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha3_256_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha3_256_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_sha3_256_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha3_256_ctx_size"
[@@noalloc]
end
module KECCAK_256 = struct
type kind = [ `KECCAK_256 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha3_256_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha3_256_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_keccak_256_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha3_256_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha3_256_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_keccak_256_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha3_256_ctx_size"
[@@noalloc]
end
module SHA3_384 = struct
type kind = [ `SHA3_384 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha3_384_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha3_384_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_sha3_384_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha3_384_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha3_384_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_sha3_384_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha3_384_ctx_size"
[@@noalloc]
end
module SHA3_512 = struct
type kind = [ `SHA3_512 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_sha3_512_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_sha3_512_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_sha3_512_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_sha3_512_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_sha3_512_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_sha3_512_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_sha3_512_ctx_size"
[@@noalloc]
end
module WHIRLPOOL = struct
type kind = [ `WHIRLPOOL ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_whirlpool_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_whirlpool_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_whirlpool_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_whirlpool_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_whirlpool_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_whirlpool_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_whirlpool_ctx_size"
[@@noalloc]
end
module BLAKE2B = struct
type kind = [ `BLAKE2B ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_blake2b_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_blake2b_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_blake2b_ba_finalize"
[@@noalloc]
external with_outlen_and_key : ctx -> size -> ba -> off -> size -> unit
= "caml_digestif_blake2b_ba_init_with_outlen_and_key"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_blake2b_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_blake2b_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_blake2b_st_finalize"
[@@noalloc]
external with_outlen_and_key : ctx -> size -> st -> off -> size -> unit
= "caml_digestif_blake2b_st_init_with_outlen_and_key"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_blake2b_ctx_size" [@@noalloc]
external key_size : unit -> int = "caml_digestif_blake2b_key_size" [@@noalloc]
external max_outlen : unit -> int = "caml_digestif_blake2b_max_outlen"
[@@noalloc]
external digest_size : ctx -> int = "caml_digestif_blake2b_digest_size"
[@@noalloc]
end
module BLAKE2S = struct
type kind = [ `BLAKE2S ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_blake2s_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_blake2s_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_blake2s_ba_finalize"
[@@noalloc]
external with_outlen_and_key : ctx -> size -> ba -> off -> size -> unit
= "caml_digestif_blake2s_ba_init_with_outlen_and_key"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_blake2s_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_blake2s_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_blake2s_st_finalize"
[@@noalloc]
external with_outlen_and_key : ctx -> size -> st -> off -> size -> unit
= "caml_digestif_blake2s_st_init_with_outlen_and_key"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_blake2s_ctx_size" [@@noalloc]
external key_size : unit -> int = "caml_digestif_blake2s_key_size" [@@noalloc]
external max_outlen : unit -> int = "caml_digestif_blake2s_max_outlen"
[@@noalloc]
external digest_size : ctx -> int = "caml_digestif_blake2s_digest_size"
[@@noalloc]
end
module RMD160 = struct
type kind = [ `RMD160 ]
module Bigstring = struct
external init : ctx -> unit = "caml_digestif_rmd160_ba_init" [@@noalloc]
external update : ctx -> ba -> off -> size -> unit
= "caml_digestif_rmd160_ba_update"
external finalize : ctx -> ba -> off -> unit
= "caml_digestif_rmd160_ba_finalize"
[@@noalloc]
end
module Bytes = struct
external init : ctx -> unit = "caml_digestif_rmd160_st_init" [@@noalloc]
external update : ctx -> st -> off -> size -> unit
= "caml_digestif_rmd160_st_update"
[@@noalloc]
external finalize : ctx -> st -> off -> unit
= "caml_digestif_rmd160_st_finalize"
[@@noalloc]
end
external ctx_size : unit -> int = "caml_digestif_rmd160_ctx_size" [@@noalloc]
end
let imin (a : int) (b : int) = if a < b then a else b
module XOR = struct
module Bigstring = struct
external xor_into : ba -> off -> ba -> off -> size -> unit
= "caml_digestif_ba_xor_into"
[@@noalloc]
let xor_into a b n =
if n > imin (Bi.length a) (Bi.length b)
then
raise (Invalid_argument "Native.Bigstring.xor_into: buffers to small")
else xor_into a 0 b 0 n
let xor a b =
let l = imin (Bi.length a) (Bi.length b) in
let r = Bi.copy (Bi.sub b 0 l) in
xor_into a r l ;
r
end
module Bytes = struct
external xor_into : st -> off -> st -> off -> size -> unit
= "caml_digestif_st_xor_into"
[@@noalloc]
let xor_into a b n =
if n > imin (By.length a) (By.length b)
then
raise (Invalid_argument "Native.Bigstring.xor_into: buffers to small")
else xor_into a 0 b 0 n
let xor a b =
let l = imin (By.length a) (By.length b) in
let r = By.copy (By.sub b 0 l) in
xor_into a r l ;
r
end
end

View file

@ -0,0 +1,19 @@
(library
(name digestif_c)
(public_name digestif.c)
(implements digestif)
(libraries eqaf)
(private_modules digestif_native digestif_eq digestif_conv digestif_by
digestif_bi)
(foreign_stubs
(language c)
(names blake2b blake2s md5 ripemd160 sha1 sha256 sha512 sha3 whirlpool misc
stubs)
(flags
(:standard -I./native/)))
(flags
(:standard -no-keep-locs)))
(include_subdirs unqualified)
(copy_files# ../src/*.ml)

View file

@ -0,0 +1,325 @@
/*
* Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BITFN_H
#define BITFN_H
#include <stdint.h>
#include <string.h>
#if !defined(__cpluplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
#if defined(_MSC_VER)
#define __INLINE __inline
#elif defined(__GNUC__)
#define __INLINE __inline__
#else
#define __INLINE
#endif
#else
#define __INLINE inline
#endif
static __INLINE void secure_zero_memory(void *v, size_t n)
{
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
memset_v(v, 0, n);
}
#ifndef NO_INLINE_ASM
/**********************************************************/
# if (defined(__i386__))
# define ARCH_HAS_SWAP32
static __INLINE uint32_t bitfn_swap32(uint32_t a)
{
__asm__ ("bswap %0" : "=r" (a) : "0" (a));
return a;
}
/**********************************************************/
# elif (defined(__arm__))
# define ARCH_HAS_SWAP32
static __INLINE uint32_t bitfn_swap32(uint32_t a)
{
uint32_t tmp = a;
__asm__ volatile ("eor %1, %0, %0, ror #16\n"
"bic %1, %1, #0xff0000\n"
"mov %0, %0, ror #8\n"
"eor %0, %0, %1, lsr #8\n"
: "=r" (a), "=r" (tmp) : "0" (a), "1" (tmp));
return a;
}
/**********************************************************/
# elif defined(__x86_64__)
# define ARCH_HAS_SWAP32
# define ARCH_HAS_SWAP64
static __INLINE uint32_t bitfn_swap32(uint32_t a)
{
__asm__ ("bswap %0" : "=r" (a) : "0" (a));
return a;
}
static __INLINE uint64_t bitfn_swap64(uint64_t a)
{
__asm__ ("bswap %0" : "=r" (a) : "0" (a));
return a;
}
# endif
#endif /* NO_INLINE_ASM */
/**********************************************************/
#ifndef ARCH_HAS_ROL32
static __INLINE uint32_t rol32(uint32_t word, uint32_t shift)
{
return (word << shift) | (word >> (32 - shift));
}
#endif
#ifndef ARCH_HAS_ROR32
static __INLINE uint32_t ror32(uint32_t word, uint32_t shift)
{
return (word >> shift) | (word << (32 - shift));
}
#endif
#ifndef ARCH_HAS_ROL64
static __INLINE uint64_t rol64(uint64_t word, uint32_t shift)
{
return (word << shift) | (word >> (64 - shift));
}
#endif
#ifndef ARCH_HAS_ROR64
static __INLINE uint64_t ror64(uint64_t word, uint32_t shift)
{
return (word >> shift) | (word << (64 - shift));
}
#endif
#ifndef ARCH_HAS_SWAP32
static __INLINE uint32_t bitfn_swap32(uint32_t a)
{
return (a << 24) | ((a & 0xff00) << 8) | ((a >> 8) & 0xff00) | (a >> 24);
}
#endif
#ifndef ARCH_HAS_ARRAY_SWAP32
static __INLINE void array_swap32(uint32_t *d, uint32_t *s, uint32_t nb)
{
while (nb--)
*d++ = bitfn_swap32(*s++);
}
#endif
#ifndef ARCH_HAS_SWAP64
static __INLINE uint64_t bitfn_swap64(uint64_t a)
{
return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) |
(((uint64_t) bitfn_swap32((uint32_t) a)) << 32);
}
#endif
#ifndef ARCH_HAS_ARRAY_SWAP64
static __INLINE void array_swap64(uint64_t *d, uint64_t *s, uint32_t nb)
{
while (nb--)
*d++ = bitfn_swap64(*s++);
}
#endif
#ifndef ARCH_HAS_MEMORY_ZERO
static __INLINE void memory_zero(void *ptr, uint32_t len)
{
uint32_t *ptr32 = ptr;
uint8_t *ptr8;
int i;
for (i = 0; (uint32_t) i < len / 4; i++)
*ptr32++ = 0;
if (len % 4) {
ptr8 = (uint8_t *) ptr32;
for (i = len % 4; i >= 0; i--)
ptr8[i] = 0;
}
}
#endif
#ifndef ARCH_HAS_ARRAY_COPY32
static __INLINE void array_copy32(uint32_t *d, uint32_t *s, uint32_t nb)
{
while (nb--) *d++ = *s++;
}
#endif
#ifndef ARCH_HAS_ARRAY_COPY64
static __INLINE void array_copy64(uint64_t *d, uint64_t *s, uint32_t nb)
{
while (nb--) *d++ = *s++;
}
#endif
static __INLINE uint64_t load64( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint64_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint64_t )( p[0] ) << 0) |
(( uint64_t )( p[1] ) << 8) |
(( uint64_t )( p[2] ) << 16) |
(( uint64_t )( p[3] ) << 24) |
(( uint64_t )( p[4] ) << 32) |
(( uint64_t )( p[5] ) << 40) |
(( uint64_t )( p[6] ) << 48) |
(( uint64_t )( p[7] ) << 56) ;
#endif
}
static __INLINE uint32_t load32( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint32_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint32_t )( p[0] ) << 0) |
(( uint32_t )( p[1] ) << 8) |
(( uint32_t )( p[2] ) << 16) |
(( uint32_t )( p[3] ) << 24) ;
#endif
}
static __INLINE void store32( void *dst, uint32_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
#endif
}
static __INLINE void store64( void *dst, uint64_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
p[4] = (uint8_t)(w >> 32);
p[5] = (uint8_t)(w >> 40);
p[6] = (uint8_t)(w >> 48);
p[7] = (uint8_t)(w >> 56);
#endif
}
#ifdef __MINGW32__
# define LITTLE_ENDIAN 1234
# define BYTE_ORDER LITTLE_ENDIAN
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
# include <sys/endian.h>
#elif defined(__OpenBSD__) || defined(__SVR4)
# include <sys/types.h>
#elif defined(__APPLE__)
# include <machine/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 )
# include <machine/endian.h>
#elif defined( __QNXNTO__ ) && defined( __LITTLEENDIAN__ )
# define LITTLE_ENDIAN 1234
# define BYTE_ORDER LITTLE_ENDIAN
#elif defined( __QNXNTO__ ) && defined( __BIGENDIAN__ )
# define BIG_ENDIAN 1234
# define BYTE_ORDER BIG_ENDIAN
#elif defined(_MSC_VER)
# define LITTLE_ENDIAN 1234
# define BYTE_ORDER LITTLE_ENDIAN
#else
# include <endian.h>
#endif
/* big endian to cpu */
#if LITTLE_ENDIAN == BYTE_ORDER
# define be32_to_cpu(a) bitfn_swap32(a)
# define cpu_to_be32(a) bitfn_swap32(a)
# define le32_to_cpu(a) (a)
# define cpu_to_le32(a) (a)
# define be64_to_cpu(a) bitfn_swap64(a)
# define cpu_to_be64(a) bitfn_swap64(a)
# define le64_to_cpu(a) (a)
# define cpu_to_le64(a) (a)
# define cpu_to_le32_array(d, s, l) array_copy32(d, s, l)
# define le32_to_cpu_array(d, s, l) array_copy32(d, s, l)
# define cpu_to_be32_array(d, s, l) array_swap32(d, s, l)
# define be32_to_cpu_array(d, s, l) array_swap32(d, s, l)
# define cpu_to_le64_array(d, s, l) array_copy64(d, s, l)
# define le64_to_cpu_array(d, s, l) array_copy64(d, s, l)
# define cpu_to_be64_array(d, s, l) array_swap64(d, s, l)
# define be64_to_cpu_array(d, s, l) array_swap64(d, s, l)
# define ror32_be(a, s) rol32(a, s)
# define rol32_be(a, s) ror32(a, s)
# define ARCH_IS_LITTLE_ENDIAN
#elif BIG_ENDIAN == BYTE_ORDER
# define be32_to_cpu(a) (a)
# define cpu_to_be32(a) (a)
# define be64_to_cpu(a) (a)
# define cpu_to_be64(a) (a)
# define le64_to_cpu(a) bitfn_swap64(a)
# define cpu_to_le64(a) bitfn_swap64(a)
# define le32_to_cpu(a) bitfn_swap32(a)
# define cpu_to_le32(a) bitfn_swap32(a)
# define cpu_to_le32_array(d, s, l) array_swap32(d, s, l)
# define le32_to_cpu_array(d, s, l) array_swap32(d, s, l)
# define cpu_to_be32_array(d, s, l) array_copy32(d, s, l)
# define be32_to_cpu_array(d, s, l) array_copy32(d, s, l)
# define cpu_to_le64_array(d, s, l) array_swap64(d, s, l)
# define le64_to_cpu_array(d, s, l) array_swap64(d, s, l)
# define cpu_to_be64_array(d, s, l) array_copy64(d, s, l)
# define be64_to_cpu_array(d, s, l) array_copy64(d, s, l)
# define ror32_be(a, s) ror32(a, s)
# define rol32_be(a, s) rol32(a, s)
# define ARCH_IS_BIG_ENDIAN
#else
# error "endian not supported"
#endif
#endif /* !BITFN_H */

View file

@ -0,0 +1,220 @@
#include <string.h>
#include "blake2b.h"
#include "bitfn.h"
static const uint64_t IV[8] =
{
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
static const uint8_t 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 }
};
#include <stdint.h>
static const struct blake2b_param P[] =
{ { BLAKE2B_OUTBYTES /* digest_length */
, 0 /* key_length */
, 1 /* fanout */
, 1 /* depth */
, 0 /* leaf_length */
, 0 /* node_offset */
, 0 /* xof_length */
, 0 /* node_depth */
, 0 /* inner_length */
, { 0 } /* reserver[14] */
, { 0 } /* salt[BLAKE2B_SLATBYTES] */
, { 0 } /* personal[BLAKE2B_PERSONALBYTES] */ } };
static void blake2b_increment_counter( struct blake2b_ctx *ctx, const uint64_t inc )
{
ctx->t[0] += inc;
ctx->t[1] += ( ctx->t[0] < inc );
}
static void blake2b_set_lastnode( struct blake2b_ctx *ctx )
{
ctx->f[1] = (uint64_t)-1;
}
static void blake2b_set_lastblock( struct blake2b_ctx *ctx )
{
if( ctx->last_node ) blake2b_set_lastnode( ctx );
ctx->f[0] = (uint64_t)-1;
}
#define G(r,i,a,b,c,d) \
do { \
a = a + b + m[sigma[r][2*i+0]]; \
d = ror64(d ^ a, 32); \
c = c + d; \
b = ror64(b ^ c, 24); \
a = a + b + m[sigma[r][2*i+1]]; \
d = ror64(d ^ a, 16); \
c = c + d; \
b = ror64(b ^ c, 63); \
} while(0)
#define R(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)
static void blake2b_compress(struct blake2b_ctx *ctx, const uint8_t block[BLAKE2B_BLOCKBYTES])
{
uint64_t m[16];
uint64_t v[16];
size_t i;
for( i = 0; i < 16; ++i ) {
m[i] = load64( block + i * sizeof( m[i] ) );
}
for( i = 0; i < 8; ++i ) {
v[i] = ctx->h[i];
}
v[ 8] = IV[0];
v[ 9] = IV[1];
v[10] = IV[2];
v[11] = IV[3];
v[12] = IV[4] ^ ctx->t[0];
v[13] = IV[5] ^ ctx->t[1];
v[14] = IV[6] ^ ctx->f[0];
v[15] = IV[7] ^ ctx->f[1];
R( 0 );
R( 1 );
R( 2 );
R( 3 );
R( 4 );
R( 5 );
R( 6 );
R( 7 );
R( 8 );
R( 9 );
R( 10 );
R( 11 );
for( i = 0; i < 8; ++i )
ctx->h[i] = ctx->h[i] ^ v[i] ^ v[i + 8];
}
#undef G
#undef R
void digestif_blake2b_update( struct blake2b_ctx *ctx, uint8_t *data, uint32_t inlen )
{
const unsigned char * in = (const unsigned char *) data;
if( inlen > 0 )
{
size_t left = ctx->buflen;
size_t fill = BLAKE2B_BLOCKBYTES - left;
if( inlen > fill )
{
ctx->buflen = 0;
memcpy( ctx->buf + left, in, fill );
blake2b_increment_counter( ctx, BLAKE2B_BLOCKBYTES );
blake2b_compress( ctx, ctx->buf );
in += fill;
inlen -= fill;
while (inlen > BLAKE2B_BLOCKBYTES)
{
blake2b_increment_counter( ctx, BLAKE2B_BLOCKBYTES );
blake2b_compress( ctx, in );
in += BLAKE2B_BLOCKBYTES;
inlen -= BLAKE2B_BLOCKBYTES;
}
}
memcpy( ctx->buf + ctx->buflen, in, inlen );
ctx->buflen += inlen;
}
}
void digestif_blake2b_init_with_outlen_and_key(struct blake2b_ctx *ctx, size_t outlen, const void *key, size_t keylen)
{
struct blake2b_param P[1];
const unsigned char * p = ( const uint8_t * )( P );
size_t i;
memset( ctx, 0, sizeof( struct blake2b_ctx ) );
P->digest_length = (uint8_t) outlen;
P->key_length = (uint8_t) keylen;
P->fanout = 1;
P->depth = 1;
P->leaf_length = 0;
P->node_offset = 0;
P->xof_length = 0;
P->node_depth = 0;
P->inner_length = 0;
memset( P->reserved, 0, sizeof( P->reserved ) );
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
for( i = 0; i < 8; ++i )
ctx->h[i] = IV[i] ^ load64(p + sizeof(uint64_t) * i);
ctx->outlen = P->digest_length;
if( keylen > 0 )
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset( block, 0, BLAKE2B_BLOCKBYTES );
memcpy( block, key, keylen );
digestif_blake2b_update( ctx, block, BLAKE2B_BLOCKBYTES );
secure_zero_memory( block, BLAKE2B_BLOCKBYTES );
}
}
void digestif_blake2b_init(struct blake2b_ctx *ctx)
{
digestif_blake2b_init_with_outlen_and_key(ctx, BLAKE2B_OUTBYTES, NULL, 0);
}
void digestif_blake2b_finalize( struct blake2b_ctx *ctx, uint8_t *out )
{
uint8_t buffer[BLAKE2B_OUTBYTES] = { 0 };
size_t i;
blake2b_increment_counter( ctx, ctx->buflen );
blake2b_set_lastblock( ctx );
memset( ctx->buf + ctx->buflen, 0, BLAKE2B_BLOCKBYTES - ctx->buflen );
blake2b_compress( ctx, ctx->buf );
for( i = 0; i < 8; ++i )
store64(buffer + sizeof( ctx->h[i] ) * i, ctx->h[i]);
secure_zero_memory( out, ctx->outlen * sizeof(uint8_t) );
memcpy( out, buffer, (ctx->outlen < BLAKE2B_OUTBYTES) ? ctx->outlen : BLAKE2B_OUTBYTES );
secure_zero_memory( buffer, sizeof(buffer) );
}

View file

@ -0,0 +1,56 @@
#ifndef CRYPTOHASH_BLAKE2B_H
#define CRYPTOHASH_BLAKE2B_H
#include <stdint.h>
#if defined(_MSC_VER)
#define PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
#else
#define PACKED(x) x __attribute((packed))
#endif
enum blake2b_constant
{
BLAKE2B_BLOCKBYTES = 128,
BLAKE2B_OUTBYTES = 64,
BLAKE2B_KEYBYTES = 64,
BLAKE2B_SALTBYTES = 16,
BLAKE2B_PERSONALBYTES = 16
};
struct blake2b_ctx
{
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
uint8_t buf[BLAKE2B_BLOCKBYTES];
size_t buflen;
size_t outlen;
uint8_t last_node;
};
PACKED(struct blake2b_param
{
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint32_t leaf_length; /* 8 */
uint32_t node_offset; /* 12 */
uint32_t xof_length; /* 16 */
uint8_t node_depth; /* 17 */
uint8_t inner_length; /* 18 */
uint8_t reserved[14]; /* 32 */
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
});
#define BLAKE2B_DIGEST_SIZE BLAKE2B_BLOCKBYTES
#define BLAKE2B_CTX_SIZE (sizeof(struct blake2b_ctx))
void digestif_blake2b_init(struct blake2b_ctx *ctx);
void digestif_blake2b_init_with_outlen_and_key(struct blake2b_ctx *ctx, size_t outlen, const void *key, size_t keylen);
void digestif_blake2b_update(struct blake2b_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_blake2b_finalize(struct blake2b_ctx *ctx, uint8_t *out);
#endif

View file

@ -0,0 +1,213 @@
#include <string.h>
#include "blake2s.h"
#include "bitfn.h"
static const uint32_t IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
static const uint8_t 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 } ,
};
#include <stdint.h>
static const struct blake2s_param P[] =
{ { BLAKE2S_OUTBYTES /* digest_length */
, 0 /* key_length */
, 1 /* fanout */
, 1 /* depth */
, 0 /* leaf_length */
, 0 /* node_offset */
, 0 /* xof_length */
, 0 /* node_depth */
, 0 /* inner_length */
, { 0 } /* salt */
, { 0 } /* personal */ } };
static void blake2s_increment_counter( struct blake2s_ctx *ctx, const uint32_t inc )
{
ctx->t[0] += inc;
ctx->t[1] += ( ctx->t[0] < inc );
}
static void blake2s_set_lastnode( struct blake2s_ctx *ctx )
{
ctx->f[1] = (uint32_t)-1;
}
static void blake2s_set_lastblock( struct blake2s_ctx *ctx )
{
if( ctx->last_node ) blake2s_set_lastnode( ctx );
ctx->f[0] = (uint32_t)-1;
}
#define G(r,i,a,b,c,d) \
do { \
a = a + b + m[sigma[r][2*i+0]]; \
d = ror32(d ^ a, 16); \
c = c + d; \
b = ror32(b ^ c, 12); \
a = a + b + m[sigma[r][2*i+1]]; \
d = ror32(d ^ a, 8); \
c = c + d; \
b = ror32(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)
static void blake2s_compress(struct blake2s_ctx *ctx, const uint8_t block[BLAKE2S_BLOCKBYTES])
{
uint32_t m[16];
uint32_t v[16];
size_t i;
for( i = 0; i < 16; ++i ) {
m[i] = load32( block + i * sizeof( m[i] ) );
}
for( i = 0; i < 8; ++i ) {
v[i] = ctx->h[i];
}
v[ 8] = IV[0];
v[ 9] = IV[1];
v[10] = IV[2];
v[11] = IV[3];
v[12] = ctx->t[0] ^ IV[4];
v[13] = ctx->t[1] ^ IV[5];
v[14] = ctx->f[0] ^ IV[6];
v[15] = ctx->f[1] ^ 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 )
ctx->h[i] = ctx->h[i] ^ v[i] ^ v[i + 8];
}
#undef G
#undef ROUND
void digestif_blake2s_update( struct blake2s_ctx *ctx, uint8_t *data, uint32_t inlen )
{
const unsigned char * in = (const unsigned char *) data;
if( inlen > 0 )
{
size_t left = ctx->buflen;
size_t fill = BLAKE2S_BLOCKBYTES - left;
if( inlen > fill )
{
ctx->buflen = 0;
memcpy( ctx->buf + left, in, fill );
blake2s_increment_counter( ctx, BLAKE2S_BLOCKBYTES );
blake2s_compress( ctx, ctx->buf );
in += fill;
inlen -= fill;
while (inlen > BLAKE2S_BLOCKBYTES)
{
blake2s_increment_counter( ctx, BLAKE2S_BLOCKBYTES );
blake2s_compress( ctx, in );
in += BLAKE2S_BLOCKBYTES;
inlen -= BLAKE2S_BLOCKBYTES;
}
}
memcpy( ctx->buf + ctx->buflen, in, inlen );
ctx->buflen += inlen;
}
}
void digestif_blake2s_init_with_outlen_and_key(struct blake2s_ctx *ctx, size_t outlen, const void *key, size_t keylen)
{
struct blake2s_param P[1];
const unsigned char * p = ( const uint8_t * )( P );
size_t i;
memset( ctx, 0, sizeof( struct blake2s_ctx ) );
P->digest_length = (uint8_t) outlen;
P->key_length = (uint8_t) keylen;
P->fanout = 1;
P->depth = 1;
P->leaf_length = 0;
P->node_offset = 0;
P->xof_length = 0;
P->node_depth = 0;
P->inner_length = 0;
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
for( i = 0; i < 8; ++i )
ctx->h[i] = IV[i] ^ load32(p + sizeof(uint32_t) * i);
ctx->outlen = P->digest_length;
if( keylen > 0 )
{
uint8_t block[BLAKE2S_BLOCKBYTES];
memset( block, 0, BLAKE2S_BLOCKBYTES );
memcpy( block, key, keylen );
digestif_blake2s_update( ctx, block, BLAKE2S_BLOCKBYTES );
secure_zero_memory( block, BLAKE2S_BLOCKBYTES );
}
}
void digestif_blake2s_init(struct blake2s_ctx *ctx)
{
digestif_blake2s_init_with_outlen_and_key(ctx, BLAKE2S_OUTBYTES, NULL, 0);
}
void digestif_blake2s_finalize( struct blake2s_ctx *ctx, uint8_t *out )
{
uint8_t buffer[BLAKE2S_OUTBYTES] = { 0 };
size_t i;
blake2s_increment_counter( ctx, ctx->buflen );
blake2s_set_lastblock( ctx );
memset( ctx->buf + ctx->buflen, 0, BLAKE2S_BLOCKBYTES - ctx->buflen );
blake2s_compress( ctx, ctx->buf );
for( i = 0; i < 8; ++i )
store32(buffer + sizeof( ctx->h[i] ) * i, ctx->h[i]);
secure_zero_memory( out, ctx->outlen * sizeof(uint8_t) );
memcpy( out, buffer, (ctx->outlen < BLAKE2S_OUTBYTES) ? ctx->outlen : BLAKE2S_OUTBYTES );
secure_zero_memory( buffer, sizeof(buffer) );
}

View file

@ -0,0 +1,55 @@
#ifndef CRYPTOHASH_BLAKE2S_H
#define CRYPTOHASH_BLAKE2S_H
#include <stdint.h>
#if defined(_MSC_VER)
#define PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
#else
#define PACKED(x) x __attribute((packed))
#endif
enum blake2s_constant
{
BLAKE2S_BLOCKBYTES = 64,
BLAKE2S_OUTBYTES = 32,
BLAKE2S_KEYBYTES = 32,
BLAKE2S_SALTBYTES = 8,
BLAKE2S_PERSONALBYTES = 8
};
struct blake2s_ctx
{
uint32_t h[8];
uint32_t t[2];
uint32_t f[2];
uint8_t buf[BLAKE2S_BLOCKBYTES];
size_t buflen;
size_t outlen;
uint8_t last_node;
};
PACKED(struct blake2s_param
{
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint32_t leaf_length; /* 8 */
uint32_t node_offset; /* 12 */
uint16_t xof_length; /* 14 */
uint8_t node_depth; /* 15 */
uint8_t inner_length; /* 16 */
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
});
#define BLAKE2S_DIGEST_SIZE BLAKE2S_BLOCKBYTES
#define BLAKE2S_CTX_SIZE (sizeof(struct blake2s_ctx))
void digestif_blake2s_init(struct blake2s_ctx *ctx);
void digestif_blake2s_init_with_outlen_and_key(struct blake2s_ctx *ctx, size_t outlen, const void *key, size_t keylen);
void digestif_blake2s_update(struct blake2s_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_blake2s_finalize(struct blake2s_ctx *ctx, uint8_t *out);
#endif

View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2014-2016 David Kaloper Meršinjak
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#if !defined(H__DIGESTIF)
#define H__DIGESTIF
#include <stdint.h>
#include <caml/mlvalues.h>
#include <caml/bigarray.h>
#include "bitfn.h"
#if defined (__x86_64__) && defined (ACCELERATE)
#include <x86intrin.h>
#endif
#if defined (__x86_64__) && defined (ACCELERATE) && defined (__SSE2__)
#define __digestif_SSE2
#endif
#ifndef __unused
# if defined(_MSC_VER) && _MSC_VER >= 1500
# define __unused(x) __pragma( warning (push) ) \
__pragma( warning (disable:4189 ) ) \
x \
__pragma( warning (pop))
# else
# define __unused(x) x __attribute__((unused))
# endif
#endif
#define __unit() value __unused(unit)
typedef unsigned long u_long;
#define _ba_uint8_off(ba, off) ((uint8_t*) Caml_ba_data_val (ba) + Long_val (off))
#define _ba_uint32_off(ba, off) ((uint32_t*) Caml_ba_data_val (ba) + Long_val (off))
#define _ba_ulong_off(ba, off) ((u_long*) Caml_ba_data_val (ba) + Long_val (off))
#define _st_uint8_off(st, off) ((uint8_t*) String_val (st) + Long_val (off))
#define _st_uint32_off(st, off) ((uint32_t*) String_val (st) + Long_val (off))
#define _st_ulong_off(st, off) ((u_long*) String_val (st) + Long_val (off))
#define _ba_uint8(ba) _ba_uint8_off (ba, 0)
#define _ba_uint32(ba) _ba_uint32_off (ba, 0)
#define _ba_ulong(ba) _ba_ulong_off (ba, 0)
#define _st_uint8(st) _st_uint8_off(st, 0)
#define _st_uint32(st) _st_uint32_off(st, 0)
#define _st_ulong(st) _st_ulong_off (st, 0)
#define _ba_uint8_option_off(ba, off) (Is_block(ba) ? _ba_uint8_off(Field(ba, 0), off) : 0)
#define _ba_uint8_option(ba) _ba_uint8_option_off (ba, 0)
#define _st_uint8_option_off(st, off) (Is_block(st) ? _st_uint8_off(Field(st, 0), off) : 0)
#define _st_uint8_option(st) _ba_uint8_option_off (st, 0)
#define __define_bc_6(f) \
CAMLprim value f ## _bc (value *v, int __unused(c) ) { return f(v[0], v[1], v[2], v[3], v[4], v[5]); }
#define __define_bc_7(f) \
CAMLprim value f ## _bc (value *v, int __unused(c) ) { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); }
#endif /* H__DIGESTIF */

View file

@ -0,0 +1,178 @@
/*
* Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <stdio.h>
#include "bitfn.h"
#include "md5.h"
void digestif_md5_init(struct md5_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->sz = 0ULL;
ctx->h[0] = 0x67452301;
ctx->h[1] = 0xefcdab89;
ctx->h[2] = 0x98badcfe;
ctx->h[3] = 0x10325476;
}
#define f1(x, y, z) (z ^ (x & (y ^ z)))
#define f2(x, y, z) f1(z, x, y)
#define f3(x, y, z) (x ^ y ^ z)
#define f4(x, y, z) (y ^ (x | ~z))
#define R(f, a, b, c, d, i, k, s) a += f(b, c, d) + w[i] + k; a = rol32(a, s); a += b
static void md5_do_chunk(struct md5_ctx *ctx, uint32_t *buf)
{
uint32_t a, b, c, d;
#ifdef ARCH_IS_BIG_ENDIAN
uint32_t w[16];
cpu_to_le32_array(w, buf, 16);
#else
uint32_t *w = buf;
#endif
a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3];
R(f1, a, b, c, d, 0, 0xd76aa478, 7);
R(f1, d, a, b, c, 1, 0xe8c7b756, 12);
R(f1, c, d, a, b, 2, 0x242070db, 17);
R(f1, b, c, d, a, 3, 0xc1bdceee, 22);
R(f1, a, b, c, d, 4, 0xf57c0faf, 7);
R(f1, d, a, b, c, 5, 0x4787c62a, 12);
R(f1, c, d, a, b, 6, 0xa8304613, 17);
R(f1, b, c, d, a, 7, 0xfd469501, 22);
R(f1, a, b, c, d, 8, 0x698098d8, 7);
R(f1, d, a, b, c, 9, 0x8b44f7af, 12);
R(f1, c, d, a, b, 10, 0xffff5bb1, 17);
R(f1, b, c, d, a, 11, 0x895cd7be, 22);
R(f1, a, b, c, d, 12, 0x6b901122, 7);
R(f1, d, a, b, c, 13, 0xfd987193, 12);
R(f1, c, d, a, b, 14, 0xa679438e, 17);
R(f1, b, c, d, a, 15, 0x49b40821, 22);
R(f2, a, b, c, d, 1, 0xf61e2562, 5);
R(f2, d, a, b, c, 6, 0xc040b340, 9);
R(f2, c, d, a, b, 11, 0x265e5a51, 14);
R(f2, b, c, d, a, 0, 0xe9b6c7aa, 20);
R(f2, a, b, c, d, 5, 0xd62f105d, 5);
R(f2, d, a, b, c, 10, 0x02441453, 9);
R(f2, c, d, a, b, 15, 0xd8a1e681, 14);
R(f2, b, c, d, a, 4, 0xe7d3fbc8, 20);
R(f2, a, b, c, d, 9, 0x21e1cde6, 5);
R(f2, d, a, b, c, 14, 0xc33707d6, 9);
R(f2, c, d, a, b, 3, 0xf4d50d87, 14);
R(f2, b, c, d, a, 8, 0x455a14ed, 20);
R(f2, a, b, c, d, 13, 0xa9e3e905, 5);
R(f2, d, a, b, c, 2, 0xfcefa3f8, 9);
R(f2, c, d, a, b, 7, 0x676f02d9, 14);
R(f2, b, c, d, a, 12, 0x8d2a4c8a, 20);
R(f3, a, b, c, d, 5, 0xfffa3942, 4);
R(f3, d, a, b, c, 8, 0x8771f681, 11);
R(f3, c, d, a, b, 11, 0x6d9d6122, 16);
R(f3, b, c, d, a, 14, 0xfde5380c, 23);
R(f3, a, b, c, d, 1, 0xa4beea44, 4);
R(f3, d, a, b, c, 4, 0x4bdecfa9, 11);
R(f3, c, d, a, b, 7, 0xf6bb4b60, 16);
R(f3, b, c, d, a, 10, 0xbebfbc70, 23);
R(f3, a, b, c, d, 13, 0x289b7ec6, 4);
R(f3, d, a, b, c, 0, 0xeaa127fa, 11);
R(f3, c, d, a, b, 3, 0xd4ef3085, 16);
R(f3, b, c, d, a, 6, 0x04881d05, 23);
R(f3, a, b, c, d, 9, 0xd9d4d039, 4);
R(f3, d, a, b, c, 12, 0xe6db99e5, 11);
R(f3, c, d, a, b, 15, 0x1fa27cf8, 16);
R(f3, b, c, d, a, 2, 0xc4ac5665, 23);
R(f4, a, b, c, d, 0, 0xf4292244, 6);
R(f4, d, a, b, c, 7, 0x432aff97, 10);
R(f4, c, d, a, b, 14, 0xab9423a7, 15);
R(f4, b, c, d, a, 5, 0xfc93a039, 21);
R(f4, a, b, c, d, 12, 0x655b59c3, 6);
R(f4, d, a, b, c, 3, 0x8f0ccc92, 10);
R(f4, c, d, a, b, 10, 0xffeff47d, 15);
R(f4, b, c, d, a, 1, 0x85845dd1, 21);
R(f4, a, b, c, d, 8, 0x6fa87e4f, 6);
R(f4, d, a, b, c, 15, 0xfe2ce6e0, 10);
R(f4, c, d, a, b, 6, 0xa3014314, 15);
R(f4, b, c, d, a, 13, 0x4e0811a1, 21);
R(f4, a, b, c, d, 4, 0xf7537e82, 6);
R(f4, d, a, b, c, 11, 0xbd3af235, 10);
R(f4, c, d, a, b, 2, 0x2ad7d2bb, 15);
R(f4, b, c, d, a, 9, 0xeb86d391, 21);
ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d;
}
void digestif_md5_update(struct md5_ctx *ctx, uint8_t *data, uint32_t len)
{
uint32_t index, to_fill;
index = (uint32_t) (ctx->sz & 0x3f);
to_fill = 64 - index;
ctx->sz += len;
if (index && len >= to_fill) {
memcpy(ctx->buf + index, data, to_fill);
md5_do_chunk(ctx, (uint32_t *) ctx->buf);
len -= to_fill;
data += to_fill;
index = 0;
}
/* process as much 64-block as possible */
for (; len >= 64; len -= 64, data += 64)
md5_do_chunk(ctx, (uint32_t *) data);
/* append data into buf */
if (len)
memcpy(ctx->buf + index, data, len);
}
void digestif_md5_finalize(struct md5_ctx *ctx, uint8_t *out)
{
static uint8_t padding[64] = { 0x80, };
uint64_t bits;
uint32_t index, padlen;
uint32_t *p = (uint32_t *) out;
/* add padding and update data with it */
bits = cpu_to_le64(ctx->sz << 3);
/* pad out to 56 */
index = (uint32_t) (ctx->sz & 0x3f);
padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
digestif_md5_update(ctx, padding, padlen);
/* append length */
digestif_md5_update(ctx, (uint8_t *) &bits, sizeof(bits));
/* output hash */
p[0] = cpu_to_le32(ctx->h[0]);
p[1] = cpu_to_le32(ctx->h[1]);
p[2] = cpu_to_le32(ctx->h[2]);
p[3] = cpu_to_le32(ctx->h[3]);
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CRYPTOHASH_MD5_H
#define CRYPTOHASH_MD5_H
#include <stdint.h>
struct md5_ctx
{
uint64_t sz;
uint8_t buf[64];
uint32_t h[4];
};
#define MD5_DIGEST_SIZE 16
#define MD5_CTX_SIZE sizeof(struct md5_ctx)
void digestif_md5_init(struct md5_ctx *ctx);
void digestif_md5_update(struct md5_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_md5_finalize(struct md5_ctx *ctx, uint8_t *out);
#endif

View file

@ -0,0 +1,40 @@
#include "digestif.h"
#define u_long_s sizeof (unsigned long)
static inline void xor_into (uint8_t *src, uint8_t *dst, size_t n) {
#if defined (__digestif_SSE2__)
while (n >= 16) {
_mm_storeu_si128 (
(__m128i*) dst,
_mm_xor_si128 (
_mm_loadu_si128 ((__m128i*) src),
_mm_loadu_si128 ((__m128i*) dst)));
src += 16;
dst += 16;
n -= 16;
}
#endif
while (n >= u_long_s) {
*((u_long *) dst) ^= *((u_long *) src);
src += u_long_s;
dst += u_long_s;
n -= u_long_s;
}
while (n-- > 0) {
*dst = *(src ++) ^ *dst;
dst++;
}
}
CAMLprim value
caml_digestif_ba_xor_into (value b1, value off1, value b2, value off2, value n) {
xor_into (_ba_uint8_off (b1, off1), _ba_uint8_off (b2, off2), Int_val (n));
return Val_unit;
}
CAMLprim value
caml_digestif_st_xor_into (value b1, value off1, value b2, value off2, value n) {
xor_into (_st_uint8_off (b1, off1), _st_uint8_off (b2, off2), Int_val (n));
return Val_unit;
}

View file

@ -0,0 +1,310 @@
#include "ripemd160.h"
#include "bitfn.h"
// adapted by Pieter Wuille in 2012; all changes are in the public domain
// modified by Ryan Castellucci in 2015; all changes are in the public domain
// modified by Romain Calascibetta in 2017; all changes are in the public domain
/*
*
* RIPEMD160.c : RIPEMD-160 implementation
*
* Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
*
* ===================================================================
* The contents of this file are dedicated to the public domain. To
* the extent that dedication to the public domain is not available,
* everyone is granted a worldwide, perpetual, royalty-free,
* non-exclusive license to exercise all rights associated with the
* contents of this file for any purpose whatsoever.
* No rights are reserved.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* ===================================================================
*
* Country of origin: Canada
*
* This implementation (written in C) is based on an implementation the author
* wrote in Python.
*
* This implementation was written with reference to the RIPEMD-160
* specification, which is available at:
* http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/
*
* It is also documented in the _Handbook of Applied Cryptography_, as
* Algorithm 9.55. It's on page 30 of the following PDF file:
* http://www.cacr.math.uwaterloo.ca/hac/about/chap9.pdf
*
* The RIPEMD-160 specification doesn't really tell us how to do padding, but
* since RIPEMD-160 is inspired by MD4, you can use the padding algorithm from
* RFC 1320.
*
* According to http://www.users.zetnet.co.uk/hopwood/crypto/scan/md.html:
* "RIPEMD-160 is big-bit-endian, little-byte-endian, and left-justified."
*/
#include <stdint.h>
#include <string.h>
/* Initial values for the chaining variables.
* This is just 0123456789ABCDEFFEDCBA9876543210F0E1D2C3 in little-endian. */
static const uint32_t initial_h[5] = { 0x67452301u, 0xEFCDAB89u, 0x98BADCFEu, 0x10325476u, 0xC3D2E1F0u };
/* Ordering of message words. Based on the permutations rho(i) and pi(i), defined as follows:
*
* rho(i) := { 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 }[i] 0 <= i <= 15
*
* pi(i) := 9*i + 5 (mod 16)
*
* Line | Round 1 | Round 2 | Round 3 | Round 4 | Round 5
* -------+-----------+-----------+-----------+-----------+-----------
* left | id | rho | rho^2 | rho^3 | rho^4
* right | pi | rho pi | rho^2 pi | rho^3 pi | rho^4 pi
*/
/* Left line */
static const uint8_t RL[5][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* Round 1: id */
{ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 }, /* Round 2: rho */
{ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 }, /* Round 3: rho^2 */
{ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 }, /* Round 4: rho^3 */
{ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 } /* Round 5: rho^4 */
};
/* Right line */
static const uint8_t RR[5][16] = {
{ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 }, /* Round 1: pi */
{ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 }, /* Round 2: rho pi */
{ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 }, /* Round 3: rho^2 pi */
{ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 }, /* Round 4: rho^3 pi */
{ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 } /* Round 5: rho^4 pi */
};
/*
* Shifts - Since we don't actually re-order the message words according to
* the permutations above (we could, but it would be slower), these tables
* come with the permutations pre-applied.
*/
/* Shifts, left line */
static const uint8_t SL[5][16] = {
{ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 }, /* Round 1 */
{ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 }, /* Round 2 */
{ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 }, /* Round 3 */
{ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 }, /* Round 4 */
{ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 } /* Round 5 */
};
/* Shifts, right line */
static const uint8_t SR[5][16] = {
{ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 }, /* Round 1 */
{ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 }, /* Round 2 */
{ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 }, /* Round 3 */
{ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 }, /* Round 4 */
{ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 } /* Round 5 */
};
/* static padding for 256 bit input */
static const uint8_t pad256[32] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* length 256 bits, little endian uint64_t */
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Boolean functions */
#define F1(x, y, z) ((x) ^ (y) ^ (z))
#define F2(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define F3(x, y, z) (((x) | ~(y)) ^ (z))
#define F4(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define F5(x, y, z) ((x) ^ ((y) | ~(z)))
/* Round constants, left line */
static const uint32_t KL[5] = {
0x00000000u, /* Round 1: 0 */
0x5A827999u, /* Round 2: floor(2**30 * sqrt(2)) */
0x6ED9EBA1u, /* Round 3: floor(2**30 * sqrt(3)) */
0x8F1BBCDCu, /* Round 4: floor(2**30 * sqrt(5)) */
0xA953FD4Eu /* Round 5: floor(2**30 * sqrt(7)) */
};
/* Round constants, right line */
static const uint32_t KR[5] = {
0x50A28BE6u, /* Round 1: floor(2**30 * cubert(2)) */
0x5C4DD124u, /* Round 2: floor(2**30 * cubert(3)) */
0x6D703EF3u, /* Round 3: floor(2**30 * cubert(5)) */
0x7A6D76E9u, /* Round 4: floor(2**30 * cubert(7)) */
0x00000000u /* Round 5: 0 */
};
void digestif_rmd160_init(struct rmd160_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->h[0] = 0x67452301UL;
ctx->h[1] = 0xefcdab89UL;
ctx->h[2] = 0x98badcfeUL;
ctx->h[3] = 0x10325476UL;
ctx->h[4] = 0xc3d2e1f0UL;
ctx->sz[0] = 0;
ctx->sz[1] = 0;
ctx->n = 0;
}
/* The RIPEMD160 compression function. */
static inline void rmd160_compress(struct rmd160_ctx *ctx, uint32_t *buf)
{
uint8_t w, round;
uint32_t T;
uint32_t AL, BL, CL, DL, EL; /* left line */
uint32_t AR, BR, CR, DR, ER; /* right line */
uint32_t X[16];
/* Byte-swap the buffer if we're on a big-endian machine */
cpu_to_le32_array(X, buf, 16);
/* Load the left and right lines with the initial state */
AL = AR = ctx->h[0];
BL = BR = ctx->h[1];
CL = CR = ctx->h[2];
DL = DR = ctx->h[3];
EL = ER = ctx->h[4];
/* Round 1 */
round = 0;
for (w = 0; w < 16; w++) { /* left line */
T = rol32(AL + F1(BL, CL, DL) + X[RL[round][w]] + KL[round], SL[round][w]) + EL;
AL = EL; EL = DL; DL = rol32(CL, 10); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = rol32(AR + F5(BR, CR, DR) + X[RR[round][w]] + KR[round], SR[round][w]) + ER;
AR = ER; ER = DR; DR = rol32(CR, 10); CR = BR; BR = T;
}
/* Round 2 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = rol32(AL + F2(BL, CL, DL) + X[RL[round][w]] + KL[round], SL[round][w]) + EL;
AL = EL; EL = DL; DL = rol32(CL, 10); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = rol32(AR + F4(BR, CR, DR) + X[RR[round][w]] + KR[round], SR[round][w]) + ER;
AR = ER; ER = DR; DR = rol32(CR, 10); CR = BR; BR = T;
}
/* Round 3 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = rol32(AL + F3(BL, CL, DL) + X[RL[round][w]] + KL[round], SL[round][w]) + EL;
AL = EL; EL = DL; DL = rol32(CL, 10); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = rol32(AR + F3(BR, CR, DR) + X[RR[round][w]] + KR[round], SR[round][w]) + ER;
AR = ER; ER = DR; DR = rol32(CR, 10); CR = BR; BR = T;
}
/* Round 4 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = rol32(AL + F4(BL, CL, DL) + X[RL[round][w]] + KL[round], SL[round][w]) + EL;
AL = EL; EL = DL; DL = rol32(CL, 10); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = rol32(AR + F2(BR, CR, DR) + X[RR[round][w]] + KR[round], SR[round][w]) + ER;
AR = ER; ER = DR; DR = rol32(CR, 10); CR = BR; BR = T;
}
/* Round 5 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = rol32(AL + F5(BL, CL, DL) + X[RL[round][w]] + KL[round], SL[round][w]) + EL;
AL = EL; EL = DL; DL = rol32(CL, 10); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = rol32(AR + F1(BR, CR, DR) + X[RR[round][w]] + KR[round], SR[round][w]) + ER;
AR = ER; ER = DR; DR = rol32(CR, 10); CR = BR; BR = T;
}
/* Final mixing stage */
T = ctx->h[1] + CL + DR;
ctx->h[1] = ctx->h[2] + DL + ER;
ctx->h[2] = ctx->h[3] + EL + AR;
ctx->h[3] = ctx->h[4] + AL + BR;
ctx->h[4] = ctx->h[0] + BL + CR;
ctx->h[0] = T;
}
void digestif_rmd160_update(struct rmd160_ctx *ctx, uint8_t *data, uint32_t len)
{
uint32_t t;
/* update length */
t = ctx->sz[0];
if ((ctx->sz[0] = t + (len << 3)) < t)
ctx->sz[1]++; /* carry from low 32 bits to high 32 bits. */
ctx->sz[1] += (len >> 29);
/* if data was left in buffer, pad it with fresh data and munge/eat block. */
if (ctx->n != 0)
{
t = 64 - ctx->n;
if (len < t) /* not enough to munge. */
{
memcpy(ctx->buf + ctx->n, data, len);
ctx->n += len;
return;
}
memcpy(ctx->buf + ctx->n, data, t);
rmd160_compress(ctx, (uint32_t *) ctx->buf);
data += t;
len -= t;
}
/* munge/eat data in 64 bytes chunks. */
while (len >= 64)
{
/* memcpy(ctx->buf, data, 64); XXX(dinosaure): from X.L. but
avoid to be fast. */
rmd160_compress(ctx, (uint32_t *) data);
data += 64;
len -= 64;
}
/* save remaining data. */
memcpy(ctx->buf, data, len);
ctx->n = len;
}
void digestif_rmd160_finalize(struct rmd160_ctx *ctx, uint8_t *out)
{
int i = ctx->n;
ctx->buf[i++] = 0x80;
if (i > 56)
{
memset(ctx->buf + i, 0, 64 - i);
rmd160_compress(ctx, (uint32_t *) ctx->buf);
i = 0;
}
memset(ctx->buf + i, 0, 56 - i);
cpu_to_le32_array((uint32_t *) (ctx->buf + 56), ctx->sz, 2);
rmd160_compress(ctx, (uint32_t *) ctx->buf);
cpu_to_le32_array((uint32_t *) out, ctx->h, 5);
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2017 Romain Calascibetta
* <romain.calascibetta@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CRYPTOHASH_RMD160_H
#define CRYPTOHASH_RMD160_H
#include <stdint.h>
struct rmd160_ctx
{
uint32_t h[5];
uint32_t sz[2];
int n;
uint8_t buf[64];
};
#define RMD160_DIGEST_SIZE 20
#define RMD160_CTX_SIZE (sizeof(struct rmd160_ctx))
void digestif_rmd160_init(struct rmd160_ctx *ctx);
void digestif_rmd160_update(struct rmd160_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_rmd160_finalize(struct rmd160_ctx *ctx, uint8_t *out);
#endif

View file

@ -0,0 +1,209 @@
/*
* Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "sha1.h"
#include "bitfn.h"
void digestif_sha1_init(struct sha1_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->h[0] = 0x67452301;
ctx->h[1] = 0xefcdab89;
ctx->h[2] = 0x98badcfe;
ctx->h[3] = 0x10325476;
ctx->h[4] = 0xc3d2e1f0;
}
#define f1(x, y, z) (z ^ (x & (y ^ z)))
#define f2(x, y, z) (x ^ y ^ z)
#define f3(x, y, z) ((x & y) + (z & (x ^ y)))
#define f4(x, y, z) f2(x, y, z)
#define K1 0x5a827999
#define K2 0x6ed9eba1
#define K3 0x8f1bbcdc
#define K4 0xca62c1d6
#define R(a, b, c, d, e, f, k, w) \
e += rol32(a, 5) + f(b, c, d) + k + w; b = rol32(b, 30)
#define M(i) (w[i & 0x0f] = rol32(w[i & 0x0f] ^ w[(i - 14) & 0x0f] \
^ w[(i - 8) & 0x0f] ^ w[(i - 3) & 0x0f], 1))
static inline void sha1_do_chunk(struct sha1_ctx *ctx, uint32_t *buf)
{
uint32_t a, b, c, d, e;
uint32_t w[16];
#define CPY(i) w[i] = be32_to_cpu(buf[i])
CPY(0); CPY(1); CPY(2); CPY(3); CPY(4); CPY(5); CPY(6); CPY(7);
CPY(8); CPY(9); CPY(10); CPY(11); CPY(12); CPY(13); CPY(14); CPY(15);
#undef CPY
a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; e = ctx->h[4];
R(a, b, c, d, e, f1, K1, w[0]);
R(e, a, b, c, d, f1, K1, w[1]);
R(d, e, a, b, c, f1, K1, w[2]);
R(c, d, e, a, b, f1, K1, w[3]);
R(b, c, d, e, a, f1, K1, w[4]);
R(a, b, c, d, e, f1, K1, w[5]);
R(e, a, b, c, d, f1, K1, w[6]);
R(d, e, a, b, c, f1, K1, w[7]);
R(c, d, e, a, b, f1, K1, w[8]);
R(b, c, d, e, a, f1, K1, w[9]);
R(a, b, c, d, e, f1, K1, w[10]);
R(e, a, b, c, d, f1, K1, w[11]);
R(d, e, a, b, c, f1, K1, w[12]);
R(c, d, e, a, b, f1, K1, w[13]);
R(b, c, d, e, a, f1, K1, w[14]);
R(a, b, c, d, e, f1, K1, w[15]);
R(e, a, b, c, d, f1, K1, M(16));
R(d, e, a, b, c, f1, K1, M(17));
R(c, d, e, a, b, f1, K1, M(18));
R(b, c, d, e, a, f1, K1, M(19));
R(a, b, c, d, e, f2, K2, M(20));
R(e, a, b, c, d, f2, K2, M(21));
R(d, e, a, b, c, f2, K2, M(22));
R(c, d, e, a, b, f2, K2, M(23));
R(b, c, d, e, a, f2, K2, M(24));
R(a, b, c, d, e, f2, K2, M(25));
R(e, a, b, c, d, f2, K2, M(26));
R(d, e, a, b, c, f2, K2, M(27));
R(c, d, e, a, b, f2, K2, M(28));
R(b, c, d, e, a, f2, K2, M(29));
R(a, b, c, d, e, f2, K2, M(30));
R(e, a, b, c, d, f2, K2, M(31));
R(d, e, a, b, c, f2, K2, M(32));
R(c, d, e, a, b, f2, K2, M(33));
R(b, c, d, e, a, f2, K2, M(34));
R(a, b, c, d, e, f2, K2, M(35));
R(e, a, b, c, d, f2, K2, M(36));
R(d, e, a, b, c, f2, K2, M(37));
R(c, d, e, a, b, f2, K2, M(38));
R(b, c, d, e, a, f2, K2, M(39));
R(a, b, c, d, e, f3, K3, M(40));
R(e, a, b, c, d, f3, K3, M(41));
R(d, e, a, b, c, f3, K3, M(42));
R(c, d, e, a, b, f3, K3, M(43));
R(b, c, d, e, a, f3, K3, M(44));
R(a, b, c, d, e, f3, K3, M(45));
R(e, a, b, c, d, f3, K3, M(46));
R(d, e, a, b, c, f3, K3, M(47));
R(c, d, e, a, b, f3, K3, M(48));
R(b, c, d, e, a, f3, K3, M(49));
R(a, b, c, d, e, f3, K3, M(50));
R(e, a, b, c, d, f3, K3, M(51));
R(d, e, a, b, c, f3, K3, M(52));
R(c, d, e, a, b, f3, K3, M(53));
R(b, c, d, e, a, f3, K3, M(54));
R(a, b, c, d, e, f3, K3, M(55));
R(e, a, b, c, d, f3, K3, M(56));
R(d, e, a, b, c, f3, K3, M(57));
R(c, d, e, a, b, f3, K3, M(58));
R(b, c, d, e, a, f3, K3, M(59));
R(a, b, c, d, e, f4, K4, M(60));
R(e, a, b, c, d, f4, K4, M(61));
R(d, e, a, b, c, f4, K4, M(62));
R(c, d, e, a, b, f4, K4, M(63));
R(b, c, d, e, a, f4, K4, M(64));
R(a, b, c, d, e, f4, K4, M(65));
R(e, a, b, c, d, f4, K4, M(66));
R(d, e, a, b, c, f4, K4, M(67));
R(c, d, e, a, b, f4, K4, M(68));
R(b, c, d, e, a, f4, K4, M(69));
R(a, b, c, d, e, f4, K4, M(70));
R(e, a, b, c, d, f4, K4, M(71));
R(d, e, a, b, c, f4, K4, M(72));
R(c, d, e, a, b, f4, K4, M(73));
R(b, c, d, e, a, f4, K4, M(74));
R(a, b, c, d, e, f4, K4, M(75));
R(e, a, b, c, d, f4, K4, M(76));
R(d, e, a, b, c, f4, K4, M(77));
R(c, d, e, a, b, f4, K4, M(78));
R(b, c, d, e, a, f4, K4, M(79));
ctx->h[0] += a;
ctx->h[1] += b;
ctx->h[2] += c;
ctx->h[3] += d;
ctx->h[4] += e;
}
void digestif_sha1_update(struct sha1_ctx *ctx, uint8_t *data, uint32_t len)
{
uint32_t index, to_fill;
index = (uint32_t) (ctx->sz & 0x3f);
to_fill = 64 - index;
ctx->sz += len;
/* process partial buffer if there's enough data to make a block */
if (index && len >= to_fill) {
memcpy(ctx->buf + index, data, to_fill);
sha1_do_chunk(ctx, (uint32_t *) ctx->buf);
len -= to_fill;
data += to_fill;
index = 0;
}
/* process as much 64-block as possible */
for (; len >= 64; len -= 64, data += 64)
sha1_do_chunk(ctx, (uint32_t *) data);
/* append data into buf */
if (len)
memcpy(ctx->buf + index, data, len);
}
void digestif_sha1_finalize(struct sha1_ctx *ctx, uint8_t *out)
{
static uint8_t padding[64] = { 0x80, };
uint64_t bits;
uint32_t index, padlen;
uint32_t *p = (uint32_t *) out;
/* add padding and update data with it */
bits = cpu_to_be64(ctx->sz << 3);
/* pad out to 56 */
index = (uint32_t) (ctx->sz & 0x3f);
padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
digestif_sha1_update(ctx, padding, padlen);
/* append length */
digestif_sha1_update(ctx, (uint8_t *) &bits, sizeof(bits));
/* output hash */
p[0] = cpu_to_be32(ctx->h[0]);
p[1] = cpu_to_be32(ctx->h[1]);
p[2] = cpu_to_be32(ctx->h[2]);
p[3] = cpu_to_be32(ctx->h[3]);
p[4] = cpu_to_be32(ctx->h[4]);
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CRYPTOHASH_SHA1_H
#define CRYPTOHASH_SHA1_H
#include <stdint.h>
struct sha1_ctx
{
uint64_t sz;
uint8_t buf[64];
uint32_t h[5];
};
#define SHA1_DIGEST_SIZE 20
#define SHA1_CTX_SIZE (sizeof(struct sha1_ctx))
void digestif_sha1_init(struct sha1_ctx *ctx);
void digestif_sha1_update(struct sha1_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_sha1_finalize(struct sha1_ctx *ctx, uint8_t *out);
#endif

View file

@ -0,0 +1,175 @@
/*
* Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "sha256.h"
#include "bitfn.h"
void digestif_sha224_init(struct sha224_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->h[0] = 0xc1059ed8;
ctx->h[1] = 0x367cd507;
ctx->h[2] = 0x3070dd17;
ctx->h[3] = 0xf70e5939;
ctx->h[4] = 0xffc00b31;
ctx->h[5] = 0x68581511;
ctx->h[6] = 0x64f98fa7;
ctx->h[7] = 0xbefa4fa4;
}
void digestif_sha256_init(struct sha256_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->h[0] = 0x6a09e667;
ctx->h[1] = 0xbb67ae85;
ctx->h[2] = 0x3c6ef372;
ctx->h[3] = 0xa54ff53a;
ctx->h[4] = 0x510e527f;
ctx->h[5] = 0x9b05688c;
ctx->h[6] = 0x1f83d9ab;
ctx->h[7] = 0x5be0cd19;
}
/* 232 times the cube root of the first 64 primes 2..311 */
static const uint32_t k[] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
#define e0(x) (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22))
#define e1(x) (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25))
#define s0(x) (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3))
#define s1(x) (ror32(x,17) ^ ror32(x,19) ^ (x >> 10))
static void sha256_do_chunk(struct sha256_ctx *ctx, uint32_t buf[])
{
uint32_t a, b, c, d, e, f, g, h, t1, t2;
int i;
uint32_t w[64];
cpu_to_be32_array(w, buf, 16);
for (i = 16; i < 64; i++)
w[i] = s1(w[i - 2]) + w[i - 7] + s0(w[i - 15]) + w[i - 16];
a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3];
e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7];
#define R(a, b, c, d, e, f, g, h, k, w) \
t1 = h + e1(e) + (g ^ (e & (f ^ g))) + k + w; \
t2 = e0(a) + ((a & b) | (c & (a | b))); \
d += t1; \
h = t1 + t2;
for (i = 0; i < 64; i += 8) {
R(a, b, c, d, e, f, g, h, k[i + 0], w[i + 0]);
R(h, a, b, c, d, e, f, g, k[i + 1], w[i + 1]);
R(g, h, a, b, c, d, e, f, k[i + 2], w[i + 2]);
R(f, g, h, a, b, c, d, e, k[i + 3], w[i + 3]);
R(e, f, g, h, a, b, c, d, k[i + 4], w[i + 4]);
R(d, e, f, g, h, a, b, c, k[i + 5], w[i + 5]);
R(c, d, e, f, g, h, a, b, k[i + 6], w[i + 6]);
R(b, c, d, e, f, g, h, a, k[i + 7], w[i + 7]);
}
#undef R
ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d;
ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h;
}
void digestif_sha224_update(struct sha224_ctx *ctx, uint8_t *data, uint32_t len)
{
digestif_sha256_update(ctx, data, len);
}
void digestif_sha256_update(struct sha256_ctx *ctx, uint8_t *data, uint32_t len)
{
uint32_t index, to_fill;
/* check for partial buffer */
index = (uint32_t) (ctx->sz & 0x3f);
to_fill = 64 - index;
ctx->sz += len;
/* process partial buffer if there's enough data to make a block */
if (index && len >= to_fill) {
memcpy(ctx->buf + index, data, to_fill);
sha256_do_chunk(ctx, (uint32_t *) ctx->buf);
len -= to_fill;
data += to_fill;
index = 0;
}
/* process as much 64-block as possible */
for (; len >= 64; len -= 64, data += 64)
sha256_do_chunk(ctx, (uint32_t *) data);
/* append data into buf */
if (len)
memcpy(ctx->buf + index, data, len);
}
void digestif_sha224_finalize(struct sha224_ctx *ctx, uint8_t *out)
{
uint8_t intermediate[SHA256_DIGEST_SIZE];
digestif_sha256_finalize(ctx, intermediate);
memcpy(out, intermediate, SHA224_DIGEST_SIZE);
}
void digestif_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out)
{
static uint8_t padding[64] = { 0x80, };
uint64_t bits;
uint32_t i, index, padlen;
uint32_t *p = (uint32_t *) out;
/* cpu -> big endian */
bits = cpu_to_be64(ctx->sz << 3);
/* pad out to 56 */
index = (uint32_t) (ctx->sz & 0x3f);
padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
digestif_sha256_update(ctx, padding, padlen);
/* append length */
digestif_sha256_update(ctx, (uint8_t *) &bits, sizeof(bits));
/* store to digest */
for (i = 0; i < 8; i++)
p[i] = cpu_to_be32(ctx->h[i]);
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CRYPTOHASH_SHA256_H
#define CRYPTOHASH_SHA256_H
#include <stdint.h>
struct sha256_ctx
{
uint64_t sz;
uint8_t buf[128];
uint32_t h[8];
};
#define sha224_ctx sha256_ctx
#define SHA224_DIGEST_SIZE 28
#define SHA224_CTX_SIZE sizeof(struct sha224_ctx)
#define SHA256_DIGEST_SIZE 32
#define SHA256_CTX_SIZE sizeof(struct sha256_ctx)
void digestif_sha224_init(struct sha224_ctx *ctx);
void digestif_sha224_update(struct sha224_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_sha224_finalize(struct sha224_ctx *ctx, uint8_t *out);
void digestif_sha256_init(struct sha256_ctx *ctx);
void digestif_sha256_update(struct sha256_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out);
#endif

View file

@ -0,0 +1,156 @@
/* Copyright (c) 2015 Markku-Juhani O. Saarinen */
#include "sha3.h"
#ifndef KECCAKF_ROUNDS
#define KECCAKF_ROUNDS 24
#endif
#ifndef ROTL64
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
#endif
// update the state with given number of rounds
static void sha3_keccakf(uint64_t st[25])
{
// constants
const uint64_t keccakf_rndc[24] = {
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
};
const int 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
};
const int 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
};
// variables
int i, j, r;
uint64_t t, bc[5];
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
uint8_t *v;
// endianess conversion. this is redundant on little-endian targets
for (i = 0; i < 25; i++) {
v = (uint8_t *) &st[i];
st[i] = ((uint64_t) v[0]) | (((uint64_t) v[1]) << 8) |
(((uint64_t) v[2]) << 16) | (((uint64_t) v[3]) << 24) |
(((uint64_t) v[4]) << 32) | (((uint64_t) v[5]) << 40) |
(((uint64_t) v[6]) << 48) | (((uint64_t) v[7]) << 56);
}
#endif
// actual iteration
for (r = 0; r < KECCAKF_ROUNDS; r++) {
// Theta
for (i = 0; i < 5; i++)
bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
for (i = 0; i < 5; i++) {
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
for (j = 0; j < 25; j += 5)
st[j + i] ^= t;
}
// Rho Pi
t = st[1];
for (i = 0; i < 24; i++) {
j = keccakf_piln[i];
bc[0] = st[j];
st[j] = ROTL64(t, keccakf_rotc[i]);
t = bc[0];
}
// Chi
for (j = 0; j < 25; j += 5) {
for (i = 0; i < 5; i++)
bc[i] = st[j + i];
for (i = 0; i < 5; i++)
st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
}
// Iota
st[0] ^= keccakf_rndc[r];
}
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
// endianess conversion. this is redundant on little-endian targets
for (i = 0; i < 25; i++) {
v = (uint8_t *) &st[i];
t = st[i];
v[0] = t & 0xFF;
v[1] = (t >> 8) & 0xFF;
v[2] = (t >> 16) & 0xFF;
v[3] = (t >> 24) & 0xFF;
v[4] = (t >> 32) & 0xFF;
v[5] = (t >> 40) & 0xFF;
v[6] = (t >> 48) & 0xFF;
v[7] = (t >> 56) & 0xFF;
}
#endif
}
// Initialize the context for SHA3
void digestif_sha3_init(struct sha3_ctx *ctx, int mdlen)
{
int i;
for (i = 0; i < 25; i++)
ctx->st.q[i] = 0;
ctx->mdlen = mdlen/8;
ctx->rsiz = 200 - 2 * ctx->mdlen;
ctx->pt = 0;
return;
}
// update state with more data
void digestif_sha3_update(struct sha3_ctx *ctx, uint8_t *data, uint32_t len)
{
uint32_t i;
int j;
j = ctx->pt;
for (i = 0; i < len; i++) {
ctx->st.b[j++] ^= data[i];
if (j >= ctx->rsiz) {
sha3_keccakf(ctx->st.q);
j = 0;
}
}
ctx->pt = j;
return;
}
// finalize and output a hash
void digestif_sha3_finalize(struct sha3_ctx *ctx, uint8_t *md, uint8_t padding)
{
int i;
//padding
ctx->st.b[ctx->pt] ^= padding;
ctx->st.b[ctx->rsiz - 1] ^= 0x80;
//call f on the last block
sha3_keccakf(ctx->st.q);
for (i = 0; i < ctx->mdlen; i++) {
md[i] = ctx->st.b[i];
}
return;
}

View file

@ -0,0 +1,24 @@
/* Copyright (c) 2015 Markku-Juhani O. Saarinen */
#ifndef CRYPTOHASH_SHA3_H
#define CRYPTOHASH_SHA3_H
#include <stdint.h>
struct sha3_ctx
{
union { // state:
uint8_t b[200]; // 8-bit bytes
uint64_t q[25]; // 64-bit words
} st;
int pt, rsiz, mdlen; // these don't overflow
};
#define SHA3_CTX_SIZE sizeof(struct sha3_ctx)
void digestif_sha3_init(struct sha3_ctx *ctx, int mdlen);
void digestif_sha3_update(struct sha3_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_sha3_finalize(struct sha3_ctx *ctx, uint8_t *out, uint8_t padding);
#endif

View file

@ -0,0 +1,195 @@
/*
* Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "bitfn.h"
#include "sha512.h"
void digestif_sha384_init(struct sha512_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->h[0] = 0xcbbb9d5dc1059ed8ULL;
ctx->h[1] = 0x629a292a367cd507ULL;
ctx->h[2] = 0x9159015a3070dd17ULL;
ctx->h[3] = 0x152fecd8f70e5939ULL;
ctx->h[4] = 0x67332667ffc00b31ULL;
ctx->h[5] = 0x8eb44a8768581511ULL;
ctx->h[6] = 0xdb0c2e0d64f98fa7ULL;
ctx->h[7] = 0x47b5481dbefa4fa4ULL;
}
void digestif_sha512_init(struct sha512_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->h[0] = 0x6a09e667f3bcc908ULL;
ctx->h[1] = 0xbb67ae8584caa73bULL;
ctx->h[2] = 0x3c6ef372fe94f82bULL;
ctx->h[3] = 0xa54ff53a5f1d36f1ULL;
ctx->h[4] = 0x510e527fade682d1ULL;
ctx->h[5] = 0x9b05688c2b3e6c1fULL;
ctx->h[6] = 0x1f83d9abfb41bd6bULL;
ctx->h[7] = 0x5be0cd19137e2179ULL;
}
/* 232 times the cube root of the first 64 primes 2..311 */
static const uint64_t k[] = {
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
};
#define e0(x) (ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39))
#define e1(x) (ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41))
#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
#define s1(x) (ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6))
static void sha512_do_chunk(struct sha512_ctx *ctx, uint64_t *buf)
{
uint64_t a, b, c, d, e, f, g, h, t1, t2;
int i;
uint64_t w[80];
cpu_to_be64_array(w, buf, 16);
for (i = 16; i < 80; i++)
w[i] = s1(w[i - 2]) + w[i - 7] + s0(w[i - 15]) + w[i - 16];
a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3];
e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7];
#define R(a, b, c, d, e, f, g, h, k, w) \
t1 = h + e1(e) + (g ^ (e & (f ^ g))) + k + w; \
t2 = e0(a) + ((a & b) | (c & (a | b))); \
d += t1; \
h = t1 + t2
for (i = 0; i < 80; i += 8) {
R(a, b, c, d, e, f, g, h, k[i + 0], w[i + 0]);
R(h, a, b, c, d, e, f, g, k[i + 1], w[i + 1]);
R(g, h, a, b, c, d, e, f, k[i + 2], w[i + 2]);
R(f, g, h, a, b, c, d, e, k[i + 3], w[i + 3]);
R(e, f, g, h, a, b, c, d, k[i + 4], w[i + 4]);
R(d, e, f, g, h, a, b, c, k[i + 5], w[i + 5]);
R(c, d, e, f, g, h, a, b, k[i + 6], w[i + 6]);
R(b, c, d, e, f, g, h, a, k[i + 7], w[i + 7]);
}
#undef R
ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d;
ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h;
}
void digestif_sha384_update(struct sha384_ctx *ctx, uint8_t *data, uint32_t len)
{
digestif_sha512_update(ctx, data, len);
}
void digestif_sha512_update(struct sha512_ctx *ctx, uint8_t *data, uint32_t len)
{
unsigned int index, to_fill;
/* check for partial buffer */
index = (unsigned int) (ctx->sz[0] & 0x7f);
to_fill = 128 - index;
ctx->sz[0] += len;
if (ctx->sz[0] < len)
ctx->sz[1]++;
/* process partial buffer if there's enough data to make a block */
if (index && len >= to_fill) {
memcpy(ctx->buf + index, data, to_fill);
sha512_do_chunk(ctx, (uint64_t *) ctx->buf);
len -= to_fill;
data += to_fill;
index = 0;
}
/* process as much 128-block as possible */
for (; len >= 128; len -= 128, data += 128)
sha512_do_chunk(ctx, (uint64_t *) data);
/* append data into buf */
if (len)
memcpy(ctx->buf + index, data, len);
}
void digestif_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out)
{
uint8_t intermediate[SHA512_DIGEST_SIZE];
digestif_sha512_finalize(ctx, intermediate);
memcpy(out, intermediate, SHA384_DIGEST_SIZE);
}
void digestif_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out)
{
static uint8_t padding[128] = { 0x80, };
uint32_t i, index, padlen;
uint64_t bits[2];
uint64_t *p = (uint64_t *) out;
/* cpu -> big endian */
bits[0] = cpu_to_be64((ctx->sz[1] << 3 | ctx->sz[0] >> 61));
bits[1] = cpu_to_be64((ctx->sz[0] << 3));
/* pad out to 56 */
index = (unsigned int) (ctx->sz[0] & 0x7f);
padlen = (index < 112) ? (112 - index) : ((128 + 112) - index);
digestif_sha512_update(ctx, padding, padlen);
/* append length */
digestif_sha512_update(ctx, (uint8_t *) bits, sizeof(bits));
/* store to digest */
for (i = 0; i < 8; i++)
p[i] = cpu_to_be64(ctx->h[i]);
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CRYPTOHASH_SHA512_H
#define CRYPTOHASH_SHA512_H
#include <stdint.h>
struct sha512_ctx
{
uint64_t sz[2];
uint8_t buf[128];
uint64_t h[8];
};
#define sha384_ctx sha512_ctx
#define SHA384_DIGEST_SIZE 48
#define SHA384_CTX_SIZE sizeof(struct sha384_ctx)
#define SHA512_DIGEST_SIZE 64
#define SHA512_CTX_SIZE sizeof(struct sha512_ctx)
void digestif_sha384_init(struct sha384_ctx *ctx);
void digestif_sha384_update(struct sha384_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out);
void digestif_sha512_init(struct sha512_ctx *ctx);
void digestif_sha512_update(struct sha512_ctx *ctx, uint8_t *data, uint32_t len);
void digestif_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out);
#endif

View file

@ -0,0 +1,282 @@
#include "digestif.h"
#include "md5.h"
#include "sha1.h"
#include "sha256.h"
#include "sha512.h"
#include "sha3.h"
#include "whirlpool.h"
#include "blake2b.h"
#include "blake2s.h"
#include "ripemd160.h"
#include <caml/memory.h>
#include <string.h>
#ifndef Bytes_val
#define Bytes_val(x) String_val(x)
#endif
#if defined(__ocaml_freestanding__) || defined(__ocaml_solo5__)
#define __define_ba_update(name) \
CAMLprim value \
caml_digestif_ ## name ## _ba_update \
(value ctx, value src, value off, value len) { \
digestif_ ## name ## _update ( \
(struct name ## _ctx *) String_val (ctx), \
_ba_uint8_off (src, off), Int_val (len)); \
return Val_unit; \
}
#define __define_sha3_ba_update(mdlen) \
CAMLprim value \
caml_digestif_sha3_ ## mdlen ## _ba_update \
(value ctx, value src, value off, value len) { \
digestif_sha3_update ( \
(struct sha3_ctx *) String_val (ctx), \
_ba_uint8_off (src, off), Int_val (len)); \
return Val_unit; \
}
#else
/* XXX(dinosaure): even if they are not defined (only defined by
* [caml/threads.h]), they exists without [threads.cmxa]. For compatibility
* reason, we keep a protection when we compile for Solo5/ocaml-freestanding
* but for the rest, these functions should be available in any cases.
*
* In some cases (Solo5 or Esperanto), [caml/threads.h] is not available but
* these functions still exist!
*/
CAMLextern void caml_enter_blocking_section (void);
CAMLextern void caml_leave_blocking_section (void);
#define __define_ba_update(name) \
CAMLprim value \
caml_digestif_ ## name ## _ba_update \
(value ctx, value src, value off, value len) { \
CAMLparam4 (ctx, src, off, len); \
uint8_t *off_ = ((uint8_t*) Caml_ba_data_val(src)) + Long_val (off); \
uint32_t len_ = Long_val (len); \
struct name ## _ctx ctx_; \
memcpy(&ctx_, Bytes_val(ctx), sizeof(struct name ## _ctx)); \
caml_enter_blocking_section(); \
digestif_ ## name ## _update (&ctx_, off_, len_); \
caml_leave_blocking_section(); \
memcpy(Bytes_val(ctx), &ctx_, sizeof(struct name ## _ctx)); \
CAMLreturn (Val_unit); \
}
#define __define_sha3_ba_update(mdlen) \
CAMLprim value \
caml_digestif_sha3_ ## mdlen ## _ba_update \
(value ctx, value src, value off, value len) { \
CAMLparam4 (ctx, src, off, len); \
uint8_t *off_ = ((uint8_t*) Caml_ba_data_val(src)) + Long_val (off); \
uint32_t len_ = Long_val (len); \
struct sha3_ctx ctx_; \
memcpy(&ctx_, Bytes_val(ctx), sizeof(struct sha3_ctx)); \
caml_enter_blocking_section(); \
digestif_sha3_update (&ctx_, off_, len_); \
caml_leave_blocking_section(); \
memcpy(Bytes_val(ctx), &ctx_, sizeof(struct sha3_ctx)); \
CAMLreturn (Val_unit); \
}
#endif
#define __define_hash(name, upper) \
\
CAMLprim value \
caml_digestif_ ## name ## _ba_init (value ctx) { \
digestif_ ## name ## _init ((struct name ## _ctx *) String_val (ctx)); \
return Val_unit; \
} \
\
CAMLprim value \
caml_digestif_ ## name ## _st_init (value ctx) { \
digestif_ ## name ## _init ((struct name ## _ctx *) String_val (ctx)); \
return Val_unit; \
} \
\
__define_ba_update(name) \
\
CAMLprim value \
caml_digestif_ ## name ## _st_update \
(value ctx, value src, value off, value len) { \
digestif_ ## name ## _update ( \
(struct name ## _ctx *) String_val (ctx), \
_st_uint8_off (src, off), Int_val (len)); \
return Val_unit; \
} \
\
CAMLprim value \
caml_digestif_ ## name ## _ba_finalize (value ctx, value dst, value off) { \
digestif_ ## name ## _finalize ( \
(struct name ## _ctx *) String_val (ctx), \
_ba_uint8_off (dst, off)); \
return Val_unit; \
} \
\
CAMLprim value \
caml_digestif_ ## name ## _st_finalize (value ctx, value dst, value off) { \
digestif_ ## name ## _finalize( \
(struct name ## _ctx *) String_val (ctx), \
_st_uint8_off (dst, off)); \
return Val_unit; \
} \
\
CAMLprim value \
caml_digestif_ ## name ## _ctx_size (__unit ()) { \
return Val_int (upper ## _CTX_SIZE); \
}
__define_hash (md5, MD5)
__define_hash (sha1, SHA1)
__define_hash (sha224, SHA224)
__define_hash (sha256, SHA256)
__define_hash (sha384, SHA384)
__define_hash (sha512, SHA512)
__define_hash (whirlpool, WHIRLPOOL)
__define_hash (blake2b, BLAKE2B)
__define_hash (blake2s, BLAKE2S)
__define_hash (rmd160, RMD160)
CAMLprim value
caml_digestif_blake2b_ba_init_with_outlen_and_key(value ctx, value outlen, value key, value off, value len)
{
digestif_blake2b_init_with_outlen_and_key(
(struct blake2b_ctx *) String_val (ctx), Int_val (outlen),
_ba_uint8_off(key, off), Int_val (len));
return Val_unit;
}
CAMLprim value
caml_digestif_blake2b_st_init_with_outlen_and_key(value ctx, value outlen, value key, value off, value len)
{
digestif_blake2b_init_with_outlen_and_key(
(struct blake2b_ctx *) String_val (ctx), Int_val (outlen),
_st_uint8_off(key, off), Int_val (len));
return Val_unit;
}
CAMLprim value
caml_digestif_blake2b_key_size(__unit ()) {
return Val_int (BLAKE2B_KEYBYTES);
}
CAMLprim value
caml_digestif_blake2b_max_outlen(__unit ()) {
return Val_int (BLAKE2B_OUTBYTES);
}
CAMLprim value
caml_digestif_blake2b_digest_size(value ctx) {
return Val_int(((struct blake2b_ctx *) String_val (ctx))->outlen);
}
CAMLprim value
caml_digestif_blake2s_ba_init_with_outlen_and_key(value ctx, value outlen, value key, value off, value len)
{
digestif_blake2s_init_with_outlen_and_key(
(struct blake2s_ctx *) String_val (ctx), Int_val (outlen),
_ba_uint8_off(key, off), Int_val (len));
return Val_unit;
}
CAMLprim value
caml_digestif_blake2s_st_init_with_outlen_and_key(value ctx, value outlen, value key, value off, value len)
{
digestif_blake2s_init_with_outlen_and_key(
(struct blake2s_ctx *) String_val (ctx), Int_val (outlen),
_st_uint8_off(key, off), Int_val (len));
return Val_unit;
}
CAMLprim value
caml_digestif_blake2s_key_size(__unit ()) {
return Val_int (BLAKE2S_KEYBYTES);
}
CAMLprim value
caml_digestif_blake2s_max_outlen(__unit ()) {
return Val_int (BLAKE2S_OUTBYTES);
}
CAMLprim value
caml_digestif_blake2s_digest_size(value ctx) {
return Val_int(((struct blake2s_ctx *) String_val (ctx))->outlen);
}
CAMLprim value
caml_digestif_keccak_256_ba_finalize
(value ctx, value dst, value off) {
digestif_sha3_finalize (
(struct sha3_ctx *) String_val (ctx),
_ba_uint8_off (dst, off), 0x01);
return Val_unit;
}
CAMLprim value
caml_digestif_keccak_256_st_finalize
(value ctx, value dst, value off) {
digestif_sha3_finalize(
(struct sha3_ctx *) String_val (ctx),
_st_uint8_off (dst, off), 0x01);
return Val_unit;
}
#define __define_hash_sha3(mdlen) \
\
CAMLprim value \
caml_digestif_sha3_ ## mdlen ## _ba_init (value ctx) { \
digestif_sha3_init ((struct sha3_ctx *) String_val (ctx), mdlen); \
return Val_unit; \
} \
\
CAMLprim value \
caml_digestif_sha3_ ## mdlen ## _st_init (value ctx) { \
digestif_sha3_init ((struct sha3_ctx *) String_val (ctx), mdlen); \
return Val_unit; \
} \
\
__define_sha3_ba_update(mdlen) \
\
CAMLprim value \
caml_digestif_sha3_ ## mdlen ## _st_update \
(value ctx, value src, value off, value len) { \
digestif_sha3_update ( \
(struct sha3_ctx *) String_val (ctx), \
_st_uint8_off (src, off), Int_val (len)); \
return Val_unit; \
} \
\
CAMLprim value \
caml_digestif_sha3_ ## mdlen ## _ba_finalize \
(value ctx, value dst, value off) { \
digestif_sha3_finalize ( \
(struct sha3_ctx *) String_val (ctx), \
_ba_uint8_off (dst, off), 0x06); \
return Val_unit; \
} \
\
CAMLprim value \
caml_digestif_sha3_ ## mdlen ## _st_finalize \
(value ctx, value dst, value off) { \
digestif_sha3_finalize( \
(struct sha3_ctx *) String_val (ctx), \
_st_uint8_off (dst, off), 0x06); \
return Val_unit; \
} \
\
CAMLprim value \
caml_digestif_sha3_ ## mdlen ## _ctx_size (__unit ()) { \
return Val_int (SHA3_CTX_SIZE); \
}
__define_hash_sha3 (224)
__define_hash_sha3 (256)
__define_hash_sha3 (384)
__define_hash_sha3 (512)

View file

@ -0,0 +1,729 @@
/* whirlpool.c - an implementation of the Whirlpool Hash Function.
*
* Copyright: 2009-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
*
* Documentation:
* P. S. L. M. Barreto, V. Rijmen, ``The Whirlpool hashing function,''
* NESSIE submission, 2000 (tweaked version, 2001)
*
* The algorithm is named after the Whirlpool Galaxy in Canes Venatici.
*/
#include <string.h>
#include "bitfn.h"
#include "whirlpool.h"
uint64_t digestif_whirlpool_sbox[8][256] = {
{
/* C0 vectors */
0x18186018c07830d8ULL, 0x23238c2305af4626ULL, 0xc6c63fc67ef991b8ULL, 0xe8e887e8136fcdfbULL,
0x878726874ca113cbULL, 0xb8b8dab8a9626d11ULL, 0x0101040108050209ULL, 0x4f4f214f426e9e0dULL,
0x3636d836adee6c9bULL, 0xa6a6a2a6590451ffULL, 0xd2d26fd2debdb90cULL, 0xf5f5f3f5fb06f70eULL,
0x7979f979ef80f296ULL, 0x6f6fa16f5fcede30ULL, 0x91917e91fcef3f6dULL, 0x52525552aa07a4f8ULL,
0x60609d6027fdc047ULL, 0xbcbccabc89766535ULL, 0x9b9b569baccd2b37ULL, 0x8e8e028e048c018aULL,
0xa3a3b6a371155bd2ULL, 0x0c0c300c603c186cULL, 0x7b7bf17bff8af684ULL, 0x3535d435b5e16a80ULL,
0x1d1d741de8693af5ULL, 0xe0e0a7e05347ddb3ULL, 0xd7d77bd7f6acb321ULL, 0xc2c22fc25eed999cULL,
0x2e2eb82e6d965c43ULL, 0x4b4b314b627a9629ULL, 0xfefedffea321e15dULL, 0x575741578216aed5ULL,
0x15155415a8412abdULL, 0x7777c1779fb6eee8ULL, 0x3737dc37a5eb6e92ULL, 0xe5e5b3e57b56d79eULL,
0x9f9f469f8cd92313ULL, 0xf0f0e7f0d317fd23ULL, 0x4a4a354a6a7f9420ULL, 0xdada4fda9e95a944ULL,
0x58587d58fa25b0a2ULL, 0xc9c903c906ca8fcfULL, 0x2929a429558d527cULL, 0x0a0a280a5022145aULL,
0xb1b1feb1e14f7f50ULL, 0xa0a0baa0691a5dc9ULL, 0x6b6bb16b7fdad614ULL, 0x85852e855cab17d9ULL,
0xbdbdcebd8173673cULL, 0x5d5d695dd234ba8fULL, 0x1010401080502090ULL, 0xf4f4f7f4f303f507ULL,
0xcbcb0bcb16c08bddULL, 0x3e3ef83eedc67cd3ULL, 0x0505140528110a2dULL, 0x676781671fe6ce78ULL,
0xe4e4b7e47353d597ULL, 0x27279c2725bb4e02ULL, 0x4141194132588273ULL, 0x8b8b168b2c9d0ba7ULL,
0xa7a7a6a7510153f6ULL, 0x7d7de97dcf94fab2ULL, 0x95956e95dcfb3749ULL, 0xd8d847d88e9fad56ULL,
0xfbfbcbfb8b30eb70ULL, 0xeeee9fee2371c1cdULL, 0x7c7ced7cc791f8bbULL, 0x6666856617e3cc71ULL,
0xdddd53dda68ea77bULL, 0x17175c17b84b2eafULL, 0x4747014702468e45ULL, 0x9e9e429e84dc211aULL,
0xcaca0fca1ec589d4ULL, 0x2d2db42d75995a58ULL, 0xbfbfc6bf9179632eULL, 0x07071c07381b0e3fULL,
0xadad8ead012347acULL, 0x5a5a755aea2fb4b0ULL, 0x838336836cb51befULL, 0x3333cc3385ff66b6ULL,
0x636391633ff2c65cULL, 0x02020802100a0412ULL, 0xaaaa92aa39384993ULL, 0x7171d971afa8e2deULL,
0xc8c807c80ecf8dc6ULL, 0x19196419c87d32d1ULL, 0x494939497270923bULL, 0xd9d943d9869aaf5fULL,
0xf2f2eff2c31df931ULL, 0xe3e3abe34b48dba8ULL, 0x5b5b715be22ab6b9ULL, 0x88881a8834920dbcULL,
0x9a9a529aa4c8293eULL, 0x262698262dbe4c0bULL, 0x3232c8328dfa64bfULL, 0xb0b0fab0e94a7d59ULL,
0xe9e983e91b6acff2ULL, 0x0f0f3c0f78331e77ULL, 0xd5d573d5e6a6b733ULL, 0x80803a8074ba1df4ULL,
0xbebec2be997c6127ULL, 0xcdcd13cd26de87ebULL, 0x3434d034bde46889ULL, 0x48483d487a759032ULL,
0xffffdbffab24e354ULL, 0x7a7af57af78ff48dULL, 0x90907a90f4ea3d64ULL, 0x5f5f615fc23ebe9dULL,
0x202080201da0403dULL, 0x6868bd6867d5d00fULL, 0x1a1a681ad07234caULL, 0xaeae82ae192c41b7ULL,
0xb4b4eab4c95e757dULL, 0x54544d549a19a8ceULL, 0x93937693ece53b7fULL, 0x222288220daa442fULL,
0x64648d6407e9c863ULL, 0xf1f1e3f1db12ff2aULL, 0x7373d173bfa2e6ccULL, 0x12124812905a2482ULL,
0x40401d403a5d807aULL, 0x0808200840281048ULL, 0xc3c32bc356e89b95ULL, 0xecec97ec337bc5dfULL,
0xdbdb4bdb9690ab4dULL, 0xa1a1bea1611f5fc0ULL, 0x8d8d0e8d1c830791ULL, 0x3d3df43df5c97ac8ULL,
0x97976697ccf1335bULL, 0x0000000000000000ULL, 0xcfcf1bcf36d483f9ULL, 0x2b2bac2b4587566eULL,
0x7676c57697b3ece1ULL, 0x8282328264b019e6ULL, 0xd6d67fd6fea9b128ULL, 0x1b1b6c1bd87736c3ULL,
0xb5b5eeb5c15b7774ULL, 0xafaf86af112943beULL, 0x6a6ab56a77dfd41dULL, 0x50505d50ba0da0eaULL,
0x45450945124c8a57ULL, 0xf3f3ebf3cb18fb38ULL, 0x3030c0309df060adULL, 0xefef9bef2b74c3c4ULL,
0x3f3ffc3fe5c37edaULL, 0x55554955921caac7ULL, 0xa2a2b2a2791059dbULL, 0xeaea8fea0365c9e9ULL,
0x656589650fecca6aULL, 0xbabad2bab9686903ULL, 0x2f2fbc2f65935e4aULL, 0xc0c027c04ee79d8eULL,
0xdede5fdebe81a160ULL, 0x1c1c701ce06c38fcULL, 0xfdfdd3fdbb2ee746ULL, 0x4d4d294d52649a1fULL,
0x92927292e4e03976ULL, 0x7575c9758fbceafaULL, 0x06061806301e0c36ULL, 0x8a8a128a249809aeULL,
0xb2b2f2b2f940794bULL, 0xe6e6bfe66359d185ULL, 0x0e0e380e70361c7eULL, 0x1f1f7c1ff8633ee7ULL,
0x6262956237f7c455ULL, 0xd4d477d4eea3b53aULL, 0xa8a89aa829324d81ULL, 0x96966296c4f43152ULL,
0xf9f9c3f99b3aef62ULL, 0xc5c533c566f697a3ULL, 0x2525942535b14a10ULL, 0x59597959f220b2abULL,
0x84842a8454ae15d0ULL, 0x7272d572b7a7e4c5ULL, 0x3939e439d5dd72ecULL, 0x4c4c2d4c5a619816ULL,
0x5e5e655eca3bbc94ULL, 0x7878fd78e785f09fULL, 0x3838e038ddd870e5ULL, 0x8c8c0a8c14860598ULL,
0xd1d163d1c6b2bf17ULL, 0xa5a5aea5410b57e4ULL, 0xe2e2afe2434dd9a1ULL, 0x616199612ff8c24eULL,
0xb3b3f6b3f1457b42ULL, 0x2121842115a54234ULL, 0x9c9c4a9c94d62508ULL, 0x1e1e781ef0663ceeULL,
0x4343114322528661ULL, 0xc7c73bc776fc93b1ULL, 0xfcfcd7fcb32be54fULL, 0x0404100420140824ULL,
0x51515951b208a2e3ULL, 0x99995e99bcc72f25ULL, 0x6d6da96d4fc4da22ULL, 0x0d0d340d68391a65ULL,
0xfafacffa8335e979ULL, 0xdfdf5bdfb684a369ULL, 0x7e7ee57ed79bfca9ULL, 0x242490243db44819ULL,
0x3b3bec3bc5d776feULL, 0xabab96ab313d4b9aULL, 0xcece1fce3ed181f0ULL, 0x1111441188552299ULL,
0x8f8f068f0c890383ULL, 0x4e4e254e4a6b9c04ULL, 0xb7b7e6b7d1517366ULL, 0xebeb8beb0b60cbe0ULL,
0x3c3cf03cfdcc78c1ULL, 0x81813e817cbf1ffdULL, 0x94946a94d4fe3540ULL, 0xf7f7fbf7eb0cf31cULL,
0xb9b9deb9a1676f18ULL, 0x13134c13985f268bULL, 0x2c2cb02c7d9c5851ULL, 0xd3d36bd3d6b8bb05ULL,
0xe7e7bbe76b5cd38cULL, 0x6e6ea56e57cbdc39ULL, 0xc4c437c46ef395aaULL, 0x03030c03180f061bULL,
0x565645568a13acdcULL, 0x44440d441a49885eULL, 0x7f7fe17fdf9efea0ULL, 0xa9a99ea921374f88ULL,
0x2a2aa82a4d825467ULL, 0xbbbbd6bbb16d6b0aULL, 0xc1c123c146e29f87ULL, 0x53535153a202a6f1ULL,
0xdcdc57dcae8ba572ULL, 0x0b0b2c0b58271653ULL, 0x9d9d4e9d9cd32701ULL, 0x6c6cad6c47c1d82bULL,
0x3131c43195f562a4ULL, 0x7474cd7487b9e8f3ULL, 0xf6f6fff6e309f115ULL, 0x464605460a438c4cULL,
0xacac8aac092645a5ULL, 0x89891e893c970fb5ULL, 0x14145014a04428b4ULL, 0xe1e1a3e15b42dfbaULL,
0x16165816b04e2ca6ULL, 0x3a3ae83acdd274f7ULL, 0x6969b9696fd0d206ULL, 0x09092409482d1241ULL,
0x7070dd70a7ade0d7ULL, 0xb6b6e2b6d954716fULL, 0xd0d067d0ceb7bd1eULL, 0xeded93ed3b7ec7d6ULL,
0xcccc17cc2edb85e2ULL, 0x424215422a578468ULL, 0x98985a98b4c22d2cULL, 0xa4a4aaa4490e55edULL,
0x2828a0285d885075ULL, 0x5c5c6d5cda31b886ULL, 0xf8f8c7f8933fed6bULL, 0x8686228644a411c2ULL,
}, {
/* C1 vectors */
0xd818186018c07830ULL, 0x2623238c2305af46ULL, 0xb8c6c63fc67ef991ULL, 0xfbe8e887e8136fcdULL,
0xcb878726874ca113ULL, 0x11b8b8dab8a9626dULL, 0x0901010401080502ULL, 0x0d4f4f214f426e9eULL,
0x9b3636d836adee6cULL, 0xffa6a6a2a6590451ULL, 0x0cd2d26fd2debdb9ULL, 0x0ef5f5f3f5fb06f7ULL,
0x967979f979ef80f2ULL, 0x306f6fa16f5fcedeULL, 0x6d91917e91fcef3fULL, 0xf852525552aa07a4ULL,
0x4760609d6027fdc0ULL, 0x35bcbccabc897665ULL, 0x379b9b569baccd2bULL, 0x8a8e8e028e048c01ULL,
0xd2a3a3b6a371155bULL, 0x6c0c0c300c603c18ULL, 0x847b7bf17bff8af6ULL, 0x803535d435b5e16aULL,
0xf51d1d741de8693aULL, 0xb3e0e0a7e05347ddULL, 0x21d7d77bd7f6acb3ULL, 0x9cc2c22fc25eed99ULL,
0x432e2eb82e6d965cULL, 0x294b4b314b627a96ULL, 0x5dfefedffea321e1ULL, 0xd5575741578216aeULL,
0xbd15155415a8412aULL, 0xe87777c1779fb6eeULL, 0x923737dc37a5eb6eULL, 0x9ee5e5b3e57b56d7ULL,
0x139f9f469f8cd923ULL, 0x23f0f0e7f0d317fdULL, 0x204a4a354a6a7f94ULL, 0x44dada4fda9e95a9ULL,
0xa258587d58fa25b0ULL, 0xcfc9c903c906ca8fULL, 0x7c2929a429558d52ULL, 0x5a0a0a280a502214ULL,
0x50b1b1feb1e14f7fULL, 0xc9a0a0baa0691a5dULL, 0x146b6bb16b7fdad6ULL, 0xd985852e855cab17ULL,
0x3cbdbdcebd817367ULL, 0x8f5d5d695dd234baULL, 0x9010104010805020ULL, 0x07f4f4f7f4f303f5ULL,
0xddcbcb0bcb16c08bULL, 0xd33e3ef83eedc67cULL, 0x2d0505140528110aULL, 0x78676781671fe6ceULL,
0x97e4e4b7e47353d5ULL, 0x0227279c2725bb4eULL, 0x7341411941325882ULL, 0xa78b8b168b2c9d0bULL,
0xf6a7a7a6a7510153ULL, 0xb27d7de97dcf94faULL, 0x4995956e95dcfb37ULL, 0x56d8d847d88e9fadULL,
0x70fbfbcbfb8b30ebULL, 0xcdeeee9fee2371c1ULL, 0xbb7c7ced7cc791f8ULL, 0x716666856617e3ccULL,
0x7bdddd53dda68ea7ULL, 0xaf17175c17b84b2eULL, 0x454747014702468eULL, 0x1a9e9e429e84dc21ULL,
0xd4caca0fca1ec589ULL, 0x582d2db42d75995aULL, 0x2ebfbfc6bf917963ULL, 0x3f07071c07381b0eULL,
0xacadad8ead012347ULL, 0xb05a5a755aea2fb4ULL, 0xef838336836cb51bULL, 0xb63333cc3385ff66ULL,
0x5c636391633ff2c6ULL, 0x1202020802100a04ULL, 0x93aaaa92aa393849ULL, 0xde7171d971afa8e2ULL,
0xc6c8c807c80ecf8dULL, 0xd119196419c87d32ULL, 0x3b49493949727092ULL, 0x5fd9d943d9869aafULL,
0x31f2f2eff2c31df9ULL, 0xa8e3e3abe34b48dbULL, 0xb95b5b715be22ab6ULL, 0xbc88881a8834920dULL,
0x3e9a9a529aa4c829ULL, 0x0b262698262dbe4cULL, 0xbf3232c8328dfa64ULL, 0x59b0b0fab0e94a7dULL,
0xf2e9e983e91b6acfULL, 0x770f0f3c0f78331eULL, 0x33d5d573d5e6a6b7ULL, 0xf480803a8074ba1dULL,
0x27bebec2be997c61ULL, 0xebcdcd13cd26de87ULL, 0x893434d034bde468ULL, 0x3248483d487a7590ULL,
0x54ffffdbffab24e3ULL, 0x8d7a7af57af78ff4ULL, 0x6490907a90f4ea3dULL, 0x9d5f5f615fc23ebeULL,
0x3d202080201da040ULL, 0x0f6868bd6867d5d0ULL, 0xca1a1a681ad07234ULL, 0xb7aeae82ae192c41ULL,
0x7db4b4eab4c95e75ULL, 0xce54544d549a19a8ULL, 0x7f93937693ece53bULL, 0x2f222288220daa44ULL,
0x6364648d6407e9c8ULL, 0x2af1f1e3f1db12ffULL, 0xcc7373d173bfa2e6ULL, 0x8212124812905a24ULL,
0x7a40401d403a5d80ULL, 0x4808082008402810ULL, 0x95c3c32bc356e89bULL, 0xdfecec97ec337bc5ULL,
0x4ddbdb4bdb9690abULL, 0xc0a1a1bea1611f5fULL, 0x918d8d0e8d1c8307ULL, 0xc83d3df43df5c97aULL,
0x5b97976697ccf133ULL, 0x0000000000000000ULL, 0xf9cfcf1bcf36d483ULL, 0x6e2b2bac2b458756ULL,
0xe17676c57697b3ecULL, 0xe68282328264b019ULL, 0x28d6d67fd6fea9b1ULL, 0xc31b1b6c1bd87736ULL,
0x74b5b5eeb5c15b77ULL, 0xbeafaf86af112943ULL, 0x1d6a6ab56a77dfd4ULL, 0xea50505d50ba0da0ULL,
0x5745450945124c8aULL, 0x38f3f3ebf3cb18fbULL, 0xad3030c0309df060ULL, 0xc4efef9bef2b74c3ULL,
0xda3f3ffc3fe5c37eULL, 0xc755554955921caaULL, 0xdba2a2b2a2791059ULL, 0xe9eaea8fea0365c9ULL,
0x6a656589650feccaULL, 0x03babad2bab96869ULL, 0x4a2f2fbc2f65935eULL, 0x8ec0c027c04ee79dULL,
0x60dede5fdebe81a1ULL, 0xfc1c1c701ce06c38ULL, 0x46fdfdd3fdbb2ee7ULL, 0x1f4d4d294d52649aULL,
0x7692927292e4e039ULL, 0xfa7575c9758fbceaULL, 0x3606061806301e0cULL, 0xae8a8a128a249809ULL,
0x4bb2b2f2b2f94079ULL, 0x85e6e6bfe66359d1ULL, 0x7e0e0e380e70361cULL, 0xe71f1f7c1ff8633eULL,
0x556262956237f7c4ULL, 0x3ad4d477d4eea3b5ULL, 0x81a8a89aa829324dULL, 0x5296966296c4f431ULL,
0x62f9f9c3f99b3aefULL, 0xa3c5c533c566f697ULL, 0x102525942535b14aULL, 0xab59597959f220b2ULL,
0xd084842a8454ae15ULL, 0xc57272d572b7a7e4ULL, 0xec3939e439d5dd72ULL, 0x164c4c2d4c5a6198ULL,
0x945e5e655eca3bbcULL, 0x9f7878fd78e785f0ULL, 0xe53838e038ddd870ULL, 0x988c8c0a8c148605ULL,
0x17d1d163d1c6b2bfULL, 0xe4a5a5aea5410b57ULL, 0xa1e2e2afe2434dd9ULL, 0x4e616199612ff8c2ULL,
0x42b3b3f6b3f1457bULL, 0x342121842115a542ULL, 0x089c9c4a9c94d625ULL, 0xee1e1e781ef0663cULL,
0x6143431143225286ULL, 0xb1c7c73bc776fc93ULL, 0x4ffcfcd7fcb32be5ULL, 0x2404041004201408ULL,
0xe351515951b208a2ULL, 0x2599995e99bcc72fULL, 0x226d6da96d4fc4daULL, 0x650d0d340d68391aULL,
0x79fafacffa8335e9ULL, 0x69dfdf5bdfb684a3ULL, 0xa97e7ee57ed79bfcULL, 0x19242490243db448ULL,
0xfe3b3bec3bc5d776ULL, 0x9aabab96ab313d4bULL, 0xf0cece1fce3ed181ULL, 0x9911114411885522ULL,
0x838f8f068f0c8903ULL, 0x044e4e254e4a6b9cULL, 0x66b7b7e6b7d15173ULL, 0xe0ebeb8beb0b60cbULL,
0xc13c3cf03cfdcc78ULL, 0xfd81813e817cbf1fULL, 0x4094946a94d4fe35ULL, 0x1cf7f7fbf7eb0cf3ULL,
0x18b9b9deb9a1676fULL, 0x8b13134c13985f26ULL, 0x512c2cb02c7d9c58ULL, 0x05d3d36bd3d6b8bbULL,
0x8ce7e7bbe76b5cd3ULL, 0x396e6ea56e57cbdcULL, 0xaac4c437c46ef395ULL, 0x1b03030c03180f06ULL,
0xdc565645568a13acULL, 0x5e44440d441a4988ULL, 0xa07f7fe17fdf9efeULL, 0x88a9a99ea921374fULL,
0x672a2aa82a4d8254ULL, 0x0abbbbd6bbb16d6bULL, 0x87c1c123c146e29fULL, 0xf153535153a202a6ULL,
0x72dcdc57dcae8ba5ULL, 0x530b0b2c0b582716ULL, 0x019d9d4e9d9cd327ULL, 0x2b6c6cad6c47c1d8ULL,
0xa43131c43195f562ULL, 0xf37474cd7487b9e8ULL, 0x15f6f6fff6e309f1ULL, 0x4c464605460a438cULL,
0xa5acac8aac092645ULL, 0xb589891e893c970fULL, 0xb414145014a04428ULL, 0xbae1e1a3e15b42dfULL,
0xa616165816b04e2cULL, 0xf73a3ae83acdd274ULL, 0x066969b9696fd0d2ULL, 0x4109092409482d12ULL,
0xd77070dd70a7ade0ULL, 0x6fb6b6e2b6d95471ULL, 0x1ed0d067d0ceb7bdULL, 0xd6eded93ed3b7ec7ULL,
0xe2cccc17cc2edb85ULL, 0x68424215422a5784ULL, 0x2c98985a98b4c22dULL, 0xeda4a4aaa4490e55ULL,
0x752828a0285d8850ULL, 0x865c5c6d5cda31b8ULL, 0x6bf8f8c7f8933fedULL, 0xc28686228644a411ULL,
}, {
/* C2 vectors */
0x30d818186018c078ULL, 0x462623238c2305afULL, 0x91b8c6c63fc67ef9ULL, 0xcdfbe8e887e8136fULL,
0x13cb878726874ca1ULL, 0x6d11b8b8dab8a962ULL, 0x0209010104010805ULL, 0x9e0d4f4f214f426eULL,
0x6c9b3636d836adeeULL, 0x51ffa6a6a2a65904ULL, 0xb90cd2d26fd2debdULL, 0xf70ef5f5f3f5fb06ULL,
0xf2967979f979ef80ULL, 0xde306f6fa16f5fceULL, 0x3f6d91917e91fcefULL, 0xa4f852525552aa07ULL,
0xc04760609d6027fdULL, 0x6535bcbccabc8976ULL, 0x2b379b9b569baccdULL, 0x018a8e8e028e048cULL,
0x5bd2a3a3b6a37115ULL, 0x186c0c0c300c603cULL, 0xf6847b7bf17bff8aULL, 0x6a803535d435b5e1ULL,
0x3af51d1d741de869ULL, 0xddb3e0e0a7e05347ULL, 0xb321d7d77bd7f6acULL, 0x999cc2c22fc25eedULL,
0x5c432e2eb82e6d96ULL, 0x96294b4b314b627aULL, 0xe15dfefedffea321ULL, 0xaed5575741578216ULL,
0x2abd15155415a841ULL, 0xeee87777c1779fb6ULL, 0x6e923737dc37a5ebULL, 0xd79ee5e5b3e57b56ULL,
0x23139f9f469f8cd9ULL, 0xfd23f0f0e7f0d317ULL, 0x94204a4a354a6a7fULL, 0xa944dada4fda9e95ULL,
0xb0a258587d58fa25ULL, 0x8fcfc9c903c906caULL, 0x527c2929a429558dULL, 0x145a0a0a280a5022ULL,
0x7f50b1b1feb1e14fULL, 0x5dc9a0a0baa0691aULL, 0xd6146b6bb16b7fdaULL, 0x17d985852e855cabULL,
0x673cbdbdcebd8173ULL, 0xba8f5d5d695dd234ULL, 0x2090101040108050ULL, 0xf507f4f4f7f4f303ULL,
0x8bddcbcb0bcb16c0ULL, 0x7cd33e3ef83eedc6ULL, 0x0a2d050514052811ULL, 0xce78676781671fe6ULL,
0xd597e4e4b7e47353ULL, 0x4e0227279c2725bbULL, 0x8273414119413258ULL, 0x0ba78b8b168b2c9dULL,
0x53f6a7a7a6a75101ULL, 0xfab27d7de97dcf94ULL, 0x374995956e95dcfbULL, 0xad56d8d847d88e9fULL,
0xeb70fbfbcbfb8b30ULL, 0xc1cdeeee9fee2371ULL, 0xf8bb7c7ced7cc791ULL, 0xcc716666856617e3ULL,
0xa77bdddd53dda68eULL, 0x2eaf17175c17b84bULL, 0x8e45474701470246ULL, 0x211a9e9e429e84dcULL,
0x89d4caca0fca1ec5ULL, 0x5a582d2db42d7599ULL, 0x632ebfbfc6bf9179ULL, 0x0e3f07071c07381bULL,
0x47acadad8ead0123ULL, 0xb4b05a5a755aea2fULL, 0x1bef838336836cb5ULL, 0x66b63333cc3385ffULL,
0xc65c636391633ff2ULL, 0x041202020802100aULL, 0x4993aaaa92aa3938ULL, 0xe2de7171d971afa8ULL,
0x8dc6c8c807c80ecfULL, 0x32d119196419c87dULL, 0x923b494939497270ULL, 0xaf5fd9d943d9869aULL,
0xf931f2f2eff2c31dULL, 0xdba8e3e3abe34b48ULL, 0xb6b95b5b715be22aULL, 0x0dbc88881a883492ULL,
0x293e9a9a529aa4c8ULL, 0x4c0b262698262dbeULL, 0x64bf3232c8328dfaULL, 0x7d59b0b0fab0e94aULL,
0xcff2e9e983e91b6aULL, 0x1e770f0f3c0f7833ULL, 0xb733d5d573d5e6a6ULL, 0x1df480803a8074baULL,
0x6127bebec2be997cULL, 0x87ebcdcd13cd26deULL, 0x68893434d034bde4ULL, 0x903248483d487a75ULL,
0xe354ffffdbffab24ULL, 0xf48d7a7af57af78fULL, 0x3d6490907a90f4eaULL, 0xbe9d5f5f615fc23eULL,
0x403d202080201da0ULL, 0xd00f6868bd6867d5ULL, 0x34ca1a1a681ad072ULL, 0x41b7aeae82ae192cULL,
0x757db4b4eab4c95eULL, 0xa8ce54544d549a19ULL, 0x3b7f93937693ece5ULL, 0x442f222288220daaULL,
0xc86364648d6407e9ULL, 0xff2af1f1e3f1db12ULL, 0xe6cc7373d173bfa2ULL, 0x248212124812905aULL,
0x807a40401d403a5dULL, 0x1048080820084028ULL, 0x9b95c3c32bc356e8ULL, 0xc5dfecec97ec337bULL,
0xab4ddbdb4bdb9690ULL, 0x5fc0a1a1bea1611fULL, 0x07918d8d0e8d1c83ULL, 0x7ac83d3df43df5c9ULL,
0x335b97976697ccf1ULL, 0x0000000000000000ULL, 0x83f9cfcf1bcf36d4ULL, 0x566e2b2bac2b4587ULL,
0xece17676c57697b3ULL, 0x19e68282328264b0ULL, 0xb128d6d67fd6fea9ULL, 0x36c31b1b6c1bd877ULL,
0x7774b5b5eeb5c15bULL, 0x43beafaf86af1129ULL, 0xd41d6a6ab56a77dfULL, 0xa0ea50505d50ba0dULL,
0x8a5745450945124cULL, 0xfb38f3f3ebf3cb18ULL, 0x60ad3030c0309df0ULL, 0xc3c4efef9bef2b74ULL,
0x7eda3f3ffc3fe5c3ULL, 0xaac755554955921cULL, 0x59dba2a2b2a27910ULL, 0xc9e9eaea8fea0365ULL,
0xca6a656589650fecULL, 0x6903babad2bab968ULL, 0x5e4a2f2fbc2f6593ULL, 0x9d8ec0c027c04ee7ULL,
0xa160dede5fdebe81ULL, 0x38fc1c1c701ce06cULL, 0xe746fdfdd3fdbb2eULL, 0x9a1f4d4d294d5264ULL,
0x397692927292e4e0ULL, 0xeafa7575c9758fbcULL, 0x0c3606061806301eULL, 0x09ae8a8a128a2498ULL,
0x794bb2b2f2b2f940ULL, 0xd185e6e6bfe66359ULL, 0x1c7e0e0e380e7036ULL, 0x3ee71f1f7c1ff863ULL,
0xc4556262956237f7ULL, 0xb53ad4d477d4eea3ULL, 0x4d81a8a89aa82932ULL, 0x315296966296c4f4ULL,
0xef62f9f9c3f99b3aULL, 0x97a3c5c533c566f6ULL, 0x4a102525942535b1ULL, 0xb2ab59597959f220ULL,
0x15d084842a8454aeULL, 0xe4c57272d572b7a7ULL, 0x72ec3939e439d5ddULL, 0x98164c4c2d4c5a61ULL,
0xbc945e5e655eca3bULL, 0xf09f7878fd78e785ULL, 0x70e53838e038ddd8ULL, 0x05988c8c0a8c1486ULL,
0xbf17d1d163d1c6b2ULL, 0x57e4a5a5aea5410bULL, 0xd9a1e2e2afe2434dULL, 0xc24e616199612ff8ULL,
0x7b42b3b3f6b3f145ULL, 0x42342121842115a5ULL, 0x25089c9c4a9c94d6ULL, 0x3cee1e1e781ef066ULL,
0x8661434311432252ULL, 0x93b1c7c73bc776fcULL, 0xe54ffcfcd7fcb32bULL, 0x0824040410042014ULL,
0xa2e351515951b208ULL, 0x2f2599995e99bcc7ULL, 0xda226d6da96d4fc4ULL, 0x1a650d0d340d6839ULL,
0xe979fafacffa8335ULL, 0xa369dfdf5bdfb684ULL, 0xfca97e7ee57ed79bULL, 0x4819242490243db4ULL,
0x76fe3b3bec3bc5d7ULL, 0x4b9aabab96ab313dULL, 0x81f0cece1fce3ed1ULL, 0x2299111144118855ULL,
0x03838f8f068f0c89ULL, 0x9c044e4e254e4a6bULL, 0x7366b7b7e6b7d151ULL, 0xcbe0ebeb8beb0b60ULL,
0x78c13c3cf03cfdccULL, 0x1ffd81813e817cbfULL, 0x354094946a94d4feULL, 0xf31cf7f7fbf7eb0cULL,
0x6f18b9b9deb9a167ULL, 0x268b13134c13985fULL, 0x58512c2cb02c7d9cULL, 0xbb05d3d36bd3d6b8ULL,
0xd38ce7e7bbe76b5cULL, 0xdc396e6ea56e57cbULL, 0x95aac4c437c46ef3ULL, 0x061b03030c03180fULL,
0xacdc565645568a13ULL, 0x885e44440d441a49ULL, 0xfea07f7fe17fdf9eULL, 0x4f88a9a99ea92137ULL,
0x54672a2aa82a4d82ULL, 0x6b0abbbbd6bbb16dULL, 0x9f87c1c123c146e2ULL, 0xa6f153535153a202ULL,
0xa572dcdc57dcae8bULL, 0x16530b0b2c0b5827ULL, 0x27019d9d4e9d9cd3ULL, 0xd82b6c6cad6c47c1ULL,
0x62a43131c43195f5ULL, 0xe8f37474cd7487b9ULL, 0xf115f6f6fff6e309ULL, 0x8c4c464605460a43ULL,
0x45a5acac8aac0926ULL, 0x0fb589891e893c97ULL, 0x28b414145014a044ULL, 0xdfbae1e1a3e15b42ULL,
0x2ca616165816b04eULL, 0x74f73a3ae83acdd2ULL, 0xd2066969b9696fd0ULL, 0x124109092409482dULL,
0xe0d77070dd70a7adULL, 0x716fb6b6e2b6d954ULL, 0xbd1ed0d067d0ceb7ULL, 0xc7d6eded93ed3b7eULL,
0x85e2cccc17cc2edbULL, 0x8468424215422a57ULL, 0x2d2c98985a98b4c2ULL, 0x55eda4a4aaa4490eULL,
0x50752828a0285d88ULL, 0xb8865c5c6d5cda31ULL, 0xed6bf8f8c7f8933fULL, 0x11c28686228644a4ULL,
}, {
/* C3 vectors */
0x7830d818186018c0ULL, 0xaf462623238c2305ULL, 0xf991b8c6c63fc67eULL, 0x6fcdfbe8e887e813ULL,
0xa113cb878726874cULL, 0x626d11b8b8dab8a9ULL, 0x0502090101040108ULL, 0x6e9e0d4f4f214f42ULL,
0xee6c9b3636d836adULL, 0x0451ffa6a6a2a659ULL, 0xbdb90cd2d26fd2deULL, 0x06f70ef5f5f3f5fbULL,
0x80f2967979f979efULL, 0xcede306f6fa16f5fULL, 0xef3f6d91917e91fcULL, 0x07a4f852525552aaULL,
0xfdc04760609d6027ULL, 0x766535bcbccabc89ULL, 0xcd2b379b9b569bacULL, 0x8c018a8e8e028e04ULL,
0x155bd2a3a3b6a371ULL, 0x3c186c0c0c300c60ULL, 0x8af6847b7bf17bffULL, 0xe16a803535d435b5ULL,
0x693af51d1d741de8ULL, 0x47ddb3e0e0a7e053ULL, 0xacb321d7d77bd7f6ULL, 0xed999cc2c22fc25eULL,
0x965c432e2eb82e6dULL, 0x7a96294b4b314b62ULL, 0x21e15dfefedffea3ULL, 0x16aed55757415782ULL,
0x412abd15155415a8ULL, 0xb6eee87777c1779fULL, 0xeb6e923737dc37a5ULL, 0x56d79ee5e5b3e57bULL,
0xd923139f9f469f8cULL, 0x17fd23f0f0e7f0d3ULL, 0x7f94204a4a354a6aULL, 0x95a944dada4fda9eULL,
0x25b0a258587d58faULL, 0xca8fcfc9c903c906ULL, 0x8d527c2929a42955ULL, 0x22145a0a0a280a50ULL,
0x4f7f50b1b1feb1e1ULL, 0x1a5dc9a0a0baa069ULL, 0xdad6146b6bb16b7fULL, 0xab17d985852e855cULL,
0x73673cbdbdcebd81ULL, 0x34ba8f5d5d695dd2ULL, 0x5020901010401080ULL, 0x03f507f4f4f7f4f3ULL,
0xc08bddcbcb0bcb16ULL, 0xc67cd33e3ef83eedULL, 0x110a2d0505140528ULL, 0xe6ce78676781671fULL,
0x53d597e4e4b7e473ULL, 0xbb4e0227279c2725ULL, 0x5882734141194132ULL, 0x9d0ba78b8b168b2cULL,
0x0153f6a7a7a6a751ULL, 0x94fab27d7de97dcfULL, 0xfb374995956e95dcULL, 0x9fad56d8d847d88eULL,
0x30eb70fbfbcbfb8bULL, 0x71c1cdeeee9fee23ULL, 0x91f8bb7c7ced7cc7ULL, 0xe3cc716666856617ULL,
0x8ea77bdddd53dda6ULL, 0x4b2eaf17175c17b8ULL, 0x468e454747014702ULL, 0xdc211a9e9e429e84ULL,
0xc589d4caca0fca1eULL, 0x995a582d2db42d75ULL, 0x79632ebfbfc6bf91ULL, 0x1b0e3f07071c0738ULL,
0x2347acadad8ead01ULL, 0x2fb4b05a5a755aeaULL, 0xb51bef838336836cULL, 0xff66b63333cc3385ULL,
0xf2c65c636391633fULL, 0x0a04120202080210ULL, 0x384993aaaa92aa39ULL, 0xa8e2de7171d971afULL,
0xcf8dc6c8c807c80eULL, 0x7d32d119196419c8ULL, 0x70923b4949394972ULL, 0x9aaf5fd9d943d986ULL,
0x1df931f2f2eff2c3ULL, 0x48dba8e3e3abe34bULL, 0x2ab6b95b5b715be2ULL, 0x920dbc88881a8834ULL,
0xc8293e9a9a529aa4ULL, 0xbe4c0b262698262dULL, 0xfa64bf3232c8328dULL, 0x4a7d59b0b0fab0e9ULL,
0x6acff2e9e983e91bULL, 0x331e770f0f3c0f78ULL, 0xa6b733d5d573d5e6ULL, 0xba1df480803a8074ULL,
0x7c6127bebec2be99ULL, 0xde87ebcdcd13cd26ULL, 0xe468893434d034bdULL, 0x75903248483d487aULL,
0x24e354ffffdbffabULL, 0x8ff48d7a7af57af7ULL, 0xea3d6490907a90f4ULL, 0x3ebe9d5f5f615fc2ULL,
0xa0403d202080201dULL, 0xd5d00f6868bd6867ULL, 0x7234ca1a1a681ad0ULL, 0x2c41b7aeae82ae19ULL,
0x5e757db4b4eab4c9ULL, 0x19a8ce54544d549aULL, 0xe53b7f93937693ecULL, 0xaa442f222288220dULL,
0xe9c86364648d6407ULL, 0x12ff2af1f1e3f1dbULL, 0xa2e6cc7373d173bfULL, 0x5a24821212481290ULL,
0x5d807a40401d403aULL, 0x2810480808200840ULL, 0xe89b95c3c32bc356ULL, 0x7bc5dfecec97ec33ULL,
0x90ab4ddbdb4bdb96ULL, 0x1f5fc0a1a1bea161ULL, 0x8307918d8d0e8d1cULL, 0xc97ac83d3df43df5ULL,
0xf1335b97976697ccULL, 0x0000000000000000ULL, 0xd483f9cfcf1bcf36ULL, 0x87566e2b2bac2b45ULL,
0xb3ece17676c57697ULL, 0xb019e68282328264ULL, 0xa9b128d6d67fd6feULL, 0x7736c31b1b6c1bd8ULL,
0x5b7774b5b5eeb5c1ULL, 0x2943beafaf86af11ULL, 0xdfd41d6a6ab56a77ULL, 0x0da0ea50505d50baULL,
0x4c8a574545094512ULL, 0x18fb38f3f3ebf3cbULL, 0xf060ad3030c0309dULL, 0x74c3c4efef9bef2bULL,
0xc37eda3f3ffc3fe5ULL, 0x1caac75555495592ULL, 0x1059dba2a2b2a279ULL, 0x65c9e9eaea8fea03ULL,
0xecca6a656589650fULL, 0x686903babad2bab9ULL, 0x935e4a2f2fbc2f65ULL, 0xe79d8ec0c027c04eULL,
0x81a160dede5fdebeULL, 0x6c38fc1c1c701ce0ULL, 0x2ee746fdfdd3fdbbULL, 0x649a1f4d4d294d52ULL,
0xe0397692927292e4ULL, 0xbceafa7575c9758fULL, 0x1e0c360606180630ULL, 0x9809ae8a8a128a24ULL,
0x40794bb2b2f2b2f9ULL, 0x59d185e6e6bfe663ULL, 0x361c7e0e0e380e70ULL, 0x633ee71f1f7c1ff8ULL,
0xf7c4556262956237ULL, 0xa3b53ad4d477d4eeULL, 0x324d81a8a89aa829ULL, 0xf4315296966296c4ULL,
0x3aef62f9f9c3f99bULL, 0xf697a3c5c533c566ULL, 0xb14a102525942535ULL, 0x20b2ab59597959f2ULL,
0xae15d084842a8454ULL, 0xa7e4c57272d572b7ULL, 0xdd72ec3939e439d5ULL, 0x6198164c4c2d4c5aULL,
0x3bbc945e5e655ecaULL, 0x85f09f7878fd78e7ULL, 0xd870e53838e038ddULL, 0x8605988c8c0a8c14ULL,
0xb2bf17d1d163d1c6ULL, 0x0b57e4a5a5aea541ULL, 0x4dd9a1e2e2afe243ULL, 0xf8c24e616199612fULL,
0x457b42b3b3f6b3f1ULL, 0xa542342121842115ULL, 0xd625089c9c4a9c94ULL, 0x663cee1e1e781ef0ULL,
0x5286614343114322ULL, 0xfc93b1c7c73bc776ULL, 0x2be54ffcfcd7fcb3ULL, 0x1408240404100420ULL,
0x08a2e351515951b2ULL, 0xc72f2599995e99bcULL, 0xc4da226d6da96d4fULL, 0x391a650d0d340d68ULL,
0x35e979fafacffa83ULL, 0x84a369dfdf5bdfb6ULL, 0x9bfca97e7ee57ed7ULL, 0xb44819242490243dULL,
0xd776fe3b3bec3bc5ULL, 0x3d4b9aabab96ab31ULL, 0xd181f0cece1fce3eULL, 0x5522991111441188ULL,
0x8903838f8f068f0cULL, 0x6b9c044e4e254e4aULL, 0x517366b7b7e6b7d1ULL, 0x60cbe0ebeb8beb0bULL,
0xcc78c13c3cf03cfdULL, 0xbf1ffd81813e817cULL, 0xfe354094946a94d4ULL, 0x0cf31cf7f7fbf7ebULL,
0x676f18b9b9deb9a1ULL, 0x5f268b13134c1398ULL, 0x9c58512c2cb02c7dULL, 0xb8bb05d3d36bd3d6ULL,
0x5cd38ce7e7bbe76bULL, 0xcbdc396e6ea56e57ULL, 0xf395aac4c437c46eULL, 0x0f061b03030c0318ULL,
0x13acdc565645568aULL, 0x49885e44440d441aULL, 0x9efea07f7fe17fdfULL, 0x374f88a9a99ea921ULL,
0x8254672a2aa82a4dULL, 0x6d6b0abbbbd6bbb1ULL, 0xe29f87c1c123c146ULL, 0x02a6f153535153a2ULL,
0x8ba572dcdc57dcaeULL, 0x2716530b0b2c0b58ULL, 0xd327019d9d4e9d9cULL, 0xc1d82b6c6cad6c47ULL,
0xf562a43131c43195ULL, 0xb9e8f37474cd7487ULL, 0x09f115f6f6fff6e3ULL, 0x438c4c464605460aULL,
0x2645a5acac8aac09ULL, 0x970fb589891e893cULL, 0x4428b414145014a0ULL, 0x42dfbae1e1a3e15bULL,
0x4e2ca616165816b0ULL, 0xd274f73a3ae83acdULL, 0xd0d2066969b9696fULL, 0x2d12410909240948ULL,
0xade0d77070dd70a7ULL, 0x54716fb6b6e2b6d9ULL, 0xb7bd1ed0d067d0ceULL, 0x7ec7d6eded93ed3bULL,
0xdb85e2cccc17cc2eULL, 0x578468424215422aULL, 0xc22d2c98985a98b4ULL, 0x0e55eda4a4aaa449ULL,
0x8850752828a0285dULL, 0x31b8865c5c6d5cdaULL, 0x3fed6bf8f8c7f893ULL, 0xa411c28686228644ULL,
}, {
/* C4 vectors */
0xc07830d818186018ULL, 0x05af462623238c23ULL, 0x7ef991b8c6c63fc6ULL, 0x136fcdfbe8e887e8ULL,
0x4ca113cb87872687ULL, 0xa9626d11b8b8dab8ULL, 0x0805020901010401ULL, 0x426e9e0d4f4f214fULL,
0xadee6c9b3636d836ULL, 0x590451ffa6a6a2a6ULL, 0xdebdb90cd2d26fd2ULL, 0xfb06f70ef5f5f3f5ULL,
0xef80f2967979f979ULL, 0x5fcede306f6fa16fULL, 0xfcef3f6d91917e91ULL, 0xaa07a4f852525552ULL,
0x27fdc04760609d60ULL, 0x89766535bcbccabcULL, 0xaccd2b379b9b569bULL, 0x048c018a8e8e028eULL,
0x71155bd2a3a3b6a3ULL, 0x603c186c0c0c300cULL, 0xff8af6847b7bf17bULL, 0xb5e16a803535d435ULL,
0xe8693af51d1d741dULL, 0x5347ddb3e0e0a7e0ULL, 0xf6acb321d7d77bd7ULL, 0x5eed999cc2c22fc2ULL,
0x6d965c432e2eb82eULL, 0x627a96294b4b314bULL, 0xa321e15dfefedffeULL, 0x8216aed557574157ULL,
0xa8412abd15155415ULL, 0x9fb6eee87777c177ULL, 0xa5eb6e923737dc37ULL, 0x7b56d79ee5e5b3e5ULL,
0x8cd923139f9f469fULL, 0xd317fd23f0f0e7f0ULL, 0x6a7f94204a4a354aULL, 0x9e95a944dada4fdaULL,
0xfa25b0a258587d58ULL, 0x06ca8fcfc9c903c9ULL, 0x558d527c2929a429ULL, 0x5022145a0a0a280aULL,
0xe14f7f50b1b1feb1ULL, 0x691a5dc9a0a0baa0ULL, 0x7fdad6146b6bb16bULL, 0x5cab17d985852e85ULL,
0x8173673cbdbdcebdULL, 0xd234ba8f5d5d695dULL, 0x8050209010104010ULL, 0xf303f507f4f4f7f4ULL,
0x16c08bddcbcb0bcbULL, 0xedc67cd33e3ef83eULL, 0x28110a2d05051405ULL, 0x1fe6ce7867678167ULL,
0x7353d597e4e4b7e4ULL, 0x25bb4e0227279c27ULL, 0x3258827341411941ULL, 0x2c9d0ba78b8b168bULL,
0x510153f6a7a7a6a7ULL, 0xcf94fab27d7de97dULL, 0xdcfb374995956e95ULL, 0x8e9fad56d8d847d8ULL,
0x8b30eb70fbfbcbfbULL, 0x2371c1cdeeee9feeULL, 0xc791f8bb7c7ced7cULL, 0x17e3cc7166668566ULL,
0xa68ea77bdddd53ddULL, 0xb84b2eaf17175c17ULL, 0x02468e4547470147ULL, 0x84dc211a9e9e429eULL,
0x1ec589d4caca0fcaULL, 0x75995a582d2db42dULL, 0x9179632ebfbfc6bfULL, 0x381b0e3f07071c07ULL,
0x012347acadad8eadULL, 0xea2fb4b05a5a755aULL, 0x6cb51bef83833683ULL, 0x85ff66b63333cc33ULL,
0x3ff2c65c63639163ULL, 0x100a041202020802ULL, 0x39384993aaaa92aaULL, 0xafa8e2de7171d971ULL,
0x0ecf8dc6c8c807c8ULL, 0xc87d32d119196419ULL, 0x7270923b49493949ULL, 0x869aaf5fd9d943d9ULL,
0xc31df931f2f2eff2ULL, 0x4b48dba8e3e3abe3ULL, 0xe22ab6b95b5b715bULL, 0x34920dbc88881a88ULL,
0xa4c8293e9a9a529aULL, 0x2dbe4c0b26269826ULL, 0x8dfa64bf3232c832ULL, 0xe94a7d59b0b0fab0ULL,
0x1b6acff2e9e983e9ULL, 0x78331e770f0f3c0fULL, 0xe6a6b733d5d573d5ULL, 0x74ba1df480803a80ULL,
0x997c6127bebec2beULL, 0x26de87ebcdcd13cdULL, 0xbde468893434d034ULL, 0x7a75903248483d48ULL,
0xab24e354ffffdbffULL, 0xf78ff48d7a7af57aULL, 0xf4ea3d6490907a90ULL, 0xc23ebe9d5f5f615fULL,
0x1da0403d20208020ULL, 0x67d5d00f6868bd68ULL, 0xd07234ca1a1a681aULL, 0x192c41b7aeae82aeULL,
0xc95e757db4b4eab4ULL, 0x9a19a8ce54544d54ULL, 0xece53b7f93937693ULL, 0x0daa442f22228822ULL,
0x07e9c86364648d64ULL, 0xdb12ff2af1f1e3f1ULL, 0xbfa2e6cc7373d173ULL, 0x905a248212124812ULL,
0x3a5d807a40401d40ULL, 0x4028104808082008ULL, 0x56e89b95c3c32bc3ULL, 0x337bc5dfecec97ecULL,
0x9690ab4ddbdb4bdbULL, 0x611f5fc0a1a1bea1ULL, 0x1c8307918d8d0e8dULL, 0xf5c97ac83d3df43dULL,
0xccf1335b97976697ULL, 0x0000000000000000ULL, 0x36d483f9cfcf1bcfULL, 0x4587566e2b2bac2bULL,
0x97b3ece17676c576ULL, 0x64b019e682823282ULL, 0xfea9b128d6d67fd6ULL, 0xd87736c31b1b6c1bULL,
0xc15b7774b5b5eeb5ULL, 0x112943beafaf86afULL, 0x77dfd41d6a6ab56aULL, 0xba0da0ea50505d50ULL,
0x124c8a5745450945ULL, 0xcb18fb38f3f3ebf3ULL, 0x9df060ad3030c030ULL, 0x2b74c3c4efef9befULL,
0xe5c37eda3f3ffc3fULL, 0x921caac755554955ULL, 0x791059dba2a2b2a2ULL, 0x0365c9e9eaea8feaULL,
0x0fecca6a65658965ULL, 0xb9686903babad2baULL, 0x65935e4a2f2fbc2fULL, 0x4ee79d8ec0c027c0ULL,
0xbe81a160dede5fdeULL, 0xe06c38fc1c1c701cULL, 0xbb2ee746fdfdd3fdULL, 0x52649a1f4d4d294dULL,
0xe4e0397692927292ULL, 0x8fbceafa7575c975ULL, 0x301e0c3606061806ULL, 0x249809ae8a8a128aULL,
0xf940794bb2b2f2b2ULL, 0x6359d185e6e6bfe6ULL, 0x70361c7e0e0e380eULL, 0xf8633ee71f1f7c1fULL,
0x37f7c45562629562ULL, 0xeea3b53ad4d477d4ULL, 0x29324d81a8a89aa8ULL, 0xc4f4315296966296ULL,
0x9b3aef62f9f9c3f9ULL, 0x66f697a3c5c533c5ULL, 0x35b14a1025259425ULL, 0xf220b2ab59597959ULL,
0x54ae15d084842a84ULL, 0xb7a7e4c57272d572ULL, 0xd5dd72ec3939e439ULL, 0x5a6198164c4c2d4cULL,
0xca3bbc945e5e655eULL, 0xe785f09f7878fd78ULL, 0xddd870e53838e038ULL, 0x148605988c8c0a8cULL,
0xc6b2bf17d1d163d1ULL, 0x410b57e4a5a5aea5ULL, 0x434dd9a1e2e2afe2ULL, 0x2ff8c24e61619961ULL,
0xf1457b42b3b3f6b3ULL, 0x15a5423421218421ULL, 0x94d625089c9c4a9cULL, 0xf0663cee1e1e781eULL,
0x2252866143431143ULL, 0x76fc93b1c7c73bc7ULL, 0xb32be54ffcfcd7fcULL, 0x2014082404041004ULL,
0xb208a2e351515951ULL, 0xbcc72f2599995e99ULL, 0x4fc4da226d6da96dULL, 0x68391a650d0d340dULL,
0x8335e979fafacffaULL, 0xb684a369dfdf5bdfULL, 0xd79bfca97e7ee57eULL, 0x3db4481924249024ULL,
0xc5d776fe3b3bec3bULL, 0x313d4b9aabab96abULL, 0x3ed181f0cece1fceULL, 0x8855229911114411ULL,
0x0c8903838f8f068fULL, 0x4a6b9c044e4e254eULL, 0xd1517366b7b7e6b7ULL, 0x0b60cbe0ebeb8bebULL,
0xfdcc78c13c3cf03cULL, 0x7cbf1ffd81813e81ULL, 0xd4fe354094946a94ULL, 0xeb0cf31cf7f7fbf7ULL,
0xa1676f18b9b9deb9ULL, 0x985f268b13134c13ULL, 0x7d9c58512c2cb02cULL, 0xd6b8bb05d3d36bd3ULL,
0x6b5cd38ce7e7bbe7ULL, 0x57cbdc396e6ea56eULL, 0x6ef395aac4c437c4ULL, 0x180f061b03030c03ULL,
0x8a13acdc56564556ULL, 0x1a49885e44440d44ULL, 0xdf9efea07f7fe17fULL, 0x21374f88a9a99ea9ULL,
0x4d8254672a2aa82aULL, 0xb16d6b0abbbbd6bbULL, 0x46e29f87c1c123c1ULL, 0xa202a6f153535153ULL,
0xae8ba572dcdc57dcULL, 0x582716530b0b2c0bULL, 0x9cd327019d9d4e9dULL, 0x47c1d82b6c6cad6cULL,
0x95f562a43131c431ULL, 0x87b9e8f37474cd74ULL, 0xe309f115f6f6fff6ULL, 0x0a438c4c46460546ULL,
0x092645a5acac8aacULL, 0x3c970fb589891e89ULL, 0xa04428b414145014ULL, 0x5b42dfbae1e1a3e1ULL,
0xb04e2ca616165816ULL, 0xcdd274f73a3ae83aULL, 0x6fd0d2066969b969ULL, 0x482d124109092409ULL,
0xa7ade0d77070dd70ULL, 0xd954716fb6b6e2b6ULL, 0xceb7bd1ed0d067d0ULL, 0x3b7ec7d6eded93edULL,
0x2edb85e2cccc17ccULL, 0x2a57846842421542ULL, 0xb4c22d2c98985a98ULL, 0x490e55eda4a4aaa4ULL,
0x5d8850752828a028ULL, 0xda31b8865c5c6d5cULL, 0x933fed6bf8f8c7f8ULL, 0x44a411c286862286ULL,
}, {
/* C5 vectors */
0x18c07830d8181860ULL, 0x2305af462623238cULL, 0xc67ef991b8c6c63fULL, 0xe8136fcdfbe8e887ULL,
0x874ca113cb878726ULL, 0xb8a9626d11b8b8daULL, 0x0108050209010104ULL, 0x4f426e9e0d4f4f21ULL,
0x36adee6c9b3636d8ULL, 0xa6590451ffa6a6a2ULL, 0xd2debdb90cd2d26fULL, 0xf5fb06f70ef5f5f3ULL,
0x79ef80f2967979f9ULL, 0x6f5fcede306f6fa1ULL, 0x91fcef3f6d91917eULL, 0x52aa07a4f8525255ULL,
0x6027fdc04760609dULL, 0xbc89766535bcbccaULL, 0x9baccd2b379b9b56ULL, 0x8e048c018a8e8e02ULL,
0xa371155bd2a3a3b6ULL, 0x0c603c186c0c0c30ULL, 0x7bff8af6847b7bf1ULL, 0x35b5e16a803535d4ULL,
0x1de8693af51d1d74ULL, 0xe05347ddb3e0e0a7ULL, 0xd7f6acb321d7d77bULL, 0xc25eed999cc2c22fULL,
0x2e6d965c432e2eb8ULL, 0x4b627a96294b4b31ULL, 0xfea321e15dfefedfULL, 0x578216aed5575741ULL,
0x15a8412abd151554ULL, 0x779fb6eee87777c1ULL, 0x37a5eb6e923737dcULL, 0xe57b56d79ee5e5b3ULL,
0x9f8cd923139f9f46ULL, 0xf0d317fd23f0f0e7ULL, 0x4a6a7f94204a4a35ULL, 0xda9e95a944dada4fULL,
0x58fa25b0a258587dULL, 0xc906ca8fcfc9c903ULL, 0x29558d527c2929a4ULL, 0x0a5022145a0a0a28ULL,
0xb1e14f7f50b1b1feULL, 0xa0691a5dc9a0a0baULL, 0x6b7fdad6146b6bb1ULL, 0x855cab17d985852eULL,
0xbd8173673cbdbdceULL, 0x5dd234ba8f5d5d69ULL, 0x1080502090101040ULL, 0xf4f303f507f4f4f7ULL,
0xcb16c08bddcbcb0bULL, 0x3eedc67cd33e3ef8ULL, 0x0528110a2d050514ULL, 0x671fe6ce78676781ULL,
0xe47353d597e4e4b7ULL, 0x2725bb4e0227279cULL, 0x4132588273414119ULL, 0x8b2c9d0ba78b8b16ULL,
0xa7510153f6a7a7a6ULL, 0x7dcf94fab27d7de9ULL, 0x95dcfb374995956eULL, 0xd88e9fad56d8d847ULL,
0xfb8b30eb70fbfbcbULL, 0xee2371c1cdeeee9fULL, 0x7cc791f8bb7c7cedULL, 0x6617e3cc71666685ULL,
0xdda68ea77bdddd53ULL, 0x17b84b2eaf17175cULL, 0x4702468e45474701ULL, 0x9e84dc211a9e9e42ULL,
0xca1ec589d4caca0fULL, 0x2d75995a582d2db4ULL, 0xbf9179632ebfbfc6ULL, 0x07381b0e3f07071cULL,
0xad012347acadad8eULL, 0x5aea2fb4b05a5a75ULL, 0x836cb51bef838336ULL, 0x3385ff66b63333ccULL,
0x633ff2c65c636391ULL, 0x02100a0412020208ULL, 0xaa39384993aaaa92ULL, 0x71afa8e2de7171d9ULL,
0xc80ecf8dc6c8c807ULL, 0x19c87d32d1191964ULL, 0x497270923b494939ULL, 0xd9869aaf5fd9d943ULL,
0xf2c31df931f2f2efULL, 0xe34b48dba8e3e3abULL, 0x5be22ab6b95b5b71ULL, 0x8834920dbc88881aULL,
0x9aa4c8293e9a9a52ULL, 0x262dbe4c0b262698ULL, 0x328dfa64bf3232c8ULL, 0xb0e94a7d59b0b0faULL,
0xe91b6acff2e9e983ULL, 0x0f78331e770f0f3cULL, 0xd5e6a6b733d5d573ULL, 0x8074ba1df480803aULL,
0xbe997c6127bebec2ULL, 0xcd26de87ebcdcd13ULL, 0x34bde468893434d0ULL, 0x487a75903248483dULL,
0xffab24e354ffffdbULL, 0x7af78ff48d7a7af5ULL, 0x90f4ea3d6490907aULL, 0x5fc23ebe9d5f5f61ULL,
0x201da0403d202080ULL, 0x6867d5d00f6868bdULL, 0x1ad07234ca1a1a68ULL, 0xae192c41b7aeae82ULL,
0xb4c95e757db4b4eaULL, 0x549a19a8ce54544dULL, 0x93ece53b7f939376ULL, 0x220daa442f222288ULL,
0x6407e9c86364648dULL, 0xf1db12ff2af1f1e3ULL, 0x73bfa2e6cc7373d1ULL, 0x12905a2482121248ULL,
0x403a5d807a40401dULL, 0x0840281048080820ULL, 0xc356e89b95c3c32bULL, 0xec337bc5dfecec97ULL,
0xdb9690ab4ddbdb4bULL, 0xa1611f5fc0a1a1beULL, 0x8d1c8307918d8d0eULL, 0x3df5c97ac83d3df4ULL,
0x97ccf1335b979766ULL, 0x0000000000000000ULL, 0xcf36d483f9cfcf1bULL, 0x2b4587566e2b2bacULL,
0x7697b3ece17676c5ULL, 0x8264b019e6828232ULL, 0xd6fea9b128d6d67fULL, 0x1bd87736c31b1b6cULL,
0xb5c15b7774b5b5eeULL, 0xaf112943beafaf86ULL, 0x6a77dfd41d6a6ab5ULL, 0x50ba0da0ea50505dULL,
0x45124c8a57454509ULL, 0xf3cb18fb38f3f3ebULL, 0x309df060ad3030c0ULL, 0xef2b74c3c4efef9bULL,
0x3fe5c37eda3f3ffcULL, 0x55921caac7555549ULL, 0xa2791059dba2a2b2ULL, 0xea0365c9e9eaea8fULL,
0x650fecca6a656589ULL, 0xbab9686903babad2ULL, 0x2f65935e4a2f2fbcULL, 0xc04ee79d8ec0c027ULL,
0xdebe81a160dede5fULL, 0x1ce06c38fc1c1c70ULL, 0xfdbb2ee746fdfdd3ULL, 0x4d52649a1f4d4d29ULL,
0x92e4e03976929272ULL, 0x758fbceafa7575c9ULL, 0x06301e0c36060618ULL, 0x8a249809ae8a8a12ULL,
0xb2f940794bb2b2f2ULL, 0xe66359d185e6e6bfULL, 0x0e70361c7e0e0e38ULL, 0x1ff8633ee71f1f7cULL,
0x6237f7c455626295ULL, 0xd4eea3b53ad4d477ULL, 0xa829324d81a8a89aULL, 0x96c4f43152969662ULL,
0xf99b3aef62f9f9c3ULL, 0xc566f697a3c5c533ULL, 0x2535b14a10252594ULL, 0x59f220b2ab595979ULL,
0x8454ae15d084842aULL, 0x72b7a7e4c57272d5ULL, 0x39d5dd72ec3939e4ULL, 0x4c5a6198164c4c2dULL,
0x5eca3bbc945e5e65ULL, 0x78e785f09f7878fdULL, 0x38ddd870e53838e0ULL, 0x8c148605988c8c0aULL,
0xd1c6b2bf17d1d163ULL, 0xa5410b57e4a5a5aeULL, 0xe2434dd9a1e2e2afULL, 0x612ff8c24e616199ULL,
0xb3f1457b42b3b3f6ULL, 0x2115a54234212184ULL, 0x9c94d625089c9c4aULL, 0x1ef0663cee1e1e78ULL,
0x4322528661434311ULL, 0xc776fc93b1c7c73bULL, 0xfcb32be54ffcfcd7ULL, 0x0420140824040410ULL,
0x51b208a2e3515159ULL, 0x99bcc72f2599995eULL, 0x6d4fc4da226d6da9ULL, 0x0d68391a650d0d34ULL,
0xfa8335e979fafacfULL, 0xdfb684a369dfdf5bULL, 0x7ed79bfca97e7ee5ULL, 0x243db44819242490ULL,
0x3bc5d776fe3b3becULL, 0xab313d4b9aabab96ULL, 0xce3ed181f0cece1fULL, 0x1188552299111144ULL,
0x8f0c8903838f8f06ULL, 0x4e4a6b9c044e4e25ULL, 0xb7d1517366b7b7e6ULL, 0xeb0b60cbe0ebeb8bULL,
0x3cfdcc78c13c3cf0ULL, 0x817cbf1ffd81813eULL, 0x94d4fe354094946aULL, 0xf7eb0cf31cf7f7fbULL,
0xb9a1676f18b9b9deULL, 0x13985f268b13134cULL, 0x2c7d9c58512c2cb0ULL, 0xd3d6b8bb05d3d36bULL,
0xe76b5cd38ce7e7bbULL, 0x6e57cbdc396e6ea5ULL, 0xc46ef395aac4c437ULL, 0x03180f061b03030cULL,
0x568a13acdc565645ULL, 0x441a49885e44440dULL, 0x7fdf9efea07f7fe1ULL, 0xa921374f88a9a99eULL,
0x2a4d8254672a2aa8ULL, 0xbbb16d6b0abbbbd6ULL, 0xc146e29f87c1c123ULL, 0x53a202a6f1535351ULL,
0xdcae8ba572dcdc57ULL, 0x0b582716530b0b2cULL, 0x9d9cd327019d9d4eULL, 0x6c47c1d82b6c6cadULL,
0x3195f562a43131c4ULL, 0x7487b9e8f37474cdULL, 0xf6e309f115f6f6ffULL, 0x460a438c4c464605ULL,
0xac092645a5acac8aULL, 0x893c970fb589891eULL, 0x14a04428b4141450ULL, 0xe15b42dfbae1e1a3ULL,
0x16b04e2ca6161658ULL, 0x3acdd274f73a3ae8ULL, 0x696fd0d2066969b9ULL, 0x09482d1241090924ULL,
0x70a7ade0d77070ddULL, 0xb6d954716fb6b6e2ULL, 0xd0ceb7bd1ed0d067ULL, 0xed3b7ec7d6eded93ULL,
0xcc2edb85e2cccc17ULL, 0x422a578468424215ULL, 0x98b4c22d2c98985aULL, 0xa4490e55eda4a4aaULL,
0x285d8850752828a0ULL, 0x5cda31b8865c5c6dULL, 0xf8933fed6bf8f8c7ULL, 0x8644a411c2868622ULL,
}, {
/* C6 vectors */
0x6018c07830d81818ULL, 0x8c2305af46262323ULL, 0x3fc67ef991b8c6c6ULL, 0x87e8136fcdfbe8e8ULL,
0x26874ca113cb8787ULL, 0xdab8a9626d11b8b8ULL, 0x0401080502090101ULL, 0x214f426e9e0d4f4fULL,
0xd836adee6c9b3636ULL, 0xa2a6590451ffa6a6ULL, 0x6fd2debdb90cd2d2ULL, 0xf3f5fb06f70ef5f5ULL,
0xf979ef80f2967979ULL, 0xa16f5fcede306f6fULL, 0x7e91fcef3f6d9191ULL, 0x5552aa07a4f85252ULL,
0x9d6027fdc0476060ULL, 0xcabc89766535bcbcULL, 0x569baccd2b379b9bULL, 0x028e048c018a8e8eULL,
0xb6a371155bd2a3a3ULL, 0x300c603c186c0c0cULL, 0xf17bff8af6847b7bULL, 0xd435b5e16a803535ULL,
0x741de8693af51d1dULL, 0xa7e05347ddb3e0e0ULL, 0x7bd7f6acb321d7d7ULL, 0x2fc25eed999cc2c2ULL,
0xb82e6d965c432e2eULL, 0x314b627a96294b4bULL, 0xdffea321e15dfefeULL, 0x41578216aed55757ULL,
0x5415a8412abd1515ULL, 0xc1779fb6eee87777ULL, 0xdc37a5eb6e923737ULL, 0xb3e57b56d79ee5e5ULL,
0x469f8cd923139f9fULL, 0xe7f0d317fd23f0f0ULL, 0x354a6a7f94204a4aULL, 0x4fda9e95a944dadaULL,
0x7d58fa25b0a25858ULL, 0x03c906ca8fcfc9c9ULL, 0xa429558d527c2929ULL, 0x280a5022145a0a0aULL,
0xfeb1e14f7f50b1b1ULL, 0xbaa0691a5dc9a0a0ULL, 0xb16b7fdad6146b6bULL, 0x2e855cab17d98585ULL,
0xcebd8173673cbdbdULL, 0x695dd234ba8f5d5dULL, 0x4010805020901010ULL, 0xf7f4f303f507f4f4ULL,
0x0bcb16c08bddcbcbULL, 0xf83eedc67cd33e3eULL, 0x140528110a2d0505ULL, 0x81671fe6ce786767ULL,
0xb7e47353d597e4e4ULL, 0x9c2725bb4e022727ULL, 0x1941325882734141ULL, 0x168b2c9d0ba78b8bULL,
0xa6a7510153f6a7a7ULL, 0xe97dcf94fab27d7dULL, 0x6e95dcfb37499595ULL, 0x47d88e9fad56d8d8ULL,
0xcbfb8b30eb70fbfbULL, 0x9fee2371c1cdeeeeULL, 0xed7cc791f8bb7c7cULL, 0x856617e3cc716666ULL,
0x53dda68ea77bddddULL, 0x5c17b84b2eaf1717ULL, 0x014702468e454747ULL, 0x429e84dc211a9e9eULL,
0x0fca1ec589d4cacaULL, 0xb42d75995a582d2dULL, 0xc6bf9179632ebfbfULL, 0x1c07381b0e3f0707ULL,
0x8ead012347acadadULL, 0x755aea2fb4b05a5aULL, 0x36836cb51bef8383ULL, 0xcc3385ff66b63333ULL,
0x91633ff2c65c6363ULL, 0x0802100a04120202ULL, 0x92aa39384993aaaaULL, 0xd971afa8e2de7171ULL,
0x07c80ecf8dc6c8c8ULL, 0x6419c87d32d11919ULL, 0x39497270923b4949ULL, 0x43d9869aaf5fd9d9ULL,
0xeff2c31df931f2f2ULL, 0xabe34b48dba8e3e3ULL, 0x715be22ab6b95b5bULL, 0x1a8834920dbc8888ULL,
0x529aa4c8293e9a9aULL, 0x98262dbe4c0b2626ULL, 0xc8328dfa64bf3232ULL, 0xfab0e94a7d59b0b0ULL,
0x83e91b6acff2e9e9ULL, 0x3c0f78331e770f0fULL, 0x73d5e6a6b733d5d5ULL, 0x3a8074ba1df48080ULL,
0xc2be997c6127bebeULL, 0x13cd26de87ebcdcdULL, 0xd034bde468893434ULL, 0x3d487a7590324848ULL,
0xdbffab24e354ffffULL, 0xf57af78ff48d7a7aULL, 0x7a90f4ea3d649090ULL, 0x615fc23ebe9d5f5fULL,
0x80201da0403d2020ULL, 0xbd6867d5d00f6868ULL, 0x681ad07234ca1a1aULL, 0x82ae192c41b7aeaeULL,
0xeab4c95e757db4b4ULL, 0x4d549a19a8ce5454ULL, 0x7693ece53b7f9393ULL, 0x88220daa442f2222ULL,
0x8d6407e9c8636464ULL, 0xe3f1db12ff2af1f1ULL, 0xd173bfa2e6cc7373ULL, 0x4812905a24821212ULL,
0x1d403a5d807a4040ULL, 0x2008402810480808ULL, 0x2bc356e89b95c3c3ULL, 0x97ec337bc5dfececULL,
0x4bdb9690ab4ddbdbULL, 0xbea1611f5fc0a1a1ULL, 0x0e8d1c8307918d8dULL, 0xf43df5c97ac83d3dULL,
0x6697ccf1335b9797ULL, 0x0000000000000000ULL, 0x1bcf36d483f9cfcfULL, 0xac2b4587566e2b2bULL,
0xc57697b3ece17676ULL, 0x328264b019e68282ULL, 0x7fd6fea9b128d6d6ULL, 0x6c1bd87736c31b1bULL,
0xeeb5c15b7774b5b5ULL, 0x86af112943beafafULL, 0xb56a77dfd41d6a6aULL, 0x5d50ba0da0ea5050ULL,
0x0945124c8a574545ULL, 0xebf3cb18fb38f3f3ULL, 0xc0309df060ad3030ULL, 0x9bef2b74c3c4efefULL,
0xfc3fe5c37eda3f3fULL, 0x4955921caac75555ULL, 0xb2a2791059dba2a2ULL, 0x8fea0365c9e9eaeaULL,
0x89650fecca6a6565ULL, 0xd2bab9686903babaULL, 0xbc2f65935e4a2f2fULL, 0x27c04ee79d8ec0c0ULL,
0x5fdebe81a160dedeULL, 0x701ce06c38fc1c1cULL, 0xd3fdbb2ee746fdfdULL, 0x294d52649a1f4d4dULL,
0x7292e4e039769292ULL, 0xc9758fbceafa7575ULL, 0x1806301e0c360606ULL, 0x128a249809ae8a8aULL,
0xf2b2f940794bb2b2ULL, 0xbfe66359d185e6e6ULL, 0x380e70361c7e0e0eULL, 0x7c1ff8633ee71f1fULL,
0x956237f7c4556262ULL, 0x77d4eea3b53ad4d4ULL, 0x9aa829324d81a8a8ULL, 0x6296c4f431529696ULL,
0xc3f99b3aef62f9f9ULL, 0x33c566f697a3c5c5ULL, 0x942535b14a102525ULL, 0x7959f220b2ab5959ULL,
0x2a8454ae15d08484ULL, 0xd572b7a7e4c57272ULL, 0xe439d5dd72ec3939ULL, 0x2d4c5a6198164c4cULL,
0x655eca3bbc945e5eULL, 0xfd78e785f09f7878ULL, 0xe038ddd870e53838ULL, 0x0a8c148605988c8cULL,
0x63d1c6b2bf17d1d1ULL, 0xaea5410b57e4a5a5ULL, 0xafe2434dd9a1e2e2ULL, 0x99612ff8c24e6161ULL,
0xf6b3f1457b42b3b3ULL, 0x842115a542342121ULL, 0x4a9c94d625089c9cULL, 0x781ef0663cee1e1eULL,
0x1143225286614343ULL, 0x3bc776fc93b1c7c7ULL, 0xd7fcb32be54ffcfcULL, 0x1004201408240404ULL,
0x5951b208a2e35151ULL, 0x5e99bcc72f259999ULL, 0xa96d4fc4da226d6dULL, 0x340d68391a650d0dULL,
0xcffa8335e979fafaULL, 0x5bdfb684a369dfdfULL, 0xe57ed79bfca97e7eULL, 0x90243db448192424ULL,
0xec3bc5d776fe3b3bULL, 0x96ab313d4b9aababULL, 0x1fce3ed181f0ceceULL, 0x4411885522991111ULL,
0x068f0c8903838f8fULL, 0x254e4a6b9c044e4eULL, 0xe6b7d1517366b7b7ULL, 0x8beb0b60cbe0ebebULL,
0xf03cfdcc78c13c3cULL, 0x3e817cbf1ffd8181ULL, 0x6a94d4fe35409494ULL, 0xfbf7eb0cf31cf7f7ULL,
0xdeb9a1676f18b9b9ULL, 0x4c13985f268b1313ULL, 0xb02c7d9c58512c2cULL, 0x6bd3d6b8bb05d3d3ULL,
0xbbe76b5cd38ce7e7ULL, 0xa56e57cbdc396e6eULL, 0x37c46ef395aac4c4ULL, 0x0c03180f061b0303ULL,
0x45568a13acdc5656ULL, 0x0d441a49885e4444ULL, 0xe17fdf9efea07f7fULL, 0x9ea921374f88a9a9ULL,
0xa82a4d8254672a2aULL, 0xd6bbb16d6b0abbbbULL, 0x23c146e29f87c1c1ULL, 0x5153a202a6f15353ULL,
0x57dcae8ba572dcdcULL, 0x2c0b582716530b0bULL, 0x4e9d9cd327019d9dULL, 0xad6c47c1d82b6c6cULL,
0xc43195f562a43131ULL, 0xcd7487b9e8f37474ULL, 0xfff6e309f115f6f6ULL, 0x05460a438c4c4646ULL,
0x8aac092645a5acacULL, 0x1e893c970fb58989ULL, 0x5014a04428b41414ULL, 0xa3e15b42dfbae1e1ULL,
0x5816b04e2ca61616ULL, 0xe83acdd274f73a3aULL, 0xb9696fd0d2066969ULL, 0x2409482d12410909ULL,
0xdd70a7ade0d77070ULL, 0xe2b6d954716fb6b6ULL, 0x67d0ceb7bd1ed0d0ULL, 0x93ed3b7ec7d6ededULL,
0x17cc2edb85e2ccccULL, 0x15422a5784684242ULL, 0x5a98b4c22d2c9898ULL, 0xaaa4490e55eda4a4ULL,
0xa0285d8850752828ULL, 0x6d5cda31b8865c5cULL, 0xc7f8933fed6bf8f8ULL, 0x228644a411c28686ULL,
}, {
/* C7 vectors */
0x186018c07830d818ULL, 0x238c2305af462623ULL, 0xc63fc67ef991b8c6ULL, 0xe887e8136fcdfbe8ULL,
0x8726874ca113cb87ULL, 0xb8dab8a9626d11b8ULL, 0x0104010805020901ULL, 0x4f214f426e9e0d4fULL,
0x36d836adee6c9b36ULL, 0xa6a2a6590451ffa6ULL, 0xd26fd2debdb90cd2ULL, 0xf5f3f5fb06f70ef5ULL,
0x79f979ef80f29679ULL, 0x6fa16f5fcede306fULL, 0x917e91fcef3f6d91ULL, 0x525552aa07a4f852ULL,
0x609d6027fdc04760ULL, 0xbccabc89766535bcULL, 0x9b569baccd2b379bULL, 0x8e028e048c018a8eULL,
0xa3b6a371155bd2a3ULL, 0x0c300c603c186c0cULL, 0x7bf17bff8af6847bULL, 0x35d435b5e16a8035ULL,
0x1d741de8693af51dULL, 0xe0a7e05347ddb3e0ULL, 0xd77bd7f6acb321d7ULL, 0xc22fc25eed999cc2ULL,
0x2eb82e6d965c432eULL, 0x4b314b627a96294bULL, 0xfedffea321e15dfeULL, 0x5741578216aed557ULL,
0x155415a8412abd15ULL, 0x77c1779fb6eee877ULL, 0x37dc37a5eb6e9237ULL, 0xe5b3e57b56d79ee5ULL,
0x9f469f8cd923139fULL, 0xf0e7f0d317fd23f0ULL, 0x4a354a6a7f94204aULL, 0xda4fda9e95a944daULL,
0x587d58fa25b0a258ULL, 0xc903c906ca8fcfc9ULL, 0x29a429558d527c29ULL, 0x0a280a5022145a0aULL,
0xb1feb1e14f7f50b1ULL, 0xa0baa0691a5dc9a0ULL, 0x6bb16b7fdad6146bULL, 0x852e855cab17d985ULL,
0xbdcebd8173673cbdULL, 0x5d695dd234ba8f5dULL, 0x1040108050209010ULL, 0xf4f7f4f303f507f4ULL,
0xcb0bcb16c08bddcbULL, 0x3ef83eedc67cd33eULL, 0x05140528110a2d05ULL, 0x6781671fe6ce7867ULL,
0xe4b7e47353d597e4ULL, 0x279c2725bb4e0227ULL, 0x4119413258827341ULL, 0x8b168b2c9d0ba78bULL,
0xa7a6a7510153f6a7ULL, 0x7de97dcf94fab27dULL, 0x956e95dcfb374995ULL, 0xd847d88e9fad56d8ULL,
0xfbcbfb8b30eb70fbULL, 0xee9fee2371c1cdeeULL, 0x7ced7cc791f8bb7cULL, 0x66856617e3cc7166ULL,
0xdd53dda68ea77bddULL, 0x175c17b84b2eaf17ULL, 0x47014702468e4547ULL, 0x9e429e84dc211a9eULL,
0xca0fca1ec589d4caULL, 0x2db42d75995a582dULL, 0xbfc6bf9179632ebfULL, 0x071c07381b0e3f07ULL,
0xad8ead012347acadULL, 0x5a755aea2fb4b05aULL, 0x8336836cb51bef83ULL, 0x33cc3385ff66b633ULL,
0x6391633ff2c65c63ULL, 0x020802100a041202ULL, 0xaa92aa39384993aaULL, 0x71d971afa8e2de71ULL,
0xc807c80ecf8dc6c8ULL, 0x196419c87d32d119ULL, 0x4939497270923b49ULL, 0xd943d9869aaf5fd9ULL,
0xf2eff2c31df931f2ULL, 0xe3abe34b48dba8e3ULL, 0x5b715be22ab6b95bULL, 0x881a8834920dbc88ULL,
0x9a529aa4c8293e9aULL, 0x2698262dbe4c0b26ULL, 0x32c8328dfa64bf32ULL, 0xb0fab0e94a7d59b0ULL,
0xe983e91b6acff2e9ULL, 0x0f3c0f78331e770fULL, 0xd573d5e6a6b733d5ULL, 0x803a8074ba1df480ULL,
0xbec2be997c6127beULL, 0xcd13cd26de87ebcdULL, 0x34d034bde4688934ULL, 0x483d487a75903248ULL,
0xffdbffab24e354ffULL, 0x7af57af78ff48d7aULL, 0x907a90f4ea3d6490ULL, 0x5f615fc23ebe9d5fULL,
0x2080201da0403d20ULL, 0x68bd6867d5d00f68ULL, 0x1a681ad07234ca1aULL, 0xae82ae192c41b7aeULL,
0xb4eab4c95e757db4ULL, 0x544d549a19a8ce54ULL, 0x937693ece53b7f93ULL, 0x2288220daa442f22ULL,
0x648d6407e9c86364ULL, 0xf1e3f1db12ff2af1ULL, 0x73d173bfa2e6cc73ULL, 0x124812905a248212ULL,
0x401d403a5d807a40ULL, 0x0820084028104808ULL, 0xc32bc356e89b95c3ULL, 0xec97ec337bc5dfecULL,
0xdb4bdb9690ab4ddbULL, 0xa1bea1611f5fc0a1ULL, 0x8d0e8d1c8307918dULL, 0x3df43df5c97ac83dULL,
0x976697ccf1335b97ULL, 0x0000000000000000ULL, 0xcf1bcf36d483f9cfULL, 0x2bac2b4587566e2bULL,
0x76c57697b3ece176ULL, 0x82328264b019e682ULL, 0xd67fd6fea9b128d6ULL, 0x1b6c1bd87736c31bULL,
0xb5eeb5c15b7774b5ULL, 0xaf86af112943beafULL, 0x6ab56a77dfd41d6aULL, 0x505d50ba0da0ea50ULL,
0x450945124c8a5745ULL, 0xf3ebf3cb18fb38f3ULL, 0x30c0309df060ad30ULL, 0xef9bef2b74c3c4efULL,
0x3ffc3fe5c37eda3fULL, 0x554955921caac755ULL, 0xa2b2a2791059dba2ULL, 0xea8fea0365c9e9eaULL,
0x6589650fecca6a65ULL, 0xbad2bab9686903baULL, 0x2fbc2f65935e4a2fULL, 0xc027c04ee79d8ec0ULL,
0xde5fdebe81a160deULL, 0x1c701ce06c38fc1cULL, 0xfdd3fdbb2ee746fdULL, 0x4d294d52649a1f4dULL,
0x927292e4e0397692ULL, 0x75c9758fbceafa75ULL, 0x061806301e0c3606ULL, 0x8a128a249809ae8aULL,
0xb2f2b2f940794bb2ULL, 0xe6bfe66359d185e6ULL, 0x0e380e70361c7e0eULL, 0x1f7c1ff8633ee71fULL,
0x62956237f7c45562ULL, 0xd477d4eea3b53ad4ULL, 0xa89aa829324d81a8ULL, 0x966296c4f4315296ULL,
0xf9c3f99b3aef62f9ULL, 0xc533c566f697a3c5ULL, 0x25942535b14a1025ULL, 0x597959f220b2ab59ULL,
0x842a8454ae15d084ULL, 0x72d572b7a7e4c572ULL, 0x39e439d5dd72ec39ULL, 0x4c2d4c5a6198164cULL,
0x5e655eca3bbc945eULL, 0x78fd78e785f09f78ULL, 0x38e038ddd870e538ULL, 0x8c0a8c148605988cULL,
0xd163d1c6b2bf17d1ULL, 0xa5aea5410b57e4a5ULL, 0xe2afe2434dd9a1e2ULL, 0x6199612ff8c24e61ULL,
0xb3f6b3f1457b42b3ULL, 0x21842115a5423421ULL, 0x9c4a9c94d625089cULL, 0x1e781ef0663cee1eULL,
0x4311432252866143ULL, 0xc73bc776fc93b1c7ULL, 0xfcd7fcb32be54ffcULL, 0x0410042014082404ULL,
0x515951b208a2e351ULL, 0x995e99bcc72f2599ULL, 0x6da96d4fc4da226dULL, 0x0d340d68391a650dULL,
0xfacffa8335e979faULL, 0xdf5bdfb684a369dfULL, 0x7ee57ed79bfca97eULL, 0x2490243db4481924ULL,
0x3bec3bc5d776fe3bULL, 0xab96ab313d4b9aabULL, 0xce1fce3ed181f0ceULL, 0x1144118855229911ULL,
0x8f068f0c8903838fULL, 0x4e254e4a6b9c044eULL, 0xb7e6b7d1517366b7ULL, 0xeb8beb0b60cbe0ebULL,
0x3cf03cfdcc78c13cULL, 0x813e817cbf1ffd81ULL, 0x946a94d4fe354094ULL, 0xf7fbf7eb0cf31cf7ULL,
0xb9deb9a1676f18b9ULL, 0x134c13985f268b13ULL, 0x2cb02c7d9c58512cULL, 0xd36bd3d6b8bb05d3ULL,
0xe7bbe76b5cd38ce7ULL, 0x6ea56e57cbdc396eULL, 0xc437c46ef395aac4ULL, 0x030c03180f061b03ULL,
0x5645568a13acdc56ULL, 0x440d441a49885e44ULL, 0x7fe17fdf9efea07fULL, 0xa99ea921374f88a9ULL,
0x2aa82a4d8254672aULL, 0xbbd6bbb16d6b0abbULL, 0xc123c146e29f87c1ULL, 0x535153a202a6f153ULL,
0xdc57dcae8ba572dcULL, 0x0b2c0b582716530bULL, 0x9d4e9d9cd327019dULL, 0x6cad6c47c1d82b6cULL,
0x31c43195f562a431ULL, 0x74cd7487b9e8f374ULL, 0xf6fff6e309f115f6ULL, 0x4605460a438c4c46ULL,
0xac8aac092645a5acULL, 0x891e893c970fb589ULL, 0x145014a04428b414ULL, 0xe1a3e15b42dfbae1ULL,
0x165816b04e2ca616ULL, 0x3ae83acdd274f73aULL, 0x69b9696fd0d20669ULL, 0x092409482d124109ULL,
0x70dd70a7ade0d770ULL, 0xb6e2b6d954716fb6ULL, 0xd067d0ceb7bd1ed0ULL, 0xed93ed3b7ec7d6edULL,
0xcc17cc2edb85e2ccULL, 0x4215422a57846842ULL, 0x985a98b4c22d2c98ULL, 0xa4aaa4490e55eda4ULL,
0x28a0285d88507528ULL, 0x5c6d5cda31b8865cULL, 0xf8c7f8933fed6bf8ULL, 0x86228644a411c286ULL,
}
};
/**
* Initialize context before calculating hash.
*
* @param ctx context to initialize
*/
void digestif_whirlpool_init(struct whirlpool_ctx* ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
/* Algorithm S-Box */
#define WHIRLPOOL_OP(src, shift) ( \
digestif_whirlpool_sbox[0][(int)(src[ shift & 7] >> 56) ] ^ \
digestif_whirlpool_sbox[1][(int)(src[(shift + 7) & 7] >> 48) & 0xff] ^ \
digestif_whirlpool_sbox[2][(int)(src[(shift + 6) & 7] >> 40) & 0xff] ^ \
digestif_whirlpool_sbox[3][(int)(src[(shift + 5) & 7] >> 32) & 0xff] ^ \
digestif_whirlpool_sbox[4][(int)(src[(shift + 4) & 7] >> 24) & 0xff] ^ \
digestif_whirlpool_sbox[5][(int)(src[(shift + 3) & 7] >> 16) & 0xff] ^ \
digestif_whirlpool_sbox[6][(int)(src[(shift + 2) & 7] >> 8) & 0xff] ^ \
digestif_whirlpool_sbox[7][(int)(src[(shift + 1) & 7] ) & 0xff])
/**
* The core transformation. Process a 512-bit block.
*
* @param hash algorithm state
* @param block the message block to process
*/
static void whirlpool_do_chunk(uint64_t *hash, uint64_t* p_block)
{
int i; /* loop counter */
uint64_t K[2][8]; /* key */
uint64_t state[2][8]; /* state */
/* alternating binary flags */
unsigned int m = 0;
/* the number of rounds of the internal dedicated block cipher */
const int number_of_rounds = 10;
/* array used in the rounds */
static const uint64_t rc[10] = {
0x1823c6e887b8014fULL,
0x36a6d2f5796f9152ULL,
0x60bc9b8ea30c7b35ULL,
0x1de0d7c22e4bfe57ULL,
0x157737e59ff04adaULL,
0x58c9290ab1a06b85ULL,
0xbd5d10f4cb3e0567ULL,
0xe427418ba77d95d8ULL,
0xfbee7c66dd17479eULL,
0xca2dbf07ad5a8333ULL
};
/* map the message buffer to a block */
for (i = 0; i < 8; i++) {
/* store K^0 and xor it with the intermediate hash state */
K[0][i] = hash[i];
state[0][i] = be64_to_cpu(p_block[i]) ^ hash[i];
hash[i] = state[0][i];
}
/* iterate over algorithm rounds */
for (i = 0; i < number_of_rounds; i++)
{
/* compute K^i from K^{i-1} */
K[m ^ 1][0] = WHIRLPOOL_OP(K[m], 0) ^ rc[i];
K[m ^ 1][1] = WHIRLPOOL_OP(K[m], 1);
K[m ^ 1][2] = WHIRLPOOL_OP(K[m], 2);
K[m ^ 1][3] = WHIRLPOOL_OP(K[m], 3);
K[m ^ 1][4] = WHIRLPOOL_OP(K[m], 4);
K[m ^ 1][5] = WHIRLPOOL_OP(K[m], 5);
K[m ^ 1][6] = WHIRLPOOL_OP(K[m], 6);
K[m ^ 1][7] = WHIRLPOOL_OP(K[m], 7);
/* apply the i-th round transformation */
state[m ^ 1][0] = WHIRLPOOL_OP(state[m], 0) ^ K[m ^ 1][0];
state[m ^ 1][1] = WHIRLPOOL_OP(state[m], 1) ^ K[m ^ 1][1];
state[m ^ 1][2] = WHIRLPOOL_OP(state[m], 2) ^ K[m ^ 1][2];
state[m ^ 1][3] = WHIRLPOOL_OP(state[m], 3) ^ K[m ^ 1][3];
state[m ^ 1][4] = WHIRLPOOL_OP(state[m], 4) ^ K[m ^ 1][4];
state[m ^ 1][5] = WHIRLPOOL_OP(state[m], 5) ^ K[m ^ 1][5];
state[m ^ 1][6] = WHIRLPOOL_OP(state[m], 6) ^ K[m ^ 1][6];
state[m ^ 1][7] = WHIRLPOOL_OP(state[m], 7) ^ K[m ^ 1][7];
m = m ^ 1;
}
/* apply the Miyaguchi-Preneel compression function */
hash[0] ^= state[0][0];
hash[1] ^= state[0][1];
hash[2] ^= state[0][2];
hash[3] ^= state[0][3];
hash[4] ^= state[0][4];
hash[5] ^= state[0][5];
hash[6] ^= state[0][6];
hash[7] ^= state[0][7];
}
/**
* Calculate message hash.
* Can be called repeatedly with chunks of the message to be hashed.
*
* @param ctx the algorithm context containing current hashing state
* @param msg message chunk
* @param size length of the message chunk
*/
void digestif_whirlpool_update(struct whirlpool_ctx* ctx, uint8_t *data, uint32_t len)
{
unsigned int index, to_fill;
/* check for partial buffer */
index = (unsigned int) (ctx->sz & 0x3f);
to_fill = 64 - index; // sizeof(ctx->buf) - index
ctx->sz += len;
/* process partial buffer if there's enough data to make a block */
if (index && len >= to_fill) {
memcpy(ctx->buf + index, data, to_fill);
whirlpool_do_chunk(ctx->h, (uint64_t*)ctx->buf);
len -= to_fill;
data += to_fill;
index = 0;
}
/* process as much 128-block as possible */
for (; len >= 64; len -= 64, data += 64)
whirlpool_do_chunk(ctx->h, (uint64_t*)data);
/* append data into buf */
if (len)
memcpy(ctx->buf + index, data, len);
}
/**
* Store calculated hash into the given array.
*
* @param ctx the algorithm context containing current hashing state
* @param result calculated hash in binary form
*/
void digestif_whirlpool_finalize(struct whirlpool_ctx* ctx, uint8_t *out)
{
uint32_t i, index;
uint64_t* msg64 = (uint64_t*)ctx->buf;
index = (uint32_t) (ctx->sz & 0x3f);
uint64_t *p = (uint64_t *) out;
/* pad message and run for last block */
ctx->buf[index++] = 0x80;
/* if no room left in the message to store 256-bit message length */
if (index > 32) {
/* then pad the rest with zeros and process it */
while (index < 64) {
ctx->buf[index++] = 0;
}
whirlpool_do_chunk(ctx->h, msg64);
index = 0;
}
/* due to optimization actually only 64-bit of message length are stored */
while (index < 56) {
ctx->buf[index++] = 0;
}
msg64[7] = be64_to_cpu(ctx->sz << 3);
whirlpool_do_chunk(ctx->h, msg64);
/* save result hash */
for (i = 0; i < 8; i++)
p[i] = cpu_to_be64(ctx->h[i]);
}

View file

@ -0,0 +1,41 @@
/* whirlpool.c - an implementation of the Whirlpool Hash Function.
*
* Copyright: 2009-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
*
* Documentation:
* P. S. L. M. Barreto, V. Rijmen, ``The Whirlpool hashing function,''
* NESSIE submission, 2000 (tweaked version, 2001)
*
* The algorithm is named after the Whirlpool Galaxy in Canes Venatici.
*/
#ifndef CRYPTOHASH_WHIRLPOOL_H
#define CRYPTOHASH_WHIRLPOOL_H
#include <stdint.h>
struct whirlpool_ctx
{
uint64_t sz;
uint8_t buf[64];
uint64_t h[8];
};
#define WHIRLPOOL_DIGEST_SIZE 64
#define WHIRLPOOL_CTX_SIZE sizeof(struct whirlpool_ctx)
void digestif_whirlpool_init(struct whirlpool_ctx* ctx);
void digestif_whirlpool_update(struct whirlpool_ctx* ctx, uint8_t *data, uint32_t len);
void digestif_whirlpool_finalize(struct whirlpool_ctx* ctx, uint8_t *out);
#endif

View file

@ -0,0 +1,353 @@
module By = Digestif_by
module Bi = Digestif_bi
let failwith fmt = Format.kasprintf failwith fmt
module Int32 = struct
include Int32
let ( lsl ) = Int32.shift_left
let ( lsr ) = Int32.shift_right_logical
let ( asr ) = Int32.shift_right
let ( lor ) = Int32.logor
let ( lxor ) = Int32.logxor
let ( land ) = Int32.logand
let lnot = Int32.lognot
let ( + ) = Int32.add
let rol32 a n = (a lsl n) lor (a lsr (32 - n))
let ror32 a n = (a lsr n) lor (a lsl (32 - n))
end
module Int64 = struct
include Int64
let ( land ) = Int64.logand
let ( lsl ) = Int64.shift_left
let ( lsr ) = Int64.shift_right_logical
let ( lor ) = Int64.logor
let ( asr ) = Int64.shift_right
let ( lxor ) = Int64.logxor
let ( + ) = Int64.add
let rol64 a n = (a lsl n) lor (a lsr (64 - n))
let ror64 a n = (a lsr n) lor (a lsl (64 - n))
end
module type S = sig
type ctx
type kind = [ `BLAKE2B ]
val init : unit -> ctx
val with_outlen_and_bytes_key : int -> By.t -> int -> int -> ctx
val with_outlen_and_bigstring_key : int -> Bi.t -> int -> int -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
val max_outlen : int
end
module Unsafe : S = struct
type kind = [ `BLAKE2B ]
type param = {
digest_length : int;
key_length : int;
fanout : int;
depth : int;
leaf_length : int32;
node_offset : int32;
xof_length : int32;
node_depth : int;
inner_length : int;
reserved : int array;
salt : int array;
personal : int array;
}
type ctx = {
mutable buflen : int;
outlen : int;
mutable last_node : int;
buf : Bytes.t;
h : int64 array;
t : int64 array;
f : int64 array;
}
let dup ctx =
{
buflen = ctx.buflen;
outlen = ctx.outlen;
last_node = ctx.last_node;
buf = By.copy ctx.buf;
h = Array.copy ctx.h;
t = Array.copy ctx.t;
f = Array.copy ctx.f;
}
let param_to_bytes param =
let arr =
[|
param.digest_length land 0xFF; param.key_length land 0xFF;
param.fanout land 0xFF;
param.depth land 0xFF (* store to little-endian *);
Int32.(to_int ((param.leaf_length lsr 0) land 0xFFl));
Int32.(to_int ((param.leaf_length lsr 8) land 0xFFl));
Int32.(to_int ((param.leaf_length lsr 16) land 0xFFl));
Int32.(to_int ((param.leaf_length lsr 24) land 0xFFl))
(* store to little-endian *);
Int32.(to_int ((param.node_offset lsr 0) land 0xFFl));
Int32.(to_int ((param.node_offset lsr 8) land 0xFFl));
Int32.(to_int ((param.node_offset lsr 16) land 0xFFl));
Int32.(to_int ((param.node_offset lsr 24) land 0xFFl))
(* store to little-endian *);
Int32.(to_int ((param.xof_length lsr 0) land 0xFFl));
Int32.(to_int ((param.xof_length lsr 8) land 0xFFl));
Int32.(to_int ((param.xof_length lsr 16) land 0xFFl));
Int32.(to_int ((param.xof_length lsr 24) land 0xFFl));
param.node_depth land 0xFF; param.inner_length land 0xFF;
param.reserved.(0) land 0xFF; param.reserved.(1) land 0xFF;
param.reserved.(2) land 0xFF; param.reserved.(3) land 0xFF;
param.reserved.(4) land 0xFF; param.reserved.(5) land 0xFF;
param.reserved.(6) land 0xFF; param.reserved.(7) land 0xFF;
param.reserved.(8) land 0xFF; param.reserved.(9) land 0xFF;
param.reserved.(10) land 0xFF; param.reserved.(11) land 0xFF;
param.reserved.(12) land 0xFF; param.reserved.(13) land 0xFF;
param.salt.(0) land 0xFF; param.salt.(1) land 0xFF;
param.salt.(2) land 0xFF; param.salt.(3) land 0xFF;
param.salt.(4) land 0xFF; param.salt.(5) land 0xFF;
param.salt.(6) land 0xFF; param.salt.(7) land 0xFF;
param.salt.(8) land 0xFF; param.salt.(9) land 0xFF;
param.salt.(10) land 0xFF; param.salt.(11) land 0xFF;
param.salt.(12) land 0xFF; param.salt.(13) land 0xFF;
param.salt.(14) land 0xFF; param.salt.(15) land 0xFF;
param.personal.(0) land 0xFF; param.personal.(1) land 0xFF;
param.personal.(2) land 0xFF; param.personal.(3) land 0xFF;
param.personal.(4) land 0xFF; param.personal.(5) land 0xFF;
param.personal.(6) land 0xFF; param.personal.(7) land 0xFF;
param.personal.(8) land 0xFF; param.personal.(9) land 0xFF;
param.personal.(10) land 0xFF; param.personal.(11) land 0xFF;
param.personal.(12) land 0xFF; param.personal.(13) land 0xFF;
param.personal.(14) land 0xFF; param.personal.(15) land 0xFF;
|] in
By.init 64 (fun i -> Char.unsafe_chr arr.(i))
let max_outlen = 64
let default_param =
{
digest_length = max_outlen;
key_length = 0;
fanout = 1;
depth = 1;
leaf_length = 0l;
node_offset = 0l;
xof_length = 0l;
node_depth = 0;
inner_length = 0;
reserved = [| 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0 |];
salt = [| 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0 |];
personal = [| 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0 |];
}
let iv =
[|
0x6a09e667f3bcc908L; 0xbb67ae8584caa73bL; 0x3c6ef372fe94f82bL;
0xa54ff53a5f1d36f1L; 0x510e527fade682d1L; 0x9b05688c2b3e6c1fL;
0x1f83d9abfb41bd6bL; 0x5be0cd19137e2179L;
|]
let increment_counter ctx inc =
let open Int64 in
ctx.t.(0) <- ctx.t.(0) + inc ;
ctx.t.(1) <- (ctx.t.(1) + if ctx.t.(0) < inc then 1L else 0L)
let set_lastnode ctx = ctx.f.(1) <- Int64.minus_one
let set_lastblock ctx =
if ctx.last_node <> 0 then set_lastnode ctx ;
ctx.f.(0) <- Int64.minus_one
let init () =
let buf = By.make 128 '\x00' in
By.fill buf 0 128 '\x00' ;
let ctx =
{
buflen = 0;
outlen = default_param.digest_length;
last_node = 0;
buf;
h = Array.make 8 0L;
t = Array.make 2 0L;
f = Array.make 2 0L;
} in
let param_bytes = param_to_bytes default_param in
for i = 0 to 7 do
ctx.h.(i) <- Int64.(iv.(i) lxor By.le64_to_cpu param_bytes (i * 8))
done ;
ctx
let sigma =
[|
[| 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 |];
|]
let compress :
type a. le64_to_cpu:(a -> int -> int64) -> ctx -> a -> int -> unit =
fun ~le64_to_cpu ctx block off ->
let v = Array.make 16 0L in
let m = Array.make 16 0L in
let g r i a_idx b_idx c_idx d_idx =
let ( ++ ) = ( + ) in
let open Int64 in
v.(a_idx) <- v.(a_idx) + v.(b_idx) + m.(sigma.(r).((2 * i) ++ 0)) ;
v.(d_idx) <- ror64 (v.(d_idx) lxor v.(a_idx)) 32 ;
v.(c_idx) <- v.(c_idx) + v.(d_idx) ;
v.(b_idx) <- ror64 (v.(b_idx) lxor v.(c_idx)) 24 ;
v.(a_idx) <- v.(a_idx) + v.(b_idx) + m.(sigma.(r).((2 * i) ++ 1)) ;
v.(d_idx) <- ror64 (v.(d_idx) lxor v.(a_idx)) 16 ;
v.(c_idx) <- v.(c_idx) + v.(d_idx) ;
v.(b_idx) <- ror64 (v.(b_idx) lxor v.(c_idx)) 63 in
let r r =
g r 0 0 4 8 12 ;
g r 1 1 5 9 13 ;
g r 2 2 6 10 14 ;
g r 3 3 7 11 15 ;
g r 4 0 5 10 15 ;
g r 5 1 6 11 12 ;
g r 6 2 7 8 13 ;
g r 7 3 4 9 14 in
for i = 0 to 15 do
m.(i) <- le64_to_cpu block (off + (i * 8))
done ;
for i = 0 to 7 do
v.(i) <- ctx.h.(i)
done ;
v.(8) <- iv.(0) ;
v.(9) <- iv.(1) ;
v.(10) <- iv.(2) ;
v.(11) <- iv.(3) ;
v.(12) <- Int64.(iv.(4) lxor ctx.t.(0)) ;
v.(13) <- Int64.(iv.(5) lxor ctx.t.(1)) ;
v.(14) <- Int64.(iv.(6) lxor ctx.f.(0)) ;
v.(15) <- Int64.(iv.(7) lxor ctx.f.(1)) ;
r 0 ;
r 1 ;
r 2 ;
r 3 ;
r 4 ;
r 5 ;
r 6 ;
r 7 ;
r 8 ;
r 9 ;
r 10 ;
r 11 ;
let ( ++ ) = ( + ) in
for i = 0 to 7 do
ctx.h.(i) <- Int64.(ctx.h.(i) lxor v.(i) lxor v.(i ++ 8))
done ;
()
let feed :
type a.
blit:(a -> int -> By.t -> int -> int -> unit) ->
le64_to_cpu:(a -> int -> int64) ->
ctx ->
a ->
int ->
int ->
unit =
fun ~blit ~le64_to_cpu ctx buf off len ->
let in_off = ref off in
let in_len = ref len in
if !in_len > 0
then (
let left = ctx.buflen in
let fill = 128 - left in
if !in_len > fill
then (
ctx.buflen <- 0 ;
blit buf !in_off ctx.buf left fill ;
increment_counter ctx 128L ;
compress ~le64_to_cpu:By.le64_to_cpu ctx ctx.buf 0 ;
in_off := !in_off + fill ;
in_len := !in_len - fill ;
while !in_len > 128 do
increment_counter ctx 128L ;
compress ~le64_to_cpu ctx buf !in_off ;
in_off := !in_off + 128 ;
in_len := !in_len - 128
done) ;
blit buf !in_off ctx.buf ctx.buflen !in_len ;
ctx.buflen <- ctx.buflen + !in_len) ;
()
let unsafe_feed_bytes = feed ~blit:By.blit ~le64_to_cpu:By.le64_to_cpu
let unsafe_feed_bigstring =
feed ~blit:By.blit_from_bigstring ~le64_to_cpu:Bi.le64_to_cpu
let with_outlen_and_key ~blit outlen key off len =
if outlen > max_outlen
then
failwith "out length can not be upper than %d (out length: %d)" max_outlen
outlen ;
let buf = By.make 128 '\x00' in
let ctx =
{
buflen = 0;
outlen;
last_node = 0;
buf;
h = Array.make 8 0L;
t = Array.make 2 0L;
f = Array.make 2 0L;
} in
let param_bytes =
param_to_bytes
{ default_param with digest_length = outlen; key_length = len } in
for i = 0 to 7 do
ctx.h.(i) <- Int64.(iv.(i) lxor By.le64_to_cpu param_bytes (i * 8))
done ;
if len > 0
then (
let block = By.make 128 '\x00' in
blit key off block 0 len ;
unsafe_feed_bytes ctx block 0 128) ;
ctx
let with_outlen_and_bytes_key outlen key off len =
with_outlen_and_key ~blit:By.blit outlen key off len
let with_outlen_and_bigstring_key outlen key off len =
with_outlen_and_key ~blit:By.blit_from_bigstring outlen key off len
let unsafe_get ctx =
let res = By.make default_param.digest_length '\x00' in
increment_counter ctx (Int64.of_int ctx.buflen) ;
set_lastblock ctx ;
By.fill ctx.buf ctx.buflen (128 - ctx.buflen) '\x00' ;
compress ~le64_to_cpu:By.le64_to_cpu ctx ctx.buf 0 ;
for i = 0 to 7 do
By.cpu_to_le64 res (i * 8) ctx.h.(i)
done ;
if ctx.outlen < default_param.digest_length
then By.sub res 0 ctx.outlen
else if ctx.outlen > default_param.digest_length
then
assert false
(* XXX(dinosaure): [ctx] can not be initialized with [outlen > digest_length = max_outlen]. *)
else res
end

View file

@ -0,0 +1,327 @@
module By = Digestif_by
module Bi = Digestif_bi
let failwith fmt = Format.kasprintf failwith fmt
module Int32 = struct
include Int32
let ( lsl ) = Int32.shift_left
let ( lsr ) = Int32.shift_right_logical
let ( asr ) = Int32.shift_right
let ( lor ) = Int32.logor
let ( lxor ) = Int32.logxor
let ( land ) = Int32.logand
let lnot = Int32.lognot
let ( + ) = Int32.add
let rol32 a n = (a lsl n) lor (a lsr (32 - n))
let ror32 a n = (a lsr n) lor (a lsl (32 - n))
end
module Int64 = struct
include Int64
let ( land ) = Int64.logand
let ( lsl ) = Int64.shift_left
let ( lsr ) = Int64.shift_right_logical
let ( lor ) = Int64.logor
let ( asr ) = Int64.shift_right
let ( lxor ) = Int64.logxor
let ( + ) = Int64.add
let rol64 a n = (a lsl n) lor (a lsr (64 - n))
let ror64 a n = (a lsr n) lor (a lsl (64 - n))
end
module type S = sig
type ctx
type kind = [ `BLAKE2S ]
val init : unit -> ctx
val with_outlen_and_bytes_key : int -> By.t -> int -> int -> ctx
val with_outlen_and_bigstring_key : int -> Bi.t -> int -> int -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
val max_outlen : int
end
module Unsafe : S = struct
type kind = [ `BLAKE2S ]
type param = {
digest_length : int;
key_length : int;
fanout : int;
depth : int;
leaf_length : int32;
node_offset : int32;
xof_length : int;
node_depth : int;
inner_length : int;
salt : int array;
personal : int array;
}
type ctx = {
mutable buflen : int;
outlen : int;
mutable last_node : int;
buf : Bytes.t;
h : int32 array;
t : int32 array;
f : int32 array;
}
let dup ctx =
{
buflen = ctx.buflen;
outlen = ctx.outlen;
last_node = ctx.last_node;
buf = By.copy ctx.buf;
h = Array.copy ctx.h;
t = Array.copy ctx.t;
f = Array.copy ctx.f;
}
let param_to_bytes param =
let arr =
[|
param.digest_length land 0xFF; param.key_length land 0xFF;
param.fanout land 0xFF;
param.depth land 0xFF (* store to little-endian *);
Int32.(to_int ((param.leaf_length lsr 0) land 0xFFl));
Int32.(to_int ((param.leaf_length lsr 8) land 0xFFl));
Int32.(to_int ((param.leaf_length lsr 16) land 0xFFl));
Int32.(to_int ((param.leaf_length lsr 24) land 0xFFl))
(* store to little-endian *);
Int32.(to_int ((param.node_offset lsr 0) land 0xFFl));
Int32.(to_int ((param.node_offset lsr 8) land 0xFFl));
Int32.(to_int ((param.node_offset lsr 16) land 0xFFl));
Int32.(to_int ((param.node_offset lsr 24) land 0xFFl))
(* store to little-endian *); (param.xof_length lsr 0) land 0xFF;
(param.xof_length lsr 8) land 0xFF; param.node_depth land 0xFF;
param.inner_length land 0xFF; param.salt.(0) land 0xFF;
param.salt.(1) land 0xFF; param.salt.(2) land 0xFF;
param.salt.(3) land 0xFF; param.salt.(4) land 0xFF;
param.salt.(5) land 0xFF; param.salt.(6) land 0xFF;
param.salt.(7) land 0xFF; param.personal.(0) land 0xFF;
param.personal.(1) land 0xFF; param.personal.(2) land 0xFF;
param.personal.(3) land 0xFF; param.personal.(4) land 0xFF;
param.personal.(5) land 0xFF; param.personal.(6) land 0xFF;
param.personal.(7) land 0xFF;
|] in
By.init 32 (fun i -> Char.unsafe_chr arr.(i))
let max_outlen = 32
let default_param =
{
digest_length = max_outlen;
key_length = 0;
fanout = 1;
depth = 1;
leaf_length = 0l;
node_offset = 0l;
xof_length = 0;
node_depth = 0;
inner_length = 0;
salt = [| 0; 0; 0; 0; 0; 0; 0; 0 |];
personal = [| 0; 0; 0; 0; 0; 0; 0; 0 |];
}
let iv =
[|
0x6A09E667l; 0xBB67AE85l; 0x3C6EF372l; 0xA54FF53Al; 0x510E527Fl;
0x9B05688Cl; 0x1F83D9ABl; 0x5BE0CD19l;
|]
let increment_counter ctx inc =
let open Int32 in
ctx.t.(0) <- ctx.t.(0) + inc ;
ctx.t.(1) <- (ctx.t.(1) + if ctx.t.(0) < inc then 1l else 0l)
let set_lastnode ctx = ctx.f.(1) <- Int32.minus_one
let set_lastblock ctx =
if ctx.last_node <> 0 then set_lastnode ctx ;
ctx.f.(0) <- Int32.minus_one
let init () =
let buf = By.make 64 '\x00' in
let ctx =
{
buflen = 0;
outlen = default_param.digest_length;
last_node = 0;
buf;
h = Array.make 8 0l;
t = Array.make 2 0l;
f = Array.make 2 0l;
} in
let param_bytes = param_to_bytes default_param in
for i = 0 to 7 do
ctx.h.(i) <- Int32.(iv.(i) lxor By.le32_to_cpu param_bytes (i * 4))
done ;
ctx
let sigma =
[|
[| 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 |];
|]
let compress :
type a. le32_to_cpu:(a -> int -> int32) -> ctx -> a -> int -> unit =
fun ~le32_to_cpu ctx block off ->
let v = Array.make 16 0l in
let m = Array.make 16 0l in
let g r i a_idx b_idx c_idx d_idx =
let ( ++ ) = ( + ) in
let open Int32 in
v.(a_idx) <- v.(a_idx) + v.(b_idx) + m.(sigma.(r).((2 * i) ++ 0)) ;
v.(d_idx) <- ror32 (v.(d_idx) lxor v.(a_idx)) 16 ;
v.(c_idx) <- v.(c_idx) + v.(d_idx) ;
v.(b_idx) <- ror32 (v.(b_idx) lxor v.(c_idx)) 12 ;
v.(a_idx) <- v.(a_idx) + v.(b_idx) + m.(sigma.(r).((2 * i) ++ 1)) ;
v.(d_idx) <- ror32 (v.(d_idx) lxor v.(a_idx)) 8 ;
v.(c_idx) <- v.(c_idx) + v.(d_idx) ;
v.(b_idx) <- ror32 (v.(b_idx) lxor v.(c_idx)) 7 in
let r r =
g r 0 0 4 8 12 ;
g r 1 1 5 9 13 ;
g r 2 2 6 10 14 ;
g r 3 3 7 11 15 ;
g r 4 0 5 10 15 ;
g r 5 1 6 11 12 ;
g r 6 2 7 8 13 ;
g r 7 3 4 9 14 in
for i = 0 to 15 do
m.(i) <- le32_to_cpu block (off + (i * 4))
done ;
for i = 0 to 7 do
v.(i) <- ctx.h.(i)
done ;
v.(8) <- iv.(0) ;
v.(9) <- iv.(1) ;
v.(10) <- iv.(2) ;
v.(11) <- iv.(3) ;
v.(12) <- Int32.(iv.(4) lxor ctx.t.(0)) ;
v.(13) <- Int32.(iv.(5) lxor ctx.t.(1)) ;
v.(14) <- Int32.(iv.(6) lxor ctx.f.(0)) ;
v.(15) <- Int32.(iv.(7) lxor ctx.f.(1)) ;
r 0 ;
r 1 ;
r 2 ;
r 3 ;
r 4 ;
r 5 ;
r 6 ;
r 7 ;
r 8 ;
r 9 ;
let ( ++ ) = ( + ) in
for i = 0 to 7 do
ctx.h.(i) <- Int32.(ctx.h.(i) lxor v.(i) lxor v.(i ++ 8))
done ;
()
let feed :
type a.
blit:(a -> int -> By.t -> int -> int -> unit) ->
le32_to_cpu:(a -> int -> int32) ->
ctx ->
a ->
int ->
int ->
unit =
fun ~blit ~le32_to_cpu ctx buf off len ->
let in_off = ref off in
let in_len = ref len in
if !in_len > 0
then (
let left = ctx.buflen in
let fill = 64 - left in
if !in_len > fill
then (
ctx.buflen <- 0 ;
blit buf !in_off ctx.buf left fill ;
increment_counter ctx 64l ;
compress ~le32_to_cpu:By.le32_to_cpu ctx ctx.buf 0 ;
in_off := !in_off + fill ;
in_len := !in_len - fill ;
while !in_len > 64 do
increment_counter ctx 64l ;
compress ~le32_to_cpu ctx buf !in_off ;
in_off := !in_off + 64 ;
in_len := !in_len - 64
done) ;
blit buf !in_off ctx.buf ctx.buflen !in_len ;
ctx.buflen <- ctx.buflen + !in_len) ;
()
let unsafe_feed_bytes = feed ~blit:By.blit ~le32_to_cpu:By.le32_to_cpu
let unsafe_feed_bigstring =
feed ~blit:By.blit_from_bigstring ~le32_to_cpu:Bi.le32_to_cpu
let with_outlen_and_key ~blit outlen key off len =
if outlen > max_outlen
then
failwith "out length can not be upper than %d (out length: %d)" max_outlen
outlen ;
let buf = By.make 64 '\x00' in
let ctx =
{
buflen = 0;
outlen;
last_node = 0;
buf;
h = Array.make 8 0l;
t = Array.make 2 0l;
f = Array.make 2 0l;
} in
let param_bytes =
param_to_bytes
{ default_param with key_length = len; digest_length = outlen } in
for i = 0 to 7 do
ctx.h.(i) <- Int32.(iv.(i) lxor By.le32_to_cpu param_bytes (i * 4))
done ;
if len > 0
then (
let block = By.make 64 '\x00' in
blit key off block 0 len ;
unsafe_feed_bytes ctx block 0 64) ;
ctx
let with_outlen_and_bytes_key outlen key off len =
with_outlen_and_key ~blit:By.blit outlen key off len
let with_outlen_and_bigstring_key outlen key off len =
with_outlen_and_key ~blit:By.blit_from_bigstring outlen key off len
let unsafe_get ctx =
let res = By.make default_param.digest_length '\x00' in
increment_counter ctx (Int32.of_int ctx.buflen) ;
set_lastblock ctx ;
By.fill ctx.buf ctx.buflen (64 - ctx.buflen) '\x00' ;
compress ~le32_to_cpu:By.le32_to_cpu ctx ctx.buf 0 ;
for i = 0 to 7 do
By.cpu_to_le32 res (i * 4) ctx.h.(i)
done ;
if ctx.outlen < default_param.digest_length
then By.sub res 0 ctx.outlen
else if ctx.outlen > default_param.digest_length
then
assert false
(* XXX(dinosaure): [ctx] can not be initialized with [outlen > digest_length = max_outlen]. *)
else res
end

View file

@ -0,0 +1,31 @@
module By = Digestif_by
module Bi = Digestif_bi
module type S = sig
type ctx
type kind = [ `SHA3_256 ]
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA3_256 ]
module U = Baijiu_sha3.Unsafe (struct
let padding = Baijiu_sha3.keccak_padding
end)
open U
type nonrec ctx = ctx
let init () = U.init 32
let unsafe_get = unsafe_get
let dup = dup
let unsafe_feed_bytes = unsafe_feed_bytes
let unsafe_feed_bigstring = unsafe_feed_bigstring
end

View file

@ -0,0 +1,189 @@
module By = Digestif_by
module Bi = Digestif_bi
module Int32 = struct
include Int32
let ( lsl ) = Int32.shift_left
let ( lsr ) = Int32.shift_right_logical
let ( asr ) = Int32.shift_right
let ( lor ) = Int32.logor
let ( lxor ) = Int32.logxor
let ( land ) = Int32.logand
let lnot = Int32.lognot
let ( + ) = Int32.add
let rol32 a n = (a lsl n) lor (a lsr (32 - n))
let ror32 a n = (a lsr n) lor (a lsl (32 - n))
end
module Int64 = struct
include Int64
let ( land ) = Int64.logand
let ( lsl ) = Int64.shift_left
end
module type S = sig
type kind = [ `MD5 ]
type ctx = { mutable size : int64; b : Bytes.t; h : int32 array }
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `MD5 ]
type ctx = { mutable size : int64; b : Bytes.t; h : int32 array }
let dup ctx = { size = ctx.size; b = By.copy ctx.b; h = Array.copy ctx.h }
let init () =
let b = By.make 64 '\x00' in
{
size = 0L;
b;
h = [| 0x67452301l; 0xefcdab89l; 0x98badcfel; 0x10325476l |];
}
let f1 x y z = Int32.(z lxor (x land (y lxor z)))
let f2 x y z = f1 z x y
let f3 x y z = Int32.(x lxor y lxor z)
let f4 x y z = Int32.(y lxor (x lor lnot z))
let md5_do_chunk :
type a. le32_to_cpu:(a -> int -> int32) -> ctx -> a -> int -> unit =
fun ~le32_to_cpu ctx buf off ->
let a, b, c, d =
(ref ctx.h.(0), ref ctx.h.(1), ref ctx.h.(2), ref ctx.h.(3)) in
let w = Array.make 16 0l in
for i = 0 to 15 do
w.(i) <- le32_to_cpu buf (off + (i * 4))
done ;
let round f a b c d i k s =
let open Int32 in
a := !a + f !b !c !d + w.(i) + k ;
a := rol32 !a s ;
a := !a + !b in
round f1 a b c d 0 0xd76aa478l 7 ;
round f1 d a b c 1 0xe8c7b756l 12 ;
round f1 c d a b 2 0x242070dbl 17 ;
round f1 b c d a 3 0xc1bdceeel 22 ;
round f1 a b c d 4 0xf57c0fafl 7 ;
round f1 d a b c 5 0x4787c62al 12 ;
round f1 c d a b 6 0xa8304613l 17 ;
round f1 b c d a 7 0xfd469501l 22 ;
round f1 a b c d 8 0x698098d8l 7 ;
round f1 d a b c 9 0x8b44f7afl 12 ;
round f1 c d a b 10 0xffff5bb1l 17 ;
round f1 b c d a 11 0x895cd7bel 22 ;
round f1 a b c d 12 0x6b901122l 7 ;
round f1 d a b c 13 0xfd987193l 12 ;
round f1 c d a b 14 0xa679438el 17 ;
round f1 b c d a 15 0x49b40821l 22 ;
round f2 a b c d 1 0xf61e2562l 5 ;
round f2 d a b c 6 0xc040b340l 9 ;
round f2 c d a b 11 0x265e5a51l 14 ;
round f2 b c d a 0 0xe9b6c7aal 20 ;
round f2 a b c d 5 0xd62f105dl 5 ;
round f2 d a b c 10 0x02441453l 9 ;
round f2 c d a b 15 0xd8a1e681l 14 ;
round f2 b c d a 4 0xe7d3fbc8l 20 ;
round f2 a b c d 9 0x21e1cde6l 5 ;
round f2 d a b c 14 0xc33707d6l 9 ;
round f2 c d a b 3 0xf4d50d87l 14 ;
round f2 b c d a 8 0x455a14edl 20 ;
round f2 a b c d 13 0xa9e3e905l 5 ;
round f2 d a b c 2 0xfcefa3f8l 9 ;
round f2 c d a b 7 0x676f02d9l 14 ;
round f2 b c d a 12 0x8d2a4c8al 20 ;
round f3 a b c d 5 0xfffa3942l 4 ;
round f3 d a b c 8 0x8771f681l 11 ;
round f3 c d a b 11 0x6d9d6122l 16 ;
round f3 b c d a 14 0xfde5380cl 23 ;
round f3 a b c d 1 0xa4beea44l 4 ;
round f3 d a b c 4 0x4bdecfa9l 11 ;
round f3 c d a b 7 0xf6bb4b60l 16 ;
round f3 b c d a 10 0xbebfbc70l 23 ;
round f3 a b c d 13 0x289b7ec6l 4 ;
round f3 d a b c 0 0xeaa127fal 11 ;
round f3 c d a b 3 0xd4ef3085l 16 ;
round f3 b c d a 6 0x04881d05l 23 ;
round f3 a b c d 9 0xd9d4d039l 4 ;
round f3 d a b c 12 0xe6db99e5l 11 ;
round f3 c d a b 15 0x1fa27cf8l 16 ;
round f3 b c d a 2 0xc4ac5665l 23 ;
round f4 a b c d 0 0xf4292244l 6 ;
round f4 d a b c 7 0x432aff97l 10 ;
round f4 c d a b 14 0xab9423a7l 15 ;
round f4 b c d a 5 0xfc93a039l 21 ;
round f4 a b c d 12 0x655b59c3l 6 ;
round f4 d a b c 3 0x8f0ccc92l 10 ;
round f4 c d a b 10 0xffeff47dl 15 ;
round f4 b c d a 1 0x85845dd1l 21 ;
round f4 a b c d 8 0x6fa87e4fl 6 ;
round f4 d a b c 15 0xfe2ce6e0l 10 ;
round f4 c d a b 6 0xa3014314l 15 ;
round f4 b c d a 13 0x4e0811a1l 21 ;
round f4 a b c d 4 0xf7537e82l 6 ;
round f4 d a b c 11 0xbd3af235l 10 ;
round f4 c d a b 2 0x2ad7d2bbl 15 ;
round f4 b c d a 9 0xeb86d391l 21 ;
let open Int32 in
ctx.h.(0) <- ctx.h.(0) + !a ;
ctx.h.(1) <- ctx.h.(1) + !b ;
ctx.h.(2) <- ctx.h.(2) + !c ;
ctx.h.(3) <- ctx.h.(3) + !d ;
()
let feed :
type a.
blit:(a -> int -> By.t -> int -> int -> unit) ->
le32_to_cpu:(a -> int -> int32) ->
ctx ->
a ->
int ->
int ->
unit =
fun ~blit ~le32_to_cpu ctx buf off len ->
let idx = ref Int64.(to_int (ctx.size land 0x3FL)) in
let len = ref len in
let off = ref off in
let to_fill = 64 - !idx in
ctx.size <- Int64.add ctx.size (Int64.of_int !len) ;
if !idx <> 0 && !len >= to_fill
then (
blit buf !off ctx.b !idx to_fill ;
md5_do_chunk ~le32_to_cpu:By.le32_to_cpu ctx ctx.b 0 ;
len := !len - to_fill ;
off := !off + to_fill ;
idx := 0) ;
while !len >= 64 do
md5_do_chunk ~le32_to_cpu ctx buf !off ;
len := !len - 64 ;
off := !off + 64
done ;
if !len <> 0 then blit buf !off ctx.b !idx !len ;
()
let unsafe_feed_bytes = feed ~blit:By.blit ~le32_to_cpu:By.le32_to_cpu
let unsafe_feed_bigstring =
feed ~blit:By.blit_from_bigstring ~le32_to_cpu:Bi.le32_to_cpu
let unsafe_get ctx =
let index = Int64.(to_int (ctx.size land 0x3FL)) in
let padlen = if index < 56 then 56 - index else 64 + 56 - index in
let padding = By.init padlen (function 0 -> '\x80' | _ -> '\x00') in
let bits = By.create 8 in
By.cpu_to_le64 bits 0 Int64.(ctx.size lsl 3) ;
unsafe_feed_bytes ctx padding 0 padlen ;
unsafe_feed_bytes ctx bits 0 8 ;
let res = By.create (4 * 4) in
for i = 0 to 3 do
By.cpu_to_le32 res (i * 4) ctx.h.(i)
done ;
res
end

View file

@ -0,0 +1,371 @@
module By = Digestif_by
module Bi = Digestif_bi
module type S = sig
type ctx
type kind = [ `RMD160 ]
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Int32 = struct
include Int32
let ( lsl ) = Int32.shift_left
let ( lsr ) = Int32.shift_right_logical
let ( asr ) = Int32.shift_right
let ( lor ) = Int32.logor
let ( lxor ) = Int32.logxor
let ( land ) = Int32.logand
let lnot = Int32.lognot
let ( + ) = Int32.add
let rol32 a n = (a lsl n) lor (a lsr (32 - n))
let ror32 a n = (a lsr n) lor (a lsl (32 - n))
end
module Int64 = struct
include Int64
let ( land ) = Int64.logand
let ( lsl ) = Int64.shift_left
end
module Unsafe : S = struct
type kind = [ `RMD160 ]
type ctx = { s : int32 array; mutable n : int; h : int32 array; b : Bytes.t }
let dup ctx =
{ s = Array.copy ctx.s; n = ctx.n; h = Array.copy ctx.h; b = By.copy ctx.b }
let init () =
let b = By.make 64 '\x00' in
{
s = [| 0l; 0l |];
n = 0;
b;
h = [| 0x67452301l; 0xefcdab89l; 0x98badcfel; 0x10325476l; 0xc3d2e1f0l |];
}
let f x y z = Int32.(x lxor y lxor z)
let g x y z = Int32.(x land y lor (lnot x land z))
let h x y z = Int32.(x lor lnot y lxor z)
let i x y z = Int32.(x land z lor (y land lnot z))
let j x y z = Int32.(x lxor (y lor lnot z))
let ff a b c d e x s =
let open Int32 in
a := !a + f !b !c !d + x ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let gg a b c d e x s =
let open Int32 in
a := !a + g !b !c !d + x + 0x5a827999l ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let hh a b c d e x s =
let open Int32 in
a := !a + h !b !c !d + x + 0x6ed9eba1l ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let ii a b c d e x s =
let open Int32 in
a := !a + i !b !c !d + x + 0x8f1bbcdcl ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let jj a b c d e x s =
let open Int32 in
a := !a + j !b !c !d + x + 0xa953fd4el ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let fff a b c d e x s =
let open Int32 in
a := !a + f !b !c !d + x ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let ggg a b c d e x s =
let open Int32 in
a := !a + g !b !c !d + x + 0x7a6d76e9l ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let hhh a b c d e x s =
let open Int32 in
a := !a + h !b !c !d + x + 0x6d703ef3l ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let iii a b c d e x s =
let open Int32 in
a := !a + i !b !c !d + x + 0x5c4dd124l ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let jjj a b c d e x s =
let open Int32 in
a := !a + j !b !c !d + x + 0x50a28be6l ;
a := rol32 !a s + !e ;
c := rol32 !c 10
let rmd160_do_chunk :
type a. le32_to_cpu:(a -> int -> int32) -> ctx -> a -> int -> unit =
fun ~le32_to_cpu ctx buff off ->
let aa, bb, cc, dd, ee, aaa, bbb, ccc, ddd, eee =
( ref ctx.h.(0),
ref ctx.h.(1),
ref ctx.h.(2),
ref ctx.h.(3),
ref ctx.h.(4),
ref ctx.h.(0),
ref ctx.h.(1),
ref ctx.h.(2),
ref ctx.h.(3),
ref ctx.h.(4) ) in
let w = Array.make 16 0l in
for i = 0 to 15 do
w.(i) <- le32_to_cpu buff (off + (i * 4))
done ;
ff aa bb cc dd ee w.(0) 11 ;
ff ee aa bb cc dd w.(1) 14 ;
ff dd ee aa bb cc w.(2) 15 ;
ff cc dd ee aa bb w.(3) 12 ;
ff bb cc dd ee aa w.(4) 5 ;
ff aa bb cc dd ee w.(5) 8 ;
ff ee aa bb cc dd w.(6) 7 ;
ff dd ee aa bb cc w.(7) 9 ;
ff cc dd ee aa bb w.(8) 11 ;
ff bb cc dd ee aa w.(9) 13 ;
ff aa bb cc dd ee w.(10) 14 ;
ff ee aa bb cc dd w.(11) 15 ;
ff dd ee aa bb cc w.(12) 6 ;
ff cc dd ee aa bb w.(13) 7 ;
ff bb cc dd ee aa w.(14) 9 ;
ff aa bb cc dd ee w.(15) 8 ;
gg ee aa bb cc dd w.(7) 7 ;
gg dd ee aa bb cc w.(4) 6 ;
gg cc dd ee aa bb w.(13) 8 ;
gg bb cc dd ee aa w.(1) 13 ;
gg aa bb cc dd ee w.(10) 11 ;
gg ee aa bb cc dd w.(6) 9 ;
gg dd ee aa bb cc w.(15) 7 ;
gg cc dd ee aa bb w.(3) 15 ;
gg bb cc dd ee aa w.(12) 7 ;
gg aa bb cc dd ee w.(0) 12 ;
gg ee aa bb cc dd w.(9) 15 ;
gg dd ee aa bb cc w.(5) 9 ;
gg cc dd ee aa bb w.(2) 11 ;
gg bb cc dd ee aa w.(14) 7 ;
gg aa bb cc dd ee w.(11) 13 ;
gg ee aa bb cc dd w.(8) 12 ;
hh dd ee aa bb cc w.(3) 11 ;
hh cc dd ee aa bb w.(10) 13 ;
hh bb cc dd ee aa w.(14) 6 ;
hh aa bb cc dd ee w.(4) 7 ;
hh ee aa bb cc dd w.(9) 14 ;
hh dd ee aa bb cc w.(15) 9 ;
hh cc dd ee aa bb w.(8) 13 ;
hh bb cc dd ee aa w.(1) 15 ;
hh aa bb cc dd ee w.(2) 14 ;
hh ee aa bb cc dd w.(7) 8 ;
hh dd ee aa bb cc w.(0) 13 ;
hh cc dd ee aa bb w.(6) 6 ;
hh bb cc dd ee aa w.(13) 5 ;
hh aa bb cc dd ee w.(11) 12 ;
hh ee aa bb cc dd w.(5) 7 ;
hh dd ee aa bb cc w.(12) 5 ;
ii cc dd ee aa bb w.(1) 11 ;
ii bb cc dd ee aa w.(9) 12 ;
ii aa bb cc dd ee w.(11) 14 ;
ii ee aa bb cc dd w.(10) 15 ;
ii dd ee aa bb cc w.(0) 14 ;
ii cc dd ee aa bb w.(8) 15 ;
ii bb cc dd ee aa w.(12) 9 ;
ii aa bb cc dd ee w.(4) 8 ;
ii ee aa bb cc dd w.(13) 9 ;
ii dd ee aa bb cc w.(3) 14 ;
ii cc dd ee aa bb w.(7) 5 ;
ii bb cc dd ee aa w.(15) 6 ;
ii aa bb cc dd ee w.(14) 8 ;
ii ee aa bb cc dd w.(5) 6 ;
ii dd ee aa bb cc w.(6) 5 ;
ii cc dd ee aa bb w.(2) 12 ;
jj bb cc dd ee aa w.(4) 9 ;
jj aa bb cc dd ee w.(0) 15 ;
jj ee aa bb cc dd w.(5) 5 ;
jj dd ee aa bb cc w.(9) 11 ;
jj cc dd ee aa bb w.(7) 6 ;
jj bb cc dd ee aa w.(12) 8 ;
jj aa bb cc dd ee w.(2) 13 ;
jj ee aa bb cc dd w.(10) 12 ;
jj dd ee aa bb cc w.(14) 5 ;
jj cc dd ee aa bb w.(1) 12 ;
jj bb cc dd ee aa w.(3) 13 ;
jj aa bb cc dd ee w.(8) 14 ;
jj ee aa bb cc dd w.(11) 11 ;
jj dd ee aa bb cc w.(6) 8 ;
jj cc dd ee aa bb w.(15) 5 ;
jj bb cc dd ee aa w.(13) 6 ;
jjj aaa bbb ccc ddd eee w.(5) 8 ;
jjj eee aaa bbb ccc ddd w.(14) 9 ;
jjj ddd eee aaa bbb ccc w.(7) 9 ;
jjj ccc ddd eee aaa bbb w.(0) 11 ;
jjj bbb ccc ddd eee aaa w.(9) 13 ;
jjj aaa bbb ccc ddd eee w.(2) 15 ;
jjj eee aaa bbb ccc ddd w.(11) 15 ;
jjj ddd eee aaa bbb ccc w.(4) 5 ;
jjj ccc ddd eee aaa bbb w.(13) 7 ;
jjj bbb ccc ddd eee aaa w.(6) 7 ;
jjj aaa bbb ccc ddd eee w.(15) 8 ;
jjj eee aaa bbb ccc ddd w.(8) 11 ;
jjj ddd eee aaa bbb ccc w.(1) 14 ;
jjj ccc ddd eee aaa bbb w.(10) 14 ;
jjj bbb ccc ddd eee aaa w.(3) 12 ;
jjj aaa bbb ccc ddd eee w.(12) 6 ;
iii eee aaa bbb ccc ddd w.(6) 9 ;
iii ddd eee aaa bbb ccc w.(11) 13 ;
iii ccc ddd eee aaa bbb w.(3) 15 ;
iii bbb ccc ddd eee aaa w.(7) 7 ;
iii aaa bbb ccc ddd eee w.(0) 12 ;
iii eee aaa bbb ccc ddd w.(13) 8 ;
iii ddd eee aaa bbb ccc w.(5) 9 ;
iii ccc ddd eee aaa bbb w.(10) 11 ;
iii bbb ccc ddd eee aaa w.(14) 7 ;
iii aaa bbb ccc ddd eee w.(15) 7 ;
iii eee aaa bbb ccc ddd w.(8) 12 ;
iii ddd eee aaa bbb ccc w.(12) 7 ;
iii ccc ddd eee aaa bbb w.(4) 6 ;
iii bbb ccc ddd eee aaa w.(9) 15 ;
iii aaa bbb ccc ddd eee w.(1) 13 ;
iii eee aaa bbb ccc ddd w.(2) 11 ;
hhh ddd eee aaa bbb ccc w.(15) 9 ;
hhh ccc ddd eee aaa bbb w.(5) 7 ;
hhh bbb ccc ddd eee aaa w.(1) 15 ;
hhh aaa bbb ccc ddd eee w.(3) 11 ;
hhh eee aaa bbb ccc ddd w.(7) 8 ;
hhh ddd eee aaa bbb ccc w.(14) 6 ;
hhh ccc ddd eee aaa bbb w.(6) 6 ;
hhh bbb ccc ddd eee aaa w.(9) 14 ;
hhh aaa bbb ccc ddd eee w.(11) 12 ;
hhh eee aaa bbb ccc ddd w.(8) 13 ;
hhh ddd eee aaa bbb ccc w.(12) 5 ;
hhh ccc ddd eee aaa bbb w.(2) 14 ;
hhh bbb ccc ddd eee aaa w.(10) 13 ;
hhh aaa bbb ccc ddd eee w.(0) 13 ;
hhh eee aaa bbb ccc ddd w.(4) 7 ;
hhh ddd eee aaa bbb ccc w.(13) 5 ;
ggg ccc ddd eee aaa bbb w.(8) 15 ;
ggg bbb ccc ddd eee aaa w.(6) 5 ;
ggg aaa bbb ccc ddd eee w.(4) 8 ;
ggg eee aaa bbb ccc ddd w.(1) 11 ;
ggg ddd eee aaa bbb ccc w.(3) 14 ;
ggg ccc ddd eee aaa bbb w.(11) 14 ;
ggg bbb ccc ddd eee aaa w.(15) 6 ;
ggg aaa bbb ccc ddd eee w.(0) 14 ;
ggg eee aaa bbb ccc ddd w.(5) 6 ;
ggg ddd eee aaa bbb ccc w.(12) 9 ;
ggg ccc ddd eee aaa bbb w.(2) 12 ;
ggg bbb ccc ddd eee aaa w.(13) 9 ;
ggg aaa bbb ccc ddd eee w.(9) 12 ;
ggg eee aaa bbb ccc ddd w.(7) 5 ;
ggg ddd eee aaa bbb ccc w.(10) 15 ;
ggg ccc ddd eee aaa bbb w.(14) 8 ;
fff bbb ccc ddd eee aaa w.(12) 8 ;
fff aaa bbb ccc ddd eee w.(15) 5 ;
fff eee aaa bbb ccc ddd w.(10) 12 ;
fff ddd eee aaa bbb ccc w.(4) 9 ;
fff ccc ddd eee aaa bbb w.(1) 12 ;
fff bbb ccc ddd eee aaa w.(5) 5 ;
fff aaa bbb ccc ddd eee w.(8) 14 ;
fff eee aaa bbb ccc ddd w.(7) 6 ;
fff ddd eee aaa bbb ccc w.(6) 8 ;
fff ccc ddd eee aaa bbb w.(2) 13 ;
fff bbb ccc ddd eee aaa w.(13) 6 ;
fff aaa bbb ccc ddd eee w.(14) 5 ;
fff eee aaa bbb ccc ddd w.(0) 15 ;
fff ddd eee aaa bbb ccc w.(3) 13 ;
fff ccc ddd eee aaa bbb w.(9) 11 ;
fff bbb ccc ddd eee aaa w.(11) 11 ;
let open Int32 in
ddd := !ddd + !cc + ctx.h.(1) ;
(* final result for h[0]. *)
ctx.h.(1) <- ctx.h.(2) + !dd + !eee ;
ctx.h.(2) <- ctx.h.(3) + !ee + !aaa ;
ctx.h.(3) <- ctx.h.(4) + !aa + !bbb ;
ctx.h.(4) <- ctx.h.(0) + !bb + !ccc ;
ctx.h.(0) <- !ddd ;
()
exception Leave
let feed :
type a.
le32_to_cpu:(a -> int -> int32) ->
blit:(a -> int -> By.t -> int -> int -> unit) ->
ctx ->
a ->
int ->
int ->
unit =
fun ~le32_to_cpu ~blit ctx buf off len ->
let t = ref ctx.s.(0) in
let off = ref off in
let len = ref len in
ctx.s.(0) <- Int32.add !t (Int32.of_int (!len lsl 3)) ;
if ctx.s.(0) < !t then ctx.s.(1) <- Int32.(ctx.s.(1) + 1l) ;
ctx.s.(1) <- Int32.add ctx.s.(1) (Int32.of_int (!len lsr 29)) ;
try
if ctx.n <> 0
then (
let t = 64 - ctx.n in
if !len < t
then (
blit buf !off ctx.b ctx.n !len ;
ctx.n <- ctx.n + !len ;
raise Leave) ;
blit buf !off ctx.b ctx.n t ;
rmd160_do_chunk ~le32_to_cpu:By.le32_to_cpu ctx ctx.b 0 ;
off := !off + t ;
len := !len - t) ;
while !len >= 64 do
rmd160_do_chunk ~le32_to_cpu ctx buf !off ;
off := !off + 64 ;
len := !len - 64
done ;
blit buf !off ctx.b 0 !len ;
ctx.n <- !len
with Leave -> ()
let unsafe_feed_bytes ctx buf off len =
feed ~blit:By.blit ~le32_to_cpu:By.le32_to_cpu ctx buf off len
let unsafe_feed_bigstring ctx buf off len =
feed ~blit:By.blit_from_bigstring ~le32_to_cpu:Bi.le32_to_cpu ctx buf off
len
let unsafe_get ctx =
let i = ref (ctx.n + 1) in
let res = By.create (5 * 4) in
By.set ctx.b ctx.n '\x80' ;
if !i > 56
then (
By.fill ctx.b !i (64 - !i) '\x00' ;
rmd160_do_chunk ~le32_to_cpu:By.le32_to_cpu ctx ctx.b 0 ;
i := 0) ;
By.fill ctx.b !i (56 - !i) '\x00' ;
By.cpu_to_le32 ctx.b 56 ctx.s.(0) ;
By.cpu_to_le32 ctx.b 60 ctx.s.(1) ;
rmd160_do_chunk ~le32_to_cpu:By.le32_to_cpu ctx ctx.b 0 ;
for i = 0 to 4 do
By.cpu_to_le32 res (i * 4) ctx.h.(i)
done ;
res
end

View file

@ -0,0 +1,221 @@
module By = Digestif_by
module Bi = Digestif_bi
module Int32 = struct
include Int32
let ( lsl ) = Int32.shift_left
let ( lsr ) = Int32.shift_right_logical
let ( asr ) = Int32.shift_right
let ( lor ) = Int32.logor
let ( lxor ) = Int32.logxor
let ( land ) = Int32.logand
let ( + ) = Int32.add
let rol32 a n = (a lsl n) lor (a lsr (32 - n))
end
module Int64 = struct
include Int64
let ( land ) = Int64.logand
let ( lsl ) = Int64.shift_left
end
module type S = sig
type ctx
type kind = [ `SHA1 ]
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA1 ]
type ctx = { mutable size : int64; b : Bytes.t; h : int32 array }
let dup ctx = { size = ctx.size; b = By.copy ctx.b; h = Array.copy ctx.h }
let init () =
let b = By.make 64 '\x00' in
{
size = 0L;
b;
h = [| 0x67452301l; 0xefcdab89l; 0x98badcfel; 0x10325476l; 0xc3d2e1f0l |];
}
let f1 x y z = Int32.(z lxor (x land (y lxor z)))
let f2 x y z = Int32.(x lxor y lxor z)
let f3 x y z = Int32.((x land y) + (z land (x lxor y)))
let f4 = f2
let k1 = 0x5a827999l
let k2 = 0x6ed9eba1l
let k3 = 0x8f1bbcdcl
let k4 = 0xca62c1d6l
let sha1_do_chunk :
type a. be32_to_cpu:(a -> int -> int32) -> ctx -> a -> int -> unit =
fun ~be32_to_cpu ctx buf off ->
let a = ref ctx.h.(0) in
let b = ref ctx.h.(1) in
let c = ref ctx.h.(2) in
let d = ref ctx.h.(3) in
let e = ref ctx.h.(4) in
let w = Array.make 16 0l in
let m i =
let ( && ) a b = a land b in
let ( -- ) a b = a - b in
let v =
Int32.(
rol32
(w.(i && 0x0F)
lxor w.((i -- 14) && 0x0F)
lxor w.((i -- 8) && 0x0F)
lxor w.((i -- 3) && 0x0F))
1) in
w.(i land 0x0F) <- v ;
w.(i land 0x0F) in
let round a b c d e f k w =
(e := Int32.(!e + rol32 !a 5 + f !b !c !d + k + w)) ;
b := Int32.(rol32 !b 30) in
for i = 0 to 15 do
w.(i) <- be32_to_cpu buf (off + (i * 4))
done ;
round a b c d e f1 k1 w.(0) ;
round e a b c d f1 k1 w.(1) ;
round d e a b c f1 k1 w.(2) ;
round c d e a b f1 k1 w.(3) ;
round b c d e a f1 k1 w.(4) ;
round a b c d e f1 k1 w.(5) ;
round e a b c d f1 k1 w.(6) ;
round d e a b c f1 k1 w.(7) ;
round c d e a b f1 k1 w.(8) ;
round b c d e a f1 k1 w.(9) ;
round a b c d e f1 k1 w.(10) ;
round e a b c d f1 k1 w.(11) ;
round d e a b c f1 k1 w.(12) ;
round c d e a b f1 k1 w.(13) ;
round b c d e a f1 k1 w.(14) ;
round a b c d e f1 k1 w.(15) ;
round e a b c d f1 k1 (m 16) ;
round d e a b c f1 k1 (m 17) ;
round c d e a b f1 k1 (m 18) ;
round b c d e a f1 k1 (m 19) ;
round a b c d e f2 k2 (m 20) ;
round e a b c d f2 k2 (m 21) ;
round d e a b c f2 k2 (m 22) ;
round c d e a b f2 k2 (m 23) ;
round b c d e a f2 k2 (m 24) ;
round a b c d e f2 k2 (m 25) ;
round e a b c d f2 k2 (m 26) ;
round d e a b c f2 k2 (m 27) ;
round c d e a b f2 k2 (m 28) ;
round b c d e a f2 k2 (m 29) ;
round a b c d e f2 k2 (m 30) ;
round e a b c d f2 k2 (m 31) ;
round d e a b c f2 k2 (m 32) ;
round c d e a b f2 k2 (m 33) ;
round b c d e a f2 k2 (m 34) ;
round a b c d e f2 k2 (m 35) ;
round e a b c d f2 k2 (m 36) ;
round d e a b c f2 k2 (m 37) ;
round c d e a b f2 k2 (m 38) ;
round b c d e a f2 k2 (m 39) ;
round a b c d e f3 k3 (m 40) ;
round e a b c d f3 k3 (m 41) ;
round d e a b c f3 k3 (m 42) ;
round c d e a b f3 k3 (m 43) ;
round b c d e a f3 k3 (m 44) ;
round a b c d e f3 k3 (m 45) ;
round e a b c d f3 k3 (m 46) ;
round d e a b c f3 k3 (m 47) ;
round c d e a b f3 k3 (m 48) ;
round b c d e a f3 k3 (m 49) ;
round a b c d e f3 k3 (m 50) ;
round e a b c d f3 k3 (m 51) ;
round d e a b c f3 k3 (m 52) ;
round c d e a b f3 k3 (m 53) ;
round b c d e a f3 k3 (m 54) ;
round a b c d e f3 k3 (m 55) ;
round e a b c d f3 k3 (m 56) ;
round d e a b c f3 k3 (m 57) ;
round c d e a b f3 k3 (m 58) ;
round b c d e a f3 k3 (m 59) ;
round a b c d e f4 k4 (m 60) ;
round e a b c d f4 k4 (m 61) ;
round d e a b c f4 k4 (m 62) ;
round c d e a b f4 k4 (m 63) ;
round b c d e a f4 k4 (m 64) ;
round a b c d e f4 k4 (m 65) ;
round e a b c d f4 k4 (m 66) ;
round d e a b c f4 k4 (m 67) ;
round c d e a b f4 k4 (m 68) ;
round b c d e a f4 k4 (m 69) ;
round a b c d e f4 k4 (m 70) ;
round e a b c d f4 k4 (m 71) ;
round d e a b c f4 k4 (m 72) ;
round c d e a b f4 k4 (m 73) ;
round b c d e a f4 k4 (m 74) ;
round a b c d e f4 k4 (m 75) ;
round e a b c d f4 k4 (m 76) ;
round d e a b c f4 k4 (m 77) ;
round c d e a b f4 k4 (m 78) ;
round b c d e a f4 k4 (m 79) ;
ctx.h.(0) <- Int32.add ctx.h.(0) !a ;
ctx.h.(1) <- Int32.add ctx.h.(1) !b ;
ctx.h.(2) <- Int32.add ctx.h.(2) !c ;
ctx.h.(3) <- Int32.add ctx.h.(3) !d ;
ctx.h.(4) <- Int32.add ctx.h.(4) !e ;
()
let feed :
type a.
blit:(a -> int -> By.t -> int -> int -> unit) ->
be32_to_cpu:(a -> int -> int32) ->
ctx ->
a ->
int ->
int ->
unit =
fun ~blit ~be32_to_cpu ctx buf off len ->
let idx = ref Int64.(to_int (ctx.size land 0x3FL)) in
let len = ref len in
let off = ref off in
let to_fill = 64 - !idx in
ctx.size <- Int64.add ctx.size (Int64.of_int !len) ;
if !idx <> 0 && !len >= to_fill
then (
blit buf !off ctx.b !idx to_fill ;
sha1_do_chunk ~be32_to_cpu:By.be32_to_cpu ctx ctx.b 0 ;
len := !len - to_fill ;
off := !off + to_fill ;
idx := 0) ;
while !len >= 64 do
sha1_do_chunk ~be32_to_cpu ctx buf !off ;
len := !len - 64 ;
off := !off + 64
done ;
if !len <> 0 then blit buf !off ctx.b !idx !len ;
()
let unsafe_feed_bytes = feed ~blit:By.blit ~be32_to_cpu:By.be32_to_cpu
let unsafe_feed_bigstring =
feed ~blit:By.blit_from_bigstring ~be32_to_cpu:Bi.be32_to_cpu
let unsafe_get ctx =
let index = Int64.(to_int (ctx.size land 0x3FL)) in
let padlen = if index < 56 then 56 - index else 64 + 56 - index in
let padding = By.init padlen (function 0 -> '\x80' | _ -> '\x00') in
let bits = By.create 8 in
By.cpu_to_be64 bits 0 Int64.(ctx.size lsl 3) ;
unsafe_feed_bytes ctx padding 0 padlen ;
unsafe_feed_bytes ctx bits 0 8 ;
let res = By.create (5 * 4) in
for i = 0 to 4 do
By.cpu_to_be32 res (i * 4) ctx.h.(i)
done ;
res
end

View file

@ -0,0 +1,41 @@
module By = Digestif_by
module Bi = Digestif_bi
module type S = sig
type ctx
type kind = [ `SHA224 ]
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA224 ]
open Baijiu_sha256.Unsafe
type nonrec ctx = ctx
let init () =
let b = By.make 128 '\x00' in
{
size = 0L;
b;
h =
[|
0xc1059ed8l; 0x367cd507l; 0x3070dd17l; 0xf70e5939l; 0xffc00b31l;
0x68581511l; 0x64f98fa7l; 0xbefa4fa4l;
|];
}
let unsafe_get ctx =
let res = unsafe_get ctx in
By.sub res 0 28
let dup = dup
let unsafe_feed_bytes = unsafe_feed_bytes
let unsafe_feed_bigstring = unsafe_feed_bigstring
end

View file

@ -0,0 +1,173 @@
module By = Digestif_by
module Bi = Digestif_bi
module Int32 = struct
include Int32
let ( lsl ) = Int32.shift_left
let ( lsr ) = Int32.shift_right_logical
let ( asr ) = Int32.shift_right
let ( lor ) = Int32.logor
let ( lxor ) = Int32.logxor
let ( land ) = Int32.logand
let ( + ) = Int32.add
let rol32 a n = (a lsl n) lor (a lsr (32 - n))
let ror32 a n = (a lsr n) lor (a lsl (32 - n))
end
module Int64 = struct
include Int64
let ( land ) = Int64.logand
let ( lsl ) = Int64.shift_left
end
module type S = sig
type kind = [ `SHA256 ]
type ctx = { mutable size : int64; b : Bytes.t; h : int32 array }
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA256 ]
type ctx = { mutable size : int64; b : Bytes.t; h : int32 array }
let dup ctx = { size = ctx.size; b = By.copy ctx.b; h = Array.copy ctx.h }
let init () =
let b = By.make 128 '\x00' in
{
size = 0L;
b;
h =
[|
0x6a09e667l; 0xbb67ae85l; 0x3c6ef372l; 0xa54ff53al; 0x510e527fl;
0x9b05688cl; 0x1f83d9abl; 0x5be0cd19l;
|];
}
let k =
[|
0x428a2f98l; 0x71374491l; 0xb5c0fbcfl; 0xe9b5dba5l; 0x3956c25bl;
0x59f111f1l; 0x923f82a4l; 0xab1c5ed5l; 0xd807aa98l; 0x12835b01l;
0x243185bel; 0x550c7dc3l; 0x72be5d74l; 0x80deb1fel; 0x9bdc06a7l;
0xc19bf174l; 0xe49b69c1l; 0xefbe4786l; 0x0fc19dc6l; 0x240ca1ccl;
0x2de92c6fl; 0x4a7484aal; 0x5cb0a9dcl; 0x76f988dal; 0x983e5152l;
0xa831c66dl; 0xb00327c8l; 0xbf597fc7l; 0xc6e00bf3l; 0xd5a79147l;
0x06ca6351l; 0x14292967l; 0x27b70a85l; 0x2e1b2138l; 0x4d2c6dfcl;
0x53380d13l; 0x650a7354l; 0x766a0abbl; 0x81c2c92el; 0x92722c85l;
0xa2bfe8a1l; 0xa81a664bl; 0xc24b8b70l; 0xc76c51a3l; 0xd192e819l;
0xd6990624l; 0xf40e3585l; 0x106aa070l; 0x19a4c116l; 0x1e376c08l;
0x2748774cl; 0x34b0bcb5l; 0x391c0cb3l; 0x4ed8aa4al; 0x5b9cca4fl;
0x682e6ff3l; 0x748f82eel; 0x78a5636fl; 0x84c87814l; 0x8cc70208l;
0x90befffal; 0xa4506cebl; 0xbef9a3f7l; 0xc67178f2l;
|]
let e0 x = Int32.(ror32 x 2 lxor ror32 x 13 lxor ror32 x 22)
let e1 x = Int32.(ror32 x 6 lxor ror32 x 11 lxor ror32 x 25)
let s0 x = Int32.(ror32 x 7 lxor ror32 x 18 lxor (x lsr 3))
let s1 x = Int32.(ror32 x 17 lxor ror32 x 19 lxor (x lsr 10))
let sha256_do_chunk :
type a. be32_to_cpu:(a -> int -> int32) -> ctx -> a -> int -> unit =
fun ~be32_to_cpu ctx buf off ->
let a, b, c, d, e, f, g, h, t1, t2 =
( ref ctx.h.(0),
ref ctx.h.(1),
ref ctx.h.(2),
ref ctx.h.(3),
ref ctx.h.(4),
ref ctx.h.(5),
ref ctx.h.(6),
ref ctx.h.(7),
ref 0l,
ref 0l ) in
let w = Array.make 64 0l in
for i = 0 to 15 do
w.(i) <- be32_to_cpu buf (off + (i * 4))
done ;
let ( -- ) a b = a - b in
for i = 16 to 63 do
w.(i) <- Int32.(s1 w.(i -- 2) + w.(i -- 7) + s0 w.(i -- 15) + w.(i -- 16))
done ;
let round a b c d e f g h k w =
let open Int32 in
t1 := !h + e1 !e + (!g lxor (!e land (!f lxor !g))) + k + w ;
t2 := e0 !a + (!a land !b lor (!c land (!a lor !b))) ;
d := !d + !t1 ;
h := !t1 + !t2 in
for i = 0 to 7 do
round a b c d e f g h k.((i * 8) + 0) w.((i * 8) + 0) ;
round h a b c d e f g k.((i * 8) + 1) w.((i * 8) + 1) ;
round g h a b c d e f k.((i * 8) + 2) w.((i * 8) + 2) ;
round f g h a b c d e k.((i * 8) + 3) w.((i * 8) + 3) ;
round e f g h a b c d k.((i * 8) + 4) w.((i * 8) + 4) ;
round d e f g h a b c k.((i * 8) + 5) w.((i * 8) + 5) ;
round c d e f g h a b k.((i * 8) + 6) w.((i * 8) + 6) ;
round b c d e f g h a k.((i * 8) + 7) w.((i * 8) + 7)
done ;
let open Int32 in
ctx.h.(0) <- ctx.h.(0) + !a ;
ctx.h.(1) <- ctx.h.(1) + !b ;
ctx.h.(2) <- ctx.h.(2) + !c ;
ctx.h.(3) <- ctx.h.(3) + !d ;
ctx.h.(4) <- ctx.h.(4) + !e ;
ctx.h.(5) <- ctx.h.(5) + !f ;
ctx.h.(6) <- ctx.h.(6) + !g ;
ctx.h.(7) <- ctx.h.(7) + !h ;
()
let feed :
type a.
blit:(a -> int -> By.t -> int -> int -> unit) ->
be32_to_cpu:(a -> int -> int32) ->
ctx ->
a ->
int ->
int ->
unit =
fun ~blit ~be32_to_cpu ctx buf off len ->
let idx = ref Int64.(to_int (ctx.size land 0x3FL)) in
let len = ref len in
let off = ref off in
let to_fill = 64 - !idx in
ctx.size <- Int64.add ctx.size (Int64.of_int !len) ;
if !idx <> 0 && !len >= to_fill
then (
blit buf !off ctx.b !idx to_fill ;
sha256_do_chunk ~be32_to_cpu:By.be32_to_cpu ctx ctx.b 0 ;
len := !len - to_fill ;
off := !off + to_fill ;
idx := 0) ;
while !len >= 64 do
sha256_do_chunk ~be32_to_cpu ctx buf !off ;
len := !len - 64 ;
off := !off + 64
done ;
if !len <> 0 then blit buf !off ctx.b !idx !len ;
()
let unsafe_feed_bytes = feed ~blit:By.blit ~be32_to_cpu:By.be32_to_cpu
let unsafe_feed_bigstring =
feed ~blit:By.blit_from_bigstring ~be32_to_cpu:Bi.be32_to_cpu
let unsafe_get ctx =
let index = Int64.(to_int (ctx.size land 0x3FL)) in
let padlen = if index < 56 then 56 - index else 64 + 56 - index in
let padding = By.init padlen (function 0 -> '\x80' | _ -> '\x00') in
let bits = By.create 8 in
By.cpu_to_be64 bits 0 Int64.(ctx.size lsl 3) ;
unsafe_feed_bytes ctx padding 0 padlen ;
unsafe_feed_bytes ctx bits 0 8 ;
let res = By.create (8 * 4) in
for i = 0 to 7 do
By.cpu_to_be32 res (i * 4) ctx.h.(i)
done ;
res
end

View file

@ -0,0 +1,187 @@
module By = Digestif_by
module Bi = Digestif_bi
let nist_padding = 0x06L
let keccak_padding = 0x01L
module Int64 = struct
include Int64
let ( lsl ) = Int64.shift_left
let ( lsr ) = Int64.shift_right_logical
let ( asr ) = Int64.shift_right
let ( lor ) = Int64.logor
let ( land ) = Int64.logand
let ( lxor ) = Int64.logxor
let ( + ) = Int64.add
let ror64 a n = (a lsr n) lor (a lsl (64 - n))
let rol64 a n = (a lsl n) lor (a lsr (64 - n))
end
module Unsafe (P : sig
val padding : int64
end) =
struct
type ctx = {
q : int64 array;
rsize : int;
(* block size *)
mdlen : int;
(* output size *)
mutable pt : int;
}
let dup ctx =
{ q = Array.copy ctx.q; rsize = ctx.rsize; mdlen = ctx.mdlen; pt = ctx.pt }
let init mdlen =
let rsize = 200 - (2 * mdlen) in
{ q = Array.make 25 0L; rsize; mdlen; pt = 0 }
let keccakf_rounds = 24
let keccaft_rndc : int64 array =
[|
0x0000000000000001L; 0x0000000000008082L; 0x800000000000808aL;
0x8000000080008000L; 0x000000000000808bL; 0x0000000080000001L;
0x8000000080008081L; 0x8000000000008009L; 0x000000000000008aL;
0x0000000000000088L; 0x0000000080008009L; 0x000000008000000aL;
0x000000008000808bL; 0x800000000000008bL; 0x8000000000008089L;
0x8000000000008003L; 0x8000000000008002L; 0x8000000000000080L;
0x000000000000800aL; 0x800000008000000aL; 0x8000000080008081L;
0x8000000000008080L; 0x0000000080000001L; 0x8000000080008008L;
|]
let keccaft_rotc : int array =
[|
1; 3; 6; 10; 15; 21; 28; 36; 45; 55; 2; 14; 27; 41; 56; 8; 25; 43; 62; 18;
39; 61; 20; 44;
|]
let keccakf_piln : int array =
[|
10; 7; 11; 17; 18; 3; 5; 16; 8; 21; 24; 4; 15; 23; 19; 13; 12; 2; 20; 14;
22; 9; 6; 1;
|]
let sha3_keccakf (q : int64 array) =
for r = 0 to keccakf_rounds - 1 do
let ( lxor ) = Int64.( lxor ) in
let lnot = Int64.lognot in
let ( land ) = Int64.( land ) in
(* Theta *)
let bc =
Array.init 5 (fun i ->
q.(i) lxor q.(i + 5) lxor q.(i + 10) lxor q.(i + 15) lxor q.(i + 20))
in
for i = 0 to 4 do
let t = bc.((i + 4) mod 5) lxor Int64.rol64 bc.((i + 1) mod 5) 1 in
for k = 0 to 4 do
let j = k * 5 in
q.(j + i) <- q.(j + i) lxor t
done
done ;
(* Rho Pi *)
let t = ref q.(1) in
let _ =
Array.iteri
(fun i rotc ->
let j = keccakf_piln.(i) in
bc.(0) <- q.(j) ;
q.(j) <- Int64.rol64 !t rotc ;
t := bc.(0))
keccaft_rotc in
(* Chi *)
for k = 0 to 4 do
let j = k * 5 in
let bc = Array.init 5 (fun i -> q.(j + i)) in
for i = 0 to 4 do
q.(j + i) <-
q.(j + i) lxor (lnot bc.((i + 1) mod 5) land bc.((i + 2) mod 5))
done
done ;
(* Iota *)
q.(0) <- q.(0) lxor keccaft_rndc.(r)
done
let masks =
[|
0xffffffffffffff00L; 0xffffffffffff00ffL; 0xffffffffff00ffffL;
0xffffffff00ffffffL; 0xffffff00ffffffffL; 0xffff00ffffffffffL;
0xff00ffffffffffffL; 0x00ffffffffffffffL;
|]
let feed :
type a. get_uint8:(a -> int -> int) -> ctx -> a -> int -> int -> unit =
fun ~get_uint8 ctx buf off len ->
let ( && ) = ( land ) in
let ( lxor ) = Int64.( lxor ) in
let ( land ) = Int64.( land ) in
let ( lor ) = Int64.( lor ) in
let ( lsr ) = Int64.( lsr ) in
let ( lsl ) = Int64.( lsl ) in
let j = ref ctx.pt in
for i = 0 to len - 1 do
let v =
(ctx.q.(!j / 8) land (0xffL lsl ((!j && 0x7) * 8))) lsr ((!j && 0x7) * 8)
in
let v = v lxor Int64.of_int (get_uint8 buf (off + i)) in
ctx.q.(!j / 8) <-
ctx.q.(!j / 8) land masks.(!j && 0x7) lor (v lsl ((!j && 0x7) * 8)) ;
incr j ;
if !j >= ctx.rsize
then (
sha3_keccakf ctx.q ;
j := 0)
done ;
ctx.pt <- !j
let unsafe_feed_bytes ctx buf off len =
let get_uint8 buf off = Char.code (By.get buf off) in
feed ~get_uint8 ctx buf off len
let unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit =
fun ctx buf off len ->
let get_uint8 buf off = Char.code (Bi.get buf off) in
feed ~get_uint8 ctx buf off len
let unsafe_get ctx =
let ( && ) = ( land ) in
let ( lxor ) = Int64.( lxor ) in
let ( lsl ) = Int64.( lsl ) in
let v = ctx.q.(ctx.pt / 8) in
let v = v lxor (P.padding lsl ((ctx.pt && 0x7) * 8)) in
ctx.q.(ctx.pt / 8) <- v ;
let v = ctx.q.((ctx.rsize - 1) / 8) in
let v = v lxor (0x80L lsl (((ctx.rsize - 1) && 0x7) * 8)) in
ctx.q.((ctx.rsize - 1) / 8) <- v ;
sha3_keccakf ctx.q ;
(* Get hash *)
(* if the hash size in bytes is not a multiple of 8 (meaning it is
not composed of whole int64 words, like for sha3_224), we
extract the whole last int64 word from the state [ctx.st] and
cut the hash at the right size after conversion to bytes. *)
let n =
let r = ctx.mdlen mod 8 in
ctx.mdlen + if r = 0 then 0 else 8 - r in
let hash = By.create n in
for i = 0 to (n / 8) - 1 do
By.unsafe_set_64 hash (i * 8)
(if Sys.big_endian then By.swap64 ctx.q.(i) else ctx.q.(i))
done ;
By.sub hash 0 ctx.mdlen
end

View file

@ -0,0 +1,42 @@
module By = Digestif_by
module Bi = Digestif_bi
module type S = sig
type ctx
type kind = [ `SHA384 ]
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA384 ]
open Baijiu_sha512.Unsafe
type nonrec ctx = ctx
let init () =
let b = By.make 128 '\x00' in
{
size = [| 0L; 0L |];
b;
h =
[|
0xcbbb9d5dc1059ed8L; 0x629a292a367cd507L; 0x9159015a3070dd17L;
0x152fecd8f70e5939L; 0x67332667ffc00b31L; 0x8eb44a8768581511L;
0xdb0c2e0d64f98fa7L; 0x47b5481dbefa4fa4L;
|];
}
let unsafe_get ctx =
let res = unsafe_get ctx in
By.sub res 0 48
let dup = dup
let unsafe_feed_bytes = unsafe_feed_bytes
let unsafe_feed_bigstring = unsafe_feed_bigstring
end

View file

@ -0,0 +1,31 @@
module By = Digestif_by
module Bi = Digestif_bi
module type S = sig
type ctx
type kind = [ `SHA3_224 ]
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA3_224 ]
module U = Baijiu_sha3.Unsafe (struct
let padding = Baijiu_sha3.nist_padding
end)
open U
type nonrec ctx = ctx
let init () = U.init 28
let unsafe_get = unsafe_get
let dup = dup
let unsafe_feed_bytes = unsafe_feed_bytes
let unsafe_feed_bigstring = unsafe_feed_bigstring
end

View file

@ -0,0 +1,31 @@
module By = Digestif_by
module Bi = Digestif_bi
module type S = sig
type ctx
type kind = [ `SHA3_256 ]
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA3_256 ]
module U = Baijiu_sha3.Unsafe (struct
let padding = Baijiu_sha3.nist_padding
end)
open U
type nonrec ctx = ctx
let init () = U.init 32
let unsafe_get = unsafe_get
let dup = dup
let unsafe_feed_bytes = unsafe_feed_bytes
let unsafe_feed_bigstring = unsafe_feed_bigstring
end

View file

@ -0,0 +1,31 @@
module By = Digestif_by
module Bi = Digestif_bi
module type S = sig
type ctx
type kind = [ `SHA3_384 ]
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA3_384 ]
module U = Baijiu_sha3.Unsafe (struct
let padding = Baijiu_sha3.nist_padding
end)
open U
type nonrec ctx = ctx
let init () = U.init 48
let unsafe_get = unsafe_get
let dup = dup
let unsafe_feed_bytes = unsafe_feed_bytes
let unsafe_feed_bigstring = unsafe_feed_bigstring
end

View file

@ -0,0 +1,31 @@
module By = Digestif_by
module Bi = Digestif_bi
module type S = sig
type ctx
type kind = [ `SHA3_512 ]
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA3_512 ]
module U = Baijiu_sha3.Unsafe (struct
let padding = Baijiu_sha3.nist_padding
end)
open U
type nonrec ctx = ctx
let init () = U.init 64
let unsafe_get = unsafe_get
let dup = dup
let unsafe_feed_bytes = unsafe_feed_bytes
let unsafe_feed_bigstring = unsafe_feed_bigstring
end

View file

@ -0,0 +1,185 @@
module By = Digestif_by
module Bi = Digestif_bi
module Int64 = struct
include Int64
let ( lsl ) = Int64.shift_left
let ( lsr ) = Int64.shift_right_logical
let ( asr ) = Int64.shift_right
let ( lor ) = Int64.logor
let ( land ) = Int64.logand
let ( lxor ) = Int64.logxor
let ( + ) = Int64.add
let ror64 a n = (a lsr n) lor (a lsl (64 - n))
let rol64 a n = (a lsl n) lor (a lsr (64 - n))
end
module type S = sig
type kind = [ `SHA512 ]
type ctx = { mutable size : int64 array; b : Bytes.t; h : int64 array }
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `SHA512 ]
type ctx = { mutable size : int64 array; b : Bytes.t; h : int64 array }
let dup ctx =
{ size = Array.copy ctx.size; b = By.copy ctx.b; h = Array.copy ctx.h }
let init () =
let b = By.make 128 '\x00' in
{
size = [| 0L; 0L |];
b;
h =
[|
0x6a09e667f3bcc908L; 0xbb67ae8584caa73bL; 0x3c6ef372fe94f82bL;
0xa54ff53a5f1d36f1L; 0x510e527fade682d1L; 0x9b05688c2b3e6c1fL;
0x1f83d9abfb41bd6bL; 0x5be0cd19137e2179L;
|];
}
let k =
[|
0x428a2f98d728ae22L; 0x7137449123ef65cdL; 0xb5c0fbcfec4d3b2fL;
0xe9b5dba58189dbbcL; 0x3956c25bf348b538L; 0x59f111f1b605d019L;
0x923f82a4af194f9bL; 0xab1c5ed5da6d8118L; 0xd807aa98a3030242L;
0x12835b0145706fbeL; 0x243185be4ee4b28cL; 0x550c7dc3d5ffb4e2L;
0x72be5d74f27b896fL; 0x80deb1fe3b1696b1L; 0x9bdc06a725c71235L;
0xc19bf174cf692694L; 0xe49b69c19ef14ad2L; 0xefbe4786384f25e3L;
0x0fc19dc68b8cd5b5L; 0x240ca1cc77ac9c65L; 0x2de92c6f592b0275L;
0x4a7484aa6ea6e483L; 0x5cb0a9dcbd41fbd4L; 0x76f988da831153b5L;
0x983e5152ee66dfabL; 0xa831c66d2db43210L; 0xb00327c898fb213fL;
0xbf597fc7beef0ee4L; 0xc6e00bf33da88fc2L; 0xd5a79147930aa725L;
0x06ca6351e003826fL; 0x142929670a0e6e70L; 0x27b70a8546d22ffcL;
0x2e1b21385c26c926L; 0x4d2c6dfc5ac42aedL; 0x53380d139d95b3dfL;
0x650a73548baf63deL; 0x766a0abb3c77b2a8L; 0x81c2c92e47edaee6L;
0x92722c851482353bL; 0xa2bfe8a14cf10364L; 0xa81a664bbc423001L;
0xc24b8b70d0f89791L; 0xc76c51a30654be30L; 0xd192e819d6ef5218L;
0xd69906245565a910L; 0xf40e35855771202aL; 0x106aa07032bbd1b8L;
0x19a4c116b8d2d0c8L; 0x1e376c085141ab53L; 0x2748774cdf8eeb99L;
0x34b0bcb5e19b48a8L; 0x391c0cb3c5c95a63L; 0x4ed8aa4ae3418acbL;
0x5b9cca4f7763e373L; 0x682e6ff3d6b2b8a3L; 0x748f82ee5defb2fcL;
0x78a5636f43172f60L; 0x84c87814a1f0ab72L; 0x8cc702081a6439ecL;
0x90befffa23631e28L; 0xa4506cebde82bde9L; 0xbef9a3f7b2c67915L;
0xc67178f2e372532bL; 0xca273eceea26619cL; 0xd186b8c721c0c207L;
0xeada7dd6cde0eb1eL; 0xf57d4f7fee6ed178L; 0x06f067aa72176fbaL;
0x0a637dc5a2c898a6L; 0x113f9804bef90daeL; 0x1b710b35131c471bL;
0x28db77f523047d84L; 0x32caab7b40c72493L; 0x3c9ebe0a15c9bebcL;
0x431d67c49c100d4cL; 0x4cc5d4becb3e42b6L; 0x597f299cfc657e2aL;
0x5fcb6fab3ad6faecL; 0x6c44198c4a475817L;
|]
let e0 x = Int64.(ror64 x 28 lxor ror64 x 34 lxor ror64 x 39)
let e1 x = Int64.(ror64 x 14 lxor ror64 x 18 lxor ror64 x 41)
let s0 x = Int64.(ror64 x 1 lxor ror64 x 8 lxor (x lsr 7))
let s1 x = Int64.(ror64 x 19 lxor ror64 x 61 lxor (x lsr 6))
let sha512_do_chunk :
type a. be64_to_cpu:(a -> int -> int64) -> ctx -> a -> int -> unit =
fun ~be64_to_cpu ctx buf off ->
let a, b, c, d, e, f, g, h, t1, t2 =
( ref ctx.h.(0),
ref ctx.h.(1),
ref ctx.h.(2),
ref ctx.h.(3),
ref ctx.h.(4),
ref ctx.h.(5),
ref ctx.h.(6),
ref ctx.h.(7),
ref 0L,
ref 0L ) in
let w = Array.make 80 0L in
for i = 0 to 15 do
w.(i) <- be64_to_cpu buf (off + (i * 8))
done ;
let ( -- ) a b = a - b in
for i = 16 to 79 do
w.(i) <- Int64.(s1 w.(i -- 2) + w.(i -- 7) + s0 w.(i -- 15) + w.(i -- 16))
done ;
let round a b c d e f g h k w =
let open Int64 in
t1 := !h + e1 !e + (!g lxor (!e land (!f lxor !g))) + k + w ;
t2 := e0 !a + (!a land !b lor (!c land (!a lor !b))) ;
d := !d + !t1 ;
h := !t1 + !t2 in
for i = 0 to 9 do
round a b c d e f g h k.((i * 8) + 0) w.((i * 8) + 0) ;
round h a b c d e f g k.((i * 8) + 1) w.((i * 8) + 1) ;
round g h a b c d e f k.((i * 8) + 2) w.((i * 8) + 2) ;
round f g h a b c d e k.((i * 8) + 3) w.((i * 8) + 3) ;
round e f g h a b c d k.((i * 8) + 4) w.((i * 8) + 4) ;
round d e f g h a b c k.((i * 8) + 5) w.((i * 8) + 5) ;
round c d e f g h a b k.((i * 8) + 6) w.((i * 8) + 6) ;
round b c d e f g h a k.((i * 8) + 7) w.((i * 8) + 7)
done ;
let open Int64 in
ctx.h.(0) <- ctx.h.(0) + !a ;
ctx.h.(1) <- ctx.h.(1) + !b ;
ctx.h.(2) <- ctx.h.(2) + !c ;
ctx.h.(3) <- ctx.h.(3) + !d ;
ctx.h.(4) <- ctx.h.(4) + !e ;
ctx.h.(5) <- ctx.h.(5) + !f ;
ctx.h.(6) <- ctx.h.(6) + !g ;
ctx.h.(7) <- ctx.h.(7) + !h ;
()
let feed :
type a.
blit:(a -> int -> By.t -> int -> int -> unit) ->
be64_to_cpu:(a -> int -> int64) ->
ctx ->
a ->
int ->
int ->
unit =
fun ~blit ~be64_to_cpu ctx buf off len ->
let idx = ref Int64.(to_int (ctx.size.(0) land 0x7FL)) in
let len = ref len in
let off = ref off in
let to_fill = 128 - !idx in
ctx.size.(0) <- Int64.add ctx.size.(0) (Int64.of_int !len) ;
if ctx.size.(0) < Int64.of_int !len
then ctx.size.(1) <- Int64.succ ctx.size.(1) ;
if !idx <> 0 && !len >= to_fill
then (
blit buf !off ctx.b !idx to_fill ;
sha512_do_chunk ~be64_to_cpu:By.be64_to_cpu ctx ctx.b 0 ;
len := !len - to_fill ;
off := !off + to_fill ;
idx := 0) ;
while !len >= 128 do
sha512_do_chunk ~be64_to_cpu ctx buf !off ;
len := !len - 128 ;
off := !off + 128
done ;
if !len <> 0 then blit buf !off ctx.b !idx !len ;
()
let unsafe_feed_bytes = feed ~blit:By.blit ~be64_to_cpu:By.be64_to_cpu
let unsafe_feed_bigstring =
feed ~blit:By.blit_from_bigstring ~be64_to_cpu:Bi.be64_to_cpu
let unsafe_get ctx =
let index = Int64.(to_int (ctx.size.(0) land 0x7FL)) in
let padlen = if index < 112 then 112 - index else 128 + 112 - index in
let padding = By.init padlen (function 0 -> '\x80' | _ -> '\x00') in
let bits = By.create 16 in
By.cpu_to_be64 bits 0 Int64.((ctx.size.(1) lsl 3) lor (ctx.size.(0) lsr 61)) ;
By.cpu_to_be64 bits 8 Int64.(ctx.size.(0) lsl 3) ;
unsafe_feed_bytes ctx padding 0 padlen ;
unsafe_feed_bytes ctx bits 0 16 ;
let res = By.create (8 * 8) in
for i = 0 to 7 do
By.cpu_to_be64 res (i * 8) ctx.h.(i)
done ;
res
end

View file

@ -0,0 +1,844 @@
module By = Digestif_by
module Bi = Digestif_bi
module Int64 = struct
include Int64
let ( lsl ) = Int64.shift_left
let ( lsr ) = Int64.shift_right_logical
let ( asr ) = Int64.shift_right
let ( lor ) = Int64.logor
let ( land ) = Int64.logand
let ( lxor ) = Int64.logxor
let ( + ) = Int64.add
let ror64 a n = (a lsr n) lor (a lsl (64 - n))
let rol64 a n = (a lsl n) lor (a lsr (64 - n))
end
module type S = sig
type kind = [ `WHIRLPOOL ]
type ctx = { mutable size : int64; b : Bytes.t; h : int64 array }
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe : S = struct
type kind = [ `WHIRLPOOL ]
type ctx = { mutable size : int64; b : Bytes.t; h : int64 array }
let dup ctx = { size = ctx.size; b = By.copy ctx.b; h = Array.copy ctx.h }
let init () =
let b = By.make 64 '\x00' in
{ size = 0L; b; h = Array.make 8 Int64.zero }
let k =
[|
[|
0x18186018c07830d8L; 0x23238c2305af4626L; 0xc6c63fc67ef991b8L;
0xe8e887e8136fcdfbL; 0x878726874ca113cbL; 0xb8b8dab8a9626d11L;
0x0101040108050209L; 0x4f4f214f426e9e0dL; 0x3636d836adee6c9bL;
0xa6a6a2a6590451ffL; 0xd2d26fd2debdb90cL; 0xf5f5f3f5fb06f70eL;
0x7979f979ef80f296L; 0x6f6fa16f5fcede30L; 0x91917e91fcef3f6dL;
0x52525552aa07a4f8L; 0x60609d6027fdc047L; 0xbcbccabc89766535L;
0x9b9b569baccd2b37L; 0x8e8e028e048c018aL; 0xa3a3b6a371155bd2L;
0x0c0c300c603c186cL; 0x7b7bf17bff8af684L; 0x3535d435b5e16a80L;
0x1d1d741de8693af5L; 0xe0e0a7e05347ddb3L; 0xd7d77bd7f6acb321L;
0xc2c22fc25eed999cL; 0x2e2eb82e6d965c43L; 0x4b4b314b627a9629L;
0xfefedffea321e15dL; 0x575741578216aed5L; 0x15155415a8412abdL;
0x7777c1779fb6eee8L; 0x3737dc37a5eb6e92L; 0xe5e5b3e57b56d79eL;
0x9f9f469f8cd92313L; 0xf0f0e7f0d317fd23L; 0x4a4a354a6a7f9420L;
0xdada4fda9e95a944L; 0x58587d58fa25b0a2L; 0xc9c903c906ca8fcfL;
0x2929a429558d527cL; 0x0a0a280a5022145aL; 0xb1b1feb1e14f7f50L;
0xa0a0baa0691a5dc9L; 0x6b6bb16b7fdad614L; 0x85852e855cab17d9L;
0xbdbdcebd8173673cL; 0x5d5d695dd234ba8fL; 0x1010401080502090L;
0xf4f4f7f4f303f507L; 0xcbcb0bcb16c08bddL; 0x3e3ef83eedc67cd3L;
0x0505140528110a2dL; 0x676781671fe6ce78L; 0xe4e4b7e47353d597L;
0x27279c2725bb4e02L; 0x4141194132588273L; 0x8b8b168b2c9d0ba7L;
0xa7a7a6a7510153f6L; 0x7d7de97dcf94fab2L; 0x95956e95dcfb3749L;
0xd8d847d88e9fad56L; 0xfbfbcbfb8b30eb70L; 0xeeee9fee2371c1cdL;
0x7c7ced7cc791f8bbL; 0x6666856617e3cc71L; 0xdddd53dda68ea77bL;
0x17175c17b84b2eafL; 0x4747014702468e45L; 0x9e9e429e84dc211aL;
0xcaca0fca1ec589d4L; 0x2d2db42d75995a58L; 0xbfbfc6bf9179632eL;
0x07071c07381b0e3fL; 0xadad8ead012347acL; 0x5a5a755aea2fb4b0L;
0x838336836cb51befL; 0x3333cc3385ff66b6L; 0x636391633ff2c65cL;
0x02020802100a0412L; 0xaaaa92aa39384993L; 0x7171d971afa8e2deL;
0xc8c807c80ecf8dc6L; 0x19196419c87d32d1L; 0x494939497270923bL;
0xd9d943d9869aaf5fL; 0xf2f2eff2c31df931L; 0xe3e3abe34b48dba8L;
0x5b5b715be22ab6b9L; 0x88881a8834920dbcL; 0x9a9a529aa4c8293eL;
0x262698262dbe4c0bL; 0x3232c8328dfa64bfL; 0xb0b0fab0e94a7d59L;
0xe9e983e91b6acff2L; 0x0f0f3c0f78331e77L; 0xd5d573d5e6a6b733L;
0x80803a8074ba1df4L; 0xbebec2be997c6127L; 0xcdcd13cd26de87ebL;
0x3434d034bde46889L; 0x48483d487a759032L; 0xffffdbffab24e354L;
0x7a7af57af78ff48dL; 0x90907a90f4ea3d64L; 0x5f5f615fc23ebe9dL;
0x202080201da0403dL; 0x6868bd6867d5d00fL; 0x1a1a681ad07234caL;
0xaeae82ae192c41b7L; 0xb4b4eab4c95e757dL; 0x54544d549a19a8ceL;
0x93937693ece53b7fL; 0x222288220daa442fL; 0x64648d6407e9c863L;
0xf1f1e3f1db12ff2aL; 0x7373d173bfa2e6ccL; 0x12124812905a2482L;
0x40401d403a5d807aL; 0x0808200840281048L; 0xc3c32bc356e89b95L;
0xecec97ec337bc5dfL; 0xdbdb4bdb9690ab4dL; 0xa1a1bea1611f5fc0L;
0x8d8d0e8d1c830791L; 0x3d3df43df5c97ac8L; 0x97976697ccf1335bL;
0x0000000000000000L; 0xcfcf1bcf36d483f9L; 0x2b2bac2b4587566eL;
0x7676c57697b3ece1L; 0x8282328264b019e6L; 0xd6d67fd6fea9b128L;
0x1b1b6c1bd87736c3L; 0xb5b5eeb5c15b7774L; 0xafaf86af112943beL;
0x6a6ab56a77dfd41dL; 0x50505d50ba0da0eaL; 0x45450945124c8a57L;
0xf3f3ebf3cb18fb38L; 0x3030c0309df060adL; 0xefef9bef2b74c3c4L;
0x3f3ffc3fe5c37edaL; 0x55554955921caac7L; 0xa2a2b2a2791059dbL;
0xeaea8fea0365c9e9L; 0x656589650fecca6aL; 0xbabad2bab9686903L;
0x2f2fbc2f65935e4aL; 0xc0c027c04ee79d8eL; 0xdede5fdebe81a160L;
0x1c1c701ce06c38fcL; 0xfdfdd3fdbb2ee746L; 0x4d4d294d52649a1fL;
0x92927292e4e03976L; 0x7575c9758fbceafaL; 0x06061806301e0c36L;
0x8a8a128a249809aeL; 0xb2b2f2b2f940794bL; 0xe6e6bfe66359d185L;
0x0e0e380e70361c7eL; 0x1f1f7c1ff8633ee7L; 0x6262956237f7c455L;
0xd4d477d4eea3b53aL; 0xa8a89aa829324d81L; 0x96966296c4f43152L;
0xf9f9c3f99b3aef62L; 0xc5c533c566f697a3L; 0x2525942535b14a10L;
0x59597959f220b2abL; 0x84842a8454ae15d0L; 0x7272d572b7a7e4c5L;
0x3939e439d5dd72ecL; 0x4c4c2d4c5a619816L; 0x5e5e655eca3bbc94L;
0x7878fd78e785f09fL; 0x3838e038ddd870e5L; 0x8c8c0a8c14860598L;
0xd1d163d1c6b2bf17L; 0xa5a5aea5410b57e4L; 0xe2e2afe2434dd9a1L;
0x616199612ff8c24eL; 0xb3b3f6b3f1457b42L; 0x2121842115a54234L;
0x9c9c4a9c94d62508L; 0x1e1e781ef0663ceeL; 0x4343114322528661L;
0xc7c73bc776fc93b1L; 0xfcfcd7fcb32be54fL; 0x0404100420140824L;
0x51515951b208a2e3L; 0x99995e99bcc72f25L; 0x6d6da96d4fc4da22L;
0x0d0d340d68391a65L; 0xfafacffa8335e979L; 0xdfdf5bdfb684a369L;
0x7e7ee57ed79bfca9L; 0x242490243db44819L; 0x3b3bec3bc5d776feL;
0xabab96ab313d4b9aL; 0xcece1fce3ed181f0L; 0x1111441188552299L;
0x8f8f068f0c890383L; 0x4e4e254e4a6b9c04L; 0xb7b7e6b7d1517366L;
0xebeb8beb0b60cbe0L; 0x3c3cf03cfdcc78c1L; 0x81813e817cbf1ffdL;
0x94946a94d4fe3540L; 0xf7f7fbf7eb0cf31cL; 0xb9b9deb9a1676f18L;
0x13134c13985f268bL; 0x2c2cb02c7d9c5851L; 0xd3d36bd3d6b8bb05L;
0xe7e7bbe76b5cd38cL; 0x6e6ea56e57cbdc39L; 0xc4c437c46ef395aaL;
0x03030c03180f061bL; 0x565645568a13acdcL; 0x44440d441a49885eL;
0x7f7fe17fdf9efea0L; 0xa9a99ea921374f88L; 0x2a2aa82a4d825467L;
0xbbbbd6bbb16d6b0aL; 0xc1c123c146e29f87L; 0x53535153a202a6f1L;
0xdcdc57dcae8ba572L; 0x0b0b2c0b58271653L; 0x9d9d4e9d9cd32701L;
0x6c6cad6c47c1d82bL; 0x3131c43195f562a4L; 0x7474cd7487b9e8f3L;
0xf6f6fff6e309f115L; 0x464605460a438c4cL; 0xacac8aac092645a5L;
0x89891e893c970fb5L; 0x14145014a04428b4L; 0xe1e1a3e15b42dfbaL;
0x16165816b04e2ca6L; 0x3a3ae83acdd274f7L; 0x6969b9696fd0d206L;
0x09092409482d1241L; 0x7070dd70a7ade0d7L; 0xb6b6e2b6d954716fL;
0xd0d067d0ceb7bd1eL; 0xeded93ed3b7ec7d6L; 0xcccc17cc2edb85e2L;
0x424215422a578468L; 0x98985a98b4c22d2cL; 0xa4a4aaa4490e55edL;
0x2828a0285d885075L; 0x5c5c6d5cda31b886L; 0xf8f8c7f8933fed6bL;
0x8686228644a411c2L;
|];
[|
0xd818186018c07830L; 0x2623238c2305af46L; 0xb8c6c63fc67ef991L;
0xfbe8e887e8136fcdL; 0xcb878726874ca113L; 0x11b8b8dab8a9626dL;
0x0901010401080502L; 0x0d4f4f214f426e9eL; 0x9b3636d836adee6cL;
0xffa6a6a2a6590451L; 0x0cd2d26fd2debdb9L; 0x0ef5f5f3f5fb06f7L;
0x967979f979ef80f2L; 0x306f6fa16f5fcedeL; 0x6d91917e91fcef3fL;
0xf852525552aa07a4L; 0x4760609d6027fdc0L; 0x35bcbccabc897665L;
0x379b9b569baccd2bL; 0x8a8e8e028e048c01L; 0xd2a3a3b6a371155bL;
0x6c0c0c300c603c18L; 0x847b7bf17bff8af6L; 0x803535d435b5e16aL;
0xf51d1d741de8693aL; 0xb3e0e0a7e05347ddL; 0x21d7d77bd7f6acb3L;
0x9cc2c22fc25eed99L; 0x432e2eb82e6d965cL; 0x294b4b314b627a96L;
0x5dfefedffea321e1L; 0xd5575741578216aeL; 0xbd15155415a8412aL;
0xe87777c1779fb6eeL; 0x923737dc37a5eb6eL; 0x9ee5e5b3e57b56d7L;
0x139f9f469f8cd923L; 0x23f0f0e7f0d317fdL; 0x204a4a354a6a7f94L;
0x44dada4fda9e95a9L; 0xa258587d58fa25b0L; 0xcfc9c903c906ca8fL;
0x7c2929a429558d52L; 0x5a0a0a280a502214L; 0x50b1b1feb1e14f7fL;
0xc9a0a0baa0691a5dL; 0x146b6bb16b7fdad6L; 0xd985852e855cab17L;
0x3cbdbdcebd817367L; 0x8f5d5d695dd234baL; 0x9010104010805020L;
0x07f4f4f7f4f303f5L; 0xddcbcb0bcb16c08bL; 0xd33e3ef83eedc67cL;
0x2d0505140528110aL; 0x78676781671fe6ceL; 0x97e4e4b7e47353d5L;
0x0227279c2725bb4eL; 0x7341411941325882L; 0xa78b8b168b2c9d0bL;
0xf6a7a7a6a7510153L; 0xb27d7de97dcf94faL; 0x4995956e95dcfb37L;
0x56d8d847d88e9fadL; 0x70fbfbcbfb8b30ebL; 0xcdeeee9fee2371c1L;
0xbb7c7ced7cc791f8L; 0x716666856617e3ccL; 0x7bdddd53dda68ea7L;
0xaf17175c17b84b2eL; 0x454747014702468eL; 0x1a9e9e429e84dc21L;
0xd4caca0fca1ec589L; 0x582d2db42d75995aL; 0x2ebfbfc6bf917963L;
0x3f07071c07381b0eL; 0xacadad8ead012347L; 0xb05a5a755aea2fb4L;
0xef838336836cb51bL; 0xb63333cc3385ff66L; 0x5c636391633ff2c6L;
0x1202020802100a04L; 0x93aaaa92aa393849L; 0xde7171d971afa8e2L;
0xc6c8c807c80ecf8dL; 0xd119196419c87d32L; 0x3b49493949727092L;
0x5fd9d943d9869aafL; 0x31f2f2eff2c31df9L; 0xa8e3e3abe34b48dbL;
0xb95b5b715be22ab6L; 0xbc88881a8834920dL; 0x3e9a9a529aa4c829L;
0x0b262698262dbe4cL; 0xbf3232c8328dfa64L; 0x59b0b0fab0e94a7dL;
0xf2e9e983e91b6acfL; 0x770f0f3c0f78331eL; 0x33d5d573d5e6a6b7L;
0xf480803a8074ba1dL; 0x27bebec2be997c61L; 0xebcdcd13cd26de87L;
0x893434d034bde468L; 0x3248483d487a7590L; 0x54ffffdbffab24e3L;
0x8d7a7af57af78ff4L; 0x6490907a90f4ea3dL; 0x9d5f5f615fc23ebeL;
0x3d202080201da040L; 0x0f6868bd6867d5d0L; 0xca1a1a681ad07234L;
0xb7aeae82ae192c41L; 0x7db4b4eab4c95e75L; 0xce54544d549a19a8L;
0x7f93937693ece53bL; 0x2f222288220daa44L; 0x6364648d6407e9c8L;
0x2af1f1e3f1db12ffL; 0xcc7373d173bfa2e6L; 0x8212124812905a24L;
0x7a40401d403a5d80L; 0x4808082008402810L; 0x95c3c32bc356e89bL;
0xdfecec97ec337bc5L; 0x4ddbdb4bdb9690abL; 0xc0a1a1bea1611f5fL;
0x918d8d0e8d1c8307L; 0xc83d3df43df5c97aL; 0x5b97976697ccf133L;
0x0000000000000000L; 0xf9cfcf1bcf36d483L; 0x6e2b2bac2b458756L;
0xe17676c57697b3ecL; 0xe68282328264b019L; 0x28d6d67fd6fea9b1L;
0xc31b1b6c1bd87736L; 0x74b5b5eeb5c15b77L; 0xbeafaf86af112943L;
0x1d6a6ab56a77dfd4L; 0xea50505d50ba0da0L; 0x5745450945124c8aL;
0x38f3f3ebf3cb18fbL; 0xad3030c0309df060L; 0xc4efef9bef2b74c3L;
0xda3f3ffc3fe5c37eL; 0xc755554955921caaL; 0xdba2a2b2a2791059L;
0xe9eaea8fea0365c9L; 0x6a656589650feccaL; 0x03babad2bab96869L;
0x4a2f2fbc2f65935eL; 0x8ec0c027c04ee79dL; 0x60dede5fdebe81a1L;
0xfc1c1c701ce06c38L; 0x46fdfdd3fdbb2ee7L; 0x1f4d4d294d52649aL;
0x7692927292e4e039L; 0xfa7575c9758fbceaL; 0x3606061806301e0cL;
0xae8a8a128a249809L; 0x4bb2b2f2b2f94079L; 0x85e6e6bfe66359d1L;
0x7e0e0e380e70361cL; 0xe71f1f7c1ff8633eL; 0x556262956237f7c4L;
0x3ad4d477d4eea3b5L; 0x81a8a89aa829324dL; 0x5296966296c4f431L;
0x62f9f9c3f99b3aefL; 0xa3c5c533c566f697L; 0x102525942535b14aL;
0xab59597959f220b2L; 0xd084842a8454ae15L; 0xc57272d572b7a7e4L;
0xec3939e439d5dd72L; 0x164c4c2d4c5a6198L; 0x945e5e655eca3bbcL;
0x9f7878fd78e785f0L; 0xe53838e038ddd870L; 0x988c8c0a8c148605L;
0x17d1d163d1c6b2bfL; 0xe4a5a5aea5410b57L; 0xa1e2e2afe2434dd9L;
0x4e616199612ff8c2L; 0x42b3b3f6b3f1457bL; 0x342121842115a542L;
0x089c9c4a9c94d625L; 0xee1e1e781ef0663cL; 0x6143431143225286L;
0xb1c7c73bc776fc93L; 0x4ffcfcd7fcb32be5L; 0x2404041004201408L;
0xe351515951b208a2L; 0x2599995e99bcc72fL; 0x226d6da96d4fc4daL;
0x650d0d340d68391aL; 0x79fafacffa8335e9L; 0x69dfdf5bdfb684a3L;
0xa97e7ee57ed79bfcL; 0x19242490243db448L; 0xfe3b3bec3bc5d776L;
0x9aabab96ab313d4bL; 0xf0cece1fce3ed181L; 0x9911114411885522L;
0x838f8f068f0c8903L; 0x044e4e254e4a6b9cL; 0x66b7b7e6b7d15173L;
0xe0ebeb8beb0b60cbL; 0xc13c3cf03cfdcc78L; 0xfd81813e817cbf1fL;
0x4094946a94d4fe35L; 0x1cf7f7fbf7eb0cf3L; 0x18b9b9deb9a1676fL;
0x8b13134c13985f26L; 0x512c2cb02c7d9c58L; 0x05d3d36bd3d6b8bbL;
0x8ce7e7bbe76b5cd3L; 0x396e6ea56e57cbdcL; 0xaac4c437c46ef395L;
0x1b03030c03180f06L; 0xdc565645568a13acL; 0x5e44440d441a4988L;
0xa07f7fe17fdf9efeL; 0x88a9a99ea921374fL; 0x672a2aa82a4d8254L;
0x0abbbbd6bbb16d6bL; 0x87c1c123c146e29fL; 0xf153535153a202a6L;
0x72dcdc57dcae8ba5L; 0x530b0b2c0b582716L; 0x019d9d4e9d9cd327L;
0x2b6c6cad6c47c1d8L; 0xa43131c43195f562L; 0xf37474cd7487b9e8L;
0x15f6f6fff6e309f1L; 0x4c464605460a438cL; 0xa5acac8aac092645L;
0xb589891e893c970fL; 0xb414145014a04428L; 0xbae1e1a3e15b42dfL;
0xa616165816b04e2cL; 0xf73a3ae83acdd274L; 0x066969b9696fd0d2L;
0x4109092409482d12L; 0xd77070dd70a7ade0L; 0x6fb6b6e2b6d95471L;
0x1ed0d067d0ceb7bdL; 0xd6eded93ed3b7ec7L; 0xe2cccc17cc2edb85L;
0x68424215422a5784L; 0x2c98985a98b4c22dL; 0xeda4a4aaa4490e55L;
0x752828a0285d8850L; 0x865c5c6d5cda31b8L; 0x6bf8f8c7f8933fedL;
0xc28686228644a411L;
|];
[|
0x30d818186018c078L; 0x462623238c2305afL; 0x91b8c6c63fc67ef9L;
0xcdfbe8e887e8136fL; 0x13cb878726874ca1L; 0x6d11b8b8dab8a962L;
0x0209010104010805L; 0x9e0d4f4f214f426eL; 0x6c9b3636d836adeeL;
0x51ffa6a6a2a65904L; 0xb90cd2d26fd2debdL; 0xf70ef5f5f3f5fb06L;
0xf2967979f979ef80L; 0xde306f6fa16f5fceL; 0x3f6d91917e91fcefL;
0xa4f852525552aa07L; 0xc04760609d6027fdL; 0x6535bcbccabc8976L;
0x2b379b9b569baccdL; 0x018a8e8e028e048cL; 0x5bd2a3a3b6a37115L;
0x186c0c0c300c603cL; 0xf6847b7bf17bff8aL; 0x6a803535d435b5e1L;
0x3af51d1d741de869L; 0xddb3e0e0a7e05347L; 0xb321d7d77bd7f6acL;
0x999cc2c22fc25eedL; 0x5c432e2eb82e6d96L; 0x96294b4b314b627aL;
0xe15dfefedffea321L; 0xaed5575741578216L; 0x2abd15155415a841L;
0xeee87777c1779fb6L; 0x6e923737dc37a5ebL; 0xd79ee5e5b3e57b56L;
0x23139f9f469f8cd9L; 0xfd23f0f0e7f0d317L; 0x94204a4a354a6a7fL;
0xa944dada4fda9e95L; 0xb0a258587d58fa25L; 0x8fcfc9c903c906caL;
0x527c2929a429558dL; 0x145a0a0a280a5022L; 0x7f50b1b1feb1e14fL;
0x5dc9a0a0baa0691aL; 0xd6146b6bb16b7fdaL; 0x17d985852e855cabL;
0x673cbdbdcebd8173L; 0xba8f5d5d695dd234L; 0x2090101040108050L;
0xf507f4f4f7f4f303L; 0x8bddcbcb0bcb16c0L; 0x7cd33e3ef83eedc6L;
0x0a2d050514052811L; 0xce78676781671fe6L; 0xd597e4e4b7e47353L;
0x4e0227279c2725bbL; 0x8273414119413258L; 0x0ba78b8b168b2c9dL;
0x53f6a7a7a6a75101L; 0xfab27d7de97dcf94L; 0x374995956e95dcfbL;
0xad56d8d847d88e9fL; 0xeb70fbfbcbfb8b30L; 0xc1cdeeee9fee2371L;
0xf8bb7c7ced7cc791L; 0xcc716666856617e3L; 0xa77bdddd53dda68eL;
0x2eaf17175c17b84bL; 0x8e45474701470246L; 0x211a9e9e429e84dcL;
0x89d4caca0fca1ec5L; 0x5a582d2db42d7599L; 0x632ebfbfc6bf9179L;
0x0e3f07071c07381bL; 0x47acadad8ead0123L; 0xb4b05a5a755aea2fL;
0x1bef838336836cb5L; 0x66b63333cc3385ffL; 0xc65c636391633ff2L;
0x041202020802100aL; 0x4993aaaa92aa3938L; 0xe2de7171d971afa8L;
0x8dc6c8c807c80ecfL; 0x32d119196419c87dL; 0x923b494939497270L;
0xaf5fd9d943d9869aL; 0xf931f2f2eff2c31dL; 0xdba8e3e3abe34b48L;
0xb6b95b5b715be22aL; 0x0dbc88881a883492L; 0x293e9a9a529aa4c8L;
0x4c0b262698262dbeL; 0x64bf3232c8328dfaL; 0x7d59b0b0fab0e94aL;
0xcff2e9e983e91b6aL; 0x1e770f0f3c0f7833L; 0xb733d5d573d5e6a6L;
0x1df480803a8074baL; 0x6127bebec2be997cL; 0x87ebcdcd13cd26deL;
0x68893434d034bde4L; 0x903248483d487a75L; 0xe354ffffdbffab24L;
0xf48d7a7af57af78fL; 0x3d6490907a90f4eaL; 0xbe9d5f5f615fc23eL;
0x403d202080201da0L; 0xd00f6868bd6867d5L; 0x34ca1a1a681ad072L;
0x41b7aeae82ae192cL; 0x757db4b4eab4c95eL; 0xa8ce54544d549a19L;
0x3b7f93937693ece5L; 0x442f222288220daaL; 0xc86364648d6407e9L;
0xff2af1f1e3f1db12L; 0xe6cc7373d173bfa2L; 0x248212124812905aL;
0x807a40401d403a5dL; 0x1048080820084028L; 0x9b95c3c32bc356e8L;
0xc5dfecec97ec337bL; 0xab4ddbdb4bdb9690L; 0x5fc0a1a1bea1611fL;
0x07918d8d0e8d1c83L; 0x7ac83d3df43df5c9L; 0x335b97976697ccf1L;
0x0000000000000000L; 0x83f9cfcf1bcf36d4L; 0x566e2b2bac2b4587L;
0xece17676c57697b3L; 0x19e68282328264b0L; 0xb128d6d67fd6fea9L;
0x36c31b1b6c1bd877L; 0x7774b5b5eeb5c15bL; 0x43beafaf86af1129L;
0xd41d6a6ab56a77dfL; 0xa0ea50505d50ba0dL; 0x8a5745450945124cL;
0xfb38f3f3ebf3cb18L; 0x60ad3030c0309df0L; 0xc3c4efef9bef2b74L;
0x7eda3f3ffc3fe5c3L; 0xaac755554955921cL; 0x59dba2a2b2a27910L;
0xc9e9eaea8fea0365L; 0xca6a656589650fecL; 0x6903babad2bab968L;
0x5e4a2f2fbc2f6593L; 0x9d8ec0c027c04ee7L; 0xa160dede5fdebe81L;
0x38fc1c1c701ce06cL; 0xe746fdfdd3fdbb2eL; 0x9a1f4d4d294d5264L;
0x397692927292e4e0L; 0xeafa7575c9758fbcL; 0x0c3606061806301eL;
0x09ae8a8a128a2498L; 0x794bb2b2f2b2f940L; 0xd185e6e6bfe66359L;
0x1c7e0e0e380e7036L; 0x3ee71f1f7c1ff863L; 0xc4556262956237f7L;
0xb53ad4d477d4eea3L; 0x4d81a8a89aa82932L; 0x315296966296c4f4L;
0xef62f9f9c3f99b3aL; 0x97a3c5c533c566f6L; 0x4a102525942535b1L;
0xb2ab59597959f220L; 0x15d084842a8454aeL; 0xe4c57272d572b7a7L;
0x72ec3939e439d5ddL; 0x98164c4c2d4c5a61L; 0xbc945e5e655eca3bL;
0xf09f7878fd78e785L; 0x70e53838e038ddd8L; 0x05988c8c0a8c1486L;
0xbf17d1d163d1c6b2L; 0x57e4a5a5aea5410bL; 0xd9a1e2e2afe2434dL;
0xc24e616199612ff8L; 0x7b42b3b3f6b3f145L; 0x42342121842115a5L;
0x25089c9c4a9c94d6L; 0x3cee1e1e781ef066L; 0x8661434311432252L;
0x93b1c7c73bc776fcL; 0xe54ffcfcd7fcb32bL; 0x0824040410042014L;
0xa2e351515951b208L; 0x2f2599995e99bcc7L; 0xda226d6da96d4fc4L;
0x1a650d0d340d6839L; 0xe979fafacffa8335L; 0xa369dfdf5bdfb684L;
0xfca97e7ee57ed79bL; 0x4819242490243db4L; 0x76fe3b3bec3bc5d7L;
0x4b9aabab96ab313dL; 0x81f0cece1fce3ed1L; 0x2299111144118855L;
0x03838f8f068f0c89L; 0x9c044e4e254e4a6bL; 0x7366b7b7e6b7d151L;
0xcbe0ebeb8beb0b60L; 0x78c13c3cf03cfdccL; 0x1ffd81813e817cbfL;
0x354094946a94d4feL; 0xf31cf7f7fbf7eb0cL; 0x6f18b9b9deb9a167L;
0x268b13134c13985fL; 0x58512c2cb02c7d9cL; 0xbb05d3d36bd3d6b8L;
0xd38ce7e7bbe76b5cL; 0xdc396e6ea56e57cbL; 0x95aac4c437c46ef3L;
0x061b03030c03180fL; 0xacdc565645568a13L; 0x885e44440d441a49L;
0xfea07f7fe17fdf9eL; 0x4f88a9a99ea92137L; 0x54672a2aa82a4d82L;
0x6b0abbbbd6bbb16dL; 0x9f87c1c123c146e2L; 0xa6f153535153a202L;
0xa572dcdc57dcae8bL; 0x16530b0b2c0b5827L; 0x27019d9d4e9d9cd3L;
0xd82b6c6cad6c47c1L; 0x62a43131c43195f5L; 0xe8f37474cd7487b9L;
0xf115f6f6fff6e309L; 0x8c4c464605460a43L; 0x45a5acac8aac0926L;
0x0fb589891e893c97L; 0x28b414145014a044L; 0xdfbae1e1a3e15b42L;
0x2ca616165816b04eL; 0x74f73a3ae83acdd2L; 0xd2066969b9696fd0L;
0x124109092409482dL; 0xe0d77070dd70a7adL; 0x716fb6b6e2b6d954L;
0xbd1ed0d067d0ceb7L; 0xc7d6eded93ed3b7eL; 0x85e2cccc17cc2edbL;
0x8468424215422a57L; 0x2d2c98985a98b4c2L; 0x55eda4a4aaa4490eL;
0x50752828a0285d88L; 0xb8865c5c6d5cda31L; 0xed6bf8f8c7f8933fL;
0x11c28686228644a4L;
|];
[|
0x7830d818186018c0L; 0xaf462623238c2305L; 0xf991b8c6c63fc67eL;
0x6fcdfbe8e887e813L; 0xa113cb878726874cL; 0x626d11b8b8dab8a9L;
0x0502090101040108L; 0x6e9e0d4f4f214f42L; 0xee6c9b3636d836adL;
0x0451ffa6a6a2a659L; 0xbdb90cd2d26fd2deL; 0x06f70ef5f5f3f5fbL;
0x80f2967979f979efL; 0xcede306f6fa16f5fL; 0xef3f6d91917e91fcL;
0x07a4f852525552aaL; 0xfdc04760609d6027L; 0x766535bcbccabc89L;
0xcd2b379b9b569bacL; 0x8c018a8e8e028e04L; 0x155bd2a3a3b6a371L;
0x3c186c0c0c300c60L; 0x8af6847b7bf17bffL; 0xe16a803535d435b5L;
0x693af51d1d741de8L; 0x47ddb3e0e0a7e053L; 0xacb321d7d77bd7f6L;
0xed999cc2c22fc25eL; 0x965c432e2eb82e6dL; 0x7a96294b4b314b62L;
0x21e15dfefedffea3L; 0x16aed55757415782L; 0x412abd15155415a8L;
0xb6eee87777c1779fL; 0xeb6e923737dc37a5L; 0x56d79ee5e5b3e57bL;
0xd923139f9f469f8cL; 0x17fd23f0f0e7f0d3L; 0x7f94204a4a354a6aL;
0x95a944dada4fda9eL; 0x25b0a258587d58faL; 0xca8fcfc9c903c906L;
0x8d527c2929a42955L; 0x22145a0a0a280a50L; 0x4f7f50b1b1feb1e1L;
0x1a5dc9a0a0baa069L; 0xdad6146b6bb16b7fL; 0xab17d985852e855cL;
0x73673cbdbdcebd81L; 0x34ba8f5d5d695dd2L; 0x5020901010401080L;
0x03f507f4f4f7f4f3L; 0xc08bddcbcb0bcb16L; 0xc67cd33e3ef83eedL;
0x110a2d0505140528L; 0xe6ce78676781671fL; 0x53d597e4e4b7e473L;
0xbb4e0227279c2725L; 0x5882734141194132L; 0x9d0ba78b8b168b2cL;
0x0153f6a7a7a6a751L; 0x94fab27d7de97dcfL; 0xfb374995956e95dcL;
0x9fad56d8d847d88eL; 0x30eb70fbfbcbfb8bL; 0x71c1cdeeee9fee23L;
0x91f8bb7c7ced7cc7L; 0xe3cc716666856617L; 0x8ea77bdddd53dda6L;
0x4b2eaf17175c17b8L; 0x468e454747014702L; 0xdc211a9e9e429e84L;
0xc589d4caca0fca1eL; 0x995a582d2db42d75L; 0x79632ebfbfc6bf91L;
0x1b0e3f07071c0738L; 0x2347acadad8ead01L; 0x2fb4b05a5a755aeaL;
0xb51bef838336836cL; 0xff66b63333cc3385L; 0xf2c65c636391633fL;
0x0a04120202080210L; 0x384993aaaa92aa39L; 0xa8e2de7171d971afL;
0xcf8dc6c8c807c80eL; 0x7d32d119196419c8L; 0x70923b4949394972L;
0x9aaf5fd9d943d986L; 0x1df931f2f2eff2c3L; 0x48dba8e3e3abe34bL;
0x2ab6b95b5b715be2L; 0x920dbc88881a8834L; 0xc8293e9a9a529aa4L;
0xbe4c0b262698262dL; 0xfa64bf3232c8328dL; 0x4a7d59b0b0fab0e9L;
0x6acff2e9e983e91bL; 0x331e770f0f3c0f78L; 0xa6b733d5d573d5e6L;
0xba1df480803a8074L; 0x7c6127bebec2be99L; 0xde87ebcdcd13cd26L;
0xe468893434d034bdL; 0x75903248483d487aL; 0x24e354ffffdbffabL;
0x8ff48d7a7af57af7L; 0xea3d6490907a90f4L; 0x3ebe9d5f5f615fc2L;
0xa0403d202080201dL; 0xd5d00f6868bd6867L; 0x7234ca1a1a681ad0L;
0x2c41b7aeae82ae19L; 0x5e757db4b4eab4c9L; 0x19a8ce54544d549aL;
0xe53b7f93937693ecL; 0xaa442f222288220dL; 0xe9c86364648d6407L;
0x12ff2af1f1e3f1dbL; 0xa2e6cc7373d173bfL; 0x5a24821212481290L;
0x5d807a40401d403aL; 0x2810480808200840L; 0xe89b95c3c32bc356L;
0x7bc5dfecec97ec33L; 0x90ab4ddbdb4bdb96L; 0x1f5fc0a1a1bea161L;
0x8307918d8d0e8d1cL; 0xc97ac83d3df43df5L; 0xf1335b97976697ccL;
0x0000000000000000L; 0xd483f9cfcf1bcf36L; 0x87566e2b2bac2b45L;
0xb3ece17676c57697L; 0xb019e68282328264L; 0xa9b128d6d67fd6feL;
0x7736c31b1b6c1bd8L; 0x5b7774b5b5eeb5c1L; 0x2943beafaf86af11L;
0xdfd41d6a6ab56a77L; 0x0da0ea50505d50baL; 0x4c8a574545094512L;
0x18fb38f3f3ebf3cbL; 0xf060ad3030c0309dL; 0x74c3c4efef9bef2bL;
0xc37eda3f3ffc3fe5L; 0x1caac75555495592L; 0x1059dba2a2b2a279L;
0x65c9e9eaea8fea03L; 0xecca6a656589650fL; 0x686903babad2bab9L;
0x935e4a2f2fbc2f65L; 0xe79d8ec0c027c04eL; 0x81a160dede5fdebeL;
0x6c38fc1c1c701ce0L; 0x2ee746fdfdd3fdbbL; 0x649a1f4d4d294d52L;
0xe0397692927292e4L; 0xbceafa7575c9758fL; 0x1e0c360606180630L;
0x9809ae8a8a128a24L; 0x40794bb2b2f2b2f9L; 0x59d185e6e6bfe663L;
0x361c7e0e0e380e70L; 0x633ee71f1f7c1ff8L; 0xf7c4556262956237L;
0xa3b53ad4d477d4eeL; 0x324d81a8a89aa829L; 0xf4315296966296c4L;
0x3aef62f9f9c3f99bL; 0xf697a3c5c533c566L; 0xb14a102525942535L;
0x20b2ab59597959f2L; 0xae15d084842a8454L; 0xa7e4c57272d572b7L;
0xdd72ec3939e439d5L; 0x6198164c4c2d4c5aL; 0x3bbc945e5e655ecaL;
0x85f09f7878fd78e7L; 0xd870e53838e038ddL; 0x8605988c8c0a8c14L;
0xb2bf17d1d163d1c6L; 0x0b57e4a5a5aea541L; 0x4dd9a1e2e2afe243L;
0xf8c24e616199612fL; 0x457b42b3b3f6b3f1L; 0xa542342121842115L;
0xd625089c9c4a9c94L; 0x663cee1e1e781ef0L; 0x5286614343114322L;
0xfc93b1c7c73bc776L; 0x2be54ffcfcd7fcb3L; 0x1408240404100420L;
0x08a2e351515951b2L; 0xc72f2599995e99bcL; 0xc4da226d6da96d4fL;
0x391a650d0d340d68L; 0x35e979fafacffa83L; 0x84a369dfdf5bdfb6L;
0x9bfca97e7ee57ed7L; 0xb44819242490243dL; 0xd776fe3b3bec3bc5L;
0x3d4b9aabab96ab31L; 0xd181f0cece1fce3eL; 0x5522991111441188L;
0x8903838f8f068f0cL; 0x6b9c044e4e254e4aL; 0x517366b7b7e6b7d1L;
0x60cbe0ebeb8beb0bL; 0xcc78c13c3cf03cfdL; 0xbf1ffd81813e817cL;
0xfe354094946a94d4L; 0x0cf31cf7f7fbf7ebL; 0x676f18b9b9deb9a1L;
0x5f268b13134c1398L; 0x9c58512c2cb02c7dL; 0xb8bb05d3d36bd3d6L;
0x5cd38ce7e7bbe76bL; 0xcbdc396e6ea56e57L; 0xf395aac4c437c46eL;
0x0f061b03030c0318L; 0x13acdc565645568aL; 0x49885e44440d441aL;
0x9efea07f7fe17fdfL; 0x374f88a9a99ea921L; 0x8254672a2aa82a4dL;
0x6d6b0abbbbd6bbb1L; 0xe29f87c1c123c146L; 0x02a6f153535153a2L;
0x8ba572dcdc57dcaeL; 0x2716530b0b2c0b58L; 0xd327019d9d4e9d9cL;
0xc1d82b6c6cad6c47L; 0xf562a43131c43195L; 0xb9e8f37474cd7487L;
0x09f115f6f6fff6e3L; 0x438c4c464605460aL; 0x2645a5acac8aac09L;
0x970fb589891e893cL; 0x4428b414145014a0L; 0x42dfbae1e1a3e15bL;
0x4e2ca616165816b0L; 0xd274f73a3ae83acdL; 0xd0d2066969b9696fL;
0x2d12410909240948L; 0xade0d77070dd70a7L; 0x54716fb6b6e2b6d9L;
0xb7bd1ed0d067d0ceL; 0x7ec7d6eded93ed3bL; 0xdb85e2cccc17cc2eL;
0x578468424215422aL; 0xc22d2c98985a98b4L; 0x0e55eda4a4aaa449L;
0x8850752828a0285dL; 0x31b8865c5c6d5cdaL; 0x3fed6bf8f8c7f893L;
0xa411c28686228644L;
|];
[|
0xc07830d818186018L; 0x05af462623238c23L; 0x7ef991b8c6c63fc6L;
0x136fcdfbe8e887e8L; 0x4ca113cb87872687L; 0xa9626d11b8b8dab8L;
0x0805020901010401L; 0x426e9e0d4f4f214fL; 0xadee6c9b3636d836L;
0x590451ffa6a6a2a6L; 0xdebdb90cd2d26fd2L; 0xfb06f70ef5f5f3f5L;
0xef80f2967979f979L; 0x5fcede306f6fa16fL; 0xfcef3f6d91917e91L;
0xaa07a4f852525552L; 0x27fdc04760609d60L; 0x89766535bcbccabcL;
0xaccd2b379b9b569bL; 0x048c018a8e8e028eL; 0x71155bd2a3a3b6a3L;
0x603c186c0c0c300cL; 0xff8af6847b7bf17bL; 0xb5e16a803535d435L;
0xe8693af51d1d741dL; 0x5347ddb3e0e0a7e0L; 0xf6acb321d7d77bd7L;
0x5eed999cc2c22fc2L; 0x6d965c432e2eb82eL; 0x627a96294b4b314bL;
0xa321e15dfefedffeL; 0x8216aed557574157L; 0xa8412abd15155415L;
0x9fb6eee87777c177L; 0xa5eb6e923737dc37L; 0x7b56d79ee5e5b3e5L;
0x8cd923139f9f469fL; 0xd317fd23f0f0e7f0L; 0x6a7f94204a4a354aL;
0x9e95a944dada4fdaL; 0xfa25b0a258587d58L; 0x06ca8fcfc9c903c9L;
0x558d527c2929a429L; 0x5022145a0a0a280aL; 0xe14f7f50b1b1feb1L;
0x691a5dc9a0a0baa0L; 0x7fdad6146b6bb16bL; 0x5cab17d985852e85L;
0x8173673cbdbdcebdL; 0xd234ba8f5d5d695dL; 0x8050209010104010L;
0xf303f507f4f4f7f4L; 0x16c08bddcbcb0bcbL; 0xedc67cd33e3ef83eL;
0x28110a2d05051405L; 0x1fe6ce7867678167L; 0x7353d597e4e4b7e4L;
0x25bb4e0227279c27L; 0x3258827341411941L; 0x2c9d0ba78b8b168bL;
0x510153f6a7a7a6a7L; 0xcf94fab27d7de97dL; 0xdcfb374995956e95L;
0x8e9fad56d8d847d8L; 0x8b30eb70fbfbcbfbL; 0x2371c1cdeeee9feeL;
0xc791f8bb7c7ced7cL; 0x17e3cc7166668566L; 0xa68ea77bdddd53ddL;
0xb84b2eaf17175c17L; 0x02468e4547470147L; 0x84dc211a9e9e429eL;
0x1ec589d4caca0fcaL; 0x75995a582d2db42dL; 0x9179632ebfbfc6bfL;
0x381b0e3f07071c07L; 0x012347acadad8eadL; 0xea2fb4b05a5a755aL;
0x6cb51bef83833683L; 0x85ff66b63333cc33L; 0x3ff2c65c63639163L;
0x100a041202020802L; 0x39384993aaaa92aaL; 0xafa8e2de7171d971L;
0x0ecf8dc6c8c807c8L; 0xc87d32d119196419L; 0x7270923b49493949L;
0x869aaf5fd9d943d9L; 0xc31df931f2f2eff2L; 0x4b48dba8e3e3abe3L;
0xe22ab6b95b5b715bL; 0x34920dbc88881a88L; 0xa4c8293e9a9a529aL;
0x2dbe4c0b26269826L; 0x8dfa64bf3232c832L; 0xe94a7d59b0b0fab0L;
0x1b6acff2e9e983e9L; 0x78331e770f0f3c0fL; 0xe6a6b733d5d573d5L;
0x74ba1df480803a80L; 0x997c6127bebec2beL; 0x26de87ebcdcd13cdL;
0xbde468893434d034L; 0x7a75903248483d48L; 0xab24e354ffffdbffL;
0xf78ff48d7a7af57aL; 0xf4ea3d6490907a90L; 0xc23ebe9d5f5f615fL;
0x1da0403d20208020L; 0x67d5d00f6868bd68L; 0xd07234ca1a1a681aL;
0x192c41b7aeae82aeL; 0xc95e757db4b4eab4L; 0x9a19a8ce54544d54L;
0xece53b7f93937693L; 0x0daa442f22228822L; 0x07e9c86364648d64L;
0xdb12ff2af1f1e3f1L; 0xbfa2e6cc7373d173L; 0x905a248212124812L;
0x3a5d807a40401d40L; 0x4028104808082008L; 0x56e89b95c3c32bc3L;
0x337bc5dfecec97ecL; 0x9690ab4ddbdb4bdbL; 0x611f5fc0a1a1bea1L;
0x1c8307918d8d0e8dL; 0xf5c97ac83d3df43dL; 0xccf1335b97976697L;
0x0000000000000000L; 0x36d483f9cfcf1bcfL; 0x4587566e2b2bac2bL;
0x97b3ece17676c576L; 0x64b019e682823282L; 0xfea9b128d6d67fd6L;
0xd87736c31b1b6c1bL; 0xc15b7774b5b5eeb5L; 0x112943beafaf86afL;
0x77dfd41d6a6ab56aL; 0xba0da0ea50505d50L; 0x124c8a5745450945L;
0xcb18fb38f3f3ebf3L; 0x9df060ad3030c030L; 0x2b74c3c4efef9befL;
0xe5c37eda3f3ffc3fL; 0x921caac755554955L; 0x791059dba2a2b2a2L;
0x0365c9e9eaea8feaL; 0x0fecca6a65658965L; 0xb9686903babad2baL;
0x65935e4a2f2fbc2fL; 0x4ee79d8ec0c027c0L; 0xbe81a160dede5fdeL;
0xe06c38fc1c1c701cL; 0xbb2ee746fdfdd3fdL; 0x52649a1f4d4d294dL;
0xe4e0397692927292L; 0x8fbceafa7575c975L; 0x301e0c3606061806L;
0x249809ae8a8a128aL; 0xf940794bb2b2f2b2L; 0x6359d185e6e6bfe6L;
0x70361c7e0e0e380eL; 0xf8633ee71f1f7c1fL; 0x37f7c45562629562L;
0xeea3b53ad4d477d4L; 0x29324d81a8a89aa8L; 0xc4f4315296966296L;
0x9b3aef62f9f9c3f9L; 0x66f697a3c5c533c5L; 0x35b14a1025259425L;
0xf220b2ab59597959L; 0x54ae15d084842a84L; 0xb7a7e4c57272d572L;
0xd5dd72ec3939e439L; 0x5a6198164c4c2d4cL; 0xca3bbc945e5e655eL;
0xe785f09f7878fd78L; 0xddd870e53838e038L; 0x148605988c8c0a8cL;
0xc6b2bf17d1d163d1L; 0x410b57e4a5a5aea5L; 0x434dd9a1e2e2afe2L;
0x2ff8c24e61619961L; 0xf1457b42b3b3f6b3L; 0x15a5423421218421L;
0x94d625089c9c4a9cL; 0xf0663cee1e1e781eL; 0x2252866143431143L;
0x76fc93b1c7c73bc7L; 0xb32be54ffcfcd7fcL; 0x2014082404041004L;
0xb208a2e351515951L; 0xbcc72f2599995e99L; 0x4fc4da226d6da96dL;
0x68391a650d0d340dL; 0x8335e979fafacffaL; 0xb684a369dfdf5bdfL;
0xd79bfca97e7ee57eL; 0x3db4481924249024L; 0xc5d776fe3b3bec3bL;
0x313d4b9aabab96abL; 0x3ed181f0cece1fceL; 0x8855229911114411L;
0x0c8903838f8f068fL; 0x4a6b9c044e4e254eL; 0xd1517366b7b7e6b7L;
0x0b60cbe0ebeb8bebL; 0xfdcc78c13c3cf03cL; 0x7cbf1ffd81813e81L;
0xd4fe354094946a94L; 0xeb0cf31cf7f7fbf7L; 0xa1676f18b9b9deb9L;
0x985f268b13134c13L; 0x7d9c58512c2cb02cL; 0xd6b8bb05d3d36bd3L;
0x6b5cd38ce7e7bbe7L; 0x57cbdc396e6ea56eL; 0x6ef395aac4c437c4L;
0x180f061b03030c03L; 0x8a13acdc56564556L; 0x1a49885e44440d44L;
0xdf9efea07f7fe17fL; 0x21374f88a9a99ea9L; 0x4d8254672a2aa82aL;
0xb16d6b0abbbbd6bbL; 0x46e29f87c1c123c1L; 0xa202a6f153535153L;
0xae8ba572dcdc57dcL; 0x582716530b0b2c0bL; 0x9cd327019d9d4e9dL;
0x47c1d82b6c6cad6cL; 0x95f562a43131c431L; 0x87b9e8f37474cd74L;
0xe309f115f6f6fff6L; 0x0a438c4c46460546L; 0x092645a5acac8aacL;
0x3c970fb589891e89L; 0xa04428b414145014L; 0x5b42dfbae1e1a3e1L;
0xb04e2ca616165816L; 0xcdd274f73a3ae83aL; 0x6fd0d2066969b969L;
0x482d124109092409L; 0xa7ade0d77070dd70L; 0xd954716fb6b6e2b6L;
0xceb7bd1ed0d067d0L; 0x3b7ec7d6eded93edL; 0x2edb85e2cccc17ccL;
0x2a57846842421542L; 0xb4c22d2c98985a98L; 0x490e55eda4a4aaa4L;
0x5d8850752828a028L; 0xda31b8865c5c6d5cL; 0x933fed6bf8f8c7f8L;
0x44a411c286862286L;
|];
[|
0x18c07830d8181860L; 0x2305af462623238cL; 0xc67ef991b8c6c63fL;
0xe8136fcdfbe8e887L; 0x874ca113cb878726L; 0xb8a9626d11b8b8daL;
0x0108050209010104L; 0x4f426e9e0d4f4f21L; 0x36adee6c9b3636d8L;
0xa6590451ffa6a6a2L; 0xd2debdb90cd2d26fL; 0xf5fb06f70ef5f5f3L;
0x79ef80f2967979f9L; 0x6f5fcede306f6fa1L; 0x91fcef3f6d91917eL;
0x52aa07a4f8525255L; 0x6027fdc04760609dL; 0xbc89766535bcbccaL;
0x9baccd2b379b9b56L; 0x8e048c018a8e8e02L; 0xa371155bd2a3a3b6L;
0x0c603c186c0c0c30L; 0x7bff8af6847b7bf1L; 0x35b5e16a803535d4L;
0x1de8693af51d1d74L; 0xe05347ddb3e0e0a7L; 0xd7f6acb321d7d77bL;
0xc25eed999cc2c22fL; 0x2e6d965c432e2eb8L; 0x4b627a96294b4b31L;
0xfea321e15dfefedfL; 0x578216aed5575741L; 0x15a8412abd151554L;
0x779fb6eee87777c1L; 0x37a5eb6e923737dcL; 0xe57b56d79ee5e5b3L;
0x9f8cd923139f9f46L; 0xf0d317fd23f0f0e7L; 0x4a6a7f94204a4a35L;
0xda9e95a944dada4fL; 0x58fa25b0a258587dL; 0xc906ca8fcfc9c903L;
0x29558d527c2929a4L; 0x0a5022145a0a0a28L; 0xb1e14f7f50b1b1feL;
0xa0691a5dc9a0a0baL; 0x6b7fdad6146b6bb1L; 0x855cab17d985852eL;
0xbd8173673cbdbdceL; 0x5dd234ba8f5d5d69L; 0x1080502090101040L;
0xf4f303f507f4f4f7L; 0xcb16c08bddcbcb0bL; 0x3eedc67cd33e3ef8L;
0x0528110a2d050514L; 0x671fe6ce78676781L; 0xe47353d597e4e4b7L;
0x2725bb4e0227279cL; 0x4132588273414119L; 0x8b2c9d0ba78b8b16L;
0xa7510153f6a7a7a6L; 0x7dcf94fab27d7de9L; 0x95dcfb374995956eL;
0xd88e9fad56d8d847L; 0xfb8b30eb70fbfbcbL; 0xee2371c1cdeeee9fL;
0x7cc791f8bb7c7cedL; 0x6617e3cc71666685L; 0xdda68ea77bdddd53L;
0x17b84b2eaf17175cL; 0x4702468e45474701L; 0x9e84dc211a9e9e42L;
0xca1ec589d4caca0fL; 0x2d75995a582d2db4L; 0xbf9179632ebfbfc6L;
0x07381b0e3f07071cL; 0xad012347acadad8eL; 0x5aea2fb4b05a5a75L;
0x836cb51bef838336L; 0x3385ff66b63333ccL; 0x633ff2c65c636391L;
0x02100a0412020208L; 0xaa39384993aaaa92L; 0x71afa8e2de7171d9L;
0xc80ecf8dc6c8c807L; 0x19c87d32d1191964L; 0x497270923b494939L;
0xd9869aaf5fd9d943L; 0xf2c31df931f2f2efL; 0xe34b48dba8e3e3abL;
0x5be22ab6b95b5b71L; 0x8834920dbc88881aL; 0x9aa4c8293e9a9a52L;
0x262dbe4c0b262698L; 0x328dfa64bf3232c8L; 0xb0e94a7d59b0b0faL;
0xe91b6acff2e9e983L; 0x0f78331e770f0f3cL; 0xd5e6a6b733d5d573L;
0x8074ba1df480803aL; 0xbe997c6127bebec2L; 0xcd26de87ebcdcd13L;
0x34bde468893434d0L; 0x487a75903248483dL; 0xffab24e354ffffdbL;
0x7af78ff48d7a7af5L; 0x90f4ea3d6490907aL; 0x5fc23ebe9d5f5f61L;
0x201da0403d202080L; 0x6867d5d00f6868bdL; 0x1ad07234ca1a1a68L;
0xae192c41b7aeae82L; 0xb4c95e757db4b4eaL; 0x549a19a8ce54544dL;
0x93ece53b7f939376L; 0x220daa442f222288L; 0x6407e9c86364648dL;
0xf1db12ff2af1f1e3L; 0x73bfa2e6cc7373d1L; 0x12905a2482121248L;
0x403a5d807a40401dL; 0x0840281048080820L; 0xc356e89b95c3c32bL;
0xec337bc5dfecec97L; 0xdb9690ab4ddbdb4bL; 0xa1611f5fc0a1a1beL;
0x8d1c8307918d8d0eL; 0x3df5c97ac83d3df4L; 0x97ccf1335b979766L;
0x0000000000000000L; 0xcf36d483f9cfcf1bL; 0x2b4587566e2b2bacL;
0x7697b3ece17676c5L; 0x8264b019e6828232L; 0xd6fea9b128d6d67fL;
0x1bd87736c31b1b6cL; 0xb5c15b7774b5b5eeL; 0xaf112943beafaf86L;
0x6a77dfd41d6a6ab5L; 0x50ba0da0ea50505dL; 0x45124c8a57454509L;
0xf3cb18fb38f3f3ebL; 0x309df060ad3030c0L; 0xef2b74c3c4efef9bL;
0x3fe5c37eda3f3ffcL; 0x55921caac7555549L; 0xa2791059dba2a2b2L;
0xea0365c9e9eaea8fL; 0x650fecca6a656589L; 0xbab9686903babad2L;
0x2f65935e4a2f2fbcL; 0xc04ee79d8ec0c027L; 0xdebe81a160dede5fL;
0x1ce06c38fc1c1c70L; 0xfdbb2ee746fdfdd3L; 0x4d52649a1f4d4d29L;
0x92e4e03976929272L; 0x758fbceafa7575c9L; 0x06301e0c36060618L;
0x8a249809ae8a8a12L; 0xb2f940794bb2b2f2L; 0xe66359d185e6e6bfL;
0x0e70361c7e0e0e38L; 0x1ff8633ee71f1f7cL; 0x6237f7c455626295L;
0xd4eea3b53ad4d477L; 0xa829324d81a8a89aL; 0x96c4f43152969662L;
0xf99b3aef62f9f9c3L; 0xc566f697a3c5c533L; 0x2535b14a10252594L;
0x59f220b2ab595979L; 0x8454ae15d084842aL; 0x72b7a7e4c57272d5L;
0x39d5dd72ec3939e4L; 0x4c5a6198164c4c2dL; 0x5eca3bbc945e5e65L;
0x78e785f09f7878fdL; 0x38ddd870e53838e0L; 0x8c148605988c8c0aL;
0xd1c6b2bf17d1d163L; 0xa5410b57e4a5a5aeL; 0xe2434dd9a1e2e2afL;
0x612ff8c24e616199L; 0xb3f1457b42b3b3f6L; 0x2115a54234212184L;
0x9c94d625089c9c4aL; 0x1ef0663cee1e1e78L; 0x4322528661434311L;
0xc776fc93b1c7c73bL; 0xfcb32be54ffcfcd7L; 0x0420140824040410L;
0x51b208a2e3515159L; 0x99bcc72f2599995eL; 0x6d4fc4da226d6da9L;
0x0d68391a650d0d34L; 0xfa8335e979fafacfL; 0xdfb684a369dfdf5bL;
0x7ed79bfca97e7ee5L; 0x243db44819242490L; 0x3bc5d776fe3b3becL;
0xab313d4b9aabab96L; 0xce3ed181f0cece1fL; 0x1188552299111144L;
0x8f0c8903838f8f06L; 0x4e4a6b9c044e4e25L; 0xb7d1517366b7b7e6L;
0xeb0b60cbe0ebeb8bL; 0x3cfdcc78c13c3cf0L; 0x817cbf1ffd81813eL;
0x94d4fe354094946aL; 0xf7eb0cf31cf7f7fbL; 0xb9a1676f18b9b9deL;
0x13985f268b13134cL; 0x2c7d9c58512c2cb0L; 0xd3d6b8bb05d3d36bL;
0xe76b5cd38ce7e7bbL; 0x6e57cbdc396e6ea5L; 0xc46ef395aac4c437L;
0x03180f061b03030cL; 0x568a13acdc565645L; 0x441a49885e44440dL;
0x7fdf9efea07f7fe1L; 0xa921374f88a9a99eL; 0x2a4d8254672a2aa8L;
0xbbb16d6b0abbbbd6L; 0xc146e29f87c1c123L; 0x53a202a6f1535351L;
0xdcae8ba572dcdc57L; 0x0b582716530b0b2cL; 0x9d9cd327019d9d4eL;
0x6c47c1d82b6c6cadL; 0x3195f562a43131c4L; 0x7487b9e8f37474cdL;
0xf6e309f115f6f6ffL; 0x460a438c4c464605L; 0xac092645a5acac8aL;
0x893c970fb589891eL; 0x14a04428b4141450L; 0xe15b42dfbae1e1a3L;
0x16b04e2ca6161658L; 0x3acdd274f73a3ae8L; 0x696fd0d2066969b9L;
0x09482d1241090924L; 0x70a7ade0d77070ddL; 0xb6d954716fb6b6e2L;
0xd0ceb7bd1ed0d067L; 0xed3b7ec7d6eded93L; 0xcc2edb85e2cccc17L;
0x422a578468424215L; 0x98b4c22d2c98985aL; 0xa4490e55eda4a4aaL;
0x285d8850752828a0L; 0x5cda31b8865c5c6dL; 0xf8933fed6bf8f8c7L;
0x8644a411c2868622L;
|];
[|
0x6018c07830d81818L; 0x8c2305af46262323L; 0x3fc67ef991b8c6c6L;
0x87e8136fcdfbe8e8L; 0x26874ca113cb8787L; 0xdab8a9626d11b8b8L;
0x0401080502090101L; 0x214f426e9e0d4f4fL; 0xd836adee6c9b3636L;
0xa2a6590451ffa6a6L; 0x6fd2debdb90cd2d2L; 0xf3f5fb06f70ef5f5L;
0xf979ef80f2967979L; 0xa16f5fcede306f6fL; 0x7e91fcef3f6d9191L;
0x5552aa07a4f85252L; 0x9d6027fdc0476060L; 0xcabc89766535bcbcL;
0x569baccd2b379b9bL; 0x028e048c018a8e8eL; 0xb6a371155bd2a3a3L;
0x300c603c186c0c0cL; 0xf17bff8af6847b7bL; 0xd435b5e16a803535L;
0x741de8693af51d1dL; 0xa7e05347ddb3e0e0L; 0x7bd7f6acb321d7d7L;
0x2fc25eed999cc2c2L; 0xb82e6d965c432e2eL; 0x314b627a96294b4bL;
0xdffea321e15dfefeL; 0x41578216aed55757L; 0x5415a8412abd1515L;
0xc1779fb6eee87777L; 0xdc37a5eb6e923737L; 0xb3e57b56d79ee5e5L;
0x469f8cd923139f9fL; 0xe7f0d317fd23f0f0L; 0x354a6a7f94204a4aL;
0x4fda9e95a944dadaL; 0x7d58fa25b0a25858L; 0x03c906ca8fcfc9c9L;
0xa429558d527c2929L; 0x280a5022145a0a0aL; 0xfeb1e14f7f50b1b1L;
0xbaa0691a5dc9a0a0L; 0xb16b7fdad6146b6bL; 0x2e855cab17d98585L;
0xcebd8173673cbdbdL; 0x695dd234ba8f5d5dL; 0x4010805020901010L;
0xf7f4f303f507f4f4L; 0x0bcb16c08bddcbcbL; 0xf83eedc67cd33e3eL;
0x140528110a2d0505L; 0x81671fe6ce786767L; 0xb7e47353d597e4e4L;
0x9c2725bb4e022727L; 0x1941325882734141L; 0x168b2c9d0ba78b8bL;
0xa6a7510153f6a7a7L; 0xe97dcf94fab27d7dL; 0x6e95dcfb37499595L;
0x47d88e9fad56d8d8L; 0xcbfb8b30eb70fbfbL; 0x9fee2371c1cdeeeeL;
0xed7cc791f8bb7c7cL; 0x856617e3cc716666L; 0x53dda68ea77bddddL;
0x5c17b84b2eaf1717L; 0x014702468e454747L; 0x429e84dc211a9e9eL;
0x0fca1ec589d4cacaL; 0xb42d75995a582d2dL; 0xc6bf9179632ebfbfL;
0x1c07381b0e3f0707L; 0x8ead012347acadadL; 0x755aea2fb4b05a5aL;
0x36836cb51bef8383L; 0xcc3385ff66b63333L; 0x91633ff2c65c6363L;
0x0802100a04120202L; 0x92aa39384993aaaaL; 0xd971afa8e2de7171L;
0x07c80ecf8dc6c8c8L; 0x6419c87d32d11919L; 0x39497270923b4949L;
0x43d9869aaf5fd9d9L; 0xeff2c31df931f2f2L; 0xabe34b48dba8e3e3L;
0x715be22ab6b95b5bL; 0x1a8834920dbc8888L; 0x529aa4c8293e9a9aL;
0x98262dbe4c0b2626L; 0xc8328dfa64bf3232L; 0xfab0e94a7d59b0b0L;
0x83e91b6acff2e9e9L; 0x3c0f78331e770f0fL; 0x73d5e6a6b733d5d5L;
0x3a8074ba1df48080L; 0xc2be997c6127bebeL; 0x13cd26de87ebcdcdL;
0xd034bde468893434L; 0x3d487a7590324848L; 0xdbffab24e354ffffL;
0xf57af78ff48d7a7aL; 0x7a90f4ea3d649090L; 0x615fc23ebe9d5f5fL;
0x80201da0403d2020L; 0xbd6867d5d00f6868L; 0x681ad07234ca1a1aL;
0x82ae192c41b7aeaeL; 0xeab4c95e757db4b4L; 0x4d549a19a8ce5454L;
0x7693ece53b7f9393L; 0x88220daa442f2222L; 0x8d6407e9c8636464L;
0xe3f1db12ff2af1f1L; 0xd173bfa2e6cc7373L; 0x4812905a24821212L;
0x1d403a5d807a4040L; 0x2008402810480808L; 0x2bc356e89b95c3c3L;
0x97ec337bc5dfececL; 0x4bdb9690ab4ddbdbL; 0xbea1611f5fc0a1a1L;
0x0e8d1c8307918d8dL; 0xf43df5c97ac83d3dL; 0x6697ccf1335b9797L;
0x0000000000000000L; 0x1bcf36d483f9cfcfL; 0xac2b4587566e2b2bL;
0xc57697b3ece17676L; 0x328264b019e68282L; 0x7fd6fea9b128d6d6L;
0x6c1bd87736c31b1bL; 0xeeb5c15b7774b5b5L; 0x86af112943beafafL;
0xb56a77dfd41d6a6aL; 0x5d50ba0da0ea5050L; 0x0945124c8a574545L;
0xebf3cb18fb38f3f3L; 0xc0309df060ad3030L; 0x9bef2b74c3c4efefL;
0xfc3fe5c37eda3f3fL; 0x4955921caac75555L; 0xb2a2791059dba2a2L;
0x8fea0365c9e9eaeaL; 0x89650fecca6a6565L; 0xd2bab9686903babaL;
0xbc2f65935e4a2f2fL; 0x27c04ee79d8ec0c0L; 0x5fdebe81a160dedeL;
0x701ce06c38fc1c1cL; 0xd3fdbb2ee746fdfdL; 0x294d52649a1f4d4dL;
0x7292e4e039769292L; 0xc9758fbceafa7575L; 0x1806301e0c360606L;
0x128a249809ae8a8aL; 0xf2b2f940794bb2b2L; 0xbfe66359d185e6e6L;
0x380e70361c7e0e0eL; 0x7c1ff8633ee71f1fL; 0x956237f7c4556262L;
0x77d4eea3b53ad4d4L; 0x9aa829324d81a8a8L; 0x6296c4f431529696L;
0xc3f99b3aef62f9f9L; 0x33c566f697a3c5c5L; 0x942535b14a102525L;
0x7959f220b2ab5959L; 0x2a8454ae15d08484L; 0xd572b7a7e4c57272L;
0xe439d5dd72ec3939L; 0x2d4c5a6198164c4cL; 0x655eca3bbc945e5eL;
0xfd78e785f09f7878L; 0xe038ddd870e53838L; 0x0a8c148605988c8cL;
0x63d1c6b2bf17d1d1L; 0xaea5410b57e4a5a5L; 0xafe2434dd9a1e2e2L;
0x99612ff8c24e6161L; 0xf6b3f1457b42b3b3L; 0x842115a542342121L;
0x4a9c94d625089c9cL; 0x781ef0663cee1e1eL; 0x1143225286614343L;
0x3bc776fc93b1c7c7L; 0xd7fcb32be54ffcfcL; 0x1004201408240404L;
0x5951b208a2e35151L; 0x5e99bcc72f259999L; 0xa96d4fc4da226d6dL;
0x340d68391a650d0dL; 0xcffa8335e979fafaL; 0x5bdfb684a369dfdfL;
0xe57ed79bfca97e7eL; 0x90243db448192424L; 0xec3bc5d776fe3b3bL;
0x96ab313d4b9aababL; 0x1fce3ed181f0ceceL; 0x4411885522991111L;
0x068f0c8903838f8fL; 0x254e4a6b9c044e4eL; 0xe6b7d1517366b7b7L;
0x8beb0b60cbe0ebebL; 0xf03cfdcc78c13c3cL; 0x3e817cbf1ffd8181L;
0x6a94d4fe35409494L; 0xfbf7eb0cf31cf7f7L; 0xdeb9a1676f18b9b9L;
0x4c13985f268b1313L; 0xb02c7d9c58512c2cL; 0x6bd3d6b8bb05d3d3L;
0xbbe76b5cd38ce7e7L; 0xa56e57cbdc396e6eL; 0x37c46ef395aac4c4L;
0x0c03180f061b0303L; 0x45568a13acdc5656L; 0x0d441a49885e4444L;
0xe17fdf9efea07f7fL; 0x9ea921374f88a9a9L; 0xa82a4d8254672a2aL;
0xd6bbb16d6b0abbbbL; 0x23c146e29f87c1c1L; 0x5153a202a6f15353L;
0x57dcae8ba572dcdcL; 0x2c0b582716530b0bL; 0x4e9d9cd327019d9dL;
0xad6c47c1d82b6c6cL; 0xc43195f562a43131L; 0xcd7487b9e8f37474L;
0xfff6e309f115f6f6L; 0x05460a438c4c4646L; 0x8aac092645a5acacL;
0x1e893c970fb58989L; 0x5014a04428b41414L; 0xa3e15b42dfbae1e1L;
0x5816b04e2ca61616L; 0xe83acdd274f73a3aL; 0xb9696fd0d2066969L;
0x2409482d12410909L; 0xdd70a7ade0d77070L; 0xe2b6d954716fb6b6L;
0x67d0ceb7bd1ed0d0L; 0x93ed3b7ec7d6ededL; 0x17cc2edb85e2ccccL;
0x15422a5784684242L; 0x5a98b4c22d2c9898L; 0xaaa4490e55eda4a4L;
0xa0285d8850752828L; 0x6d5cda31b8865c5cL; 0xc7f8933fed6bf8f8L;
0x228644a411c28686L;
|];
[|
0x186018c07830d818L; 0x238c2305af462623L; 0xc63fc67ef991b8c6L;
0xe887e8136fcdfbe8L; 0x8726874ca113cb87L; 0xb8dab8a9626d11b8L;
0x0104010805020901L; 0x4f214f426e9e0d4fL; 0x36d836adee6c9b36L;
0xa6a2a6590451ffa6L; 0xd26fd2debdb90cd2L; 0xf5f3f5fb06f70ef5L;
0x79f979ef80f29679L; 0x6fa16f5fcede306fL; 0x917e91fcef3f6d91L;
0x525552aa07a4f852L; 0x609d6027fdc04760L; 0xbccabc89766535bcL;
0x9b569baccd2b379bL; 0x8e028e048c018a8eL; 0xa3b6a371155bd2a3L;
0x0c300c603c186c0cL; 0x7bf17bff8af6847bL; 0x35d435b5e16a8035L;
0x1d741de8693af51dL; 0xe0a7e05347ddb3e0L; 0xd77bd7f6acb321d7L;
0xc22fc25eed999cc2L; 0x2eb82e6d965c432eL; 0x4b314b627a96294bL;
0xfedffea321e15dfeL; 0x5741578216aed557L; 0x155415a8412abd15L;
0x77c1779fb6eee877L; 0x37dc37a5eb6e9237L; 0xe5b3e57b56d79ee5L;
0x9f469f8cd923139fL; 0xf0e7f0d317fd23f0L; 0x4a354a6a7f94204aL;
0xda4fda9e95a944daL; 0x587d58fa25b0a258L; 0xc903c906ca8fcfc9L;
0x29a429558d527c29L; 0x0a280a5022145a0aL; 0xb1feb1e14f7f50b1L;
0xa0baa0691a5dc9a0L; 0x6bb16b7fdad6146bL; 0x852e855cab17d985L;
0xbdcebd8173673cbdL; 0x5d695dd234ba8f5dL; 0x1040108050209010L;
0xf4f7f4f303f507f4L; 0xcb0bcb16c08bddcbL; 0x3ef83eedc67cd33eL;
0x05140528110a2d05L; 0x6781671fe6ce7867L; 0xe4b7e47353d597e4L;
0x279c2725bb4e0227L; 0x4119413258827341L; 0x8b168b2c9d0ba78bL;
0xa7a6a7510153f6a7L; 0x7de97dcf94fab27dL; 0x956e95dcfb374995L;
0xd847d88e9fad56d8L; 0xfbcbfb8b30eb70fbL; 0xee9fee2371c1cdeeL;
0x7ced7cc791f8bb7cL; 0x66856617e3cc7166L; 0xdd53dda68ea77bddL;
0x175c17b84b2eaf17L; 0x47014702468e4547L; 0x9e429e84dc211a9eL;
0xca0fca1ec589d4caL; 0x2db42d75995a582dL; 0xbfc6bf9179632ebfL;
0x071c07381b0e3f07L; 0xad8ead012347acadL; 0x5a755aea2fb4b05aL;
0x8336836cb51bef83L; 0x33cc3385ff66b633L; 0x6391633ff2c65c63L;
0x020802100a041202L; 0xaa92aa39384993aaL; 0x71d971afa8e2de71L;
0xc807c80ecf8dc6c8L; 0x196419c87d32d119L; 0x4939497270923b49L;
0xd943d9869aaf5fd9L; 0xf2eff2c31df931f2L; 0xe3abe34b48dba8e3L;
0x5b715be22ab6b95bL; 0x881a8834920dbc88L; 0x9a529aa4c8293e9aL;
0x2698262dbe4c0b26L; 0x32c8328dfa64bf32L; 0xb0fab0e94a7d59b0L;
0xe983e91b6acff2e9L; 0x0f3c0f78331e770fL; 0xd573d5e6a6b733d5L;
0x803a8074ba1df480L; 0xbec2be997c6127beL; 0xcd13cd26de87ebcdL;
0x34d034bde4688934L; 0x483d487a75903248L; 0xffdbffab24e354ffL;
0x7af57af78ff48d7aL; 0x907a90f4ea3d6490L; 0x5f615fc23ebe9d5fL;
0x2080201da0403d20L; 0x68bd6867d5d00f68L; 0x1a681ad07234ca1aL;
0xae82ae192c41b7aeL; 0xb4eab4c95e757db4L; 0x544d549a19a8ce54L;
0x937693ece53b7f93L; 0x2288220daa442f22L; 0x648d6407e9c86364L;
0xf1e3f1db12ff2af1L; 0x73d173bfa2e6cc73L; 0x124812905a248212L;
0x401d403a5d807a40L; 0x0820084028104808L; 0xc32bc356e89b95c3L;
0xec97ec337bc5dfecL; 0xdb4bdb9690ab4ddbL; 0xa1bea1611f5fc0a1L;
0x8d0e8d1c8307918dL; 0x3df43df5c97ac83dL; 0x976697ccf1335b97L;
0x0000000000000000L; 0xcf1bcf36d483f9cfL; 0x2bac2b4587566e2bL;
0x76c57697b3ece176L; 0x82328264b019e682L; 0xd67fd6fea9b128d6L;
0x1b6c1bd87736c31bL; 0xb5eeb5c15b7774b5L; 0xaf86af112943beafL;
0x6ab56a77dfd41d6aL; 0x505d50ba0da0ea50L; 0x450945124c8a5745L;
0xf3ebf3cb18fb38f3L; 0x30c0309df060ad30L; 0xef9bef2b74c3c4efL;
0x3ffc3fe5c37eda3fL; 0x554955921caac755L; 0xa2b2a2791059dba2L;
0xea8fea0365c9e9eaL; 0x6589650fecca6a65L; 0xbad2bab9686903baL;
0x2fbc2f65935e4a2fL; 0xc027c04ee79d8ec0L; 0xde5fdebe81a160deL;
0x1c701ce06c38fc1cL; 0xfdd3fdbb2ee746fdL; 0x4d294d52649a1f4dL;
0x927292e4e0397692L; 0x75c9758fbceafa75L; 0x061806301e0c3606L;
0x8a128a249809ae8aL; 0xb2f2b2f940794bb2L; 0xe6bfe66359d185e6L;
0x0e380e70361c7e0eL; 0x1f7c1ff8633ee71fL; 0x62956237f7c45562L;
0xd477d4eea3b53ad4L; 0xa89aa829324d81a8L; 0x966296c4f4315296L;
0xf9c3f99b3aef62f9L; 0xc533c566f697a3c5L; 0x25942535b14a1025L;
0x597959f220b2ab59L; 0x842a8454ae15d084L; 0x72d572b7a7e4c572L;
0x39e439d5dd72ec39L; 0x4c2d4c5a6198164cL; 0x5e655eca3bbc945eL;
0x78fd78e785f09f78L; 0x38e038ddd870e538L; 0x8c0a8c148605988cL;
0xd163d1c6b2bf17d1L; 0xa5aea5410b57e4a5L; 0xe2afe2434dd9a1e2L;
0x6199612ff8c24e61L; 0xb3f6b3f1457b42b3L; 0x21842115a5423421L;
0x9c4a9c94d625089cL; 0x1e781ef0663cee1eL; 0x4311432252866143L;
0xc73bc776fc93b1c7L; 0xfcd7fcb32be54ffcL; 0x0410042014082404L;
0x515951b208a2e351L; 0x995e99bcc72f2599L; 0x6da96d4fc4da226dL;
0x0d340d68391a650dL; 0xfacffa8335e979faL; 0xdf5bdfb684a369dfL;
0x7ee57ed79bfca97eL; 0x2490243db4481924L; 0x3bec3bc5d776fe3bL;
0xab96ab313d4b9aabL; 0xce1fce3ed181f0ceL; 0x1144118855229911L;
0x8f068f0c8903838fL; 0x4e254e4a6b9c044eL; 0xb7e6b7d1517366b7L;
0xeb8beb0b60cbe0ebL; 0x3cf03cfdcc78c13cL; 0x813e817cbf1ffd81L;
0x946a94d4fe354094L; 0xf7fbf7eb0cf31cf7L; 0xb9deb9a1676f18b9L;
0x134c13985f268b13L; 0x2cb02c7d9c58512cL; 0xd36bd3d6b8bb05d3L;
0xe7bbe76b5cd38ce7L; 0x6ea56e57cbdc396eL; 0xc437c46ef395aac4L;
0x030c03180f061b03L; 0x5645568a13acdc56L; 0x440d441a49885e44L;
0x7fe17fdf9efea07fL; 0xa99ea921374f88a9L; 0x2aa82a4d8254672aL;
0xbbd6bbb16d6b0abbL; 0xc123c146e29f87c1L; 0x535153a202a6f153L;
0xdc57dcae8ba572dcL; 0x0b2c0b582716530bL; 0x9d4e9d9cd327019dL;
0x6cad6c47c1d82b6cL; 0x31c43195f562a431L; 0x74cd7487b9e8f374L;
0xf6fff6e309f115f6L; 0x4605460a438c4c46L; 0xac8aac092645a5acL;
0x891e893c970fb589L; 0x145014a04428b414L; 0xe1a3e15b42dfbae1L;
0x165816b04e2ca616L; 0x3ae83acdd274f73aL; 0x69b9696fd0d20669L;
0x092409482d124109L; 0x70dd70a7ade0d770L; 0xb6e2b6d954716fb6L;
0xd067d0ceb7bd1ed0L; 0xed93ed3b7ec7d6edL; 0xcc17cc2edb85e2ccL;
0x4215422a57846842L; 0x985a98b4c22d2c98L; 0xa4aaa4490e55eda4L;
0x28a0285d88507528L; 0x5c6d5cda31b8865cL; 0xf8c7f8933fed6bf8L;
0x86228644a411c286L;
|];
|]
let whirlpool_do_chunk :
type a. be64_to_cpu:(a -> int -> int64) -> ctx -> a -> int -> unit =
fun ~be64_to_cpu ctx buf off ->
let key = Array.init 2 (fun _ -> Array.make 8 Int64.zero) in
let state = Array.init 2 (fun _ -> Array.make 8 Int64.zero) in
let m = ref 0 in
let rc =
[|
0x1823c6e887b8014fL; 0x36a6d2f5796f9152L; 0x60bc9b8ea30c7b35L;
0x1de0d7c22e4bfe57L; 0x157737e59ff04adaL; 0x58c9290ab1a06b85L;
0xbd5d10f4cb3e0567L; 0xe427418ba77d95d8L; 0xfbee7c66dd17479eL;
0xca2dbf07ad5a8333L;
|] in
for i = 0 to 7 do
key.(0).(i) <- ctx.h.(i) ;
let off = off + (i * 8) in
state.(0).(i) <- Int64.(be64_to_cpu buf off lxor ctx.h.(i)) ;
ctx.h.(i) <- state.(0).(i)
done ;
let wp_op src shift =
let mask v = Int64.(to_int (v land 0xffL)) in
let get_k i =
k.(i).(mask
(Int64.shift_right src.((shift + 8 - i) land 7) (56 - (8 * i))))
in
Array.fold_left Int64.logxor Int64.zero (Array.init 8 get_k) in
for i = 0 to 9 do
let m0, m1 = (!m, !m lxor 1) in
let upd_key i = key.(m1).(i) <- wp_op key.(m0) i in
let upd_state i =
state.(m1).(i) <- Int64.(wp_op state.(m0) i lxor key.(m1).(i)) in
for i = 0 to 7 do
upd_key i
done ;
key.(m1).(0) <- Int64.(key.(m1).(0) lxor rc.(i)) ;
for i = 0 to 7 do
upd_state i
done ;
m := !m lxor 1
done ;
let upd_hash i = Int64.(ctx.h.(i) <- ctx.h.(i) lxor state.(0).(i)) in
for i = 0 to 7 do
upd_hash i
done ;
()
let feed :
type a.
blit:(a -> int -> By.t -> int -> int -> unit) ->
be64_to_cpu:(a -> int -> int64) ->
ctx ->
a ->
int ->
int ->
unit =
fun ~blit ~be64_to_cpu ctx buf off len ->
let idx = ref Int64.(to_int (ctx.size land 0x3FL)) in
let len = ref len in
let off = ref off in
let to_fill = 64 - !idx in
ctx.size <- Int64.add ctx.size (Int64.of_int !len) ;
if !idx <> 0 && !len >= to_fill
then (
blit buf !off ctx.b !idx to_fill ;
whirlpool_do_chunk ~be64_to_cpu:By.be64_to_cpu ctx ctx.b 0 ;
len := !len - to_fill ;
off := !off + to_fill ;
idx := 0) ;
while !len >= 64 do
whirlpool_do_chunk ~be64_to_cpu ctx buf !off ;
len := !len - 64 ;
off := !off + 64
done ;
if !len <> 0 then blit buf !off ctx.b !idx !len ;
()
let unsafe_feed_bytes = feed ~blit:By.blit ~be64_to_cpu:By.be64_to_cpu
let unsafe_feed_bigstring =
feed ~blit:By.blit_from_bigstring ~be64_to_cpu:Bi.be64_to_cpu
let unsafe_get ctx =
let index = Int64.(to_int (ctx.size land 0x3FL)) + 1 in
By.set ctx.b (index - 1) '\x80' ;
if index > 32
then (
By.fill ctx.b index (64 - index) '\x00' ;
whirlpool_do_chunk ~be64_to_cpu:By.be64_to_cpu ctx ctx.b 0 ;
By.fill ctx.b 0 56 '\x00')
else By.fill ctx.b index (56 - index) '\x00' ;
By.cpu_to_be64 ctx.b 56 Int64.(ctx.size lsl 3) ;
whirlpool_do_chunk ~be64_to_cpu:By.be64_to_cpu ctx ctx.b 0 ;
let res = By.create (8 * 8) in
for i = 0 to 7 do
By.cpu_to_be64 res (i * 8) ctx.h.(i)
done ;
res
end

View file

@ -0,0 +1,732 @@
type bigstring =
(char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
type 'a iter = ('a -> unit) -> unit
type 'a compare = 'a -> 'a -> int
type 'a equal = 'a -> 'a -> bool
type 'a pp = Format.formatter -> 'a -> unit
module By = Digestif_by
module Bi = Digestif_bi
module Eq = Digestif_eq
module Conv = Digestif_conv
let failwith fmt = Format.ksprintf failwith fmt
module type S = sig
val digest_size : int
type ctx
type hmac
type t
val empty : ctx
val init : unit -> ctx
val feed_bytes : ctx -> ?off:int -> ?len:int -> Bytes.t -> ctx
val feed_string : ctx -> ?off:int -> ?len:int -> String.t -> ctx
val feed_bigstring : ctx -> ?off:int -> ?len:int -> bigstring -> ctx
val feedi_bytes : ctx -> Bytes.t iter -> ctx
val feedi_string : ctx -> String.t iter -> ctx
val feedi_bigstring : ctx -> bigstring iter -> ctx
val get : ctx -> t
val hmac_init : key:string -> hmac
val hmac_feed_bytes : hmac -> ?off:int -> ?len:int -> Bytes.t -> hmac
val hmac_feed_string : hmac -> ?off:int -> ?len:int -> String.t -> hmac
val hmac_feed_bigstring : hmac -> ?off:int -> ?len:int -> bigstring -> hmac
val hmac_feedi_bytes : hmac -> Bytes.t iter -> hmac
val hmac_feedi_string : hmac -> String.t iter -> hmac
val hmac_feedi_bigstring : hmac -> bigstring iter -> hmac
val hmac_get : hmac -> t
val digest_bytes : ?off:int -> ?len:int -> Bytes.t -> t
val digest_string : ?off:int -> ?len:int -> String.t -> t
val digest_bigstring : ?off:int -> ?len:int -> bigstring -> t
val digesti_bytes : Bytes.t iter -> t
val digesti_string : String.t iter -> t
val digesti_bigstring : bigstring iter -> t
val digestv_bytes : Bytes.t list -> t
val digestv_string : String.t list -> t
val digestv_bigstring : bigstring list -> t
val hmac_bytes : key:string -> ?off:int -> ?len:int -> Bytes.t -> t
val hmac_string : key:string -> ?off:int -> ?len:int -> String.t -> t
val hmac_bigstring : key:string -> ?off:int -> ?len:int -> bigstring -> t
val hmaci_bytes : key:string -> Bytes.t iter -> t
val hmaci_string : key:string -> String.t iter -> t
val hmaci_bigstring : key:string -> bigstring iter -> t
val hmacv_bytes : key:string -> Bytes.t list -> t
val hmacv_string : key:string -> String.t list -> t
val hmacv_bigstring : key:string -> bigstring list -> t
val unsafe_compare : t compare
val equal : t equal
val pp : t pp
val of_hex : string -> t
val of_hex_opt : string -> t option
val consistent_of_hex : string -> t
val consistent_of_hex_opt : string -> t option
val to_hex : t -> string
val of_raw_string : string -> t
val of_raw_string_opt : string -> t option
val to_raw_string : t -> string
val get_into_bytes : ctx -> ?off:int -> bytes -> unit
end
module type MAC = sig
type t
val mac_bytes : key:string -> ?off:int -> ?len:int -> Bytes.t -> t
val mac_string : key:string -> ?off:int -> ?len:int -> String.t -> t
val mac_bigstring : key:string -> ?off:int -> ?len:int -> bigstring -> t
val maci_bytes : key:string -> Bytes.t iter -> t
val maci_string : key:string -> String.t iter -> t
val maci_bigstring : key:string -> bigstring iter -> t
val macv_bytes : key:string -> Bytes.t list -> t
val macv_string : key:string -> String.t list -> t
val macv_bigstring : key:string -> bigstring list -> t
end
module type Desc = sig
val digest_size : int
val block_size : int
end
module type Hash = sig
type ctx
val init : unit -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
end
module Unsafe (Hash : Hash) (D : Desc) = struct
open Hash
let digest_size = D.digest_size
let block_size = D.block_size
let empty = init ()
let init = init
let unsafe_feed_bytes ctx ?off ?len buf =
let off, len =
match (off, len) with
| Some off, Some len -> (off, len)
| Some off, None -> (off, By.length buf - off)
| None, Some len -> (0, len)
| None, None -> (0, By.length buf) in
if off < 0 || len < 0 || off > By.length buf - len
then invalid_arg "offset out of bounds"
else unsafe_feed_bytes ctx buf off len
let unsafe_feed_string ctx ?off ?len buf =
unsafe_feed_bytes ctx ?off ?len (By.unsafe_of_string buf)
let unsafe_feed_bigstring ctx ?off ?len buf =
let off, len =
match (off, len) with
| Some off, Some len -> (off, len)
| Some off, None -> (off, Bi.length buf - off)
| None, Some len -> (0, len)
| None, None -> (0, Bi.length buf) in
if off < 0 || len < 0 || off > Bi.length buf - len
then invalid_arg "offset out of bounds"
else unsafe_feed_bigstring ctx buf off len
let unsafe_get = unsafe_get
let get_into_bytes ctx ?(off = 0) buf =
if off < 0 || off >= Bytes.length buf
then invalid_arg "offset out of bounds" ;
if Bytes.length buf - off < digest_size
then invalid_arg "destination too small" ;
let raw = unsafe_get (Hash.dup ctx) in
Bytes.blit raw 0 buf off digest_size
end
module Core (Hash : Hash) (D : Desc) = struct
type t = string
type ctx = Hash.ctx
include Unsafe (Hash) (D)
include Conv.Make (D)
include Eq.Make (D)
let get t =
let t = Hash.dup t in
unsafe_get t |> By.unsafe_to_string
let feed_bytes t ?off ?len buf =
let t = Hash.dup t in
unsafe_feed_bytes t ?off ?len buf ;
t
let feed_string t ?off ?len buf =
let t = Hash.dup t in
unsafe_feed_string t ?off ?len buf ;
t
let feed_bigstring t ?off ?len buf =
let t = Hash.dup t in
unsafe_feed_bigstring t ?off ?len buf ;
t
let feedi_bytes t iter =
let t = Hash.dup t in
let feed buf = unsafe_feed_bytes t buf in
iter feed ;
t
let feedi_string t iter =
let t = Hash.dup t in
let feed buf = unsafe_feed_string t buf in
iter feed ;
t
let feedi_bigstring t iter =
let t = Hash.dup t in
let feed buf = unsafe_feed_bigstring t buf in
iter feed ;
t
let digest_bytes ?off ?len buf = feed_bytes empty ?off ?len buf |> get
let digest_string ?off ?len buf = feed_string empty ?off ?len buf |> get
let digest_bigstring ?off ?len buf = feed_bigstring empty ?off ?len buf |> get
let digesti_bytes iter = feedi_bytes empty iter |> get
let digesti_string iter = feedi_string empty iter |> get
let digesti_bigstring iter = feedi_bigstring empty iter |> get
let digestv_bytes lst = digesti_bytes (fun f -> List.iter f lst)
let digestv_string lst = digesti_string (fun f -> List.iter f lst)
let digestv_bigstring lst = digesti_bigstring (fun f -> List.iter f lst)
end
module Make (H : Hash) (D : Desc) = struct
include Core (H) (D)
type hmac = ctx * string
let bytes_opad = By.init block_size (fun _ -> '\x5c')
let bytes_ipad = By.init block_size (fun _ -> '\x36')
let rec norm_bytes key =
match Stdlib.compare (String.length key) block_size with
| 1 -> norm_bytes (digest_string key)
| -1 -> By.rpad (Bytes.unsafe_of_string key) block_size '\000'
| _ -> By.of_string key
let hmac_init ~key =
let key = norm_bytes key in
let outer = Xor.Bytes.xor key bytes_opad in
let inner = Xor.Bytes.xor key bytes_ipad in
let ctx = feed_bytes empty inner in
(ctx, Bytes.unsafe_to_string outer)
let hmac_feed_bytes (t, outer) ?off ?len buf =
(feed_bytes t ?off ?len buf, outer)
let hmac_feed_string (t, outer) ?off ?len buf =
(feed_string t ?off ?len buf, outer)
let hmac_feed_bigstring (t, outer) ?off ?len buf =
(feed_bigstring t ?off ?len buf, outer)
let hmac_get (ctx, outer) =
feed_string (feed_string empty outer) (get ctx) |> get
let hmac_feedi_bytes (t, outer) iter = (feedi_bytes t iter, outer)
let hmac_feedi_string (t, outer) iter = (feedi_string t iter, outer)
let hmac_feedi_bigstring (t, outer) iter = (feedi_bigstring t iter, outer)
let hmaci_bytes ~key iter =
let t = hmac_init ~key in
hmac_feedi_bytes t iter |> hmac_get
let hmaci_string ~key iter =
let t = hmac_init ~key in
hmac_feedi_string t iter |> hmac_get
let hmaci_bigstring ~key iter =
let t = hmac_init ~key in
hmac_feedi_bigstring t iter |> hmac_get
let hmac_bytes ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> By.sub buf off len
| Some off, None -> By.sub buf off (By.length buf - off)
| None, Some len -> By.sub buf 0 len
| None, None -> buf in
hmaci_bytes ~key (fun f -> f buf)
let hmac_string ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> String.sub buf off len
| Some off, None -> String.sub buf off (String.length buf - off)
| None, Some len -> String.sub buf 0 len
| None, None -> buf in
hmaci_string ~key (fun f -> f buf)
let hmac_bigstring ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> Bi.sub buf off len
| Some off, None -> Bi.sub buf off (Bi.length buf - off)
| None, Some len -> Bi.sub buf 0 len
| None, None -> buf in
hmaci_bigstring ~key (fun f -> f buf)
let hmacv_bytes ~key bufs = hmaci_bytes ~key (fun f -> List.iter f bufs)
let hmacv_string ~key bufs = hmaci_string ~key (fun f -> List.iter f bufs)
let hmacv_bigstring ~key bufs =
hmaci_bigstring ~key (fun f -> List.iter f bufs)
end
module type Hash_BLAKE2 = sig
type ctx
val with_outlen_and_bytes_key : int -> By.t -> int -> int -> ctx
val unsafe_feed_bytes : ctx -> By.t -> int -> int -> unit
val unsafe_feed_bigstring : ctx -> Bi.t -> int -> int -> unit
val unsafe_get : ctx -> By.t
val dup : ctx -> ctx
val max_outlen : int
end
module Make_BLAKE2 (H : Hash_BLAKE2) (D : Desc) = struct
let () =
if D.digest_size > H.max_outlen
then
failwith "Invalid digest_size:%d to make a BLAKE2{S,B} implementation"
D.digest_size
include
Make
(struct
type ctx = H.ctx
let init () = H.with_outlen_and_bytes_key D.digest_size By.empty 0 0
let unsafe_feed_bytes = H.unsafe_feed_bytes
let unsafe_feed_bigstring = H.unsafe_feed_bigstring
let unsafe_get = H.unsafe_get
let dup = H.dup
end)
(D)
type outer = t
module Keyed = struct
type t = outer
let maci_bytes ~key iter =
let ctx =
H.with_outlen_and_bytes_key digest_size
(Bytes.unsafe_of_string key)
0 (String.length key) in
feedi_bytes ctx iter |> get
let maci_string ~key iter =
let ctx =
H.with_outlen_and_bytes_key digest_size
(Bytes.unsafe_of_string key)
0 (String.length key) in
feedi_string ctx iter |> get
let maci_bigstring ~key iter =
let ctx =
H.with_outlen_and_bytes_key digest_size
(Bytes.unsafe_of_string key)
0 (String.length key) in
feedi_bigstring ctx iter |> get
let mac_bytes ~key ?off ?len buf : t =
let buf =
match (off, len) with
| Some off, Some len -> By.sub buf off len
| Some off, None -> By.sub buf off (By.length buf - off)
| None, Some len -> By.sub buf 0 len
| None, None -> buf in
maci_bytes ~key (fun f -> f buf)
let mac_string ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> String.sub buf off len
| Some off, None -> String.sub buf off (String.length buf - off)
| None, Some len -> String.sub buf 0 len
| None, None -> buf in
maci_string ~key (fun f -> f buf)
let mac_bigstring ~key ?off ?len buf =
let buf =
match (off, len) with
| Some off, Some len -> Bi.sub buf off len
| Some off, None -> Bi.sub buf off (Bi.length buf - off)
| None, Some len -> Bi.sub buf 0 len
| None, None -> buf in
maci_bigstring ~key (fun f -> f buf)
let macv_bytes ~key bufs = maci_bytes ~key (fun f -> List.iter f bufs)
let macv_string ~key bufs = maci_string ~key (fun f -> List.iter f bufs)
let macv_bigstring ~key bufs =
maci_bigstring ~key (fun f -> List.iter f bufs)
end
end
module MD5 : S =
Make
(Baijiu_md5.Unsafe)
(struct
let digest_size, block_size = (16, 64)
end)
module SHA1 : S =
Make
(Baijiu_sha1.Unsafe)
(struct
let digest_size, block_size = (20, 64)
end)
module SHA224 : S =
Make
(Baijiu_sha224.Unsafe)
(struct
let digest_size, block_size = (28, 64)
end)
module SHA256 : S =
Make
(Baijiu_sha256.Unsafe)
(struct
let digest_size, block_size = (32, 64)
end)
module SHA384 : S =
Make
(Baijiu_sha384.Unsafe)
(struct
let digest_size, block_size = (48, 128)
end)
module SHA512 : S =
Make
(Baijiu_sha512.Unsafe)
(struct
let digest_size, block_size = (64, 128)
end)
module SHA3_224 : S =
Make
(Baijiu_sha3_224.Unsafe)
(struct
let digest_size, block_size = (28, 144)
end)
module SHA3_256 : S =
Make
(Baijiu_sha3_256.Unsafe)
(struct
let digest_size, block_size = (32, 136)
end)
module KECCAK_256 : S =
Make
(Baijiu_keccak_256.Unsafe)
(struct
let digest_size, block_size = (32, 136)
end)
module SHA3_384 : S =
Make
(Baijiu_sha3_384.Unsafe)
(struct
let digest_size, block_size = (48, 104)
end)
module SHA3_512 : S =
Make
(Baijiu_sha3_512.Unsafe)
(struct
let digest_size, block_size = (64, 72)
end)
module WHIRLPOOL : S =
Make
(Baijiu_whirlpool.Unsafe)
(struct
let digest_size, block_size = (64, 64)
end)
module BLAKE2B : sig
include S
module Keyed : MAC with type t = t
end =
Make_BLAKE2
(Baijiu_blake2b.Unsafe)
(struct
let digest_size, block_size = (64, 128)
end)
module BLAKE2S : sig
include S
module Keyed : MAC with type t = t
end =
Make_BLAKE2
(Baijiu_blake2s.Unsafe)
(struct
let digest_size, block_size = (32, 64)
end)
module RMD160 : S =
Make
(Baijiu_rmd160.Unsafe)
(struct
let digest_size, block_size = (20, 64)
end)
module Make_BLAKE2B (D : sig
val digest_size : int
end) : S = struct
include
Make_BLAKE2
(Baijiu_blake2b.Unsafe)
(struct
let digest_size, block_size = (D.digest_size, 128)
end)
end
module Make_BLAKE2S (D : sig
val digest_size : int
end) : S = struct
include
Make_BLAKE2
(Baijiu_blake2s.Unsafe)
(struct
let digest_size, block_size = (D.digest_size, 64)
end)
end
type 'k hash =
| MD5 : MD5.t hash
| SHA1 : SHA1.t hash
| RMD160 : RMD160.t hash
| SHA224 : SHA224.t hash
| SHA256 : SHA256.t hash
| SHA384 : SHA384.t hash
| SHA512 : SHA512.t hash
| SHA3_224 : SHA3_224.t hash
| SHA3_256 : SHA3_256.t hash
| KECCAK_256 : KECCAK_256.t hash
| SHA3_384 : SHA3_384.t hash
| SHA3_512 : SHA3_512.t hash
| WHIRLPOOL : WHIRLPOOL.t hash
| BLAKE2B : BLAKE2B.t hash
| BLAKE2S : BLAKE2S.t hash
let md5 = MD5
let sha1 = SHA1
let rmd160 = RMD160
let sha224 = SHA224
let sha256 = SHA256
let sha384 = SHA384
let sha512 = SHA512
let sha3_224 = SHA3_224
let sha3_256 = SHA3_256
let keccak_256 = KECCAK_256
let sha3_384 = SHA3_384
let sha3_512 = SHA3_512
let whirlpool = WHIRLPOOL
let blake2b = BLAKE2B
let blake2s = BLAKE2S
type hash' =
[ `MD5
| `SHA1
| `RMD160
| `SHA224
| `SHA256
| `SHA384
| `SHA512
| `SHA3_224
| `SHA3_256
| `KECCAK_256
| `SHA3_384
| `SHA3_512
| `WHIRLPOOL
| `BLAKE2B
| `BLAKE2S ]
let hash_to_hash' : type a. a hash -> hash' = function
| MD5 -> `MD5
| SHA1 -> `SHA1
| RMD160 -> `RMD160
| SHA224 -> `SHA224
| SHA256 -> `SHA256
| SHA384 -> `SHA384
| SHA512 -> `SHA512
| SHA3_224 -> `SHA3_224
| SHA3_256 -> `SHA3_256
| KECCAK_256 -> `KECCAK_256
| SHA3_384 -> `SHA3_384
| SHA3_512 -> `SHA3_512
| WHIRLPOOL -> `WHIRLPOOL
| BLAKE2B -> `BLAKE2B
| BLAKE2S -> `BLAKE2S
let module_of_hash' : hash' -> (module S) = function
| `MD5 -> (module MD5)
| `SHA1 -> (module SHA1)
| `RMD160 -> (module RMD160)
| `SHA224 -> (module SHA224)
| `SHA256 -> (module SHA256)
| `SHA384 -> (module SHA384)
| `SHA512 -> (module SHA512)
| `SHA3_224 -> (module SHA3_224)
| `SHA3_256 -> (module SHA3_256)
| `KECCAK_256 -> (module KECCAK_256)
| `SHA3_384 -> (module SHA3_384)
| `SHA3_512 -> (module SHA3_512)
| `WHIRLPOOL -> (module WHIRLPOOL)
| `BLAKE2B -> (module BLAKE2B)
| `BLAKE2S -> (module BLAKE2S)
let module_of : type k. k hash -> (module S with type t = k) = function
| MD5 -> (module MD5)
| SHA1 -> (module SHA1)
| RMD160 -> (module RMD160)
| SHA224 -> (module SHA224)
| SHA256 -> (module SHA256)
| SHA384 -> (module SHA384)
| SHA512 -> (module SHA512)
| SHA3_224 -> (module SHA3_224)
| SHA3_256 -> (module SHA3_256)
| KECCAK_256 -> (module KECCAK_256)
| SHA3_384 -> (module SHA3_384)
| SHA3_512 -> (module SHA3_512)
| WHIRLPOOL -> (module WHIRLPOOL)
| BLAKE2B -> (module BLAKE2B)
| BLAKE2S -> (module BLAKE2S)
type 'hash t = 'hash
let digest_bytes : type k. k hash -> Bytes.t -> k t =
fun hash buf ->
let module H = (val module_of hash) in
H.digest_bytes buf
let digest_string : type k. k hash -> String.t -> k t =
fun hash buf ->
let module H = (val module_of hash) in
H.digest_string buf
let digest_bigstring : type k. k hash -> bigstring -> k t =
fun hash buf ->
let module H = (val module_of hash) in
H.digest_bigstring buf
let digesti_bytes : type k. k hash -> Bytes.t iter -> k t =
fun hash iter ->
let module H = (val module_of hash) in
H.digesti_bytes iter
let digesti_string : type k. k hash -> String.t iter -> k t =
fun hash iter ->
let module H = (val module_of hash) in
H.digesti_string iter
let digesti_bigstring : type k. k hash -> bigstring iter -> k t =
fun hash iter ->
let module H = (val module_of hash) in
H.digesti_bigstring iter
let hmaci_bytes : type k. k hash -> key:string -> Bytes.t iter -> k t =
fun hash ~key iter ->
let module H = (val module_of hash) in
H.hmaci_bytes ~key iter
let hmaci_string : type k. k hash -> key:string -> String.t iter -> k t =
fun hash ~key iter ->
let module H = (val module_of hash) in
H.hmaci_string ~key iter
let hmaci_bigstring : type k. k hash -> key:string -> bigstring iter -> k t =
fun hash ~key iter ->
let module H = (val module_of hash) in
H.hmaci_bigstring ~key iter
(* XXX(dinosaure): unsafe part to avoid overhead. *)
let unsafe_compare : type k. k hash -> k t -> k t -> int =
fun hash a b ->
let module H = (val module_of hash) in
H.unsafe_compare a b
let equal : type k. k hash -> k t equal =
fun hash a b ->
let module H = (val module_of hash) in
H.equal a b
let pp : type k. k hash -> k t pp =
fun hash ppf t ->
let module H = (val module_of hash) in
H.pp ppf t
let of_hex : type k. k hash -> string -> k t =
fun hash hex ->
let module H = (val module_of hash) in
H.of_hex hex
let of_hex_opt : type k. k hash -> string -> k t option =
fun hash hex ->
let module H = (val module_of hash) in
H.of_hex_opt hex
let consistent_of_hex : type k. k hash -> string -> k t =
fun hash hex ->
let module H = (val module_of hash) in
H.consistent_of_hex hex
let consistent_of_hex_opt : type k. k hash -> string -> k t option =
fun hash hex ->
let module H = (val module_of hash) in
H.consistent_of_hex_opt hex
let to_hex : type k. k hash -> k t -> string =
fun hash t ->
let module H = (val module_of hash) in
H.to_hex t
let of_raw_string : type k. k hash -> string -> k t =
fun hash s ->
let module H = (val module_of hash) in
H.of_raw_string s
let of_raw_string_opt : type k. k hash -> string -> k t option =
fun hash s ->
let module H = (val module_of hash) in
H.of_raw_string_opt s
let to_raw_string : type k. k hash -> k t -> string =
fun hash t ->
let module H = (val module_of hash) in
H.to_raw_string t
let of_digest (type hash) (module H : S with type t = hash) (hash : H.t) :
hash t =
hash
let of_md5 hash = hash
let of_sha1 hash = hash
let of_rmd160 hash = hash
let of_sha224 hash = hash
let of_sha256 hash = hash
let of_sha384 hash = hash
let of_sha512 hash = hash
let of_sha3_224 hash = hash
let of_sha3_256 hash = hash
let of_keccak_256 hash = hash
let of_sha3_384 hash = hash
let of_sha3_512 hash = hash
let of_whirlpool hash = hash
let of_blake2b hash = hash
let of_blake2s hash = hash

View file

@ -0,0 +1,13 @@
(library
(name digestif_ocaml)
(public_name digestif.ocaml)
(implements digestif)
(libraries eqaf)
(private_modules xor digestif_eq digestif_conv digestif_by digestif_bi
baijiu_whirlpool baijiu_sha1 baijiu_sha256 baijiu_sha384 baijiu_sha224
baijiu_sha512 baijiu_sha3_224 baijiu_sha256 baijiu_sha3_384
baijiu_sha3_512 baijiu_rmd160 baijiu_md5 baijiu_blake2s baijiu_blake2b)
(flags
(:standard -no-keep-locs)))
(copy_files# ../src/*.ml)

View file

@ -0,0 +1,57 @@
module Nat = struct
include Nativeint
let ( lxor ) = Nativeint.logxor
end
module type BUFFER = sig
type t
val length : t -> int
val sub : t -> int -> int -> t
val copy : t -> t
val benat_to_cpu : t -> int -> nativeint
val cpu_to_benat : t -> int -> nativeint -> unit
end
let imin (a : int) (b : int) = if a < b then a else b
module Make (B : BUFFER) = struct
let size_of_long = Sys.word_size / 8
(* XXX(dinosaure): I'm not sure about this code. May be we don't need the
first loop and the _optimization_ is irrelevant. *)
let xor_into src src_off dst dst_off n =
let n = ref n in
let i = ref 0 in
while !n >= size_of_long do
B.cpu_to_benat dst (dst_off + !i)
Nat.(
B.benat_to_cpu dst (dst_off + !i)
lxor B.benat_to_cpu src (src_off + !i)) ;
n := !n - size_of_long ;
i := !i + size_of_long
done ;
while !n > 0 do
B.cpu_to_benat dst (dst_off + !i)
Nat.(
B.benat_to_cpu src (src_off + !i)
lxor B.benat_to_cpu dst (dst_off + !i)) ;
incr i ;
decr n
done
let xor_into a b n =
if n > imin (B.length a) (B.length b)
then raise (Invalid_argument "Baijiu.Xor.xor_inrot: buffers to small")
else xor_into a 0 b 0 n
let xor a b =
let l = imin (B.length a) (B.length b) in
let r = B.copy (B.sub b 0 l) in
xor_into a r l ;
r
end
module Bytes = Make (Digestif_by)
module Bigstring = Make (Digestif_bi)

View file

@ -0,0 +1,392 @@
type bigstring =
(char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
type 'a iter = ('a -> unit) -> unit
(** A general (inner) iterator. It applies the provided function to a collection
of elements. For instance:
- [let iter_k : 'a -> 'a iter = fun x f -> f x]
- [let iter_pair : 'a * 'a -> 'a iter = fun (x, y) -> f x; f y]
- [let iter_list : 'a list -> 'a iter = fun l f -> List.iter f l] *)
type 'a compare = 'a -> 'a -> int
type 'a equal = 'a -> 'a -> bool
type 'a pp = Format.formatter -> 'a -> unit
module type S = sig
val digest_size : int
(** Size of hash results, in bytes. *)
type ctx
type hmac
type t
val empty : ctx
(** An empty hash context. *)
val init : unit -> ctx
(** Create a new hash state. *)
val feed_bytes : ctx -> ?off:int -> ?len:int -> Bytes.t -> ctx
(** [feed_bytes msg t] adds informations in [msg] to [t]. [feed] is analogous
to appending: [feed (feed t msg1) msg2 = feed t (append msg1 msg2)] *)
val feed_string : ctx -> ?off:int -> ?len:int -> String.t -> ctx
(** Same as {!feed_bytes} but for {!String.t}. *)
val feed_bigstring : ctx -> ?off:int -> ?len:int -> bigstring -> ctx
(** Same as {!feed_bytes} but for {!bigstring}. *)
val feedi_bytes : ctx -> Bytes.t iter -> ctx
(** [feedi_bytes t iter = let r = ref t in iter (fun msg -> r := feed !r msg);
!r] *)
val feedi_string : ctx -> String.t iter -> ctx
(** Same as {!feed_bytes} but for {!String.t}. *)
val feedi_bigstring : ctx -> bigstring iter -> ctx
(** Same as {!feed_bytes} but for {!bigstring}. *)
val get : ctx -> t
(** [get t] is the digest corresponding to [t]. *)
val hmac_init : key:string -> hmac
(** Create a new hmac state. *)
val hmac_feed_bytes : hmac -> ?off:int -> ?len:int -> Bytes.t -> hmac
(** [hmac_feed_bytes msg t] adds informations in [msg] to [t]. [hmac_feed] is
analogous to appending:
[hmac_feed (hmac_feed t msg1) msg2 = hmac_feed t
(append msg1 msg2)] *)
val hmac_feed_string : hmac -> ?off:int -> ?len:int -> String.t -> hmac
(** Same as {!hmac_feed_bytes} but for {!String.t}. *)
val hmac_feed_bigstring : hmac -> ?off:int -> ?len:int -> bigstring -> hmac
(** Same as {!hmac_feed_bytes} but for {!bigstring}. *)
val hmac_feedi_bytes : hmac -> Bytes.t iter -> hmac
(** [hmac_feedi_bytes t iter = let r = ref t in iter (fun msg -> r := hmac_feed !r msg);
!r] *)
val hmac_feedi_string : hmac -> String.t iter -> hmac
(** Same as {!hmac_feedi_bytes} but for {!String.t}. *)
val hmac_feedi_bigstring : hmac -> bigstring iter -> hmac
(** Same as {!hmac_feedi_bytes} but for {!bigstring}. *)
val hmac_get : hmac -> t
(** [hmac_get t] is the hmac corresponding to [t]. *)
val digest_bytes : ?off:int -> ?len:int -> Bytes.t -> t
(** [digest_bytes msg] is the digest of [msg].
[digest_bytes msg = get (feed_bytes empty msg)]. *)
val digest_string : ?off:int -> ?len:int -> String.t -> t
(** Same as {!digest_bytes} but for a {!String.t}. *)
val digest_bigstring : ?off:int -> ?len:int -> bigstring -> t
(** Same as {!digest_bytes} but for a {!bigstring}. *)
val digesti_bytes : Bytes.t iter -> t
(** [digesti_bytes iter = feedi_bytes empty iter |> get]. *)
val digesti_string : String.t iter -> t
(** Same as {!digesti_bytes} but for {!String.t}. *)
val digesti_bigstring : bigstring iter -> t
(** Same as {!digesti_bigstring} but for {!bigstring}. *)
val digestv_bytes : Bytes.t list -> t
(** Specialization of {!digesti_bytes} with a list of {!Bytes.t} (see
{!iter}). *)
val digestv_string : String.t list -> t
(** Same as {!digestv_bytes} but for {!String.t}. *)
val digestv_bigstring : bigstring list -> t
(** Same as {!digestv_bytes} but for {!bigstring}. *)
val hmac_bytes : key:string -> ?off:int -> ?len:int -> Bytes.t -> t
(** [hmac_bytes ~key bytes] is the authentication code for {!Bytes.t} under
the secret [key], generated using the standard HMAC construction over this
hash algorithm. *)
val hmac_string : key:string -> ?off:int -> ?len:int -> String.t -> t
(** Same as {!hmac_bytes} but for {!String.t}. *)
val hmac_bigstring : key:string -> ?off:int -> ?len:int -> bigstring -> t
(** Same as {!hmac_bytes} but for {!bigstring}. *)
val hmaci_bytes : key:string -> Bytes.t iter -> t
(** Authentication code under the secret [key] over a collection of
{!Bytes.t}. *)
val hmaci_string : key:string -> String.t iter -> t
(** Same as {!hmaci_bytes} but for {!String.t}. *)
val hmaci_bigstring : key:string -> bigstring iter -> t
(** Same as {!hmaci_bytes} but for {!bigstring}. *)
val hmacv_bytes : key:string -> Bytes.t list -> t
(** Specialization of {!hmaci_bytes} with a list of {!Bytes.t} (see {!iter}). *)
val hmacv_string : key:string -> String.t list -> t
(** Same as {!hmacv_bytes} but for {!String.t}. *)
val hmacv_bigstring : key:string -> bigstring list -> t
(** Same as {!hmacv_bigstring} but for {!bigstring}. *)
val unsafe_compare : t compare
(** [unsafe_compare] function returns [0] on equality and a negative/positive
[int] depending on the difference (like {!String.compare}). This is
usually OK, but this is not constant time, so in some cases it could leak
some information. *)
val equal : t equal
(** The equal (constant-time) function for {!t}. *)
val pp : t pp
(** Pretty-printer of {!t}. *)
val of_hex : string -> t
(** [of_hex] tries to parse an hexadecimal representation of {!t}. [of_hex]
raises an [invalid_argument] when input is malformed. We take only firsts
{!digest_size} hexadecimal values and ignore rest of input. If it has not
enough hexadecimal values, trailing values of the output hash are zero
([\x00]), *)
val of_hex_opt : string -> t option
(** [of_hex] tries to parse an hexadecimal representation of {!t}. [of_hex]
returns [None] when input is malformed. We take only first {!digest_size}
hexadecimal values and ignore rest of input. If it has not enough
hexadecimal values, trailing values of the output hash are zero ([\x00]). *)
val consistent_of_hex : string -> t
(** [consistent_of_hex] tries to parse an hexadecimal representation of {!t}.
[consistent_of_hex] raises an [invalid_argument] when input is malformed.
However, instead {!of_hex}, [consistent_of_hex] expects exactly
[{!digest_size} * 2] hexadecimal values (but continues to ignore
whitespaces). *)
val consistent_of_hex_opt : string -> t option
(** [consistent_of_hex_opt] tries to parse an hexadecimal representation of
{!t}. [consistent_of_hex] returns [None] when input is malformed. However,
instead {!of_hex}, [consistent_of_hex] expects exactly
[{!digest_size} * 2] hexadecimal values (but continues to ignore
whitespaces). *)
val to_hex : t -> string
(** [to_hex] makes a hex-decimal representation of {!t}. *)
val of_raw_string : string -> t
(** [of_raw_string s] see [s] as a hash. Useful when reading serialized
hashes. *)
val of_raw_string_opt : string -> t option
(** [of_raw_string_opt s] see [s] as a hash. Useful when reading serialized
hashes. Returns [None] if [s] is not the {!digest_size} bytes long. *)
val to_raw_string : t -> string
(** [to_raw_string s] is [(s :> string)]. *)
val get_into_bytes : ctx -> ?off:int -> bytes -> unit
(** [get_into_bytes ctx ?off buf] writes the result into the given [buf] at
[off] (defaults to [0]).
It's equivalent to:
{[
let get_into_bytes ctx ?(off = 0) buf =
let t = get ctx in
let str = to_raw_string t in
Bytes.blit_string str 0 buf off digest_size
]}
except [get_into_bytes] does not allocate an intermediate string. *)
end
(** Some hash algorithms expose extra MAC constructs. The interface is similar
to the [hmac_*] functions in [S]. *)
module type MAC = sig
type t
val mac_bytes : key:string -> ?off:int -> ?len:int -> Bytes.t -> t
val mac_string : key:string -> ?off:int -> ?len:int -> String.t -> t
val mac_bigstring : key:string -> ?off:int -> ?len:int -> bigstring -> t
val maci_bytes : key:string -> Bytes.t iter -> t
val maci_string : key:string -> String.t iter -> t
val maci_bigstring : key:string -> bigstring iter -> t
val macv_bytes : key:string -> Bytes.t list -> t
val macv_string : key:string -> String.t list -> t
val macv_bigstring : key:string -> bigstring list -> t
end
module MD5 : S
module SHA1 : S
module SHA224 : S
module SHA256 : S
module SHA384 : S
module SHA512 : S
module SHA3_224 : S
(** SHA3 224 hash algorithm.
@since 0.9.0 *)
module SHA3_256 : S
(** SHA3 256 hash algorithm.
@since 0.9.0 *)
module KECCAK_256 : S
(** KECCAK 256 hash algorithm.
@since 1.1.0 *)
module SHA3_384 : S
(** SHA3 384 hash algorithm.
@since 0.9.0 *)
module SHA3_512 : S
(** SHA3 512 hash algorithm.
@since 0.9.0 *)
module WHIRLPOOL : S
(** WHIRLPOOL hash algorithm.
@since 0.7.1 *)
module BLAKE2B : sig
include S
module Keyed : MAC with type t = t
end
module BLAKE2S : sig
include S
module Keyed : MAC with type t = t
end
module RMD160 : S
(** RMD160 hash algorithm.
@since 0.4 *)
module Make_BLAKE2B (D : sig
val digest_size : int
end) : S
module Make_BLAKE2S (D : sig
val digest_size : int
end) : S
type 'k hash =
| MD5 : MD5.t hash
| SHA1 : SHA1.t hash
| RMD160 : RMD160.t hash
| SHA224 : SHA224.t hash
| SHA256 : SHA256.t hash
| SHA384 : SHA384.t hash
| SHA512 : SHA512.t hash
| SHA3_224 : SHA3_224.t hash
| SHA3_256 : SHA3_256.t hash
| KECCAK_256 : KECCAK_256.t hash
| SHA3_384 : SHA3_384.t hash
| SHA3_512 : SHA3_512.t hash
| WHIRLPOOL : WHIRLPOOL.t hash
| BLAKE2B : BLAKE2B.t hash
| BLAKE2S : BLAKE2S.t hash
type hash' =
[ `MD5
| `SHA1
| `RMD160
| `SHA224
| `SHA256
| `SHA384
| `SHA512
| `SHA3_224
| `SHA3_256
| `KECCAK_256
| `SHA3_384
| `SHA3_512
| `WHIRLPOOL
| `BLAKE2B
| `BLAKE2S ]
val module_of_hash' : hash' -> (module S)
val hash_to_hash' : _ hash -> hash'
val md5 : MD5.t hash
val sha1 : SHA1.t hash
val rmd160 : RMD160.t hash
val sha224 : SHA224.t hash
val sha256 : SHA256.t hash
val sha384 : SHA384.t hash
val sha512 : SHA512.t hash
val sha3_224 : SHA3_224.t hash
val sha3_256 : SHA3_256.t hash
val keccak_256 : KECCAK_256.t hash
val sha3_384 : SHA3_384.t hash
val sha3_512 : SHA3_512.t hash
val whirlpool : WHIRLPOOL.t hash
val blake2b : BLAKE2B.t hash
val blake2s : BLAKE2S.t hash
type 'kind t
val module_of : 'k hash -> (module S with type t = 'k)
val digest_bytes : 'k hash -> Bytes.t -> 'k t
val digest_string : 'k hash -> String.t -> 'k t
val digest_bigstring : 'k hash -> bigstring -> 'k t
val digesti_bytes : 'k hash -> Bytes.t iter -> 'k t
val digesti_string : 'k hash -> String.t iter -> 'k t
val digesti_bigstring : 'k hash -> bigstring iter -> 'k t
val hmaci_bytes : 'k hash -> key:string -> Bytes.t iter -> 'k t
val hmaci_string : 'k hash -> key:string -> String.t iter -> 'k t
val hmaci_bigstring : 'k hash -> key:string -> bigstring iter -> 'k t
val pp : 'k hash -> 'k t pp
val equal : 'k hash -> 'k t equal
val unsafe_compare : 'k hash -> 'k t compare
val to_hex : 'k hash -> 'k t -> string
val of_hex : 'k hash -> string -> 'k t
val of_hex_opt : 'k hash -> string -> 'k t option
val consistent_of_hex : 'k hash -> string -> 'k t
val consistent_of_hex_opt : 'k hash -> string -> 'k t option
val of_raw_string : 'k hash -> string -> 'k t
val of_raw_string_opt : 'k hash -> string -> 'k t option
val to_raw_string : 'k hash -> 'k t -> string
val of_digest : (module S with type t = 'hash) -> 'hash -> 'hash t
val of_md5 : MD5.t -> MD5.t t
val of_sha1 : SHA1.t -> SHA1.t t
val of_rmd160 : RMD160.t -> RMD160.t t
(** @since 0.4 *)
val of_sha224 : SHA224.t -> SHA224.t t
val of_sha256 : SHA256.t -> SHA256.t t
val of_sha384 : SHA384.t -> SHA384.t t
val of_sha512 : SHA512.t -> SHA512.t t
val of_sha3_224 : SHA3_224.t -> SHA3_224.t t
(** @since 0.9.0 *)
val of_sha3_256 : SHA3_256.t -> SHA3_256.t t
(** @since 0.9.0 *)
val of_keccak_256 : KECCAK_256.t -> KECCAK_256.t t
(** @since 1.1.0 *)
val of_sha3_384 : SHA3_384.t -> SHA3_384.t t
(** @since 0.9.0 *)
val of_sha3_512 : SHA3_512.t -> SHA3_512.t t
(** @since 0.9.0 *)
val of_whirlpool : WHIRLPOOL.t -> WHIRLPOOL.t t
(** @since 0.7.1 *)
val of_blake2b : BLAKE2B.t -> BLAKE2B.t t
val of_blake2s : BLAKE2S.t -> BLAKE2S.t t

View file

@ -0,0 +1,82 @@
open Bigarray
type t = (char, int8_unsigned_elt, c_layout) Array1.t
let create n = Array1.create Char c_layout n
let length = Array1.dim
let sub = Array1.sub
let empty = Array1.create Char c_layout 0
let get = Array1.get
let copy t =
let r = create (length t) in
Array1.blit t r ;
r
let init l f =
let v = Array1.create Char c_layout l in
for i = 0 to l - 1 do
Array1.set v i (f i)
done ;
v
external unsafe_get_32 : t -> int -> int32 = "%caml_bigstring_get32u"
external unsafe_get_64 : t -> int -> int64 = "%caml_bigstring_get64u"
let unsafe_get_nat : t -> int -> nativeint =
fun s i ->
if Sys.word_size = 32
then Nativeint.of_int32 @@ unsafe_get_32 s i
else Int64.to_nativeint @@ unsafe_get_64 s i
external unsafe_set_32 : t -> int -> int32 -> unit = "%caml_bigstring_set32u"
external unsafe_set_64 : t -> int -> int64 -> unit = "%caml_bigstring_set64u"
let unsafe_set_nat : t -> int -> nativeint -> unit =
fun s i v ->
if Sys.word_size = 32
then unsafe_set_32 s i (Nativeint.to_int32 v)
else unsafe_set_64 s i (Int64.of_nativeint v)
let to_string v = String.init (length v) (Array1.get v)
let blit_from_bytes src src_off dst dst_off len =
for i = 0 to len - 1 do
Array1.set dst (dst_off + i) (Bytes.get src (src_off + i))
done
external swap32 : int32 -> int32 = "%bswap_int32"
external swap64 : int64 -> int64 = "%bswap_int64"
external swapnat : nativeint -> nativeint = "%bswap_native"
let cpu_to_be32 s i v =
if Sys.big_endian then unsafe_set_32 s i v else unsafe_set_32 s i (swap32 v)
let cpu_to_le32 s i v =
if Sys.big_endian then unsafe_set_32 s i (swap32 v) else unsafe_set_32 s i v
let cpu_to_be64 s i v =
if Sys.big_endian then unsafe_set_64 s i v else unsafe_set_64 s i (swap64 v)
let cpu_to_le64 s i v =
if Sys.big_endian then unsafe_set_64 s i (swap64 v) else unsafe_set_64 s i v
let be32_to_cpu s i =
if Sys.big_endian then unsafe_get_32 s i else swap32 @@ unsafe_get_32 s i
let le32_to_cpu s i =
if Sys.big_endian then swap32 @@ unsafe_get_32 s i else unsafe_get_32 s i
let be64_to_cpu s i =
if Sys.big_endian then unsafe_get_64 s i else swap64 @@ unsafe_get_64 s i
let le64_to_cpu s i =
if Sys.big_endian then swap64 @@ unsafe_get_64 s i else unsafe_get_64 s i
let benat_to_cpu s i =
if Sys.big_endian then unsafe_get_nat s i else swapnat @@ unsafe_get_nat s i
let cpu_to_benat s i v =
if Sys.big_endian
then unsafe_set_nat s i v
else unsafe_set_nat s i (swapnat v)

View file

@ -0,0 +1,67 @@
include Bytes
external unsafe_get_32 : t -> int -> int32 = "%caml_bytes_get32u"
external unsafe_get_64 : t -> int -> int64 = "%caml_bytes_get64u"
let unsafe_get_nat : t -> int -> nativeint =
fun s i ->
if Sys.word_size = 32
then Nativeint.of_int32 @@ unsafe_get_32 s i
else Int64.to_nativeint @@ unsafe_get_64 s i
external unsafe_set_32 : t -> int -> int32 -> unit = "%caml_bytes_set32u"
external unsafe_set_64 : t -> int -> int64 -> unit = "%caml_bytes_set64u"
let unsafe_set_nat : t -> int -> nativeint -> unit =
fun s i v ->
if Sys.word_size = 32
then unsafe_set_32 s i (Nativeint.to_int32 v)
else unsafe_set_64 s i (Int64.of_nativeint v)
let blit_from_bigstring src src_off dst dst_off len =
for i = 0 to len - 1 do
set dst (dst_off + i) src.{src_off + i}
done
let rpad a size x =
let l = length a in
let b = create size in
blit a 0 b 0 l ;
fill b l (size - l) x ;
b
external swap32 : int32 -> int32 = "%bswap_int32"
external swap64 : int64 -> int64 = "%bswap_int64"
external swapnat : nativeint -> nativeint = "%bswap_native"
let cpu_to_be32 s i v =
if Sys.big_endian then unsafe_set_32 s i v else unsafe_set_32 s i (swap32 v)
let cpu_to_le32 s i v =
if Sys.big_endian then unsafe_set_32 s i (swap32 v) else unsafe_set_32 s i v
let cpu_to_be64 s i v =
if Sys.big_endian then unsafe_set_64 s i v else unsafe_set_64 s i (swap64 v)
let cpu_to_le64 s i v =
if Sys.big_endian then unsafe_set_64 s i (swap64 v) else unsafe_set_64 s i v
let be32_to_cpu s i =
if Sys.big_endian then unsafe_get_32 s i else swap32 @@ unsafe_get_32 s i
let le32_to_cpu s i =
if Sys.big_endian then swap32 @@ unsafe_get_32 s i else unsafe_get_32 s i
let be64_to_cpu s i =
if Sys.big_endian then unsafe_get_64 s i else swap64 @@ unsafe_get_64 s i
let le64_to_cpu s i =
if Sys.big_endian then swap64 @@ unsafe_get_64 s i else unsafe_get_64 s i
let benat_to_cpu s i =
if Sys.big_endian then unsafe_get_nat s i else swapnat @@ unsafe_get_nat s i
let cpu_to_benat s i v =
if Sys.big_endian
then unsafe_set_nat s i v
else unsafe_set_nat s i (swapnat v)

View file

@ -0,0 +1,104 @@
let invalid_arg fmt = Format.ksprintf (fun s -> invalid_arg s) fmt
module Make (D : sig
val digest_size : int
end) =
struct
let to_hex hash =
let res = Bytes.create (D.digest_size * 2) in
let chr x =
match x with
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 -> Char.chr (48 + x)
| _ -> Char.chr (97 + (x - 10)) in
for i = 0 to D.digest_size - 1 do
let v = Char.code hash.[i] in
Bytes.unsafe_set res (i * 2) (chr (v lsr 4)) ;
Bytes.unsafe_set res ((i * 2) + 1) (chr (v land 0x0F))
done ;
Bytes.unsafe_to_string res
let code x =
match x with
| '0' .. '9' -> Char.code x - Char.code '0'
| 'A' .. 'F' -> Char.code x - Char.code 'A' + 10
| 'a' .. 'f' -> Char.code x - Char.code 'a' + 10
| _ -> invalid_arg "of_hex: %02X" (Char.code x)
let decode chr1 chr2 = Char.chr ((code chr1 lsl 4) lor code chr2)
let of_hex hex =
let offset = ref 0 in
let rec go have_first idx =
if !offset + idx >= String.length hex
then '\x00'
else
match hex.[!offset + idx] with
| ' ' | '\t' | '\r' | '\n' ->
incr offset ;
go have_first idx
| chr2 when have_first -> chr2
| chr1 ->
incr offset ;
let chr2 = go true idx in
if chr2 <> '\x00'
then decode chr1 chr2
else invalid_arg "of_hex: odd number of hex characters" in
String.init D.digest_size (go false)
let of_hex_opt hex =
match of_hex hex with
| digest -> Some digest
| exception Invalid_argument _ -> None
let consistent_of_hex str =
let offset = ref 0 in
let rec go have_first idx =
if !offset + idx >= String.length str
then invalid_arg "Not enough hex value"
else
match str.[!offset + idx] with
| ' ' | '\t' | '\r' | '\n' ->
incr offset ;
go have_first idx
| chr2 when have_first -> chr2
| chr1 ->
incr offset ;
let chr2 = go true idx in
decode chr1 chr2 in
let res = String.init D.digest_size (go false) in
let is_wsp = function ' ' | '\t' | '\r' | '\n' -> true | _ -> false in
while
D.digest_size + !offset < String.length str
&& is_wsp str.[!offset + (D.digest_size * 2)]
do
incr offset
done ;
if !offset + D.digest_size = String.length str
then res
else
invalid_arg "Too much enough bytes (reach: %d, expect: %d)"
(!offset + (D.digest_size * 2))
(String.length str)
let consistent_of_hex_opt hex =
match consistent_of_hex hex with
| digest -> Some digest
| exception Invalid_argument _ -> None
let pp ppf hash =
for i = 0 to D.digest_size - 1 do
Format.fprintf ppf "%02x" (Char.code hash.[i])
done
let of_raw_string x =
if String.length x <> D.digest_size
then invalid_arg "invalid hash size"
else x
let of_raw_string_opt x =
match of_raw_string x with
| digest -> Some digest
| exception Invalid_argument _ -> None
let to_raw_string x = x
end

View file

@ -0,0 +1,8 @@
module Make (D : sig
val digest_size : int
end) =
struct
let _ = D.digest_size
let equal a b = Eqaf.equal a b
let unsafe_compare a b = String.compare a b
end

View file

@ -0,0 +1,8 @@
(library
(name digestif)
(public_name digestif)
(modules digestif)
(wrapped false)
(virtual_modules digestif)
(default_implementation digestif.c)
(libraries eqaf))

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,44 @@
(executable
(name test)
(modules test)
(libraries fmt alcotest digestif.c))
(rule
(alias runtest)
(deps
(:test test.exe)
../blake2b.test
../blake2s.test
../sha3_224_fips_202.txt
../sha3_256_fips_202.txt
../sha3_384_fips_202.txt
../sha3_512_fips_202.txt
../keccak_256.txt)
(action
(run %{test} --color=always)))
(executable
(name test_cve)
(modules test_cve)
(enabled_if
(or
(= %{architecture} "arm64")
(= %{architecture} "amd64")))
(libraries fmt alcotest digestif.c))
(rule
(alias runtest)
(enabled_if
(or
(= %{architecture} "arm64")
(= %{architecture} "amd64")))
(deps
(:test test_cve.exe))
(action
(run %{test} --quick-tests --color=always)))
(rule
(copy# ../test.ml test.ml))
(rule
(copy# ../test_cve.ml test_cve.ml))

View file

@ -0,0 +1,11 @@
(executable
(name test_conv)
(modules test_conv)
(libraries digestif.c fmt alcotest))
(rule
(alias runtest)
(enabled_if
(= ${os_type} "Unix"))
(action
(run ./test_conv.exe --color=always)))

View file

@ -0,0 +1,112 @@
external random_seed : unit -> int array = "caml_sys_random_seed"
let seed = random_seed ()
let () = Random.full_init seed
let () = Fmt.epr "seed: %a.\n%!" Fmt.(Dump.array int) seed
let strf = Fmt.str
let invalid_arg = Fmt.invalid_arg
let list_init f l =
let rec go acc = function
| 0 -> List.rev acc
| n -> go (f n :: acc) (pred n) in
go [] l
let random_string length _ =
let ic = open_in_bin "/dev/urandom" in
let rs = really_input_string ic length in
close_in ic ;
rs
let hashes = list_init (random_string Digestif.SHA1.digest_size) 32
let hashes = List.map Digestif.SHA1.of_raw_string hashes
let consistent_hex =
List.map Digestif.SHA1.to_hex (* XXX(dinosaure): an oracle [to_hex]? *) hashes
let random_wsp length =
let go _ =
match Random.int 4 with
| 0 -> ' '
| 1 -> '\t'
| 2 -> '\n'
| 3 -> '\r'
| _ -> assert false in
String.init length go
let spaces_expand hex =
let rt = ref [] in
String.iter
(fun chr -> rt := !rt @ [ random_wsp (Random.int 10); String.make 1 chr ])
hex ;
String.concat "" !rt
let spaces_hex = List.map spaces_expand consistent_hex
let random_hex length =
let go _ =
match Random.int (10 + 26 + 26) with
| n when n < 10 -> Char.chr (Char.code '0' + n)
| n when n < 10 + 26 -> Char.chr (Char.code 'a' + n - 10)
| n -> Char.chr (Char.code 'A' + n - (10 + 26)) in
String.init length go
let inconsistent_hex =
let expand hex =
String.concat ""
[ spaces_expand hex; spaces_expand (random_hex (5 + Random.int 20)) ]
in
List.map expand consistent_hex
let test_consistent_hex_success i hex =
Alcotest.test_case (strf "consistent hex:%d" i) `Quick @@ fun () ->
ignore @@ Digestif.SHA1.consistent_of_hex hex
let test_hex_success i hex =
Alcotest.test_case (strf "hex:%d" i) `Quick @@ fun () ->
ignore @@ Digestif.SHA1.of_hex hex
let test_consistent_hex_fail i hex =
Alcotest.test_case (strf "consistent hex fail:%d" i) `Quick @@ fun () ->
try
let _ = Digestif.SHA1.consistent_of_hex hex in
assert false
with Invalid_argument _ -> ()
let sha1 = Alcotest.testable Digestif.SHA1.pp Digestif.SHA1.equal
let test_hex_iso i random_input =
Alcotest.test_case (strf "iso:%d" i) `Quick @@ fun () ->
let hash : Digestif.SHA1.t = Digestif.SHA1.of_raw_string random_input in
let hex = Digestif.SHA1.to_hex hash in
Alcotest.(check sha1) "iso hex" (Digestif.SHA1.of_hex hex) hash
let test_consistent_hex_iso i random_input =
Alcotest.test_case (strf "iso:%d" i) `Quick @@ fun () ->
let hash : Digestif.SHA1.t = Digestif.SHA1.of_raw_string random_input in
let hex = Digestif.SHA1.to_hex hash in
Alcotest.(check sha1)
"iso consistent hex"
(Digestif.SHA1.consistent_of_hex hex)
hash
let tests () =
Alcotest.run "digestif"
[
("of_hex 0", List.mapi test_hex_success consistent_hex);
( "consistent_of_hex 0",
List.mapi test_consistent_hex_success consistent_hex );
("of_hex 1", List.mapi test_hex_success spaces_hex);
("consistent_of_hex 1", List.mapi test_consistent_hex_success spaces_hex);
("of_hex 2", List.mapi test_hex_success inconsistent_hex);
( "consistent_of_hex 2",
List.mapi test_consistent_hex_fail inconsistent_hex );
( "iso of_hex",
List.mapi test_hex_iso
(list_init (random_string Digestif.SHA1.digest_size) 64) );
( "iso consistent_of_hex",
List.mapi test_consistent_hex_iso
(list_init (random_string Digestif.SHA1.digest_size) 64) );
]
let () = tests ()

View file

@ -0,0 +1,44 @@
(executable
(name test)
(modules test)
(libraries fmt alcotest digestif.ocaml))
(rule
(alias runtest)
(deps
(:test test.exe)
../blake2b.test
../blake2s.test
../sha3_224_fips_202.txt
../sha3_256_fips_202.txt
../sha3_384_fips_202.txt
../sha3_512_fips_202.txt
../keccak_256.txt)
(action
(run %{test} --quick-tests --color=always)))
(executable
(name test_cve)
(modules test_cve)
(enabled_if
(or
(= %{architecture} "arm64")
(= %{architecture} "amd64")))
(libraries fmt alcotest digestif.ocaml))
(rule
(alias runtest)
(enabled_if
(or
(= %{architecture} "arm64")
(= %{architecture} "amd64")))
(deps
(:test test_cve.exe))
(action
(run %{test} --quick-tests --color=always)))
(rule
(copy# ../test.ml test.ml))
(rule
(copy# ../test_cve.ml test_cve.ml))

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,751 @@
type _ s = Bytes : Bytes.t s | String : String.t s | Bigstring : bigstring s
and bigstring =
(char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
let title :
type a k.
[ `HMAC | `HMAC_feed | `Digest ] -> k Digestif.hash -> a s -> string =
fun computation hash input ->
let pp_computation ppf = function
| `HMAC -> Fmt.string ppf "hmac"
| `HMAC_feed -> Fmt.string ppf "hmac_feed"
| `Digest -> Fmt.string ppf "digest" in
let pp_hash : type k. k Digestif.hash Fmt.t =
fun ppf -> function
| Digestif.MD5 -> Fmt.string ppf "md5"
| Digestif.SHA1 -> Fmt.string ppf "sha1"
| Digestif.RMD160 -> Fmt.string ppf "rmd160"
| Digestif.SHA224 -> Fmt.string ppf "sha224"
| Digestif.SHA256 -> Fmt.string ppf "sha256"
| Digestif.SHA384 -> Fmt.string ppf "sha384"
| Digestif.SHA512 -> Fmt.string ppf "sha512"
| Digestif.SHA3_224 -> Fmt.string ppf "sha3_224"
| Digestif.SHA3_256 -> Fmt.string ppf "sha3_256"
| Digestif.KECCAK_256 -> Fmt.string ppf "keccak_256"
| Digestif.SHA3_384 -> Fmt.string ppf "sha3_384"
| Digestif.SHA3_512 -> Fmt.string ppf "sha3_512"
| Digestif.WHIRLPOOL -> Fmt.string ppf "whirlpool"
| Digestif.BLAKE2B -> Fmt.string ppf "blake2b"
| Digestif.BLAKE2S -> Fmt.string ppf "blake2s" in
let pp_input : type a. a s Fmt.t =
fun ppf -> function
| Bytes -> Fmt.string ppf "bytes"
| String -> Fmt.string ppf "string"
| Bigstring -> Fmt.string ppf "bigstring" in
Fmt.str "%a:%a:%a" pp_computation computation pp_hash hash pp_input input
let bytes = Bytes
let string = String
let bigstring = Bigstring
let test_hmac :
type k a. a s -> k Digestif.hash -> string -> a -> k Digestif.t -> unit =
fun kind hash key input expect ->
let title = title `HMAC hash kind in
let test_hash = Alcotest.testable (Digestif.pp hash) (Digestif.equal hash) in
match kind with
| Bytes ->
let result = Digestif.hmaci_bytes hash ~key (fun f -> f input) in
Alcotest.(check test_hash) title expect result
| String ->
let result = Digestif.hmaci_string hash ~key (fun f -> f input) in
Alcotest.(check test_hash) title expect result
| Bigstring ->
let result = Digestif.hmaci_bigstring hash ~key (fun f -> f input) in
Alcotest.(check test_hash) title expect result
let test_hmac_feed :
type k a. a s -> k Digestif.hash -> string -> a -> k -> unit =
fun kind hash key input expect ->
let title = title `HMAC_feed hash kind in
let module H = (val Digestif.module_of hash) in
let test_hash = Alcotest.testable H.pp H.equal in
let hmac_ctx = H.hmac_init ~key in
let total_len =
match kind with
| Bytes -> Bytes.length input
| String -> String.length input
| Bigstring -> Bigarray.Array1.dim input in
let rec loop hmac_ctx off =
if off = total_len
then hmac_ctx
else
let len = min (total_len - off) 16 in
let hmac_ctx =
match kind with
| Bytes -> H.hmac_feed_bytes hmac_ctx ~off ~len input
| String -> H.hmac_feed_string hmac_ctx ~off ~len input
| Bigstring -> H.hmac_feed_bigstring hmac_ctx ~off ~len input in
loop hmac_ctx (off + len) in
Alcotest.check test_hash title expect (H.hmac_get (loop hmac_ctx 0))
let test_digest : type k a. a s -> k Digestif.hash -> a -> k Digestif.t -> unit
=
fun kind hash input expect ->
let title = title `Digest hash kind in
let test_hash = Alcotest.testable (Digestif.pp hash) (Digestif.equal hash) in
match kind with
| Bytes ->
let result = Digestif.digesti_bytes hash (fun f -> f input) in
Alcotest.(check test_hash) title expect result
| String ->
let result = Digestif.digesti_string hash (fun f -> f input) in
Alcotest.(check test_hash) title expect result
| Bigstring ->
let result = Digestif.digesti_bigstring hash (fun f -> f input) in
Alcotest.(check test_hash) title expect result
let make_hmac :
type a k.
name:string ->
a s ->
k Digestif.hash ->
string ->
a ->
k Digestif.t ->
unit Alcotest.test_case =
fun ~name kind hash key input expect ->
(name, `Quick, fun () -> test_hmac kind hash key input expect)
let make_hmac_feed :
type a k.
name:string ->
a s ->
k Digestif.hash ->
string ->
a ->
k ->
unit Alcotest.test_case =
fun ~name kind hash key input expect ->
(name, `Quick, fun () -> test_hmac_feed kind hash key input expect)
let make_digest :
type a k.
name:string ->
a s ->
k Digestif.hash ->
a ->
k Digestif.t ->
unit Alcotest.test_case =
fun ~name kind hash input expect ->
(name, `Quick, fun () -> test_digest kind hash input expect)
let combine a b c =
let rec aux r a b c =
match (a, b, c) with
| xa :: ra, xb :: rb, xc :: rc -> aux ((xa, xb, xc) :: r) ra rb rc
| [], [], [] -> List.rev r
| _ -> raise (Invalid_argument "combine") in
aux [] a b c
let makes ~name kind hash keys inputs expects =
List.map
(fun (key, input, expect) -> make_hmac ~name kind hash key input expect)
(combine keys inputs expects)
let makes' ~name kind hash keys inputs expects =
List.map
(fun (key, input, expect) ->
make_hmac_feed ~name kind hash key input expect)
(combine keys inputs expects)
let to_bigstring s =
let ln = Bytes.length s in
let bi = Bigarray.Array1.create Bigarray.Char Bigarray.c_layout ln in
for i = 0 to ln - 1 do
bi.{i} <- Bytes.get s i
done ;
bi
let split3 lst =
let rec go (ax, ay, az) = function
| (x, y, z) :: r -> go (x :: ax, y :: ay, z :: az) r
| [] -> (List.rev ax, List.rev ay, List.rev az) in
go ([], [], []) lst
let keys_by, keys_st, keys_bi =
[
"Salut"; "Jefe"; "Lorenzo"; "Le son qui fait plaiz'";
"La c'est un peu chaud en vrai";
]
|> List.map (fun s ->
(Bytes.unsafe_of_string s, s, to_bigstring (Bytes.unsafe_of_string s)))
|> split3
let inputs_by, inputs_st, inputs_bi =
[
"Hi There"; "what do ya want for nothing?";
"C'est Lolo je bois de l'Ice Tea quand j'suis fonsde";
"Mes pecs dansent le flamenco, Lolo l'empereur du sale, dans le deal on \
m'surnomme Joe La Crapule";
"Y'a un pack de douze a cote du cadavre dans le coffre. Pourquoi t'etais \
Charlie mais t'etais pas Jean-Pierre Coffe. Ca sniffe tellement la coke, \
mes crottes de nez c'est d'la MD. J'deteste juste les keufs, j'aime bien \
les obeses et les pedes. Mamene finira dans le dico'. J'ai qu'un reuf: le \
poto Rico. Ca rotte-ca l'argent des clodos. C'est moi qu'ecrit tous les \
pornos. Cite-moi en controle de philo'. Toutes les miss grimpent aux \
rideaux.";
]
|> List.map (fun s ->
(Bytes.unsafe_of_string s, s, to_bigstring (Bytes.unsafe_of_string s)))
|> split3
let results_md5 =
[
"689e721d493b6eeea482947be736c808"; "750c783e6ab0b503eaa86e310a5db738";
"1cdd24eef6163afee7adc7c53dd6c9df"; "0316ebcad933675e84a81850e24d55b2";
"9ee938a2659d546ccc2e5993601964eb";
]
|> List.map (Digestif.of_hex Digestif.md5)
let results_sha1 =
[
"b0a6490a6fcb9479a7aa2306ecb56730d6225dba";
"effcdf6ae5eb2fa2d27416d5f184df9c259a7c79";
"d80589525b1cc9f5e5ffd48ffd73d710ac89a3f1";
"0a5212b295e11a1de5c71873e70ce54f45119516";
"deaf6465e5945a0d04cba439c628ee9f47b95aef";
]
|> List.map (Digestif.of_hex Digestif.sha1)
let results_sha224 =
[
"9a26f1380aae8c580441676891765c8a647ddf16a7d12fa427090901";
"a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44";
"b94a09654fc749ae6cb21c7765bf4938ff9af03e13d83fbf23342ce7";
"7c66e4c7297a22ca80e2e1db9774afea64b1e086be366d2da3e6bc83";
"438dc3311243cd54cc7ee24c9aac8528a1750abc595f06e68a331d2a";
]
|> List.map (Digestif.of_hex Digestif.sha224)
let results_sha256, results_sha256' =
let raw_results_sha256 =
[
"2178f5f21b4311607bf9347bcde5f6552edb9ec5aa13b954d53de2fbfd8b75de";
"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843";
"aa36cd61caddefe26b07ba1d3d07ea978ed575c9d1f921837dff9f73e019713e";
"a7c8b53d68678a8e6e4d403c6b97cf0f82c4ef7b835c41039c0a73aa4d627d05";
"b2a83b628f7e0da71c3879b81075775072d0d35935c62cc6c5a79b337ccccca1";
] in
( List.map (Digestif.of_hex Digestif.sha256) raw_results_sha256,
List.map Digestif.SHA256.of_hex raw_results_sha256 )
let results_sha384 =
[
"43e75797c1d875c5e5e7e90d0525061703d6b95b6137461566c2d067304458e62c144bbe12c0b741dcfaa38f7d41575e";
"af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649";
"bd3b5c82edcd0f206aadff7aa89dbbc3a7655844ffc9f8f9fa17c90eb36b13ec7828fba7252c3f5d90cff666ea44d557";
"16461c2a44877c69fb38e4dce2edc822d68517917fc84d252de64132bd43c7cbe3310b7e8661741b7728000e8abf51e0";
"2c3751d1dc792344514928fad94672a256cf2f66344e4df96b0cc4cc3f6800aa5a628e9becf5f65672e1acf013284893";
]
|> List.map (Digestif.of_hex Digestif.sha384)
let results_sha512 =
[
"5f26752be4a1282646ed8c6a611d4c621e22e3fa96e9e6bc9e19a86deaacf0315151c46f779c3184632ab5793e2ddcb2ff87ca11cc886130f033364b08aef4e2";
"164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737";
"c2f2077f538171d7c6cbee0c94948f82987117a50229fb0b48a534e3c63553a9a9704cdb460c597c8b46b631e49c22a9d2d46bded40f8a77652f754ec725e351";
"89d7284e89642ec195f7a8ef098ef4e411fa3df17a07724cf13033bc6b7863968aad449cee973df9b92800d803ba3e14244231a86253cfacd1de882a542e945f";
"f6ecfca37d2abcff4b362f1919629e784c4b618af77e1061bb992c11d7f518716f5df5978b0a1455d68ceeb10ced9251306d2f26181407be76a219d48c36b592";
]
|> List.map (Digestif.of_hex Digestif.sha512)
let results_sha3_224 =
[
"27d199d761adfa5530313acdf7e1680fbdea09236ac6395b43c4a0e6";
"7fdb8dd88bd2f60d1b798634ad386811c2cfc85bfaf5d52bbace5e66";
"179895b711ca2bebf420a2e7255564d4cb2217ea3ac8b2d45f29d127";
"5bc718d440729ba7d857543eed04cbec3374eb835da33e99f8e0561f";
"0f44044cd2cb5a02ec3b7dff4367c54a1ace6cb7d602e005684aee7c";
]
|> List.map (Digestif.of_hex Digestif.sha3_224)
let results_sha3_256 =
[
"bb25b6f7672dab6734313c8c63aab800b2c451c81833509c1afdb986be9bdea3";
"c7d4072e788877ae3596bbb0da73b887c9171f93095b294ae857fbe2645e1ba5";
"f58a4c9641f87ead6c16525906857f5fce149bb822c4fe7a2abcaebe823d9e0f";
"1dcc5f9bcfb9fa35349d51c40672b2bd971afc32f9cf5e478ec442d6d90be4ce";
"8d1de07fd2312402f94d061a88b02dc1e0173e9d89750284b78d2bb004e9d3c1";
]
|> List.map (Digestif.of_hex Digestif.sha3_256)
let results_keccak_256 =
[
"0dbf49d1c2d4625f87592309b3c7ceb2c1a2194dc866bb21be7ac6abb733f0f1";
"aa9aed448c7abc8b5e326ffa6a01cdedf7b4b831881468c044ba8dd4566369a1";
"7fce3f69adac930d657ce6998d6ad5ee102b5e7560e6690b4ca855e5d4c268a0";
"c6cf40deda9a1028823641235499c9b1891c6e2ab7d2bfa9db06890ce8bc855e";
"8af5e3a5ebc1a9927d43765c85ca455de007e357ea250ae3ed65b55765d3252a";
]
|> List.map (Digestif.of_hex Digestif.keccak_256)
let results_sha3_384 =
[
"fddae4c273e970a5f530cc737b15c1f0546caf0900e29fdf0ce57512a4c6898ca38931d1d3d9827cf16712c52da814e6";
"f1101f8cbf9766fd6764d2ed61903f21ca9b18f57cf3e1a23ca13508a93243ce48c045dc007f26a21b3f5e0e9df4c20a";
"ba546a5edbd7cdf49f2669553241e9867af842eb508432e8191d64282a9bb6e856311be49c8e673d72f212d446d0bee9";
"f8d65fe91fe24a009263e9aee0267c48cafbe422b899a76763eb7ec095b6f0293033a504925a345ec70a3d984f98540d";
"2485a07f2b1585572d492db2dcfffcc30a35e019ad6490af3bef94e514b66f90913fb11a9a365e42d2d03e3cad28b847";
]
|> List.map (Digestif.of_hex Digestif.sha3_384)
let results_sha3_512 =
[
"c2f4417c4dbc86cea2054beb755029c29c8dbed7781595fc9d5222214538a6975afc23f2f9e96683d33f547ea0df897bd1ca766fbb2c4ea674b9b9484e9e782a";
"5a4bfeab6166427c7a3647b747292b8384537cdb89afb3bf5665e4c5e709350b287baec921fd7ca0ee7a0c31d022a95e1fc92ba9d77df883960275beb4e62024";
"967c75d948f8b1efc263c4581287186500bf38daecda304fe68f34dacd622f299218ad47a4a112db5eedd5c8a30b03fefa17d20ddc3a735848f08fdc2d7ae592";
"ba3d37e455183ac5a9af109512d97bcc5e34daa5e10796625db8661519a4027b2cf89d282302bd8a620b8813ee98f781a9388e4f479e189899d820c1dcd50b8c";
"ce4a9d6e2b98b7fbb9ea668cd21b18c361d1d929fc6914192069b8c2672682a36ece8a6de07b17d4448afbc701b460264994ae9c79f26cfdd14a8fdc108d62a1";
]
|> List.map (Digestif.of_hex Digestif.sha3_512)
let results_whirlpool =
[
"1174a4781245c2c78435b68bd0eb5e462f66a455ccfde94f61be594f9db841e7f4e85ba740f31dfd89186724f953cbd454451e987c608958dc9b563fd9594776";
"3d595ccd1d4f4cfd045af53ba7d5c8283fee6ded6eaf1269071b6b4ea64800056b5077c6a942cfa1221bd4e5aed791276e5dd46a407d2b8007163d3e7cd1de66";
"7af46cc6bb193d7958bd55a91509c99570cbd233d48a8fbf05207017040e27671024a21fad3877ecd2a309fc13c403ea8e83c6423ab8d695b654dbf6a1d2e8ee";
"a8646f7e371a1f9de1169d21de9a59ff2a32c73617c9b73708a226081b9316e81442e793e094c41a89e79705f1832c22e0cd3ac93d3b68a6842ddf35169908ae";
"b80dc14932e92fda0ba7f09e1db20d514633d15c2b89ad96a96198f4f751f2acf34e4fe0c9e2d13c4efaf7082c0871584b8dde7a367703d6fdf4f400a52f9432";
]
|> List.map (Digestif.of_hex Digestif.whirlpool)
let results_blake2b =
[
"aba2eef053923ba3a671b54244580ca7c8dfa9c487431c3437e1a8504e166ed894778045a5c6a314fadee110a5254f6f370e9db1d3093a62e0448a5e91b1d4c6";
"6ff884f8ddc2a6586b3c98a4cd6ebdf14ec10204b6710073eb5865ade37a2643b8807c1335d107ecdb9ffeaeb6828c4625ba172c66379efcd222c2de11727ab4";
"42aadab231ff4edbdad29a18262bbb6ba74cf0850f40b64a92dc62a92608a65f06af850aa1988cd1e379cf9cc9a8f64d61125d7b3def292ae57e537bc202e812";
"4abf562dc64f4062ea59ae9b4e2061a7a6c1a75af74b3663fd05aa4437420b8deea657e395a7dbac02aef7b7d70dc8b8a8db99aa8db028961a5ee66bac22b0f0";
"69f9e4236cd0c50204e4f8b86dc1751d37cc195835e9db25c9b366f41e1d86cdeec6a8702dfed1bc0ed0d6a1e2c5af275c331ec91f884c979021fb64021915de";
]
|> List.map (Digestif.of_hex Digestif.blake2b)
let results_rmd160 =
[
"65b3cb3360881842a0d454bd6e7bc1bfe838b384";
"dda6c0213a485a9e24f4742064a7f033b43c4069";
"f071dcd2514fd89de78a5a2db1128dfa3e54d503";
"bda5511e63389385218a8d902a70f2d8dc4dc074";
"6c2486f169432281b6d71ae5b6765239c3cc1ea6";
]
|> List.map (Digestif.of_hex Digestif.rmd160)
let results_blake2s =
[
"5bb23bbe41678b23e6d38881d2515fdf5df253dd2e9a80075ea759c93e1bca3a";
"90b6281e2f3038c9056af0b4a7e763cae6fe5d9eb4386a0ec95237890c104ff0";
"5d0064cb2848ab5dc948876a6be3e5685301a744735c25858c0bd283a7940eb7";
"6903efd2383b13adaa985d00ca271ccb420ab8f953841081c9c15a2dfebf866c";
"b8e167de23a5f136dc26bf06da0d724ebf7310903c2f702403b66810a230d622";
]
|> List.map (Digestif.of_hex Digestif.blake2s)
module BLAKE2 = struct
let input_blake2b_file = "../blake2b.test"
let input_blake2s_file = "../blake2s.test"
let fold_s f a s =
let r = ref a in
String.iter (fun x -> r := f !r x) s ;
!r
let of_hex len hex =
let code x =
match x with
| '0' .. '9' -> Char.code x - 48
| 'A' .. 'F' -> Char.code x - 55
| 'a' .. 'z' -> Char.code x - 87
| _ -> raise (Invalid_argument "of_hex") in
let wsp = function ' ' | '\t' | '\r' | '\n' -> true | _ -> false in
fold_s
(fun (res, i, acc) -> function
| chr when wsp chr -> (res, i, acc)
| chr ->
match (acc, code chr) with
| None, x -> (res, i, Some (x lsl 4))
| Some y, x ->
Bytes.set res i (Char.unsafe_chr (x lor y)) ;
(res, succ i, None))
(Bytes.create len, 0, None)
hex
|> (function
| _, _, Some _ -> invalid_arg "of_hex"
| res, i, _ ->
if i = len
then res
else (
for i = i to len - 1 do
Bytes.set res i '\000'
done ;
res))
|> Bytes.unsafe_to_string
let parse kind ic =
ignore @@ input_line ic ;
ignore @@ input_line ic ;
let rec loop state acc =
match (state, input_line ic) with
| `In, line ->
let i = ref "" in
Scanf.sscanf line "in:\t%s" (fun v ->
i := of_hex (String.length v / 2) v) ;
loop (`Key !i) acc
| `Key i, line -> (
let k = ref None in
Scanf.sscanf line "key:\t%s" (fun v ->
k := Some (Digestif.to_raw_string kind (Digestif.of_hex kind v))) ;
match !k with
| Some k -> loop (`Hash (i, (k :> string))) acc
| None -> loop `In acc)
| `Hash (i, k), line -> (
let h = ref None in
Scanf.sscanf line "hash:\t%s" (fun v ->
h := Some (Digestif.of_hex kind v)) ;
match !h with
| Some h -> loop (`Res (i, k, h)) acc
| None -> loop `In acc)
| `Res v, "" -> loop `In (v :: acc)
| `Res v, _ ->
(* avoid malformed line *)
loop (`Res v) acc
| exception End_of_file -> List.rev acc in
loop `In []
let test_mac :
type k a.
a s ->
k Digestif.hash ->
(module Digestif.MAC) ->
string ->
a ->
k Digestif.t ->
unit =
fun kind hash (module Mac) key input expect ->
let title = title `HMAC hash kind in
let check (result : Mac.t) =
Alcotest.(check string)
title
(Digestif.to_raw_string hash expect)
(Obj.magic result)
(* XXX(dinosaure): ok, this is really bad but I'm lazy to keep type
equality on [Mac] - extend interface and play with [with type t = t]
anywhere. *) in
match kind with
| Bytes -> check @@ Mac.maci_bytes ~key (fun f -> f input)
| String -> check @@ Mac.maci_string ~key (fun f -> f input)
| Bigstring -> check @@ Mac.maci_bigstring ~key (fun f -> f input)
let make_keyed_blake m ~name kind hash key input expect =
(name, `Quick, fun () -> test_mac kind hash m key input expect)
let tests m kind filename =
let ic = open_in filename in
let tests = parse kind ic in
close_in ic ;
List.map
(fun (input, key, expect) ->
make_keyed_blake m ~name:"blake2{b,s}" string kind key input expect)
tests
let tests_blake2s =
tests (module Digestif.BLAKE2S.Keyed) Digestif.blake2s input_blake2s_file
let tests_blake2b =
tests (module Digestif.BLAKE2B.Keyed) Digestif.blake2b input_blake2b_file
end
module RMD160 = struct
let inputs =
[
""; "a"; "abc"; "message digest"; "abcdefghijklmnopqrstuvwxyz";
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
"12345678901234567890123456789012345678901234567890123456789012345678901234567890";
]
let expects =
[
"9c1185a5c5e9fc54612808977ee8f548b2258d31";
"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe";
"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc";
"5d0689ef49d2fae572b881b123a85ffa21595f36";
"f71c27109c692c1b56bbdceb5b9d2865b3708dbc";
"12a053384a9c0c88e405a06c27dcf49ada62eb2b";
"b0e20b6e3116640286ed3a87a5713079b21f5189";
"9b752e45573d4b39f4dbd3323cab82bf63326bfb";
]
let million : expect:Digestif.RMD160.t Digestif.t -> unit Alcotest.test_case =
fun ~expect ->
let iter n f =
let rec go = function
| 0 -> ()
| n ->
f "a" ;
go (n - 1) in
go n in
let result = Digestif.digesti_string Digestif.rmd160 (iter 1_000_000) in
let test_hash =
Alcotest.testable Digestif.(pp rmd160) Digestif.(equal rmd160) in
( "give me a million",
`Slow,
fun () -> Alcotest.(check test_hash) "rmd160" expect result )
let tests =
let expect_million =
Digestif.of_hex Digestif.rmd160 "52783243c1697bdbe16d37f97f68f08325dc1528"
in
List.map
(fun (input, expect) ->
make_digest ~name:"rmd160" string Digestif.rmd160 input expect)
(List.combine inputs (List.map Digestif.(of_hex rmd160) expects))
@ [ million ~expect:expect_million ]
end
let str = Alcotest.testable (fun ppf -> Fmt.pf ppf "%S") String.equal
let blake2s_spe digest_size =
Alcotest.test_case (Fmt.str "BLAKE2S (digest-size: %d)" digest_size) `Quick
@@ fun () ->
let module Hash = Digestif.Make_BLAKE2S (struct
let digest_size = digest_size
end) in
Fmt.epr ">>> Use digest_string\n%!" ;
let hash0 = Hash.digest_string "" in
Fmt.epr ">>> Use feed_string\n%!" ;
let hash1 = Hash.get (Hash.feed_string Hash.empty "") in
let raw_hash0 = Hash.to_raw_string hash0 in
let raw_hash1 = Hash.to_raw_string hash1 in
Alcotest.(check int) "raw length" digest_size (String.length raw_hash0) ;
Alcotest.(check int) "raw length" digest_size (String.length raw_hash1) ;
let hash = Alcotest.testable Hash.pp Hash.equal in
Alcotest.(check hash) "hash" hash0 hash1 ;
Alcotest.(check str) "raw hash" raw_hash0 raw_hash1
let blake2b_spe digest_size =
Alcotest.test_case (Fmt.str "BLAKE2B (digest-size: %d)" digest_size) `Quick
@@ fun () ->
let module Hash = Digestif.Make_BLAKE2B (struct
let digest_size = digest_size
end) in
let hash0 = Hash.digest_string "" in
let hash1 = Hash.get (Hash.feed_string Hash.empty "") in
let raw_hash0 = Hash.to_raw_string hash0 in
let raw_hash1 = Hash.to_raw_string hash1 in
Alcotest.(check int) "raw length" digest_size (String.length raw_hash0) ;
Alcotest.(check int) "raw length" digest_size (String.length raw_hash1) ;
let hash = Alcotest.testable Hash.pp Hash.equal in
Alcotest.(check hash) "hash" hash0 hash1 ;
Alcotest.(check str) "raw hash" raw_hash0 raw_hash1
type kind = V : 'a Digestif.hash -> kind
let ( <.> ) f g x = f (g x)
let code x =
match x with
| '0' .. '9' -> Char.code x - Char.code '0'
| 'A' .. 'F' -> Char.code x - Char.code 'A' + 10
| 'a' .. 'f' -> Char.code x - Char.code 'a' + 10
| _ -> Fmt.invalid_arg "of_hex: %02X" (Char.code x)
let decode chr1 chr2 = Char.chr ((code chr1 lsl 4) lor code chr2)
let of_hex hex =
let offset = ref 0 in
let rec go have_first idx =
if !offset + idx >= String.length hex
then '\x00'
else
match hex.[!offset + idx] with
| ' ' | '\t' | '\r' | '\n' ->
incr offset ;
go have_first idx
| chr2 when have_first -> chr2
| chr1 ->
incr offset ;
let chr2 = go true idx in
if chr2 <> '\x00'
then decode chr1 chr2
else invalid_arg "of_hex: odd number of hex characters" in
String.init (String.length hex / 2) (go false)
let sha3_of_name str =
match Astring.String.cut ~sep:":" str with
| None -> Fmt.invalid_arg "Invalid line: %S" str
| Some (_name, value) -> (
let value = Astring.String.trim value in
match value with
| "SHA3-224" -> V Digestif.sha3_224
| "SHA3-256" -> V Digestif.sha3_256
| "SHA3-384" -> V Digestif.sha3_384
| "SHA3-512" -> V Digestif.sha3_512
| v -> Fmt.invalid_arg "Invalid kind of hash: %s" v)
let parse_field str =
match Astring.String.cut ~sep:":" str with
| Some (_key, v) -> Astring.String.trim v
| None -> Fmt.invalid_arg "Invalid line: %S" str
let empty = "\"\""
let sha3_vector_tests filename =
Alcotest.test_case filename `Quick @@ fun () ->
let ic = open_in filename in
let _algorithm_type = input_line ic in
let _source = input_line ic in
let (V hash) = sha3_of_name (input_line ic) in
let rec go () =
try
let comment = parse_field (input_line ic) in
let message = parse_field (input_line ic) in
Fmt.epr ">>> %S.\n%!" comment ;
Fmt.epr ">>> %S.\n%!" (if message = empty then "" else of_hex message) ;
let digest = (Digestif.of_hex hash <.> parse_field <.> input_line) ic in
let _verify = input_line ic in
let result =
if message = empty
then Digestif.digest_string hash ""
else Digestif.digest_string hash (of_hex message) in
Alcotest.(check (testable (Digestif.pp hash) (Digestif.equal hash)))
comment digest result ;
go ()
with End_of_file -> () in
go () ;
close_in ic
let keccak_vector_tests filename =
Alcotest.test_case filename `Quick @@ fun () ->
let ic = open_in filename in
let _algorithm_type = input_line ic in
let _name = input_line ic in
let hash = Digestif.keccak_256 in
let rec go () =
try
let comment = parse_field (input_line ic) in
let message = parse_field (input_line ic) in
let digest = (Digestif.of_hex hash <.> parse_field <.> input_line) ic in
let _verify = input_line ic in
let result =
if message = empty
then Digestif.digest_string hash ""
else Digestif.digest_string hash (of_hex message) in
Alcotest.(check (testable (Digestif.pp hash) (Digestif.equal hash)))
comment digest result ;
go ()
with End_of_file -> () in
go () ;
close_in ic
let tests () =
Alcotest.run "digestif"
[
("md5", makes ~name:"md5" bytes Digestif.md5 keys_st inputs_by results_md5);
( "md5 (bigstring)",
makes ~name:"md5" bigstring Digestif.md5 keys_st inputs_bi results_md5
);
( "sha1",
makes ~name:"sha1" bytes Digestif.sha1 keys_st inputs_by results_sha1 );
( "sha1 (bigstring)",
makes ~name:"sha1" bigstring Digestif.sha1 keys_st inputs_bi
results_sha1 );
( "sha224",
makes ~name:"sha224" bytes Digestif.sha224 keys_st inputs_by
results_sha224 );
( "sha224 (bigstring)",
makes ~name:"sha224" bigstring Digestif.sha224 keys_st inputs_bi
results_sha224 );
( "sha256",
makes ~name:"sha256" bytes Digestif.sha256 keys_st inputs_by
results_sha256 );
( "sha256 (bigstring)",
makes ~name:"sha256" bigstring Digestif.sha256 keys_st inputs_bi
results_sha256 );
( "sha256 (feed bytes)",
makes' ~name:"sha256" bytes Digestif.sha256 keys_st inputs_by
results_sha256' );
( "sha384",
makes ~name:"sha384" bytes Digestif.sha384 keys_st inputs_by
results_sha384 );
( "sha384 (bigstring)",
makes ~name:"sha384" bigstring Digestif.sha384 keys_st inputs_bi
results_sha384 );
( "sha512",
makes ~name:"sha512" bytes Digestif.sha512 keys_st inputs_by
results_sha512 );
( "sha512 (bigstring)",
makes ~name:"sha512" bigstring Digestif.sha512 keys_st inputs_bi
results_sha512 );
( "sha3_224",
makes ~name:"sha3_224" bytes Digestif.sha3_224 keys_st inputs_by
results_sha3_224 );
( "sha3_224 (bigstring)",
makes ~name:"sha3_224" bigstring Digestif.sha3_224 keys_st inputs_bi
results_sha3_224 );
( "sha3_256",
makes ~name:"sha3_256" bytes Digestif.sha3_256 keys_st inputs_by
results_sha3_256 );
( "sha3_256 (bigstring)",
makes ~name:"sha3_256" bigstring Digestif.sha3_256 keys_st inputs_bi
results_sha3_256 );
( "keccak_256",
makes ~name:"keccak_256" bytes Digestif.keccak_256 keys_st inputs_by
results_keccak_256 );
( "keccak_256 (bigstring)",
makes ~name:"keccak_256" bigstring Digestif.keccak_256 keys_st inputs_bi
results_keccak_256 );
( "sha3_384",
makes ~name:"sha3_384" bytes Digestif.sha3_384 keys_st inputs_by
results_sha3_384 );
( "sha3_384 (bigstring)",
makes ~name:"sha3_384" bigstring Digestif.sha3_384 keys_st inputs_bi
results_sha3_384 );
( "sha3_512",
makes ~name:"sha3_512" bytes Digestif.sha3_512 keys_st inputs_by
results_sha3_512 );
( "sha3_512 (bigstring)",
makes ~name:"sha3_512" bigstring Digestif.sha3_512 keys_st inputs_bi
results_sha3_512 );
( "whirlpool",
makes ~name:"whirlpool" bytes Digestif.whirlpool keys_st inputs_by
results_whirlpool );
( "whirlpool (bigstring)",
makes ~name:"whirlpool" bigstring Digestif.whirlpool keys_st inputs_bi
results_whirlpool );
( "blake2b",
makes ~name:"blake2b" bytes Digestif.blake2b keys_st inputs_by
results_blake2b );
( "blake2b (bigstring)",
makes ~name:"blake2b" bigstring Digestif.blake2b keys_st inputs_bi
results_blake2b );
( "rmd160",
makes ~name:"rmd160" bytes Digestif.rmd160 keys_st inputs_by
results_rmd160 );
( "rmd160 (bigstring)",
makes ~name:"rmd160" bigstring Digestif.rmd160 keys_st inputs_bi
results_rmd160 );
( "blake2s",
makes ~name:"blake2s" bytes Digestif.blake2s keys_st inputs_by
results_blake2s );
( "blake2s (bigstring)",
makes ~name:"blake2s" bigstring Digestif.blake2s keys_st inputs_bi
results_blake2s );
("blake2s (keyed, input file)", BLAKE2.tests_blake2s);
("blake2b (keyed, input file)", BLAKE2.tests_blake2b);
( "blake2s (specialization)",
[ blake2s_spe 32; blake2s_spe 8; blake2s_spe 16 ] );
( "blake2b (specialization)",
[ blake2b_spe 32; blake2b_spe 64; blake2b_spe 16 ] );
("ripemd160", RMD160.tests);
( "sha3 (vector tests)",
[
sha3_vector_tests "../sha3_224_fips_202.txt";
sha3_vector_tests "../sha3_256_fips_202.txt";
sha3_vector_tests "../sha3_384_fips_202.txt";
sha3_vector_tests "../sha3_512_fips_202.txt";
keccak_vector_tests "../keccak_256.txt";
] );
]
let () = tests ()

View file

@ -0,0 +1,66 @@
external unsafe_set_uint8 :
(char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t ->
int ->
int ->
unit = "%caml_ba_set_1"
external unsafe_set_uint32 :
(char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t ->
int ->
int32 ->
unit = "%caml_bigstring_set32"
let fill ba chr =
let len = Bigarray.Array1.dim ba in
let len0 = len land 3 in
let len1 = len asr 2 in
let v0 = Char.code chr in
let v1 = Int32.of_int v0 in
for i = 0 to len1 - 1 do
let i = i * 4 in
unsafe_set_uint32 ba i v1
done ;
for i = 0 to len0 - 1 do
let i = (len1 * 4) + i in
unsafe_set_uint8 ba i v0
done
let sha3_cve_2022_37454_0 =
Alcotest.test_case "buffer overflow" `Slow @@ fun () ->
Gc.full_major () ;
let a = Bigarray.Array1.create Bigarray.char Bigarray.c_layout 1 in
let b = Bigarray.Array1.create Bigarray.char Bigarray.c_layout 4294967295 in
fill a '\x00' ;
fill b '\x00' ;
let ctx = Digestif.SHA3_224.empty in
let ctx = Digestif.SHA3_224.feed_bigstring ctx a in
let ctx = Digestif.SHA3_224.feed_bigstring ctx b in
let hash = Digestif.SHA3_224.get ctx in
Alcotest.(check (testable Digestif.SHA3_224.pp Digestif.SHA3_224.equal))
"result" hash
(Digestif.SHA3_224.of_hex
"c5bcc3bc73b5ef45e91d2d7c70b64f196fac08eee4e4acf6e6571ebe")
let sha3_cve_2022_37454_1 =
Alcotest.test_case "infinite loop" `Slow @@ fun () ->
Gc.full_major () ;
let a = Bigarray.Array1.create Bigarray.char Bigarray.c_layout 1 in
let b = Bigarray.Array1.create Bigarray.char Bigarray.c_layout 4294967296 in
fill a '\x00' ;
fill b '\x00' ;
let ctx = Digestif.SHA3_224.empty in
let ctx = Digestif.SHA3_224.feed_bigstring ctx a in
let ctx = Digestif.SHA3_224.feed_bigstring ctx b in
let hash = Digestif.SHA3_224.get ctx in
Alcotest.(check (testable Digestif.SHA3_224.pp Digestif.SHA3_224.equal))
"result" hash
(Digestif.SHA3_224.of_hex
"bdd5167212d2dc69665f5a8875ab87f23d5ce7849132f56371a19096")
let () =
Alcotest.run "digestif (CVE)"
[
("sha3 (CVE-2022-37454)", [ sha3_cve_2022_37454_0; sha3_cve_2022_37454_1 ]);
]

View file

@ -0,0 +1,155 @@
#use "topfind"
#require "astring"
#require "fpath"
#require "bos"
open Rresult
let is_opt x = String.length x > 1 && x.[0] = '-'
let parse_opt_arg x =
let l = String.length x in
if x.[1] <> '-'
then
if l = 2
then (x, None)
else (String.sub x 0 2, Some (String.sub x 2 (l - 2)))
else
try
let i = String.index x '=' in
(String.sub x 0 i, Some (String.sub x (i + 1) (l - i - 1)))
with Not_found -> (x, None)
type arg =
| Path of Fpath.t
| Library of [ `Abs of Fpath.t | `Rel of Fpath.t | `Name of string ]
let parse_lL_value name value =
match name with
| "-L" -> (
match Fpath.of_string value with
| Ok v when Fpath.is_dir_path v && Sys.is_directory value -> R.ok (Path v)
| Ok v when Sys.is_directory value -> R.ok (Path (Fpath.to_dir_path v))
| Ok v -> R.error_msgf "Directory <%a> does not exist" Fpath.pp v
| Error err -> Error err)
| "-l" -> (
match Astring.String.cut ~sep:":" value with
| Some ("", path) -> (
match Fpath.of_string path with
| Ok v when Fpath.is_abs v && Sys.file_exists path ->
Ok (Library (`Abs v))
| Ok v when Fpath.is_rel v -> Ok (Library (`Rel v))
| Ok v -> R.error_msgf "Library <%a> does not exist" Fpath.pp v
| Error err -> Error err)
| Some (_, _) -> R.error_msgf "Invalid <namespec> %S" value
| None ->
match Fpath.of_string value with
| Ok v when Fpath.is_file_path v && Fpath.filename v = value ->
Ok (Library (`Name value))
| Ok v -> R.error_msgf "Invalid library name <%a>" Fpath.pp v
| Error err -> Error err)
| _ -> Fmt.failwith "Invalid argument name %S" name
let parse_lL_args args =
let rec go lL_args = function
| [] | "--" :: _ -> R.ok (List.rev lL_args)
| x :: args -> (
if not (is_opt x)
then go lL_args args
else
let name, value = parse_opt_arg x in
match name with
| "-L" | "-l" -> (
match value with
| Some value ->
parse_lL_value name value >>= fun v -> go (v :: lL_args) args
| None ->
match args with
| [] -> R.error_msgf "%s must have a value." name
| value :: args ->
if is_opt value
then R.error_msgf "%s must have a value." name
else
parse_lL_value name value >>= fun v ->
go (v :: lL_args) args)
| _ -> go lL_args args) in
go [] args
let is_path = function Path _ -> true | Library _ -> false
let prj_path = function Path x -> x | _ -> assert false
let prj_libraries = function Library x -> x | _ -> assert false
let libraries_exist args =
let paths, libraries = List.partition is_path args in
let paths = List.map prj_path paths in
let libraries = List.map prj_libraries libraries in
let rec go = function
| [] -> R.ok ()
| `Rel library :: libraries ->
let rec check = function
| [] -> R.error_msgf "Library <:%a> does not exist." Fpath.pp library
| p0 :: ps -> (
let path = Fpath.(p0 // library) in
Bos.OS.Path.exists path >>= function
| true -> go libraries
| false -> check ps) in
check paths
| `Name library :: libraries ->
let lib = Fmt.str "lib%s.a" library in
let rec check = function
| [] -> R.error_msgf "Library lib%s.a does not exist." library
| p0 :: ps -> (
let path = Fpath.(p0 / lib) in
Bos.OS.Path.exists path >>= function
| true -> go libraries
| false -> check ps) in
check paths
| `Abs path :: libraries -> (
Bos.OS.Path.exists path >>= function
| true -> go libraries
| false -> R.error_msgf "Library <%a> does not exist." Fpath.pp path)
in
go libraries
let exists lib =
let open Bos in
let command = Cmd.(v "ocamlfind" % "query" % lib) in
OS.Cmd.run_out command |> OS.Cmd.out_null >>= function
| (), (_, `Exited 0) -> R.ok true
| _ -> R.ok false
let query target lib =
let open Bos in
let format = Fmt.str "-L%%d %%(%s_linkopts)" target in
let command = Cmd.(v "ocamlfind" % "query" % "-format" % format % lib) in
OS.Cmd.run_out command
|> OS.Cmd.out_lines
>>= (function
| output, (_, `Exited 0) -> R.ok output
| _ -> R.error_msgf "<ocamlfind> does not properly exit.")
>>| String.concat " "
>>| Astring.String.cuts ~sep:" " ~empty:false
let run () =
(exists "mirage-xen-posix" >>= function
| true -> query "xen" "digestif" >>= parse_lL_args >>= libraries_exist
| false -> R.ok ())
>>= fun () ->
(exists "ocaml-freestanding" >>= function
| true ->
query "freestanding" "digestif" >>= parse_lL_args >>= libraries_exist
| false -> R.ok ())
>>= fun () -> R.ok ()
let exit_success = 0
let exit_failure = 1
let () =
match run () with
| Ok () -> exit exit_success
| Error (`Msg err) ->
Fmt.epr "%s\n%!" err ;
exit exit_failure