Full Code of sphincs/sphincsplus for AI

master 7ec789ace687 cached
161 files
526.4 KB
182.2k tokens
349 symbols
1 requests
Download .txt
Showing preview only (565K chars total). Download the full file or copy to clipboard to get everything.
Repository: sphincs/sphincsplus
Branch: master
Commit: 7ec789ace687
Files: 161
Total size: 526.4 KB

Directory structure:
gitextract_8vizip4a/

├── .github/
│   └── workflows/
│       ├── test-haraka-aesni.yml
│       ├── test-ref.yml
│       ├── test-sha2-avx2.yml
│       └── test-shake-avx2.yml
├── .reuse/
│   └── dep5
├── LICENSE
├── LICENSES/
│   ├── 0BSD.txt
│   ├── CC0-1.0.txt
│   ├── LicenseRef-SPHINCS-PLUS-Public-Domain.txt
│   ├── MIT-0.txt
│   └── MIT.txt
├── README.md
├── SHA256SUMS
├── benchmark.py
├── haraka-aesni/
│   ├── .gitignore
│   ├── Makefile
│   ├── context.h
│   ├── haraka.c
│   ├── harakax4.h
│   ├── hash_harakax4.c
│   ├── test/
│   │   └── benchmark.c
│   ├── thash_haraka_robustx4.c
│   └── thash_haraka_simplex4.c
├── ref/
│   ├── .gitignore
│   ├── Makefile
│   ├── PQCgenKAT_sign.c
│   ├── address.c
│   ├── address.h
│   ├── api.h
│   ├── context.h
│   ├── fips202.c
│   ├── fips202.h
│   ├── fors.c
│   ├── fors.h
│   ├── haraka.c
│   ├── haraka.h
│   ├── haraka_offsets.h
│   ├── hash.h
│   ├── hash_haraka.c
│   ├── hash_sha2.c
│   ├── hash_shake.c
│   ├── merkle.c
│   ├── merkle.h
│   ├── params/
│   │   ├── params-sphincs-haraka-128f.h
│   │   ├── params-sphincs-haraka-128s.h
│   │   ├── params-sphincs-haraka-192f.h
│   │   ├── params-sphincs-haraka-192s.h
│   │   ├── params-sphincs-haraka-256f.h
│   │   ├── params-sphincs-haraka-256s.h
│   │   ├── params-sphincs-sha2-128f.h
│   │   ├── params-sphincs-sha2-128s.h
│   │   ├── params-sphincs-sha2-192f.h
│   │   ├── params-sphincs-sha2-192s.h
│   │   ├── params-sphincs-sha2-256f.h
│   │   ├── params-sphincs-sha2-256s.h
│   │   ├── params-sphincs-shake-128f.h
│   │   ├── params-sphincs-shake-128s.h
│   │   ├── params-sphincs-shake-192f.h
│   │   ├── params-sphincs-shake-192s.h
│   │   ├── params-sphincs-shake-256f.h
│   │   └── params-sphincs-shake-256s.h
│   ├── params.h
│   ├── randombytes.c
│   ├── randombytes.h
│   ├── rng.c
│   ├── rng.h
│   ├── sha2.c
│   ├── sha2.h
│   ├── sha2_offsets.h
│   ├── shake_offsets.h
│   ├── sign.c
│   ├── test/
│   │   ├── benchmark.c
│   │   ├── cycles.c
│   │   ├── cycles.h
│   │   ├── fors.c
│   │   ├── haraka.c
│   │   └── spx.c
│   ├── thash.h
│   ├── thash_haraka_robust.c
│   ├── thash_haraka_simple.c
│   ├── thash_sha2_robust.c
│   ├── thash_sha2_simple.c
│   ├── thash_shake_robust.c
│   ├── thash_shake_simple.c
│   ├── utils.c
│   ├── utils.h
│   ├── utilsx1.c
│   ├── utilsx1.h
│   ├── wots.c
│   ├── wots.h
│   ├── wotsx1.c
│   └── wotsx1.h
├── sha2-avx2/
│   ├── .gitignore
│   ├── Makefile
│   ├── context.h
│   ├── fors.c
│   ├── hash_sha2x8.c
│   ├── hashx8.h
│   ├── merkle.c
│   ├── sha256avx.c
│   ├── sha256avx.h
│   ├── sha256x8.c
│   ├── sha256x8.h
│   ├── sha512x4.c
│   ├── sha512x4.h
│   ├── test/
│   │   ├── benchmark.c
│   │   └── thashx8.c
│   ├── thash_sha2_robustx8.c
│   ├── thash_sha2_simplex8.c
│   ├── thashx8.h
│   ├── utilsx8.c
│   ├── utilsx8.h
│   ├── wots.c
│   └── wotsx8.h
├── shake-a64/
│   ├── .gitignore
│   ├── Makefile
│   ├── context.h
│   ├── f1600x2.h
│   ├── f1600x2.s
│   ├── f1600x2_const.c
│   ├── fips202x2.c
│   ├── fips202x2.h
│   ├── fors.c
│   ├── hash_shakex2.c
│   ├── hashx2.h
│   ├── merkle.c
│   ├── test/
│   │   ├── benchmark.c
│   │   └── thashx2.c
│   ├── thash.h
│   ├── thash_shake_robustx2.c
│   ├── thash_shake_simplex2.c
│   ├── thashx2.h
│   ├── utilsx2.c
│   ├── utilsx2.h
│   ├── wots.c
│   └── wotsx2.h
├── shake-avx2/
│   ├── .gitignore
│   ├── Makefile
│   ├── context.h
│   ├── fips202x4.c
│   ├── fips202x4.h
│   ├── fors.c
│   ├── hash_shakex4.c
│   ├── hashx4.h
│   ├── keccak4x/
│   │   ├── KeccakP-1600-times4-SIMD256.c
│   │   ├── KeccakP-1600-times4-SnP.h
│   │   ├── KeccakP-1600-unrolling.macros
│   │   ├── SIMD256-config.h
│   │   ├── align.h
│   │   └── brg_endian.h
│   ├── merkle.c
│   ├── test/
│   │   ├── benchmark.c
│   │   └── thashx4.c
│   ├── thash_shake_robustx4.c
│   ├── thash_shake_simplex4.c
│   ├── thashx4.h
│   ├── utilsx4.c
│   ├── utilsx4.h
│   ├── wots.c
│   └── wotsx4.h
└── vectors.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/test-haraka-aesni.yml
================================================
name: Tests for haraka-aesni implementation

on:
  - push
  - pull_request

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        size:
          - 128
          - 192
          - 256
        option:
          - s
          - f
        thash:
          - simple
          - robust
    steps:
      - uses: actions/checkout@v1
      - name: Run make
        run: |
          make -C haraka-aesni THASH=${{ matrix.thash }} clean
          make -C haraka-aesni THASH=${{ matrix.thash }} PARAMS=sphincs-haraka-${{ matrix.size }}${{ matrix.option }} tests
          make -C haraka-aesni THASH=${{ matrix.thash }} PARAMS=sphincs-haraka-${{ matrix.size }}${{ matrix.option }} test
          make -C haraka-aesni THASH=${{ matrix.thash }} PARAMS=sphincs-haraka-${{ matrix.size }}${{ matrix.option }} PQCgenKAT_sign
      - name: Run PQCgenKAT_sign
        run: python3 vectors.py sphincs-haraka-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} haraka-aesni

#  vim: set ft=yaml ts=2 sw=2 et :


================================================
FILE: .github/workflows/test-ref.yml
================================================
name: Tests for ref implementation

on:
  - push
  - pull_request

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        hash:
          - sha2
          - shake
          - haraka
        size:
          - 128
          - 192
          - 256
        option:
          - s
          - f
        thash:
          - simple
          - robust
    steps:
      - uses: actions/checkout@v1
      - name: Run make
        run: |
          make -C ref HASH=${{ matrix.hash }} THASH=${{ matrix.thash }} clean
          make -C ref HASH=${{ matrix.hash }} THASH=${{ matrix.thash }} PARAMS=sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }} tests
          make -C ref HASH=${{ matrix.hash }} THASH=${{ matrix.thash }} PARAMS=sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }} test
          make -C ref THASH=${{ matrix.thash }} PQCgenKAT_sign
      - name: Run PQCgenKAT_sign
        run: python3 vectors.py sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} ref

#  vim: set ft=yaml ts=2 sw=2 et :


================================================
FILE: .github/workflows/test-sha2-avx2.yml
================================================
name: Tests for sha2-avx2 implementation

on:
  - push
  - pull_request

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        size:
          - 128
          - 192
          - 256
        option:
          - s
          - f
        thash:
          - simple
          - robust
    steps:
      - uses: actions/checkout@v1
      - name: Run make
        run: |
          make -C sha2-avx2 THASH=${{ matrix.thash }} clean
          make -C sha2-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-sha2-${{ matrix.size }}${{ matrix.option }} tests
          make -C sha2-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-sha2-${{ matrix.size }}${{ matrix.option }} test
          make -C sha2-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-sha2-${{ matrix.size }}${{ matrix.option }} PQCgenKAT_sign
      - name: Run PQCgenKAT_sign
        run: python3 vectors.py sphincs-sha2-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} sha2-avx2

#  vim: set ft=yaml ts=2 sw=2 et :


================================================
FILE: .github/workflows/test-shake-avx2.yml
================================================
name: Tests for shake-avx2 implementation

on:
  - push
  - pull_request

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        size:
          - 128
          - 192
          - 256
        option:
          - s
          - f
        thash:
          - simple
          - robust
    steps:
      - uses: actions/checkout@v1
      - name: Run make
        run: |
          make -C shake-avx2 THASH=${{ matrix.thash }} clean
          make -C shake-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-shake-${{ matrix.size }}${{ matrix.option }} tests
          make -C shake-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-shake-${{ matrix.size }}${{ matrix.option }} test
          make -C shake-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-shake-${{ matrix.size }}${{ matrix.option }} PQCgenKAT_sign
      - name: Run PQCgenKAT_sign
        run: python3 vectors.py sphincs-shake-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} shake-avx2

#  vim: set ft=yaml ts=2 sw=2 et :


================================================
FILE: .reuse/dep5
================================================
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: SPHINCS+
Upstream-Contact: contact@sphincs.org
Souce: https://github.com/sphincs/sphincsplus

Files: *
License: LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0

Files: ref/haraka.c
Copyright: 2016 Thomas Pornin <pornin@bolet.org> and SPHINCS+ team
License: (LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0) AND MIT

Files: ref/PQCgenKAT_sign.c ref/rng.c ref/rng.h
Copyright: 2017 Bassham, Lawrence E (Fed).
License: All rights reserved.


================================================
FILE: LICENSE
================================================
SPDX-License-Identifier: (LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0) AND MIT



================================================
FILE: LICENSES/0BSD.txt
================================================
BSD Zero Clause License

Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted.

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.


================================================
FILE: LICENSES/CC0-1.0.txt
================================================
Creative Commons Legal Code

CC0 1.0 Universal

    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
    HEREUNDER.

Statement of Purpose

The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").

Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.

For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.

1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:

  i. the right to reproduce, adapt, distribute, perform, display,
     communicate, and translate a Work;
 ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
     likeness depicted in a Work;
 iv. rights protecting against unfair competition in regards to a Work,
     subject to the limitations in paragraph 4(a), below;
  v. rights protecting the extraction, dissemination, use and reuse of data
     in a Work;
 vi. database rights (such as those arising under Directive 96/9/EC of the
     European Parliament and of the Council of 11 March 1996 on the legal
     protection of databases, and under any national implementation
     thereof, including any amended or successor version of such
     directive); and
vii. other similar, equivalent or corresponding rights throughout the
     world based on applicable law or treaty, and any national
     implementations thereof.

2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.

3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.

4. Limitations and Disclaimers.

 a. No trademark or patent rights held by Affirmer are waived, abandoned,
    surrendered, licensed or otherwise affected by this document.
 b. Affirmer offers the Work as-is and makes no representations or
    warranties of any kind concerning the Work, express, implied,
    statutory or otherwise, including without limitation warranties of
    title, merchantability, fitness for a particular purpose, non
    infringement, or the absence of latent or other defects, accuracy, or
    the present or absence of errors, whether or not discoverable, all to
    the greatest extent permissible under applicable law.
 c. Affirmer disclaims responsibility for clearing rights of other persons
    that may apply to the Work or any use thereof, including without
    limitation any person's Copyright and Related Rights in the Work.
    Further, Affirmer disclaims responsibility for obtaining any necessary
    consents, permissions or other rights required for any use of the
    Work.
 d. Affirmer understands and acknowledges that Creative Commons is not a
    party to this document and has no duty or obligation with respect to
    this CC0 or use of the Work.



================================================
FILE: LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt
================================================
This work is hereby placed into the public domain.



================================================
FILE: LICENSES/MIT-0.txt
================================================
MIT No Attribution

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.

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.



================================================
FILE: LICENSES/MIT.txt
================================================
MIT License

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 (including the next paragraph) 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.



================================================
FILE: README.md
================================================
## SPHINCS+

This repository contains the software that accompanies the [SPHINCS+ submission](https://sphincs.org/) to [NIST's Post-Quantum Cryptography](https://csrc.nist.gov/Projects/Post-Quantum-Cryptography) project.

![][test-ref]
![][test-sha256-avx2]
![][test-shake256-avx2]
![][test-haraka-aesni]

### Parameters

The [SPHINCS+ specification](https://sphincs.org/data/sphincs+-specification.pdf) proposed a set of 36 named instances, specifying hash functions and concrete parameters for the security level, tree dimensions, WOTS+ and FORS. This reference implementation allows for more flexibility, as parameters can be specified in a `params.h` file. The proposed parameter sets have been predefined in `ref/params/params-*.h`, and the hash function can be varied by linking with the different implementations of `hash.h`, i.e., `hash_haraka.c`, `hash_sha2.c` and `hash_shake.c`, as well as different implementations of `thash.h`, i.e., `*_robust.c` and `*_simple.c`. This is demonstrated in the `Makefile`. See the table below for a summary of the parameter sets. These parameters target the NIST security categories 1, 3 and 5; for each category, there is a parameter set geared towards either small signatures or fast signature generation.

|               | n  | h  | d  | log(t) | k  |  w  | bit security | pk bytes | sk bytes | sig bytes |
| :------------ | -: | -: | -: | -----: | -: | --: | -----------: | -------: | -------: | --------: |
| SPHINCS+-128s | 16 | 63 |  7 |     12 | 14 |  16 |          133 |       32 |       64 |     7,856 |
| SPHINCS+-128f | 16 | 66 | 22 |      6 | 33 |  16 |          128 |       32 |       64 |    17,088 |
| SPHINCS+-192s | 24 | 63 |  7 |     14 | 17 |  16 |          193 |       48 |       96 |    16,224 |
| SPHINCS+-192f | 24 | 66 | 22 |      8 | 33 |  16 |          194 |       48 |       96 |    35,664 |
| SPHINCS+-256s | 32 | 64 |  8 |     14 | 22 |  16 |          255 |       64 |      128 |    29,792 |
| SPHINCS+-256f | 32 | 68 | 17 |      9 | 35 |  16 |          255 |       64 |      128 |    49,856 |

### License

All included code has been placed into
[Public Domain](LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt)
and is available under various open source licenses
([Creative Commons Zero v1.0 Universal (CC0-1.0)](LICENSES/CC0-1.0.txt),
[BSD Zero Clause License (0BSD)](LICENSES/0BSD.txt), and
[MIT No Attribution (MIT-0)](LICENSES/MIT-0.txt),
see the [LICENSE file](LICENSE) and the licenses in the [LICENSES folder](LICENSES)), with the exception of `rng.c`, `rng.h` and `PQCgenKAT_sign.c`, which were provided by NIST, and parts of `ref/haraka.c`, which are under
[MIT license (MIT)](LICENSES/MIT.txt).

[test-ref]: https://github.com/sphincs/sphincsplus/actions/workflows/test-ref.yml/badge.svg
[test-sha256-avx2]: https://github.com/sphincs/sphincsplus/actions/workflows/test-sha256-avx2.yml/badge.svg
[test-shake256-avx2]: https://github.com/sphincs/sphincsplus/actions/workflows/test-shake256-avx2.yml/badge.svg
[test-haraka-aesni]: https://github.com/sphincs/sphincsplus/actions/workflows/test-haraka-aesni.yml/badge.svg


================================================
FILE: SHA256SUMS
================================================
9e1b3168520c917b6de676caa7a5799ec972e55caa150090e8452c80c299545e sphincs-haraka-128f-robust
c6a28dcf0667bd91c7bb46814ac7408c0375727fe5fec7d41332149006d3f9d7 sphincs-haraka-128f-simple
f93f4a554322080545a70f85ce936a12acc2fe928a243e3d13546ffe87872a9e sphincs-haraka-128s-robust
3c9b181d3d96c066039b77e9accd926745fe1ecb010039d3579140b877da6f33 sphincs-haraka-128s-simple
8876bfae8924983db27acfeaee6252d37cea86f05fcc4b16ea2c902d717e6a6e sphincs-haraka-192f-robust
df26bd02796f5ad9d6ff412793960e79ec911cbf4521656814895e6ef5a1db83 sphincs-haraka-192f-simple
6cfde6cb5f9ce93eb3f7b0845e1149f661f92000f54e9d340c0bff504920ec7e sphincs-haraka-192s-robust
64037177e1524f2b2d3ea4a79fdaf9352eb39a3aa6e68bc9d3316b7c2b835820 sphincs-haraka-192s-simple
a838509fa6ec49ade2638efc35d9e29fdb56bd9b843d5e1f48210a2cab218332 sphincs-haraka-256f-robust
e1e3258be6b4467bcea81392363f657a58278a5b99fe240f29e388b0fe72f5da sphincs-haraka-256f-simple
b5c5cc535f03789c25c018c009615ac62ba5b64188e4db5e3ede5513e3704dcc sphincs-haraka-256s-robust
9428a566a2c2ee03665fc0eb2dbf208deb1b28716dc8c2d5e7c036a9f83d31da sphincs-haraka-256s-simple
b6c82007bbce794f9fd67de708cd4d959319c744b918ddb28795fd491b713aa9 sphincs-sha2-128f-robust
708f6ab77f8026361e975f7be7b9b5d1cd8aca56e4a3604c85ef3f9fe6618549 sphincs-sha2-128f-simple
f4c2f31082fc8ad15419edc4f24c34a83d909f75eb37ea5ffe53df0fb5ef5306 sphincs-sha2-128s-robust
65942fac8e225fde77dd277d297e68c94c2e25a2a4089f88be4b56fa92b18a84 sphincs-sha2-128s-simple
b8e617db2099e617dfc372ff732eead88872aea791e2fe82628568d75dd03c78 sphincs-sha2-192f-robust
84b1a342683bcad658efb6c65f7367c6b30623e74e3a24c2238d19eaf74722ab sphincs-sha2-192f-simple
50c4b94dc788446077b48af1d8fa0170dc2114b4cb72a19f1d8c7628f9dadfd6 sphincs-sha2-192s-robust
13efa67b9297afa051b9b30e2686266350c8b4000caa49aa432516e2a86d0b68 sphincs-sha2-192s-simple
dc3330f8f19c816f45ee9a1127bf2b8a8c900e05df9a964bb760f0adf8f9b1b3 sphincs-sha2-256f-robust
46e286dc1a20012789c1bf4793a8eb2043dd0c11df729fa36d9f96b0aeffdac6 sphincs-sha2-256f-simple
1f42b407e1e351861ba23e520b1974f399e349fcb66c614d727a38fb4e646634 sphincs-sha2-256s-robust
c816ca365a667e4d6564a95ac576bc9d7be0de7e66eff93e6f05dd4f134a183f sphincs-sha2-256s-simple
4be71430814589ce7c861030c7cdce0aa73f75885b693b41fdb7c34d8f32fa79 sphincs-shake-128f-robust
5167df2ce46f33b76ccf0688f7769217d91878bd7d9b431080a3032eba51da10 sphincs-shake-128f-simple
fbe6c99d6ccc42fc9af5babbac532f28288d4164b182515dffeb1cd47f351d12 sphincs-shake-128s-robust
e7d5caee1941be99b6dfe46a95fc4535a34792f429e61d1cdc7fd3bbafe9ff02 sphincs-shake-128s-simple
243d0e25de08fea547b0beae5f778a48bd55e56066435f9cdb9afc60a722699e sphincs-shake-192f-robust
f204fd1cd5dce187441d104ae7159b64322b6a4afae708d48dc9966fe418ec4e sphincs-shake-192f-simple
cb13eaa2b1c074f53c87f1025e6bb1b356ad8de3bea9388b90a058a6460766bb sphincs-shake-192s-robust
4cc01c4a562d738ac54f5abfead35ecc4f46a1e2531fa12b4bc2819f4560c351 sphincs-shake-192s-simple
5a736aeba47f8d84e3ca47126715affcb4ce6cef13e3c9f6af220827973aa383 sphincs-shake-256f-robust
127f7ab83c740344546fe30777b221e8cb39f30fc4242d07d7608dc31a9835d4 sphincs-shake-256f-simple
4d2ca7d10f2206c3cb9a26c6b00a0361601a1fe2dddf102fbfd6d3dac0be10fe sphincs-shake-256s-robust
4ce4552e2e9b009a9016eb6dbcbefae3da2de151d61e2f392d4b9517eaeab91d sphincs-shake-256s-simple


================================================
FILE: benchmark.py
================================================
#! /usr/bin/env python3
import fileinput
import itertools
import os
import sys
from subprocess import DEVNULL, run

implementations = [
                   ('ref', ['shake', 'sha2', 'haraka']),
                   ('haraka-aesni', ['haraka']),
                   ('shake-avx2', ['shake']),
                   ('sha2-avx2', ['sha2']),
                   ]

options = ["f", "s"]
sizes = [128, 192, 256]
thashes = ['robust', 'simple']

for impl, fns in implementations:
    params = os.path.join(impl, "params.h")
    for fn in fns:
        for opt, size, thash in itertools.product(options, sizes, thashes):
            paramset = "sphincs-{}-{}{}".format(fn, size, opt)
            paramfile = "params-{}.h".format(paramset)

            print("Benchmarking", paramset, thash, "using", impl, flush=True)

            params = 'PARAMS={}'.format(paramset)  # overrides Makefile var
            thash = 'THASH={}'.format(thash)  # overrides Makefile var

            run(["make", "-C", impl, "clean", thash, params],
                stdout=DEVNULL, stderr=sys.stderr)
            run(["make", "-C", impl, "benchmarks", thash, params],
                stdout=DEVNULL, stderr=sys.stderr)
            run(["make", "-C", impl, "benchmark", thash, params],
                stdout=sys.stdout, stderr=sys.stderr)

            print(flush=True)



================================================
FILE: haraka-aesni/.gitignore
================================================
test/*
!test/*.c
PQCsignKAT_*.rsp
PQCsignKAT_*.req
PQCgenKAT_sign


================================================
FILE: haraka-aesni/Makefile
================================================
PARAMS = sphincs-haraka-128f
THASH = robust

CC = /usr/bin/gcc
CFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -march=native -fomit-frame-pointer -flto -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS)


SOURCES = hash_haraka.c hash_harakax4.c thash_haraka_$(THASH).c thash_haraka_$(THASH)x4.c address.c randombytes.c merkle.c wots.c utils.c utilsx4.c fors.c sign.c haraka.c
HEADERS = params.h hash.h hashx4.h thash.h thashx4.h address.h randombytes.h merkle.c wots.h utils.h utilsx4.h fors.h api.h haraka.h harakax4.h

DET_SOURCES = $(SOURCES:randombytes.%=rng.%)
DET_HEADERS = $(HEADERS:randombytes.%=rng.%)

TESTS = test/fors \
		test/spx \

BENCHMARK = test/benchmark

.PHONY: clean test benchmark

default: PQCgenKAT_sign

all: PQCgenKAT_sign tests benchmarks

tests: $(TESTS)

test: $(TESTS:=.exec)

benchmarks: $(BENCHMARK)

benchmark: $(BENCHMARK:=.exec)

PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS)
	$(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto

test/%: test/%.c $(SOURCES) $(HEADERS)
	$(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS)

test/%.exec: test/%
	@$<

clean:
	-$(RM) $(TESTS)
	-$(RM) $(BENCHMARK)
	-$(RM) PQCgenKAT_sign
	-$(RM) PQCsignKAT_*.rsp
	-$(RM) PQCsignKAT_*.req


================================================
FILE: haraka-aesni/context.h
================================================
#ifndef SPX_CONTEXT_H
#define SPX_CONTEXT_H

#include <stdint.h>

#include "params.h"
#include "immintrin.h"

typedef struct {
    uint8_t pub_seed[SPX_N];
    uint8_t sk_seed[SPX_N];

    __m128i rc[40];
} spx_ctx;

#endif


================================================
FILE: haraka-aesni/haraka.c
================================================
/*
Plain C implementation of the Haraka256 and Haraka512 permutations.
*/
#include <immintrin.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include "haraka.h"
#include "harakax4.h"
#include "utils.h"

#define HARAKAS_RATE 32

#define u64 unsigned long
#define u128 __m128i

#define LOAD(src) _mm_loadu_si128((u128 *)(src))
#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src)

#define XOR128(a, b) _mm_xor_si128(a, b)

#define AES2(s0, s1, rci) \
  s0 = _mm_aesenc_si128(s0, *(rci)); \
  s1 = _mm_aesenc_si128(s1, *(rci + 1)); \
  s0 = _mm_aesenc_si128(s0, *(rci + 2)); \
  s1 = _mm_aesenc_si128(s1, *(rci + 3));

#define AES2_4x(s0, s1, s2, s3, rci) \
  AES2(s0[0], s0[1], rci); \
  AES2(s1[0], s1[1], rci); \
  AES2(s2[0], s2[1], rci); \
  AES2(s3[0], s3[1], rci);

#define AES4(s0, s1, s2, s3, rci) \
  s0 = _mm_aesenc_si128(s0, *(rci)); \
  s1 = _mm_aesenc_si128(s1, *(rci + 1)); \
  s2 = _mm_aesenc_si128(s2, *(rci + 2)); \
  s3 = _mm_aesenc_si128(s3, *(rci + 3)); \
  s0 = _mm_aesenc_si128(s0, *(rci + 4)); \
  s1 = _mm_aesenc_si128(s1, *(rci + 5)); \
  s2 = _mm_aesenc_si128(s2, *(rci + 6)); \
  s3 = _mm_aesenc_si128(s3, *(rci + 7));

#define AES4_4x(s0, s1, s2, s3, rci) \
  AES4(s0[0], s0[1], s0[2], s0[3], rci); \
  AES4(s1[0], s1[1], s1[2], s1[3], rci); \
  AES4(s2[0], s2[1], s2[2], s2[3], rci); \
  AES4(s3[0], s3[1], s3[2], s3[3], rci);

#define MIX2(s0, s1) \
  tmp = _mm_unpacklo_epi32(s0, s1); \
  s1 = _mm_unpackhi_epi32(s0, s1); \
  s0 = tmp;

#define MIX4(s0, s1, s2, s3) \
  tmp  = _mm_unpacklo_epi32(s0, s1); \
  s0 = _mm_unpackhi_epi32(s0, s1); \
  s1 = _mm_unpacklo_epi32(s2, s3); \
  s2 = _mm_unpackhi_epi32(s2, s3); \
  s3 = _mm_unpacklo_epi32(s0, s2); \
  s0 = _mm_unpackhi_epi32(s0, s2); \
  s2 = _mm_unpackhi_epi32(s1, tmp); \
  s1 = _mm_unpacklo_epi32(s1, tmp);

#define TRUNCSTORE(out, s0, s1, s2, s3) \
  _mm_storeu_si128((u128 *)out, \
                   _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \
  _mm_storeu_si128((u128 *)(out + 16), \
                   _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0)));

static void load_haraka_constants(u128 *rc)
{
    rc[0] = _mm_set_epi32(0x0684704c,0xe620c00a,0xb2c5fef0,0x75817b9d);
    rc[1] = _mm_set_epi32(0x8b66b4e1,0x88f3a06b,0x640f6ba4,0x2f08f717);
    rc[2] = _mm_set_epi32(0x3402de2d,0x53f28498,0xcf029d60,0x9f029114);
    rc[3] = _mm_set_epi32(0x0ed6eae6,0x2e7b4f08,0xbbf3bcaf,0xfd5b4f79);
    rc[4] = _mm_set_epi32(0xcbcfb0cb,0x4872448b,0x79eecd1c,0xbe397044);
    rc[5] = _mm_set_epi32(0x7eeacdee,0x6e9032b7,0x8d5335ed,0x2b8a057b);
    rc[6] = _mm_set_epi32(0x67c28f43,0x5e2e7cd0,0xe2412761,0xda4fef1b);
    rc[7] = _mm_set_epi32(0x2924d9b0,0xafcacc07,0x675ffde2,0x1fc70b3b);
    rc[8] = _mm_set_epi32(0xab4d63f1,0xe6867fe9,0xecdb8fca,0xb9d465ee);
    rc[9] = _mm_set_epi32(0x1c30bf84,0xd4b7cd64,0x5b2a404f,0xad037e33);
    rc[10] = _mm_set_epi32(0xb2cc0bb9,0x941723bf,0x69028b2e,0x8df69800);
    rc[11] = _mm_set_epi32(0xfa0478a6,0xde6f5572,0x4aaa9ec8,0x5c9d2d8a);
    rc[12] = _mm_set_epi32(0xdfb49f2b,0x6b772a12,0x0efa4f2e,0x29129fd4);
    rc[13] = _mm_set_epi32(0x1ea10344,0xf449a236,0x32d611ae,0xbb6a12ee);
    rc[14] = _mm_set_epi32(0xaf044988,0x4b050084,0x5f9600c9,0x9ca8eca6);
    rc[15] = _mm_set_epi32(0x21025ed8,0x9d199c4f,0x78a2c7e3,0x27e593ec);
    rc[16] = _mm_set_epi32(0xbf3aaaf8,0xa759c9b7,0xb9282ecd,0x82d40173);
    rc[17] = _mm_set_epi32(0x6260700d,0x6186b017,0x37f2efd9,0x10307d6b);
    rc[18] = _mm_set_epi32(0x5aca45c2,0x21300443,0x81c29153,0xf6fc9ac6);
    rc[19] = _mm_set_epi32(0x9223973c,0x226b68bb,0x2caf92e8,0x36d1943a);
    rc[20] = _mm_set_epi32(0xd3bf9238,0x225886eb,0x6cbab958,0xe51071b4);
    rc[21] = _mm_set_epi32(0xdb863ce5,0xaef0c677,0x933dfddd,0x24e1128d);
    rc[22] = _mm_set_epi32(0xbb606268,0xffeba09c,0x83e48de3,0xcb2212b1);
    rc[23] = _mm_set_epi32(0x734bd3dc,0xe2e4d19c,0x2db91a4e,0xc72bf77d);
    rc[24] = _mm_set_epi32(0x43bb47c3,0x61301b43,0x4b1415c4,0x2cb3924e);
    rc[25] = _mm_set_epi32(0xdba775a8,0xe707eff6,0x03b231dd,0x16eb6899);
    rc[26] = _mm_set_epi32(0x6df3614b,0x3c755977,0x8e5e2302,0x7eca472c);
    rc[27] = _mm_set_epi32(0xcda75a17,0xd6de7d77,0x6d1be5b9,0xb88617f9);
    rc[28] = _mm_set_epi32(0xec6b43f0,0x6ba8e9aa,0x9d6c069d,0xa946ee5d);
    rc[29] = _mm_set_epi32(0xcb1e6950,0xf957332b,0xa2531159,0x3bf327c1);
    rc[30] = _mm_set_epi32(0x2cee0c75,0x00da619c,0xe4ed0353,0x600ed0d9);
    rc[31] = _mm_set_epi32(0xf0b1a5a1,0x96e90cab,0x80bbbabc,0x63a4a350);
    rc[32] = _mm_set_epi32(0xae3db102,0x5e962988,0xab0dde30,0x938dca39);
    rc[33] = _mm_set_epi32(0x17bb8f38,0xd554a40b,0x8814f3a8,0x2e75b442);
    rc[34] = _mm_set_epi32(0x34bb8a5b,0x5f427fd7,0xaeb6b779,0x360a16f6);
    rc[35] = _mm_set_epi32(0x26f65241,0xcbe55438,0x43ce5918,0xffbaafde);
    rc[36] = _mm_set_epi32(0x4ce99a54,0xb9f3026a,0xa2ca9cf7,0x839ec978);
    rc[37] = _mm_set_epi32(0xae51a51a,0x1bdff7be,0x40c06e28,0x22901235);
    rc[38] = _mm_set_epi32(0xa0c1613c,0xba7ed22b,0xc173bc0f,0x48a659cf);
    rc[39] = _mm_set_epi32(0x756acc03,0x02288288,0x4ad6bdfd,0xe9c59da1);
}

void tweak_constants(spx_ctx *ctx)
{
    int i;
    unsigned char buf[40*16];

    /* Use the standard constants to generate tweaked ones. */
    load_haraka_constants(ctx->rc);

    /* Constants for pk.seed */
    haraka_S(buf, 40*16, ctx->pub_seed, SPX_N, ctx);

    /* Tweak constants with the pub_seed */
    for (i = 0; i < 40; i++) {
        ctx->rc[i] = LOAD(buf + i*16);
    }
}

static void haraka_S_absorb(unsigned char *s, unsigned int r,
                            const unsigned char *m, unsigned long long mlen,
                            unsigned char p, const spx_ctx *ctx)
{
    unsigned long long i;
    SPX_VLA(unsigned char, t, r);

    while (mlen >= r) {
        // XOR block to state
        STORE(s, XOR128(LOAD(s), LOAD(m)));
        STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16)));
        haraka512_perm(s, s, ctx);
        mlen -= r;
        m += r;
    }

    for (i = 0; i < r; ++i) {
        t[i] = 0;
    }
    for (i = 0; i < mlen; ++i) {
        t[i] = m[i];
    }
    t[i] = p;
    t[r - 1] |= 128;
    STORE(s, XOR128(LOAD(s), LOAD(t)));
    STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16)));
}

static void haraka_S_absorb4x(unsigned char *s,
                              unsigned int r,
                              const unsigned char *m0,
                              const unsigned char *m1,
                              const unsigned char *m2,
                              const unsigned char *m3,
                              unsigned long long int mlen,
                              unsigned char p,
                              const spx_ctx *ctx)
{
    unsigned long long i;
    SPX_VLA(unsigned char, t0, r);
    SPX_VLA(unsigned char, t1, r);
    SPX_VLA(unsigned char, t2, r);
    SPX_VLA(unsigned char, t3, r);

    while (mlen >= r) {
        // XOR block to state
        STORE(s, XOR128(LOAD(s), LOAD(m0)));
        STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16)));
        STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1)));
        STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16)));
        STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2)));
        STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16)));
        STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3)));
        STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16)));

        haraka512_perm_x4(s, s, ctx);
        mlen -= r;
        m0 += r;
        m1 += r;
        m2 += r;
        m3 += r;
    }

    for (i = 0; i < r; ++i) {
        t0[i] = 0;
        t1[i] = 0;
        t2[i] = 0;
        t3[i] = 0;
    }
    for (i = 0; i < mlen; ++i) {
        t0[i] = m0[i];
        t1[i] = m1[i];
        t2[i] = m2[i];
        t3[i] = m3[i];
    }

    t0[i] = p;
    t1[i] = p;
    t2[i] = p;
    t3[i] = p;

    t0[r - 1] |= 128;
    t1[r - 1] |= 128;
    t2[r - 1] |= 128;
    t3[r - 1] |= 128;

    STORE(s, XOR128(LOAD(s), LOAD(t0)));
    STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16)));
    STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1)));
    STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16)));
    STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2)));
    STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16)));
    STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3)));
    STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16)));            
}

static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks,
                                   unsigned char *s, unsigned int r,
                                   const spx_ctx *ctx)
{
    while (nblocks > 0) {
        haraka512_perm(s, s, ctx);
        STORE(h, LOAD(s));
        STORE(h + 16, LOAD(s + 16));
        h += r;
        nblocks--;
    }
}

static void haraka_S_squeezeblocks4x(unsigned char *h0,
                                     unsigned char *h1,
                                     unsigned char *h2,
                                     unsigned char *h3,
                                     unsigned long long nblocks,
                                     unsigned char *s, 
                                     unsigned int r,
                                     const spx_ctx *ctx)
{
    while (nblocks > 0) {
        haraka512_perm_x4(s, s, ctx);
        STORE(h0, LOAD(s));
        STORE(h0 + 16, LOAD(s + 16));
        STORE(h1, LOAD(s + 64));
        STORE(h1 + 16, LOAD(s + 80));
        STORE(h2, LOAD(s + 128));
        STORE(h2 + 16, LOAD(s + 144));
        STORE(h3, LOAD(s + 192));
        STORE(h3 + 16, LOAD(s + 208));                        
        h0 += r;
        h1 += r;
        h2 += r;
        h3 += r;
        nblocks--;
    }
}

void haraka_S_inc_init(uint8_t *s_inc)
{
    size_t i;

    for (i = 0; i < 64; i++) {
        s_inc[i] = 0;
    }
    s_inc[64] = 0;
}

void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen,
        const spx_ctx *ctx)
{
    size_t i;

    /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */
    while (mlen + s_inc[64] >= HARAKAS_RATE) {
        for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) {
            /* Take the i'th byte from message
               xor with the s_inc[64] + i'th byte of the state */
            s_inc[s_inc[64] + i] ^= m[i];
        }
        mlen -= (size_t)(HARAKAS_RATE - s_inc[64]);
        m += HARAKAS_RATE - s_inc[64];
        s_inc[64] = 0;

        haraka512_perm(s_inc, s_inc, ctx);
    }

    for (i = 0; i < mlen; i++) {
        s_inc[s_inc[64] + i] ^= m[i];
    }
    s_inc[64] += mlen;
}

void haraka_S_inc_finalize(uint8_t *s_inc)
{
    /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE,
       so we can always use one more byte for p in the current state. */
    s_inc[s_inc[64]] ^= 0x1F;
    s_inc[HARAKAS_RATE - 1] ^= 128;
    s_inc[64] = 0;
}

void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc,
        const spx_ctx *ctx)
{
    size_t i;

    /* First consume any bytes we still have sitting around */
    for (i = 0; i < outlen && i < s_inc[64]; i++) {
        /* There are s_inc[64] bytes left, so r - s_inc[64] is the first
           available byte. We consume from there, i.e., up to r. */
        out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)];
    }
    out += i;
    outlen -= i;
    s_inc[64] -= i;

    /* Then squeeze the remaining necessary blocks */
    while (outlen > 0) {
        haraka512_perm(s_inc, s_inc, ctx);

        for (i = 0; i < outlen && i < HARAKAS_RATE; i++) {
            out[i] = s_inc[i];
        }
        out += i;
        outlen -= i;
        s_inc[64] = HARAKAS_RATE - i;
    }
}

void haraka_S(unsigned char *out, unsigned long long outlen,
              const unsigned char *in, unsigned long long inlen,
              const spx_ctx *ctx)
{
    unsigned long long i;
    unsigned char s[64];
    unsigned char d[32];

    for (i = 0; i < 64; i++) {
        s[i] = 0;
    }
    haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx);

    haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx);
    out += (outlen / HARAKAS_RATE) * HARAKAS_RATE;

    if (outlen % HARAKAS_RATE) {
        haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx);
        for (i = 0; i < outlen % HARAKAS_RATE; i++) {
            out[i] = d[i];
        }
    }
}

void haraka_Sx4(unsigned char *out0,
                unsigned char *out1,
                unsigned char *out2,
                unsigned char *out3, 
                unsigned long long outlen,
                const unsigned char *in0,
                const unsigned char *in1,
                const unsigned char *in2,
                const unsigned char *in3, 
                unsigned long long inlen,
                const spx_ctx *ctx)
{
    unsigned long long i;
    unsigned char s[64 * 4];
    unsigned char d0[32];
    unsigned char d1[32];
    unsigned char d2[32];
    unsigned char d3[32];

    for (i = 0; i < 64 * 4; i++) {
        s[i] = 0;
    }
    haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx);

    haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s,
            HARAKAS_RATE, ctx);
    out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE;
    out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE;
    out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE;
    out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE;

    if (outlen % HARAKAS_RATE) {
        haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx);
        for (i = 0; i < outlen % HARAKAS_RATE; i++) {
            out0[i] = d0[i];
            out1[i] = d1[i];
            out2[i] = d2[i];
            out3[i] = d3[i];
        }
    }
}

void haraka512_perm(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx)
{
    u128 s[4], tmp;
  
    s[0] = LOAD(in);
    s[1] = LOAD(in + 16);
    s[2] = LOAD(in + 32);
    s[3] = LOAD(in + 48);
  
    AES4(s[0], s[1], s[2], s[3], ctx->rc);
    MIX4(s[0], s[1], s[2], s[3]);
  
    AES4(s[0], s[1], s[2], s[3], ctx->rc + 8);
    MIX4(s[0], s[1], s[2], s[3]);
  
    AES4(s[0], s[1], s[2], s[3], ctx->rc + 16);
    MIX4(s[0], s[1], s[2], s[3]);
  
    AES4(s[0], s[1], s[2], s[3], ctx->rc + 24);
    MIX4(s[0], s[1], s[2], s[3]);
  
    AES4(s[0], s[1], s[2], s[3], ctx->rc + 32);
    MIX4(s[0], s[1], s[2], s[3]);
  
    STORE(out, s[0]);
    STORE(out + 16, s[1]);
    STORE(out + 32, s[2]);
    STORE(out + 48, s[3]);
}

void haraka512_perm_x4(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx) 
{
    u128 s[4][4], tmp;
    
    s[0][0] = LOAD(in);
    s[0][1] = LOAD(in + 16);
    s[0][2] = LOAD(in + 32);
    s[0][3] = LOAD(in + 48);
    s[1][0] = LOAD(in + 64);
    s[1][1] = LOAD(in + 80);
    s[1][2] = LOAD(in + 96);
    s[1][3] = LOAD(in + 112);
    s[2][0] = LOAD(in + 128);
    s[2][1] = LOAD(in + 144);
    s[2][2] = LOAD(in + 160);
    s[2][3] = LOAD(in + 176);
    s[3][0] = LOAD(in + 192);
    s[3][1] = LOAD(in + 208);
    s[3][2] = LOAD(in + 224);
    s[3][3] = LOAD(in + 240);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);
    
    STORE(out, s[0][0]);
    STORE(out + 16, s[0][1]);
    STORE(out + 32, s[0][2]);
    STORE(out + 48, s[0][3]);
    STORE(out + 64, s[1][0]);
    STORE(out + 80, s[1][1]);
    STORE(out + 96, s[1][2]);
    STORE(out + 112, s[1][3]);
    STORE(out + 128, s[2][0]);
    STORE(out + 144, s[2][1]);
    STORE(out + 160, s[2][2]);
    STORE(out + 176, s[2][3]);
    STORE(out + 192, s[3][0]);
    STORE(out + 208, s[3][1]);
    STORE(out + 224, s[3][2]);
    STORE(out + 240, s[3][3]);
}

void haraka512(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx)
{
    u128 s[4], tmp;

    s[0] = LOAD(in);
    s[1] = LOAD(in + 16);
    s[2] = LOAD(in + 32);
    s[3] = LOAD(in + 48); 

    AES4(s[0], s[1], s[2], s[3], ctx->rc);
    MIX4(s[0], s[1], s[2], s[3]);

    AES4(s[0], s[1], s[2], s[3], ctx->rc + 8);
    MIX4(s[0], s[1], s[2], s[3]);

    AES4(s[0], s[1], s[2], s[3], ctx->rc + 16);
    MIX4(s[0], s[1], s[2], s[3]);

    AES4(s[0], s[1], s[2], s[3], ctx->rc + 24);
    MIX4(s[0], s[1], s[2], s[3]);

    AES4(s[0], s[1], s[2], s[3], ctx->rc + 32);
    MIX4(s[0], s[1], s[2], s[3]);   

    s[0] = XOR128(s[0], LOAD(in));
    s[1] = XOR128(s[1], LOAD(in + 16));
    s[2] = XOR128(s[2], LOAD(in + 32));
    s[3] = XOR128(s[3], LOAD(in + 48));

    // truncate and store result
    TRUNCSTORE(out, s[0], s[1], s[2], s[3]);  
}

void haraka512x4(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx) 
{  
    u128 s[4][4], tmp;
    
    s[0][0] = LOAD(in);
    s[0][1] = LOAD(in + 16);
    s[0][2] = LOAD(in + 32);
    s[0][3] = LOAD(in + 48);
    s[1][0] = LOAD(in + 64);
    s[1][1] = LOAD(in + 80);
    s[1][2] = LOAD(in + 96);
    s[1][3] = LOAD(in + 112);
    s[2][0] = LOAD(in + 128);
    s[2][1] = LOAD(in + 144);
    s[2][2] = LOAD(in + 160);
    s[2][3] = LOAD(in + 176);
    s[3][0] = LOAD(in + 192);
    s[3][1] = LOAD(in + 208);
    s[3][2] = LOAD(in + 224);
    s[3][3] = LOAD(in + 240);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);
    
    AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32);
    MIX4(s[0][0], s[0][1], s[0][2], s[0][3]);
    MIX4(s[1][0], s[1][1], s[1][2], s[1][3]);
    MIX4(s[2][0], s[2][1], s[2][2], s[2][3]);
    MIX4(s[3][0], s[3][1], s[3][2], s[3][3]);   

    s[0][0] = XOR128(s[0][0], LOAD(in));
    s[0][1] = XOR128(s[0][1], LOAD(in + 16));
    s[0][2] = XOR128(s[0][2], LOAD(in + 32));
    s[0][3] = XOR128(s[0][3], LOAD(in + 48));
    s[1][0] = XOR128(s[1][0], LOAD(in + 64));
    s[1][1] = XOR128(s[1][1], LOAD(in + 80));
    s[1][2] = XOR128(s[1][2], LOAD(in + 96));
    s[1][3] = XOR128(s[1][3], LOAD(in + 112));
    s[2][0] = XOR128(s[2][0], LOAD(in + 128));
    s[2][1] = XOR128(s[2][1], LOAD(in + 144));
    s[2][2] = XOR128(s[2][2], LOAD(in + 160));
    s[2][3] = XOR128(s[2][3], LOAD(in + 176));
    s[3][0] = XOR128(s[3][0], LOAD(in + 192));
    s[3][1] = XOR128(s[3][1], LOAD(in + 208));
    s[3][2] = XOR128(s[3][2], LOAD(in + 224));
    s[3][3] = XOR128(s[3][3], LOAD(in + 240));
    
    TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]);
    TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]);
    TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]);
    TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]);    
}

void haraka256(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx) 
{
    u128 s[2], tmp;
  
    s[0] = LOAD(in);
    s[1] = LOAD(in + 16);
  
    AES2(s[0], s[1], ctx->rc);
    MIX2(s[0], s[1]);
  
    AES2(s[0], s[1], ctx->rc + 4);
    MIX2(s[0], s[1]);
  
    AES2(s[0], s[1], ctx->rc + 8);
    MIX2(s[0], s[1]);
  
    AES2(s[0], s[1], ctx->rc + 12);
    MIX2(s[0], s[1]);
  
    AES2(s[0], s[1], ctx->rc + 16);
    MIX2(s[0], s[1]);
  
    s[0] = XOR128(s[0], LOAD(in));
    s[1] = XOR128(s[1], LOAD(in + 16));
  
    STORE(out, s[0]);
    STORE(out + 16, s[1]);
}

void haraka256x4(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx) 
{
    u128 s[4][2], tmp;

    s[0][0] = LOAD(in);
    s[0][1] = LOAD(in + 16);
    s[1][0] = LOAD(in + 32);
    s[1][1] = LOAD(in + 48);
    s[2][0] = LOAD(in + 64);
    s[2][1] = LOAD(in + 80);
    s[3][0] = LOAD(in + 96);
    s[3][1] = LOAD(in + 112);

    // Round 1
    AES2_4x(s[0], s[1], s[2], s[3], ctx->rc);

    MIX2(s[0][0], s[0][1]);
    MIX2(s[1][0], s[1][1]);
    MIX2(s[2][0], s[2][1]);
    MIX2(s[3][0], s[3][1]);

    // Round 2
    AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4);

    MIX2(s[0][0], s[0][1]);
    MIX2(s[1][0], s[1][1]);
    MIX2(s[2][0], s[2][1]);
    MIX2(s[3][0], s[3][1]);

    // Round 3
    AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8);

    MIX2(s[0][0], s[0][1]);
    MIX2(s[1][0], s[1][1]);
    MIX2(s[2][0], s[2][1]);
    MIX2(s[3][0], s[3][1]);

    // Round 4
    AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12);

    MIX2(s[0][0], s[0][1]);
    MIX2(s[1][0], s[1][1]);
    MIX2(s[2][0], s[2][1]);
    MIX2(s[3][0], s[3][1]);
    
    // Round 5
    AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16);
    
    MIX2(s[0][0], s[0][1]);
    MIX2(s[1][0], s[1][1]);
    MIX2(s[2][0], s[2][1]);
    MIX2(s[3][0], s[3][1]);
    
    // Feed Forward
    s[0][0] = _mm_xor_si128(s[0][0], LOAD(in));
    s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16));
    s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32));
    s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48));
    s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64));
    s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80));
    s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96));
    s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112));
    
    STORE(out, s[0][0]);
    STORE(out + 16, s[0][1]);
    STORE(out + 32, s[1][0]);
    STORE(out + 48, s[1][1]);
    STORE(out + 64, s[2][0]);
    STORE(out + 80, s[2][1]);
    STORE(out + 96, s[3][0]);
    STORE(out + 112, s[3][1]);
}


================================================
FILE: haraka-aesni/harakax4.h
================================================
#ifndef SPX_HARAKAX4_H
#define SPX_HARAKAX4_H

#include "context.h"
#include "params.h"

/* Haraka Sponge */
#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4)
void haraka_Sx4(unsigned char *out0,
                unsigned char *out1,
                unsigned char *out2,
                unsigned char *out3,
                unsigned long long outlen,
                const unsigned char *in0,
                const unsigned char *in1,
                const unsigned char *in2,
                const unsigned char *in3,
                unsigned long long inlen,
                const spx_ctx *ctx);

/* Applies the 512-bit Haraka permutation x4 to in. */
#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4)
void haraka512_perm_x4(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx);

/* Implementation of Haraka-512 x4*/
#define haraka512x4 SPX_NAMESPACE(haraka512x4)
void haraka512x4(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx);

/* Implementation of Haraka-256 x4 */
#define haraka256x4 SPX_NAMESPACE(haraka256x4)
void haraka256x4(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx);

#endif


================================================
FILE: haraka-aesni/hash_harakax4.c
================================================
#include <stdint.h>
#include <string.h>

#include "address.h"
#include "params.h"
#include "harakax4.h"
#include "hashx4.h"

/*
 * 4-way parallel version of prf_addr; takes 4x as much input and output
 */
#define prf_addrx4 SPX_NAMESPACE(prf_addrx4)
void prf_addrx4(unsigned char *out0,
                unsigned char *out1,
                unsigned char *out2,
                unsigned char *out3,
                const spx_ctx *ctx,
                const uint32_t addrx4[4*8])
{
    unsigned char bufx4[4 * 64] = {0};
    /* Since SPX_N may be smaller than 32, we need temporary buffers. */
    unsigned char outbuf[4 * 32];
    unsigned int i;

    for (i = 0; i < 4; i++) {
        memcpy(bufx4 + i*64, addrx4 + i*8, SPX_ADDR_BYTES);
        memcpy(bufx4 + i*64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N);
    }

    haraka512x4(outbuf, bufx4, ctx);

    memcpy(out0, outbuf, SPX_N);
    memcpy(out1, outbuf + 32, SPX_N);
    memcpy(out2, outbuf + 64, SPX_N);
    memcpy(out3, outbuf + 96, SPX_N);
}


================================================
FILE: haraka-aesni/test/benchmark.c
================================================
#define _POSIX_C_SOURCE 199309L

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "../api.h"
#include "../fors.h"
#include "../wotsx4.h"
#include "../params.h"
#include "../randombytes.h"

#define SPX_MLEN 32
#define NTESTS 10

static void wots_gen_pkx4(unsigned char* pk, const spx_ctx *ctx,
         uint32_t addr[8]);

static int cmp_llu(const void *a, const void*b)
{
  if(*(unsigned long long *)a < *(unsigned long long *)b) return -1;
  if(*(unsigned long long *)a > *(unsigned long long *)b) return 1;
  return 0;
}

static unsigned long long median(unsigned long long *l, size_t llen)
{
  qsort(l,llen,sizeof(unsigned long long),cmp_llu);

  if(llen%2) return l[llen/2];
  else return (l[llen/2-1]+l[llen/2])/2;
}

static void delta(unsigned long long *l, size_t llen)
{
    unsigned int i;
    for(i = 0; i < llen - 1; i++) {
        l[i] = l[i+1] - l[i];
    }
}

static unsigned long long cpucycles(void)
{
  unsigned long long result;
  __asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax"
    : "=a" (result) ::  "%rdx");
  return result;
}

static void printfcomma (unsigned long long n)
{
    if (n < 1000) {
        printf("%llu", n);
        return;
    }
    printfcomma(n / 1000);
    printf (",%03llu", n % 1000);
}

static void printfalignedcomma (unsigned long long n, int len)
{
    unsigned long long ncopy = n;
    int i = 0;

    while (ncopy > 9) {
        len -= 1;
        ncopy /= 10;
        i += 1;  // to account for commas
    }
    i = i/3 - 1;  // to account for commas
    for (; i < len; i++) {
        printf(" ");
    }
    printfcomma(n);
}

static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul)
{
    unsigned long long med;

    result /= NTESTS;
    delta(l, NTESTS + 1);
    med = median(l, llen);
    printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6);
    printfalignedcomma(med, 12);
    printf(" cycles,  %5llux: ", mul);
    printfalignedcomma(mul*med, 12);
    printf(" cycles\n");
}

#define MEASURE(TEXT, MUL, FNCALL)\
    printf(TEXT);\
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\
    for(i = 0; i < NTESTS; i++) {\
        t[i] = cpucycles();\
        FNCALL;\
    }\
    t[NTESTS] = cpucycles();\
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\
    result = (stop.tv_sec - start.tv_sec) * 1e6 + (stop.tv_nsec - start.tv_nsec) / 1e3;\
    display_result(result, t, NTESTS, MUL);

int main(void)
{
    /* Make stdout buffer more responsive. */
    setbuf(stdout, NULL);

    spx_ctx ctx;
    unsigned char pk[SPX_PK_BYTES];
    unsigned char sk[SPX_SK_BYTES];
    unsigned char *m = malloc(SPX_MLEN);
    unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN);
    unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN);

    unsigned char fors_pk[SPX_FORS_PK_BYTES];
    unsigned char fors_m[SPX_FORS_MSG_BYTES];
    unsigned char fors_sig[SPX_FORS_BYTES];
    unsigned char addr[SPX_ADDR_BYTES];

    unsigned char wots_pk[SPX_WOTS_PK_BYTES];

    unsigned long long smlen;
    unsigned long long mlen;
    unsigned long long t[NTESTS+1];
    struct timespec start, stop;
    double result;
    int i;

    randombytes(m, SPX_MLEN);
    randombytes(addr, SPX_ADDR_BYTES);

    printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n",
           SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES,
           SPX_WOTS_W);

    printf("Running %d iterations.\n", NTESTS);

    MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk));
    MEASURE("  - WOTS pk gen..    ", (1 << SPX_TREE_HEIGHT), wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr));
    MEASURE("Signing..            ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk));
    MEASURE("  - FORS signing..   ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr));
    MEASURE("  - WOTS pk gen..    ", SPX_D * (1 << SPX_TREE_HEIGHT), wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr));
    MEASURE("Verifying..          ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk));

    printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0);
    printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0);
    printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0);

    free(m);
    free(sm);
    free(mout);

    return 0;
}

static void wots_gen_pkx4(unsigned char *pk, const spx_ctx *ctx,
                 uint32_t addr[8]) {
    struct leaf_info_x4 leaf;
    unsigned steps[ SPX_WOTS_LEN ] = { 0 };
    INITIALIZE_LEAF_INFO_X4(leaf, addr, steps);
    wots_gen_leafx4(pk, ctx, 0, &leaf);
}


================================================
FILE: haraka-aesni/thash_haraka_robustx4.c
================================================
#include <stdint.h>
#include <string.h>

#include "thashx4.h"
#include "address.h"
#include "params.h"
#include "utils.h"

#include "harakax4.h"

/**
 * 4-way parallel version of thash; takes 4x as much input and output
 */
#define thashx4 SPX_NAMESPACE(thashx4)
void thashx4(unsigned char *out0,
             unsigned char *out1,
             unsigned char *out2,
             unsigned char *out3,
             const unsigned char *in0,
             const unsigned char *in1,
             const unsigned char *in2,
             const unsigned char *in3, unsigned int inblocks,
             const spx_ctx *ctx, uint32_t addrx4[4*8])
{
    SPX_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks*SPX_N);
    SPX_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks*SPX_N);
    SPX_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks*SPX_N);
    SPX_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks*SPX_N);
    SPX_VLA(unsigned char, bitmask0, inblocks * SPX_N);
    SPX_VLA(unsigned char, bitmask1, inblocks * SPX_N);
    SPX_VLA(unsigned char, bitmask2, inblocks * SPX_N);
    SPX_VLA(unsigned char, bitmask3, inblocks * SPX_N);
    unsigned char outbuf[32 * 4];
    unsigned char buf_tmp[64 * 4];
    unsigned int i;

    if (inblocks == 1) {
        memset(buf_tmp, 0, 64 * 4);

        // Generate masks first in buffer
        memcpy(buf_tmp,      addrx4 + 0*8, 32);
        memcpy(buf_tmp + 32, addrx4 + 1*8, 32);
        memcpy(buf_tmp + 64, addrx4 + 2*8, 32);
        memcpy(buf_tmp + 96, addrx4 + 3*8, 32);

        haraka256x4(outbuf, buf_tmp, ctx);

        /* move addresses to make room for inputs; zero old values */
        memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES);
        memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES);
        memcpy(buf_tmp + 64,  buf_tmp + 32, SPX_ADDR_BYTES);
        /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */

        /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */
        memset(buf_tmp + 32, 0, SPX_ADDR_BYTES);
        /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */
        memset(buf_tmp + 96, 0, SPX_ADDR_BYTES);

        for (i = 0; i < SPX_N; i++) {
            buf_tmp[SPX_ADDR_BYTES + i]       = in0[i] ^ outbuf[i];
            buf_tmp[SPX_ADDR_BYTES + i + 64]  = in1[i] ^ outbuf[i + 32];
            buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64];
            buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96];
        }

        haraka512x4(outbuf, buf_tmp, ctx);

        memcpy(out0, outbuf,      SPX_N);
        memcpy(out1, outbuf + 32, SPX_N);
        memcpy(out2, outbuf + 64, SPX_N);
        memcpy(out3, outbuf + 96, SPX_N);
    } else {
        /* All other tweakable hashes*/
        memcpy(buf0, addrx4 + 0*8, 32);
        memcpy(buf1, addrx4 + 1*8, 32);
        memcpy(buf2, addrx4 + 2*8, 32);
        memcpy(buf3, addrx4 + 3*8, 32);

        haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N,
                   buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx);

        for (i = 0; i < inblocks * SPX_N; i++) {
            buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i];
            buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i];
            buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i];
            buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i];
        }

        haraka_Sx4(out0, out1, out2, out3, SPX_N,
                   buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks*SPX_N,
                   ctx);
    }
}


================================================
FILE: haraka-aesni/thash_haraka_simplex4.c
================================================
#include <stdint.h>
#include <string.h>

#include "thashx4.h"
#include "address.h"
#include "params.h"
#include "utils.h"

#include "harakax4.h"

/**
 * 4-way parallel version of thash; takes 4x as much input and output
 */
#define thashx4 SPX_NAMESPACE(thashx4)
void thashx4(unsigned char *out0,
             unsigned char *out1,
             unsigned char *out2,
             unsigned char *out3,
             const unsigned char *in0,
             const unsigned char *in1,
             const unsigned char *in2,
             const unsigned char *in3, unsigned int inblocks,
             const spx_ctx *ctx, uint32_t addrx4[4*8])
{
    SPX_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks*SPX_N);
    SPX_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks*SPX_N);
    SPX_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks*SPX_N);
    SPX_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks*SPX_N);
    unsigned char outbuf[32 * 4];
    unsigned char buf_tmp[64 * 4];

    if (inblocks == 1) {
        memset(buf_tmp, 0, 64 * 4);

        memcpy(buf_tmp,       addrx4 + 0*8, 32);
        memcpy(buf_tmp + 64,  addrx4 + 1*8, 32);
        memcpy(buf_tmp + 128, addrx4 + 2*8, 32);
        memcpy(buf_tmp + 192, addrx4 + 3*8, 32);

        memcpy(buf_tmp + SPX_ADDR_BYTES,       in0, SPX_N);
        memcpy(buf_tmp + SPX_ADDR_BYTES + 64,  in1, SPX_N);
        memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N);
        memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N);

        haraka512x4(outbuf, buf_tmp, ctx);

        memcpy(out0, outbuf,      SPX_N);
        memcpy(out1, outbuf + 32, SPX_N);
        memcpy(out2, outbuf + 64, SPX_N);
        memcpy(out3, outbuf + 96, SPX_N);
    } else {
        /* All other tweakable hashes*/
        memcpy(buf0, addrx4 + 0*8, 32);
        memcpy(buf1, addrx4 + 1*8, 32);
        memcpy(buf2, addrx4 + 2*8, 32);
        memcpy(buf3, addrx4 + 3*8, 32);

        memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N);
        memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N);
        memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N);
        memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N);

        haraka_Sx4(out0, out1, out2, out3, SPX_N,
                   buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks*SPX_N,
                   ctx);
    }
}


================================================
FILE: ref/.gitignore
================================================
test/*
!test/*.c
PQCsignKAT_*.rsp
PQCsignKAT_*.req
PQCgenKAT_sign


================================================
FILE: ref/Makefile
================================================
PARAMS = sphincs-haraka-128f
THASH = robust

CC=/usr/bin/gcc
CFLAGS=-Wall -Wextra -Wpedantic -O3 -std=c99 -Wconversion -Wmissing-prototypes -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS)

SOURCES =          address.c randombytes.c merkle.c wots.c wotsx1.c utils.c utilsx1.c fors.c sign.c
HEADERS = params.h address.h randombytes.h merkle.h wots.h wotsx1.h utils.h utilsx1.h fors.h api.h  hash.h thash.h

ifneq (,$(findstring shake,$(PARAMS)))
	SOURCES += fips202.c hash_shake.c thash_shake_$(THASH).c
	HEADERS += fips202.h
endif
ifneq (,$(findstring haraka,$(PARAMS)))
	SOURCES += haraka.c hash_haraka.c thash_haraka_$(THASH).c
	HEADERS += haraka.h
endif
ifneq (,$(findstring sha2,$(PARAMS)))
	SOURCES += sha2.c hash_sha2.c thash_sha2_$(THASH).c
	HEADERS += sha2.h
endif

DET_SOURCES = $(SOURCES:randombytes.%=rng.%)
DET_HEADERS = $(HEADERS:randombytes.%=rng.%)

TESTS =         test/fors \
		test/spx \

BENCHMARK = test/benchmark

.PHONY: clean test benchmark

default: PQCgenKAT_sign

all: PQCgenKAT_sign tests benchmarks

tests: $(TESTS)

test: $(TESTS:=.exec)

benchmarks: $(BENCHMARK)

benchmark: $(BENCHMARK:=.exec)

PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS)
	$(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto

test/benchmark: test/benchmark.c test/cycles.c $(SOURCES) $(HEADERS)
	$(CC) $(CFLAGS) -o $@ test/cycles.c $(SOURCES) $< $(LDLIBS)

test/%: test/%.c $(SOURCES) $(HEADERS)
	$(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS)

test/haraka: test/haraka.c $(filter-out haraka.c,$(SOURCES)) $(HEADERS)
	$(CC) $(CFLAGS) -o $@ $(filter-out haraka.c,$(SOURCES)) $< $(LDLIBS)

test/%.exec: test/%
	@$<

clean:
	-$(RM) $(TESTS)
	-$(RM) $(BENCHMARK)
	-$(RM) PQCgenKAT_sign
	-$(RM) PQCsignKAT_*.rsp
	-$(RM) PQCsignKAT_*.req


================================================
FILE: ref/PQCgenKAT_sign.c
================================================

//
//  PQCgenKAT_sign.c
//
//  Created by Bassham, Lawrence E (Fed) on 8/29/17.
//  Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "rng.h"
#include "api.h"

#define	MAX_MARKER_LEN		50

#define KAT_SUCCESS          0
#define KAT_FILE_OPEN_ERROR -1
#define KAT_DATA_ERROR      -3
#define KAT_CRYPTO_FAILURE  -4

int		FindMarker(FILE *infile, const char *marker);
int		ReadHex(FILE *infile, unsigned char *A, int Length, char *str);
void	fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L);

char    AlgName[] = "My Alg Name";

int
main(void)
{
    char                fn_req[32], fn_rsp[32];
    FILE                *fp_req, *fp_rsp;
    unsigned char       seed[48];
    unsigned char       msg[3300];
    unsigned char       entropy_input[48];
    unsigned char       *m, *sm, *m1;
    unsigned long long  mlen, smlen, mlen1;
    int                 count;
    int                 done;
    unsigned char       pk[CRYPTO_PUBLICKEYBYTES], sk[CRYPTO_SECRETKEYBYTES];
    int                 ret_val;

    // Create the REQUEST file
    sprintf(fn_req, "PQCsignKAT_%d.req", CRYPTO_SECRETKEYBYTES);
    if ( (fp_req = fopen(fn_req, "w")) == NULL ) {
        printf("Couldn't open <%s> for write\n", fn_req);
        return KAT_FILE_OPEN_ERROR;
    }
    sprintf(fn_rsp, "PQCsignKAT_%d.rsp", CRYPTO_SECRETKEYBYTES);
    if ( (fp_rsp = fopen(fn_rsp, "w")) == NULL ) {
        printf("Couldn't open <%s> for write\n", fn_rsp);
        return KAT_FILE_OPEN_ERROR;
    }

    for (int i=0; i<48; i++)
        entropy_input[i] = (unsigned char)i;

    randombytes_init(entropy_input, NULL);
    for (int i=0; i<100; i++) {
        fprintf(fp_req, "count = %d\n", i);
        randombytes(seed, 48);
        fprintBstr(fp_req, "seed = ", seed, 48);
        mlen = (unsigned long long int)(33*(i+1));
        fprintf(fp_req, "mlen = %llu\n", mlen);
        randombytes(msg, mlen);
        fprintBstr(fp_req, "msg = ", msg, mlen);
        fprintf(fp_req, "pk =\n");
        fprintf(fp_req, "sk =\n");
        fprintf(fp_req, "smlen =\n");
        fprintf(fp_req, "sm =\n\n");
    }
    fclose(fp_req);

    //Create the RESPONSE file based on what's in the REQUEST file
    if ( (fp_req = fopen(fn_req, "r")) == NULL ) {
        printf("Couldn't open <%s> for read\n", fn_req);
        return KAT_FILE_OPEN_ERROR;
    }

    fprintf(fp_rsp, "# %s\n\n", CRYPTO_ALGNAME);
    done = 0;
    do {
        if ( FindMarker(fp_req, "count = ") )
            ret_val = fscanf(fp_req, "%d", &count);
        else {
            done = 1;
            break;
        }
        fprintf(fp_rsp, "count = %d\n", count);

        if ( !ReadHex(fp_req, seed, 48, "seed = ") ) {
            printf("ERROR: unable to read 'seed' from <%s>\n", fn_req);
            return KAT_DATA_ERROR;
        }
        fprintBstr(fp_rsp, "seed = ", seed, 48);

        randombytes_init(seed, NULL);

        if ( FindMarker(fp_req, "mlen = ") )
            ret_val = fscanf(fp_req, "%llu", &mlen);
        else {
            printf("ERROR: unable to read 'mlen' from <%s>\n", fn_req);
            return KAT_DATA_ERROR;
        }
        fprintf(fp_rsp, "mlen = %llu\n", mlen);

        m = (unsigned char *)calloc(mlen, sizeof(unsigned char));
        m1 = (unsigned char *)calloc(mlen+CRYPTO_BYTES, sizeof(unsigned char));
        sm = (unsigned char *)calloc(mlen+CRYPTO_BYTES, sizeof(unsigned char));

        if ( !ReadHex(fp_req, m, (int)mlen, "msg = ") ) {
            printf("ERROR: unable to read 'msg' from <%s>\n", fn_req);
            return KAT_DATA_ERROR;
        }
        fprintBstr(fp_rsp, "msg = ", m, mlen);

        // Generate the public/private keypair
        if ( (ret_val = crypto_sign_keypair(pk, sk)) != 0) {
            printf("crypto_sign_keypair returned <%d>\n", ret_val);
            return KAT_CRYPTO_FAILURE;
        }
        fprintBstr(fp_rsp, "pk = ", pk, CRYPTO_PUBLICKEYBYTES);
        fprintBstr(fp_rsp, "sk = ", sk, CRYPTO_SECRETKEYBYTES);

        if ( (ret_val = crypto_sign(sm, &smlen, m, mlen, sk)) != 0) {
            printf("crypto_sign returned <%d>\n", ret_val);
            return KAT_CRYPTO_FAILURE;
        }
        fprintf(fp_rsp, "smlen = %llu\n", smlen);
        fprintBstr(fp_rsp, "sm = ", sm, smlen);
        fprintf(fp_rsp, "\n");

        if ( (ret_val = crypto_sign_open(m1, &mlen1, sm, smlen, pk)) != 0) {
            printf("crypto_sign_open returned <%d>\n", ret_val);
            return KAT_CRYPTO_FAILURE;
        }

        if ( mlen != mlen1 ) {
            printf("crypto_sign_open returned bad 'mlen': Got <%llu>, expected <%llu>\n", mlen1, mlen);
            return KAT_CRYPTO_FAILURE;
        }

        if ( memcmp(m, m1, mlen) ) {
            printf("crypto_sign_open returned bad 'm' value\n");
            return KAT_CRYPTO_FAILURE;
        }

        free(m);
        free(m1);
        free(sm);

    } while ( !done );

    fclose(fp_req);
    fclose(fp_rsp);

    return KAT_SUCCESS;
}

//
// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.)
//
int
FindMarker(FILE *infile, const char *marker)
{
	char	line[MAX_MARKER_LEN];
	size_t		i, len;
	int curr_line;

	len = strlen(marker);
	if ( len > MAX_MARKER_LEN-1 )
		len = MAX_MARKER_LEN-1;

	for ( i=0; i<len; i++ )
	  {
	    curr_line = fgetc(infile);
	    line[i] = (char)curr_line;
	    if (curr_line == EOF )
	      return 0;
	  }
	line[len] = '\0';

	while ( 1 ) {
		if ( !strncmp(line, marker, len) )
			return 1;

		for ( i=0; i<len-1; i++ )
			line[i] = line[i+1];
		curr_line = fgetc(infile);
		line[len-1] = (char)curr_line;
		if (curr_line == EOF )
		    return 0;
		line[len] = '\0';
	}

	// shouldn't get here
	return 0;
}

//
// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.)
//
int
ReadHex(FILE *infile, unsigned char *A, int Length, char *str)
{
	int			i, ch, started;
	unsigned char	ich;

	if ( Length == 0 ) {
		A[0] = 0x00;
		return 1;
	}
	memset(A, 0x00, (size_t)Length);
	started = 0;
	if ( FindMarker(infile, str) )
		while ( (ch = fgetc(infile)) != EOF ) {
			if ( !isxdigit(ch) ) {
				if ( !started ) {
					if ( ch == '\n' )
						break;
					else
						continue;
				}
				else
					break;
			}
			started = 1;
			if ( (ch >= '0') && (ch <= '9') )
				ich = (unsigned char)(ch - '0');
			else if ( (ch >= 'A') && (ch <= 'F') )
				ich = (unsigned char)(ch - 'A' + 10);
			else if ( (ch >= 'a') && (ch <= 'f') )
				ich = (unsigned char)(ch - 'a' + 10);
            else // shouldn't ever get here
                ich = 0;

			for ( i=0; i<Length-1; i++ )
				A[i] = (unsigned char)((A[i] << 4) | (A[i+1] >> 4));
			A[Length-1] = (unsigned char)((A[Length-1] << 4) | ich);
		}
	else
		return 0;

	return 1;
}

void
fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L)
{
	unsigned long long  i;

	fprintf(fp, "%s", S);

	for ( i=0; i<L; i++ )
		fprintf(fp, "%02X", A[i]);

	if ( L == 0 )
		fprintf(fp, "00");

	fprintf(fp, "\n");
}



================================================
FILE: ref/address.c
================================================
#include <stdint.h>
#include <string.h>

#include "address.h"
#include "params.h"
#include "utils.h"

/*
 * Specify which level of Merkle tree (the "layer") we're working on
 */
void set_layer_addr(uint32_t addr[8], uint32_t layer)
{
    ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer;
}

/*
 * Specify which Merkle tree within the level (the "tree address") we're working on
 */
void set_tree_addr(uint32_t addr[8], uint64_t tree)
{
#if (SPX_TREE_HEIGHT * (SPX_D - 1)) > 64
    #error Subtree addressing is currently limited to at most 2^64 trees
#endif
    ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree );
}

/*
 * Specify the reason we'll use this address structure for, that is, what
 * hash will we compute with it.  This is used so that unrelated types of
 * hashes don't accidentally get the same address structure.  The type will be
 * one of the SPX_ADDR_TYPE constants
 */
void set_type(uint32_t addr[8], uint32_t type)
{
    ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type;
}

/*
 * Copy the layer and tree fields of the address structure.  This is used
 * when we're doing multiple types of hashes within the same Merkle tree
 */
void copy_subtree_addr(uint32_t out[8], const uint32_t in[8])
{
    memcpy( out, in, SPX_OFFSET_TREE+8 );
}

/* These functions are used for OTS addresses. */

/*
 * Specify which Merkle leaf we're working on; that is, which OTS keypair
 * we're talking about.
 */
void set_keypair_addr(uint32_t addr[8], uint32_t keypair)
{
    u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_KP_ADDR], keypair);
}

/*
 * Copy the layer, tree and keypair fields of the address structure.  This is
 * used when we're doing multiple things within the same OTS keypair
 */
void copy_keypair_addr(uint32_t out[8], const uint32_t in[8])
{
    memcpy( out, in, SPX_OFFSET_TREE+8 );
    memcpy( (unsigned char *)out + SPX_OFFSET_KP_ADDR, (unsigned char *)in + SPX_OFFSET_KP_ADDR, 4); 
}

/*
 * Specify which Merkle chain within the OTS we're working with
 * (the chain address)
 */
void set_chain_addr(uint32_t addr[8], uint32_t chain)
{
    ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain;
}

/*
 * Specify where in the Merkle chain we are
* (the hash address)
 */
void set_hash_addr(uint32_t addr[8], uint32_t hash)
{
    ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash;
}

/* These functions are used for all hash tree addresses (including FORS). */

/*
 * Specify the height of the node in the Merkle/FORS tree we are in
 * (the tree height)
 */
void set_tree_height(uint32_t addr[8], uint32_t tree_height)
{
    ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height;
}

/*
 * Specify the distance from the left edge of the node in the Merkle/FORS tree
 * (the tree index)
 */
void set_tree_index(uint32_t addr[8], uint32_t tree_index)
{
    u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index );
}


================================================
FILE: ref/address.h
================================================
#ifndef SPX_ADDRESS_H
#define SPX_ADDRESS_H

#include <stdint.h>
#include "params.h"

/* The hash types that are passed to set_type */
#define SPX_ADDR_TYPE_WOTS 0
#define SPX_ADDR_TYPE_WOTSPK 1
#define SPX_ADDR_TYPE_HASHTREE 2
#define SPX_ADDR_TYPE_FORSTREE 3
#define SPX_ADDR_TYPE_FORSPK 4
#define SPX_ADDR_TYPE_WOTSPRF 5
#define SPX_ADDR_TYPE_FORSPRF 6

#define set_layer_addr SPX_NAMESPACE(set_layer_addr)
void set_layer_addr(uint32_t addr[8], uint32_t layer);

#define set_tree_addr SPX_NAMESPACE(set_tree_addr)
void set_tree_addr(uint32_t addr[8], uint64_t tree);

#define set_type SPX_NAMESPACE(set_type)
void set_type(uint32_t addr[8], uint32_t type);

/* Copies the layer and tree part of one address into the other */
#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr)
void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]);

/* These functions are used for WOTS and FORS addresses. */

#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr)
void set_keypair_addr(uint32_t addr[8], uint32_t keypair);

#define set_chain_addr SPX_NAMESPACE(set_chain_addr)
void set_chain_addr(uint32_t addr[8], uint32_t chain);

#define set_hash_addr SPX_NAMESPACE(set_hash_addr)
void set_hash_addr(uint32_t addr[8], uint32_t hash);

#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr)
void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]);

/* These functions are used for all hash tree addresses (including FORS). */

#define set_tree_height SPX_NAMESPACE(set_tree_height)
void set_tree_height(uint32_t addr[8], uint32_t tree_height);

#define set_tree_index SPX_NAMESPACE(set_tree_index)
void set_tree_index(uint32_t addr[8], uint32_t tree_index);

#endif


================================================
FILE: ref/api.h
================================================
#ifndef SPX_API_H
#define SPX_API_H

#include <stddef.h>
#include <stdint.h>

#include "params.h"

#define CRYPTO_ALGNAME "SPHINCS+"

#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES
#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES
#define CRYPTO_BYTES SPX_BYTES
#define CRYPTO_SEEDBYTES 3*SPX_N

/*
 * Returns the length of a secret key, in bytes
 */
unsigned long long crypto_sign_secretkeybytes(void);

/*
 * Returns the length of a public key, in bytes
 */
unsigned long long crypto_sign_publickeybytes(void);

/*
 * Returns the length of a signature, in bytes
 */
unsigned long long crypto_sign_bytes(void);

/*
 * Returns the length of the seed required to generate a key pair, in bytes
 */
unsigned long long crypto_sign_seedbytes(void);

/*
 * Generates a SPHINCS+ key pair given a seed.
 * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
 * Format pk: [root || PUB_SEED]
 */
int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk,
                             const unsigned char *seed);

/*
 * Generates a SPHINCS+ key pair.
 * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
 * Format pk: [root || PUB_SEED]
 */
int crypto_sign_keypair(unsigned char *pk, unsigned char *sk);

/**
 * Returns an array containing a detached signature.
 */
int crypto_sign_signature(uint8_t *sig, size_t *siglen,
                          const uint8_t *m, size_t mlen, const uint8_t *sk);

/**
 * Verifies a detached signature and message under a given public key.
 */
int crypto_sign_verify(const uint8_t *sig, size_t siglen,
                       const uint8_t *m, size_t mlen, const uint8_t *pk);

/**
 * Returns an array containing the signature followed by the message.
 */
int crypto_sign(unsigned char *sm, unsigned long long *smlen,
                const unsigned char *m, unsigned long long mlen,
                const unsigned char *sk);

/**
 * Verifies a given signature-message pair under a given public key.
 */
int crypto_sign_open(unsigned char *m, unsigned long long *mlen,
                     const unsigned char *sm, unsigned long long smlen,
                     const unsigned char *pk);

#endif


================================================
FILE: ref/context.h
================================================
#ifndef SPX_CONTEXT_H
#define SPX_CONTEXT_H

#include <stdint.h>

#include "params.h"

typedef struct {
    uint8_t pub_seed[SPX_N];
    uint8_t sk_seed[SPX_N];

#ifdef SPX_SHA2
    // sha256 state that absorbed pub_seed
    uint8_t state_seeded[40];

# if SPX_SHA512
    // sha512 state that absorbed pub_seed
    uint8_t state_seeded_512[72];
# endif
#endif

#ifdef SPX_HARAKA
    uint64_t tweaked512_rc64[10][8];
    uint32_t tweaked256_rc32[10][8];
#endif
} spx_ctx;

#endif


================================================
FILE: ref/fips202.c
================================================
/* Based on the public domain implementation in
 * crypto_hash/keccakc512/simple/ from http://bench.cr.yp.to/supercop.html
 * by Ronny Van Keer
 * and the public domain "TweetFips202" implementation
 * from https://twitter.com/tweetfips202
 * by Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */

#include <stddef.h>
#include <stdint.h>

#include "fips202.h"

#define NROUNDS 24
#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64 - (offset))))

/*************************************************
 * Name:        load64
 *
 * Description: Load 8 bytes into uint64_t in little-endian order
 *
 * Arguments:   - const uint8_t *x: pointer to input byte array
 *
 * Returns the loaded 64-bit unsigned integer
 **************************************************/
static uint64_t load64(const uint8_t *x) {
    uint64_t r = 0;
    for (size_t i = 0; i < 8; ++i) {
        r |= (uint64_t)x[i] << 8 * i;
    }

    return r;
}

/*************************************************
 * Name:        store64
 *
 * Description: Store a 64-bit integer to a byte array in little-endian order
 *
 * Arguments:   - uint8_t *x: pointer to the output byte array
 *              - uint64_t u: input 64-bit unsigned integer
 **************************************************/
static void store64(uint8_t *x, uint64_t u) {
    for (size_t i = 0; i < 8; ++i) {
        x[i] = (uint8_t) (u >> 8 * i);
    }
}

/* Keccak round constants */
static const uint64_t KeccakF_RoundConstants[NROUNDS] = {
    0x0000000000000001ULL, 0x0000000000008082ULL,
    0x800000000000808aULL, 0x8000000080008000ULL,
    0x000000000000808bULL, 0x0000000080000001ULL,
    0x8000000080008081ULL, 0x8000000000008009ULL,
    0x000000000000008aULL, 0x0000000000000088ULL,
    0x0000000080008009ULL, 0x000000008000000aULL,
    0x000000008000808bULL, 0x800000000000008bULL,
    0x8000000000008089ULL, 0x8000000000008003ULL,
    0x8000000000008002ULL, 0x8000000000000080ULL,
    0x000000000000800aULL, 0x800000008000000aULL,
    0x8000000080008081ULL, 0x8000000000008080ULL,
    0x0000000080000001ULL, 0x8000000080008008ULL
};

/*************************************************
 * Name:        KeccakF1600_StatePermute
 *
 * Description: The Keccak F1600 Permutation
 *
 * Arguments:   - uint64_t *state: pointer to input/output Keccak state
 **************************************************/
static void KeccakF1600_StatePermute(uint64_t *state) {
    int round;

    uint64_t Aba, Abe, Abi, Abo, Abu;
    uint64_t Aga, Age, Agi, Ago, Agu;
    uint64_t Aka, Ake, Aki, Ako, Aku;
    uint64_t Ama, Ame, Ami, Amo, Amu;
    uint64_t Asa, Ase, Asi, Aso, Asu;
    uint64_t BCa, BCe, BCi, BCo, BCu;
    uint64_t Da, De, Di, Do, Du;
    uint64_t Eba, Ebe, Ebi, Ebo, Ebu;
    uint64_t Ega, Ege, Egi, Ego, Egu;
    uint64_t Eka, Eke, Eki, Eko, Eku;
    uint64_t Ema, Eme, Emi, Emo, Emu;
    uint64_t Esa, Ese, Esi, Eso, Esu;

    // copyFromState(A, state)
    Aba = state[0];
    Abe = state[1];
    Abi = state[2];
    Abo = state[3];
    Abu = state[4];
    Aga = state[5];
    Age = state[6];
    Agi = state[7];
    Ago = state[8];
    Agu = state[9];
    Aka = state[10];
    Ake = state[11];
    Aki = state[12];
    Ako = state[13];
    Aku = state[14];
    Ama = state[15];
    Ame = state[16];
    Ami = state[17];
    Amo = state[18];
    Amu = state[19];
    Asa = state[20];
    Ase = state[21];
    Asi = state[22];
    Aso = state[23];
    Asu = state[24];

    for (round = 0; round < NROUNDS; round += 2) {
        //    prepareTheta
        BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa;
        BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase;
        BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi;
        BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso;
        BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu;

        // thetaRhoPiChiIotaPrepareTheta(round  , A, E)
        Da = BCu ^ ROL(BCe, 1);
        De = BCa ^ ROL(BCi, 1);
        Di = BCe ^ ROL(BCo, 1);
        Do = BCi ^ ROL(BCu, 1);
        Du = BCo ^ ROL(BCa, 1);

        Aba ^= Da;
        BCa = Aba;
        Age ^= De;
        BCe = ROL(Age, 44);
        Aki ^= Di;
        BCi = ROL(Aki, 43);
        Amo ^= Do;
        BCo = ROL(Amo, 21);
        Asu ^= Du;
        BCu = ROL(Asu, 14);
        Eba = BCa ^ ((~BCe) & BCi);
        Eba ^= KeccakF_RoundConstants[round];
        Ebe = BCe ^ ((~BCi) & BCo);
        Ebi = BCi ^ ((~BCo) & BCu);
        Ebo = BCo ^ ((~BCu) & BCa);
        Ebu = BCu ^ ((~BCa) & BCe);

        Abo ^= Do;
        BCa = ROL(Abo, 28);
        Agu ^= Du;
        BCe = ROL(Agu, 20);
        Aka ^= Da;
        BCi = ROL(Aka, 3);
        Ame ^= De;
        BCo = ROL(Ame, 45);
        Asi ^= Di;
        BCu = ROL(Asi, 61);
        Ega = BCa ^ ((~BCe) & BCi);
        Ege = BCe ^ ((~BCi) & BCo);
        Egi = BCi ^ ((~BCo) & BCu);
        Ego = BCo ^ ((~BCu) & BCa);
        Egu = BCu ^ ((~BCa) & BCe);

        Abe ^= De;
        BCa = ROL(Abe, 1);
        Agi ^= Di;
        BCe = ROL(Agi, 6);
        Ako ^= Do;
        BCi = ROL(Ako, 25);
        Amu ^= Du;
        BCo = ROL(Amu, 8);
        Asa ^= Da;
        BCu = ROL(Asa, 18);
        Eka = BCa ^ ((~BCe) & BCi);
        Eke = BCe ^ ((~BCi) & BCo);
        Eki = BCi ^ ((~BCo) & BCu);
        Eko = BCo ^ ((~BCu) & BCa);
        Eku = BCu ^ ((~BCa) & BCe);

        Abu ^= Du;
        BCa = ROL(Abu, 27);
        Aga ^= Da;
        BCe = ROL(Aga, 36);
        Ake ^= De;
        BCi = ROL(Ake, 10);
        Ami ^= Di;
        BCo = ROL(Ami, 15);
        Aso ^= Do;
        BCu = ROL(Aso, 56);
        Ema = BCa ^ ((~BCe) & BCi);
        Eme = BCe ^ ((~BCi) & BCo);
        Emi = BCi ^ ((~BCo) & BCu);
        Emo = BCo ^ ((~BCu) & BCa);
        Emu = BCu ^ ((~BCa) & BCe);

        Abi ^= Di;
        BCa = ROL(Abi, 62);
        Ago ^= Do;
        BCe = ROL(Ago, 55);
        Aku ^= Du;
        BCi = ROL(Aku, 39);
        Ama ^= Da;
        BCo = ROL(Ama, 41);
        Ase ^= De;
        BCu = ROL(Ase, 2);
        Esa = BCa ^ ((~BCe) & BCi);
        Ese = BCe ^ ((~BCi) & BCo);
        Esi = BCi ^ ((~BCo) & BCu);
        Eso = BCo ^ ((~BCu) & BCa);
        Esu = BCu ^ ((~BCa) & BCe);

        //    prepareTheta
        BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa;
        BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese;
        BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi;
        BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso;
        BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu;

        // thetaRhoPiChiIotaPrepareTheta(round+1, E, A)
        Da = BCu ^ ROL(BCe, 1);
        De = BCa ^ ROL(BCi, 1);
        Di = BCe ^ ROL(BCo, 1);
        Do = BCi ^ ROL(BCu, 1);
        Du = BCo ^ ROL(BCa, 1);

        Eba ^= Da;
        BCa = Eba;
        Ege ^= De;
        BCe = ROL(Ege, 44);
        Eki ^= Di;
        BCi = ROL(Eki, 43);
        Emo ^= Do;
        BCo = ROL(Emo, 21);
        Esu ^= Du;
        BCu = ROL(Esu, 14);
        Aba = BCa ^ ((~BCe) & BCi);
        Aba ^= KeccakF_RoundConstants[round + 1];
        Abe = BCe ^ ((~BCi) & BCo);
        Abi = BCi ^ ((~BCo) & BCu);
        Abo = BCo ^ ((~BCu) & BCa);
        Abu = BCu ^ ((~BCa) & BCe);

        Ebo ^= Do;
        BCa = ROL(Ebo, 28);
        Egu ^= Du;
        BCe = ROL(Egu, 20);
        Eka ^= Da;
        BCi = ROL(Eka, 3);
        Eme ^= De;
        BCo = ROL(Eme, 45);
        Esi ^= Di;
        BCu = ROL(Esi, 61);
        Aga = BCa ^ ((~BCe) & BCi);
        Age = BCe ^ ((~BCi) & BCo);
        Agi = BCi ^ ((~BCo) & BCu);
        Ago = BCo ^ ((~BCu) & BCa);
        Agu = BCu ^ ((~BCa) & BCe);

        Ebe ^= De;
        BCa = ROL(Ebe, 1);
        Egi ^= Di;
        BCe = ROL(Egi, 6);
        Eko ^= Do;
        BCi = ROL(Eko, 25);
        Emu ^= Du;
        BCo = ROL(Emu, 8);
        Esa ^= Da;
        BCu = ROL(Esa, 18);
        Aka = BCa ^ ((~BCe) & BCi);
        Ake = BCe ^ ((~BCi) & BCo);
        Aki = BCi ^ ((~BCo) & BCu);
        Ako = BCo ^ ((~BCu) & BCa);
        Aku = BCu ^ ((~BCa) & BCe);

        Ebu ^= Du;
        BCa = ROL(Ebu, 27);
        Ega ^= Da;
        BCe = ROL(Ega, 36);
        Eke ^= De;
        BCi = ROL(Eke, 10);
        Emi ^= Di;
        BCo = ROL(Emi, 15);
        Eso ^= Do;
        BCu = ROL(Eso, 56);
        Ama = BCa ^ ((~BCe) & BCi);
        Ame = BCe ^ ((~BCi) & BCo);
        Ami = BCi ^ ((~BCo) & BCu);
        Amo = BCo ^ ((~BCu) & BCa);
        Amu = BCu ^ ((~BCa) & BCe);

        Ebi ^= Di;
        BCa = ROL(Ebi, 62);
        Ego ^= Do;
        BCe = ROL(Ego, 55);
        Eku ^= Du;
        BCi = ROL(Eku, 39);
        Ema ^= Da;
        BCo = ROL(Ema, 41);
        Ese ^= De;
        BCu = ROL(Ese, 2);
        Asa = BCa ^ ((~BCe) & BCi);
        Ase = BCe ^ ((~BCi) & BCo);
        Asi = BCi ^ ((~BCo) & BCu);
        Aso = BCo ^ ((~BCu) & BCa);
        Asu = BCu ^ ((~BCa) & BCe);
    }

    // copyToState(state, A)
    state[0] = Aba;
    state[1] = Abe;
    state[2] = Abi;
    state[3] = Abo;
    state[4] = Abu;
    state[5] = Aga;
    state[6] = Age;
    state[7] = Agi;
    state[8] = Ago;
    state[9] = Agu;
    state[10] = Aka;
    state[11] = Ake;
    state[12] = Aki;
    state[13] = Ako;
    state[14] = Aku;
    state[15] = Ama;
    state[16] = Ame;
    state[17] = Ami;
    state[18] = Amo;
    state[19] = Amu;
    state[20] = Asa;
    state[21] = Ase;
    state[22] = Asi;
    state[23] = Aso;
    state[24] = Asu;
}

/*************************************************
 * Name:        keccak_absorb
 *
 * Description: Absorb step of Keccak;
 *              non-incremental, starts by zeroeing the state.
 *
 * Arguments:   - uint64_t *s: pointer to (uninitialized) output Keccak state
 *              - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
 *              - const uint8_t *m: pointer to input to be absorbed into s
 *              - size_t mlen: length of input in bytes
 *              - uint8_t p: domain-separation byte for different
 *                                 Keccak-derived functions
 **************************************************/
static void keccak_absorb(uint64_t *s, uint32_t r, const uint8_t *m,
                          size_t mlen, uint8_t p) {
    size_t i;
    uint8_t t[200];

    /* Zero state */
    for (i = 0; i < 25; ++i) {
        s[i] = 0;
    }

    while (mlen >= r) {
        for (i = 0; i < r / 8; ++i) {
            s[i] ^= load64(m + 8 * i);
        }

        KeccakF1600_StatePermute(s);
        mlen -= r;
        m += r;
    }

    for (i = 0; i < r; ++i) {
        t[i] = 0;
    }
    for (i = 0; i < mlen; ++i) {
        t[i] = m[i];
    }
    t[i] = p;
    t[r - 1] |= 128;
    for (i = 0; i < r / 8; ++i) {
        s[i] ^= load64(t + 8 * i);
    }
}

/*************************************************
 * Name:        keccak_squeezeblocks
 *
 * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each.
 *              Modifies the state. Can be called multiple times to keep
 *              squeezing, i.e., is incremental.
 *
 * Arguments:   - uint8_t *h: pointer to output blocks
 *              - size_t nblocks: number of blocks to be
 *                                                squeezed (written to h)
 *              - uint64_t *s: pointer to input/output Keccak state
 *              - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
 **************************************************/
static void keccak_squeezeblocks(uint8_t *h, size_t nblocks,
                                 uint64_t *s, uint32_t r) {
    while (nblocks > 0) {
        KeccakF1600_StatePermute(s);
        for (size_t i = 0; i < (r >> 3); i++) {
            store64(h + 8 * i, s[i]);
        }
        h += r;
        nblocks--;
    }
}

/*************************************************
 * Name:        keccak_inc_init
 *
 * Description: Initializes the incremental Keccak state to zero.
 *
 * Arguments:   - uint64_t *s_inc: pointer to input/output incremental state
 *                First 25 values represent Keccak state.
 *                26th value represents either the number of absorbed bytes
 *                that have not been permuted, or not-yet-squeezed bytes.
 **************************************************/
static void keccak_inc_init(uint64_t *s_inc) {
    size_t i;

    for (i = 0; i < 25; ++i) {
        s_inc[i] = 0;
    }
    s_inc[25] = 0;
}

/*************************************************
 * Name:        keccak_inc_absorb
 *
 * Description: Incremental keccak absorb
 *              Preceded by keccak_inc_init, succeeded by keccak_inc_finalize
 *
 * Arguments:   - uint64_t *s_inc: pointer to input/output incremental state
 *                First 25 values represent Keccak state.
 *                26th value represents either the number of absorbed bytes
 *                that have not been permuted, or not-yet-squeezed bytes.
 *              - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
 *              - const uint8_t *m: pointer to input to be absorbed into s
 *              - size_t mlen: length of input in bytes
 **************************************************/
static void keccak_inc_absorb(uint64_t *s_inc, uint32_t r, const uint8_t *m,
                              size_t mlen) {
    size_t i;

    /* Recall that s_inc[25] is the non-absorbed bytes xored into the state */
    while (mlen + s_inc[25] >= r) {
        for (i = 0; i < r - s_inc[25]; i++) {
            /* Take the i'th byte from message
               xor with the s_inc[25] + i'th byte of the state; little-endian */
            s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07));
        }
        mlen -= (size_t)(r - s_inc[25]);
        m += r - s_inc[25];
        s_inc[25] = 0;

        KeccakF1600_StatePermute(s_inc);
    }

    for (i = 0; i < mlen; i++) {
        s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07));
    }
    s_inc[25] += mlen;
}

/*************************************************
 * Name:        keccak_inc_finalize
 *
 * Description: Finalizes Keccak absorb phase, prepares for squeezing
 *
 * Arguments:   - uint64_t *s_inc: pointer to input/output incremental state
 *                First 25 values represent Keccak state.
 *                26th value represents either the number of absorbed bytes
 *                that have not been permuted, or not-yet-squeezed bytes.
 *              - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
 *              - uint8_t p: domain-separation byte for different
 *                                 Keccak-derived functions
 **************************************************/
static void keccak_inc_finalize(uint64_t *s_inc, uint32_t r, uint8_t p) {
    /* After keccak_inc_absorb, we are guaranteed that s_inc[25] < r,
       so we can always use one more byte for p in the current state. */
    s_inc[s_inc[25] >> 3] ^= (uint64_t)p << (8 * (s_inc[25] & 0x07));
    s_inc[(r - 1) >> 3] ^= (uint64_t)128 << (8 * ((r - 1) & 0x07));
    s_inc[25] = 0;
}

/*************************************************
 * Name:        keccak_inc_squeeze
 *
 * Description: Incremental Keccak squeeze; can be called on byte-level
 *
 * Arguments:   - uint8_t *h: pointer to output bytes
 *              - size_t outlen: number of bytes to be squeezed
 *              - uint64_t *s_inc: pointer to input/output incremental state
 *                First 25 values represent Keccak state.
 *                26th value represents either the number of absorbed bytes
 *                that have not been permuted, or not-yet-squeezed bytes.
 *              - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
 **************************************************/
static void keccak_inc_squeeze(uint8_t *h, size_t outlen,
                               uint64_t *s_inc, uint32_t r) {
    size_t i;

    /* First consume any bytes we still have sitting around */
    for (i = 0; i < outlen && i < s_inc[25]; i++) {
        /* There are s_inc[25] bytes left, so r - s_inc[25] is the first
           available byte. We consume from there, i.e., up to r. */
        h[i] = (uint8_t)(s_inc[(r - s_inc[25] + i) >> 3] >> (8 * ((r - s_inc[25] + i) & 0x07)));
    }
    h += i;
    outlen -= i;
    s_inc[25] -= i;

    /* Then squeeze the remaining necessary blocks */
    while (outlen > 0) {
        KeccakF1600_StatePermute(s_inc);

        for (i = 0; i < outlen && i < r; i++) {
            h[i] = (uint8_t)(s_inc[i >> 3] >> (8 * (i & 0x07)));
        }
        h += i;
        outlen -= i;
        s_inc[25] = r - i;
    }
}

void shake256_inc_init(uint64_t *s_inc) {
    keccak_inc_init(s_inc);
}

void shake256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen) {
    keccak_inc_absorb(s_inc, SHAKE256_RATE, input, inlen);
}

void shake256_inc_finalize(uint64_t *s_inc) {
    keccak_inc_finalize(s_inc, SHAKE256_RATE, 0x1F);
}

void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc) {
    keccak_inc_squeeze(output, outlen, s_inc, SHAKE256_RATE);
}

/*************************************************
 * Name:        shake256_absorb
 *
 * Description: Absorb step of the SHAKE256 XOF.
 *              non-incremental, starts by zeroeing the state.
 *
 * Arguments:   - uint64_t *s: pointer to (uninitialized) output Keccak state
 *              - const uint8_t *input: pointer to input to be absorbed
 *                                            into s
 *              - size_t inlen: length of input in bytes
 **************************************************/
void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen) {
    keccak_absorb(s, SHAKE256_RATE, input, inlen, 0x1F);
}

/*************************************************
 * Name:        shake256_squeezeblocks
 *
 * Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of
 *              SHAKE256_RATE bytes each. Modifies the state. Can be called
 *              multiple times to keep squeezing, i.e., is incremental.
 *
 * Arguments:   - uint8_t *output: pointer to output blocks
 *              - size_t nblocks: number of blocks to be squeezed
 *                                (written to output)
 *              - uint64_t *s: pointer to input/output Keccak state
 **************************************************/
void shake256_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s) {
    keccak_squeezeblocks(output, nblocks, s, SHAKE256_RATE);
}

/*************************************************
 * Name:        shake256
 *
 * Description: SHAKE256 XOF with non-incremental API
 *
 * Arguments:   - uint8_t *output: pointer to output
 *              - size_t outlen: requested output length in bytes
 *              - const uint8_t *input: pointer to input
 *              - size_t inlen: length of input in bytes
 **************************************************/
void shake256(uint8_t *output, size_t outlen,
              const uint8_t *input, size_t inlen) {
    size_t nblocks = outlen / SHAKE256_RATE;
    uint8_t t[SHAKE256_RATE];
    uint64_t s[25];

    shake256_absorb(s, input, inlen);
    shake256_squeezeblocks(output, nblocks, s);

    output += nblocks * SHAKE256_RATE;
    outlen -= nblocks * SHAKE256_RATE;

    if (outlen) {
        shake256_squeezeblocks(t, 1, s);
        for (size_t i = 0; i < outlen; ++i) {
            output[i] = t[i];
        }
    }
}


================================================
FILE: ref/fips202.h
================================================
#ifndef SPX_FIPS202_H
#define SPX_FIPS202_H

#include <stddef.h>
#include <stdint.h>

#define SHAKE128_RATE 168
#define SHAKE256_RATE 136
#define SHA3_256_RATE 136
#define SHA3_512_RATE 72

void shake128_absorb(uint64_t *s, const uint8_t *input, size_t inlen);

void shake128_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s);

void shake128_inc_init(uint64_t *s_inc);
void shake128_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen);
void shake128_inc_finalize(uint64_t *s_inc);
void shake128_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc);

void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen);
void shake256_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s);

void shake256_inc_init(uint64_t *s_inc);
void shake256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen);
void shake256_inc_finalize(uint64_t *s_inc);
void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc);

void shake128(uint8_t *output, size_t outlen,
              const uint8_t *input, size_t inlen);

void shake256(uint8_t *output, size_t outlen,
              const uint8_t *input, size_t inlen);

void sha3_256_inc_init(uint64_t *s_inc);
void sha3_256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen);
void sha3_256_inc_finalize(uint8_t *output, uint64_t *s_inc);

void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen);

void sha3_512_inc_init(uint64_t *s_inc);
void sha3_512_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen);
void sha3_512_inc_finalize(uint8_t *output, uint64_t *s_inc);

void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen);

#endif


================================================
FILE: ref/fors.c
================================================
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include "fors.h"
#include "utils.h"
#include "utilsx1.h"
#include "hash.h"
#include "thash.h"
#include "address.h"

static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx,
                        uint32_t fors_leaf_addr[8])
{
    prf_addr(sk, ctx, fors_leaf_addr);
}

static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
                            const spx_ctx *ctx,
                            uint32_t fors_leaf_addr[8])
{
    thash(leaf, sk, 1, ctx, fors_leaf_addr);
}

struct fors_gen_leaf_info {
    uint32_t leaf_addrx[8];
};

static void fors_gen_leafx1(unsigned char *leaf,
                            const spx_ctx *ctx,
                            uint32_t addr_idx, void *info)
{
    struct fors_gen_leaf_info *fors_info = info;
    uint32_t *fors_leaf_addr = fors_info->leaf_addrx;

    /* Only set the parts that the caller doesn't set */
    set_tree_index(fors_leaf_addr, addr_idx);
    set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF);
    fors_gen_sk(leaf, ctx, fors_leaf_addr);

    set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE);
    fors_sk_to_leaf(leaf, leaf,
                    ctx, fors_leaf_addr);
}

/**
 * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers.
 * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
 * Assumes indices has space for SPX_FORS_TREES integers.
 */
static void message_to_indices(uint32_t *indices, const unsigned char *m)
{
    unsigned int i, j;
    unsigned int offset = 0;

    for (i = 0; i < SPX_FORS_TREES; i++) {
        indices[i] = 0;
        for (j = 0; j < SPX_FORS_HEIGHT; j++) {
            indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 1u) << j;
            offset++;
        }
    }
}

/**
 * Signs a message m, deriving the secret key from sk_seed and the FTS address.
 * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
 */
void fors_sign(unsigned char *sig, unsigned char *pk,
               const unsigned char *m,
               const spx_ctx *ctx,
               const uint32_t fors_addr[8])
{
    uint32_t indices[SPX_FORS_TREES];
    unsigned char roots[SPX_FORS_TREES * SPX_N];
    uint32_t fors_tree_addr[8] = {0};
    struct fors_gen_leaf_info fors_info = {0};
    uint32_t *fors_leaf_addr = fors_info.leaf_addrx;
    uint32_t fors_pk_addr[8] = {0};
    uint32_t idx_offset;
    unsigned int i;

    copy_keypair_addr(fors_tree_addr, fors_addr);
    copy_keypair_addr(fors_leaf_addr, fors_addr);

    copy_keypair_addr(fors_pk_addr, fors_addr);
    set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK);

    message_to_indices(indices, m);

    for (i = 0; i < SPX_FORS_TREES; i++) {
        idx_offset = i * (1 << SPX_FORS_HEIGHT);

        set_tree_height(fors_tree_addr, 0);
        set_tree_index(fors_tree_addr, indices[i] + idx_offset);
        set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF);

        /* Include the secret key part that produces the selected leaf node. */
        fors_gen_sk(sig, ctx, fors_tree_addr);
        set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
        sig += SPX_N;

        /* Compute the authentication path for this leaf node. */
        treehashx1(roots + i*SPX_N, sig, ctx,
                 indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1,
                 fors_tree_addr, &fors_info);

        sig += SPX_N * SPX_FORS_HEIGHT;
    }

    /* Hash horizontally across all tree roots to derive the public key. */
    thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr);
}

/**
 * Derives the FORS public key from a signature.
 * This can be used for verification by comparing to a known public key, or to
 * subsequently verify a signature on the derived public key. The latter is the
 * typical use-case when used as an FTS below an OTS in a hypertree.
 * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
 */
void fors_pk_from_sig(unsigned char *pk,
                      const unsigned char *sig, const unsigned char *m,
                      const spx_ctx* ctx,
                      const uint32_t fors_addr[8])
{
    uint32_t indices[SPX_FORS_TREES];
    unsigned char roots[SPX_FORS_TREES * SPX_N];
    unsigned char leaf[SPX_N];
    uint32_t fors_tree_addr[8] = {0};
    uint32_t fors_pk_addr[8] = {0};
    uint32_t idx_offset;
    unsigned int i;

    copy_keypair_addr(fors_tree_addr, fors_addr);
    copy_keypair_addr(fors_pk_addr, fors_addr);

    set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
    set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK);

    message_to_indices(indices, m);

    for (i = 0; i < SPX_FORS_TREES; i++) {
        idx_offset = i * (1 << SPX_FORS_HEIGHT);

        set_tree_height(fors_tree_addr, 0);
        set_tree_index(fors_tree_addr, indices[i] + idx_offset);

        /* Derive the leaf from the included secret key part. */
        fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr);
        sig += SPX_N;

        /* Derive the corresponding root node of this tree. */
        compute_root(roots + i*SPX_N, leaf, indices[i], idx_offset,
                     sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr);
        sig += SPX_N * SPX_FORS_HEIGHT;
    }

    /* Hash horizontally across all tree roots to derive the public key. */
    thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr);
}


================================================
FILE: ref/fors.h
================================================
#ifndef SPX_FORS_H
#define SPX_FORS_H

#include <stdint.h>

#include "params.h"
#include "context.h"

/**
 * Signs a message m, deriving the secret key from sk_seed and the FTS address.
 * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
 */
#define fors_sign SPX_NAMESPACE(fors_sign)
void fors_sign(unsigned char *sig, unsigned char *pk,
               const unsigned char *m,
               const spx_ctx* ctx,
               const uint32_t fors_addr[8]);

/**
 * Derives the FORS public key from a signature.
 * This can be used for verification by comparing to a known public key, or to
 * subsequently verify a signature on the derived public key. The latter is the
 * typical use-case when used as an FTS below an OTS in a hypertree.
 * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
 */
#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig)
void fors_pk_from_sig(unsigned char *pk,
                      const unsigned char *sig, const unsigned char *m,
                      const spx_ctx* ctx,
                      const uint32_t fors_addr[8]);

#endif


================================================
FILE: ref/haraka.c
================================================
/*
 * Constant time implementation of the Haraka hash function.
 *
 * The bit-sliced implementation of the AES round functions are
 * based on the AES implementation in BearSSL written 
 * by Thomas Pornin <pornin@bolet.org>, licensed as follows:
 *
 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
 *
 * 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.
 */

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>

#include "haraka.h"
#include "utils.h"

#define HARAKAS_RATE 32

static const uint64_t haraka512_rc64[10][8] = {
    {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1},
    {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0},
    {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599},
    {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef},
    {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4},
    {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67},
    {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba},
    {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96},
    {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c},
    {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c},
};

static inline uint32_t br_dec32le(const unsigned char *src)
{
    return (uint32_t)src[0]
           | ((uint32_t)src[1] << 8)
           | ((uint32_t)src[2] << 16)
           | ((uint32_t)src[3] << 24);
}

static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src)
{
    while (num-- > 0) {
        *v ++ = br_dec32le(src);
        src += 4;
    }
}

static inline void br_enc32le(unsigned char *dst, uint32_t x)
{
    dst[0] = (unsigned char)x;
    dst[1] = (unsigned char)(x >> 8);
    dst[2] = (unsigned char)(x >> 16);
    dst[3] = (unsigned char)(x >> 24);
}


static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num)
{
    while (num-- > 0) {
        br_enc32le(dst, *v ++);
        dst += 4;
    }
}

static void br_aes_ct64_bitslice_Sbox(uint64_t *q) {
    /*
     * This S-box implementation is a straightforward translation of
     * the circuit described by Boyar and Peralta in "A new
     * combinational logic minimization technique with applications
     * to cryptology" (https://eprint.iacr.org/2009/191.pdf).
     *
     * Note that variables x* (input) and s* (output) are numbered
     * in "reverse" order (x0 is the high bit, x7 is the low bit).
     */

    uint64_t x0, x1, x2, x3, x4, x5, x6, x7;
    uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9;
    uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19;
    uint64_t y20, y21;
    uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9;
    uint64_t z10, z11, z12, z13, z14, z15, z16, z17;
    uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
    uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19;
    uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29;
    uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39;
    uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49;
    uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59;
    uint64_t t60, t61, t62, t63, t64, t65, t66, t67;
    uint64_t s0, s1, s2, s3, s4, s5, s6, s7;

    x0 = q[7];
    x1 = q[6];
    x2 = q[5];
    x3 = q[4];
    x4 = q[3];
    x5 = q[2];
    x6 = q[1];
    x7 = q[0];

    /*
     * Top linear transformation.
     */
    y14 = x3 ^ x5;
    y13 = x0 ^ x6;
    y9 = x0 ^ x3;
    y8 = x0 ^ x5;
    t0 = x1 ^ x2;
    y1 = t0 ^ x7;
    y4 = y1 ^ x3;
    y12 = y13 ^ y14;
    y2 = y1 ^ x0;
    y5 = y1 ^ x6;
    y3 = y5 ^ y8;
    t1 = x4 ^ y12;
    y15 = t1 ^ x5;
    y20 = t1 ^ x1;
    y6 = y15 ^ x7;
    y10 = y15 ^ t0;
    y11 = y20 ^ y9;
    y7 = x7 ^ y11;
    y17 = y10 ^ y11;
    y19 = y10 ^ y8;
    y16 = t0 ^ y11;
    y21 = y13 ^ y16;
    y18 = x0 ^ y16;

    /*
     * Non-linear section.
     */
    t2 = y12 & y15;
    t3 = y3 & y6;
    t4 = t3 ^ t2;
    t5 = y4 & x7;
    t6 = t5 ^ t2;
    t7 = y13 & y16;
    t8 = y5 & y1;
    t9 = t8 ^ t7;
    t10 = y2 & y7;
    t11 = t10 ^ t7;
    t12 = y9 & y11;
    t13 = y14 & y17;
    t14 = t13 ^ t12;
    t15 = y8 & y10;
    t16 = t15 ^ t12;
    t17 = t4 ^ t14;
    t18 = t6 ^ t16;
    t19 = t9 ^ t14;
    t20 = t11 ^ t16;
    t21 = t17 ^ y20;
    t22 = t18 ^ y19;
    t23 = t19 ^ y21;
    t24 = t20 ^ y18;

    t25 = t21 ^ t22;
    t26 = t21 & t23;
    t27 = t24 ^ t26;
    t28 = t25 & t27;
    t29 = t28 ^ t22;
    t30 = t23 ^ t24;
    t31 = t22 ^ t26;
    t32 = t31 & t30;
    t33 = t32 ^ t24;
    t34 = t23 ^ t33;
    t35 = t27 ^ t33;
    t36 = t24 & t35;
    t37 = t36 ^ t34;
    t38 = t27 ^ t36;
    t39 = t29 & t38;
    t40 = t25 ^ t39;

    t41 = t40 ^ t37;
    t42 = t29 ^ t33;
    t43 = t29 ^ t40;
    t44 = t33 ^ t37;
    t45 = t42 ^ t41;
    z0 = t44 & y15;
    z1 = t37 & y6;
    z2 = t33 & x7;
    z3 = t43 & y16;
    z4 = t40 & y1;
    z5 = t29 & y7;
    z6 = t42 & y11;
    z7 = t45 & y17;
    z8 = t41 & y10;
    z9 = t44 & y12;
    z10 = t37 & y3;
    z11 = t33 & y4;
    z12 = t43 & y13;
    z13 = t40 & y5;
    z14 = t29 & y2;
    z15 = t42 & y9;
    z16 = t45 & y14;
    z17 = t41 & y8;

    /*
     * Bottom linear transformation.
     */
    t46 = z15 ^ z16;
    t47 = z10 ^ z11;
    t48 = z5 ^ z13;
    t49 = z9 ^ z10;
    t50 = z2 ^ z12;
    t51 = z2 ^ z5;
    t52 = z7 ^ z8;
    t53 = z0 ^ z3;
    t54 = z6 ^ z7;
    t55 = z16 ^ z17;
    t56 = z12 ^ t48;
    t57 = t50 ^ t53;
    t58 = z4 ^ t46;
    t59 = z3 ^ t54;
    t60 = t46 ^ t57;
    t61 = z14 ^ t57;
    t62 = t52 ^ t58;
    t63 = t49 ^ t58;
    t64 = z4 ^ t59;
    t65 = t61 ^ t62;
    t66 = z1 ^ t63;
    s0 = t59 ^ t63;
    s6 = t56 ^ ~t62;
    s7 = t48 ^ ~t60;
    t67 = t64 ^ t65;
    s3 = t53 ^ t66;
    s4 = t51 ^ t66;
    s5 = t47 ^ t65;
    s1 = t64 ^ ~s3;
    s2 = t55 ^ ~t67;

    q[7] = s0;
    q[6] = s1;
    q[5] = s2;
    q[4] = s3;
    q[3] = s4;
    q[2] = s5;
    q[1] = s6;
    q[0] = s7;
}

static void br_aes_ct_bitslice_Sbox(uint32_t *q)
{
    /*
     * This S-box implementation is a straightforward translation of
     * the circuit described by Boyar and Peralta in "A new
     * combinational logic minimization technique with applications
     * to cryptology" (https://eprint.iacr.org/2009/191.pdf).
     *
     * Note that variables x* (input) and s* (output) are numbered
     * in "reverse" order (x0 is the high bit, x7 is the low bit).
     */

    uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
    uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9;
    uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19;
    uint32_t y20, y21;
    uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9;
    uint32_t z10, z11, z12, z13, z14, z15, z16, z17;
    uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
    uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19;
    uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29;
    uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39;
    uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49;
    uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59;
    uint32_t t60, t61, t62, t63, t64, t65, t66, t67;
    uint32_t s0, s1, s2, s3, s4, s5, s6, s7;

    x0 = q[7];
    x1 = q[6];
    x2 = q[5];
    x3 = q[4];
    x4 = q[3];
    x5 = q[2];
    x6 = q[1];
    x7 = q[0];

    /*
     * Top linear transformation.
     */
    y14 = x3 ^ x5;
    y13 = x0 ^ x6;
    y9 = x0 ^ x3;
    y8 = x0 ^ x5;
    t0 = x1 ^ x2;
    y1 = t0 ^ x7;
    y4 = y1 ^ x3;
    y12 = y13 ^ y14;
    y2 = y1 ^ x0;
    y5 = y1 ^ x6;
    y3 = y5 ^ y8;
    t1 = x4 ^ y12;
    y15 = t1 ^ x5;
    y20 = t1 ^ x1;
    y6 = y15 ^ x7;
    y10 = y15 ^ t0;
    y11 = y20 ^ y9;
    y7 = x7 ^ y11;
    y17 = y10 ^ y11;
    y19 = y10 ^ y8;
    y16 = t0 ^ y11;
    y21 = y13 ^ y16;
    y18 = x0 ^ y16;

    /*
     * Non-linear section.
     */
    t2 = y12 & y15;
    t3 = y3 & y6;
    t4 = t3 ^ t2;
    t5 = y4 & x7;
    t6 = t5 ^ t2;
    t7 = y13 & y16;
    t8 = y5 & y1;
    t9 = t8 ^ t7;
    t10 = y2 & y7;
    t11 = t10 ^ t7;
    t12 = y9 & y11;
    t13 = y14 & y17;
    t14 = t13 ^ t12;
    t15 = y8 & y10;
    t16 = t15 ^ t12;
    t17 = t4 ^ t14;
    t18 = t6 ^ t16;
    t19 = t9 ^ t14;
    t20 = t11 ^ t16;
    t21 = t17 ^ y20;
    t22 = t18 ^ y19;
    t23 = t19 ^ y21;
    t24 = t20 ^ y18;

    t25 = t21 ^ t22;
    t26 = t21 & t23;
    t27 = t24 ^ t26;
    t28 = t25 & t27;
    t29 = t28 ^ t22;
    t30 = t23 ^ t24;
    t31 = t22 ^ t26;
    t32 = t31 & t30;
    t33 = t32 ^ t24;
    t34 = t23 ^ t33;
    t35 = t27 ^ t33;
    t36 = t24 & t35;
    t37 = t36 ^ t34;
    t38 = t27 ^ t36;
    t39 = t29 & t38;
    t40 = t25 ^ t39;

    t41 = t40 ^ t37;
    t42 = t29 ^ t33;
    t43 = t29 ^ t40;
    t44 = t33 ^ t37;
    t45 = t42 ^ t41;
    z0 = t44 & y15;
    z1 = t37 & y6;
    z2 = t33 & x7;
    z3 = t43 & y16;
    z4 = t40 & y1;
    z5 = t29 & y7;
    z6 = t42 & y11;
    z7 = t45 & y17;
    z8 = t41 & y10;
    z9 = t44 & y12;
    z10 = t37 & y3;
    z11 = t33 & y4;
    z12 = t43 & y13;
    z13 = t40 & y5;
    z14 = t29 & y2;
    z15 = t42 & y9;
    z16 = t45 & y14;
    z17 = t41 & y8;

    /*
     * Bottom linear transformation.
     */
    t46 = z15 ^ z16;
    t47 = z10 ^ z11;
    t48 = z5 ^ z13;
    t49 = z9 ^ z10;
    t50 = z2 ^ z12;
    t51 = z2 ^ z5;
    t52 = z7 ^ z8;
    t53 = z0 ^ z3;
    t54 = z6 ^ z7;
    t55 = z16 ^ z17;
    t56 = z12 ^ t48;
    t57 = t50 ^ t53;
    t58 = z4 ^ t46;
    t59 = z3 ^ t54;
    t60 = t46 ^ t57;
    t61 = z14 ^ t57;
    t62 = t52 ^ t58;
    t63 = t49 ^ t58;
    t64 = z4 ^ t59;
    t65 = t61 ^ t62;
    t66 = z1 ^ t63;
    s0 = t59 ^ t63;
    s6 = t56 ^ ~t62;
    s7 = t48 ^ ~t60;
    t67 = t64 ^ t65;
    s3 = t53 ^ t66;
    s4 = t51 ^ t66;
    s5 = t47 ^ t65;
    s1 = t64 ^ ~s3;
    s2 = t55 ^ ~t67;

    q[7] = s0;
    q[6] = s1;
    q[5] = s2;
    q[4] = s3;
    q[3] = s4;
    q[2] = s5;
    q[1] = s6;
    q[0] = s7;
}

static void br_aes_ct_ortho(uint32_t *q)
{
#define SWAPN_32(cl, ch, s, x, y)   do { \
        uint32_t a, b; \
        a = (x); \
        b = (y); \
        (x) = (a & (uint32_t)cl) | ((b & (uint32_t)cl) << (s)); \
        (y) = ((a & (uint32_t)ch) >> (s)) | (b & (uint32_t)ch); \
    } while (0)

#define SWAP2_32(x, y)   SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y)
#define SWAP4_32(x, y)   SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y)
#define SWAP8_32(x, y)   SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y)

    SWAP2_32(q[0], q[1]);
    SWAP2_32(q[2], q[3]);
    SWAP2_32(q[4], q[5]);
    SWAP2_32(q[6], q[7]);

    SWAP4_32(q[0], q[2]);
    SWAP4_32(q[1], q[3]);
    SWAP4_32(q[4], q[6]);
    SWAP4_32(q[5], q[7]);

    SWAP8_32(q[0], q[4]);
    SWAP8_32(q[1], q[5]);
    SWAP8_32(q[2], q[6]);
    SWAP8_32(q[3], q[7]);
}

static inline void add_round_key32(uint32_t *q, const uint32_t *sk)
{
    q[0] ^= sk[0];
    q[1] ^= sk[1];
    q[2] ^= sk[2];
    q[3] ^= sk[3];
    q[4] ^= sk[4];
    q[5] ^= sk[5];
    q[6] ^= sk[6];
    q[7] ^= sk[7];
}

static inline void shift_rows32(uint32_t *q)
{
    int i;

    for (i = 0; i < 8; i++) {
        uint32_t x;

        x = q[i];
        q[i] = (x & 0x000000FF)
            | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6)
            | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4)
            | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2);
    }
}

static inline uint32_t rotr16(uint32_t x)
{
    return (x << 16) | (x >> 16);
}

static inline void mix_columns32(uint32_t *q)
{
    uint32_t q0, q1, q2, q3, q4, q5, q6, q7;
    uint32_t r0, r1, r2, r3, r4, r5, r6, r7;

    q0 = q[0];
    q1 = q[1];
    q2 = q[2];
    q3 = q[3];
    q4 = q[4];
    q5 = q[5];
    q6 = q[6];
    q7 = q[7];
    r0 = (q0 >> 8) | (q0 << 24);
    r1 = (q1 >> 8) | (q1 << 24);
    r2 = (q2 >> 8) | (q2 << 24);
    r3 = (q3 >> 8) | (q3 << 24);
    r4 = (q4 >> 8) | (q4 << 24);
    r5 = (q5 >> 8) | (q5 << 24);
    r6 = (q6 >> 8) | (q6 << 24);
    r7 = (q7 >> 8) | (q7 << 24);

    q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0);
    q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1);
    q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2);
    q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3);
    q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4);
    q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5);
    q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6);
    q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7);
}

static void br_aes_ct64_ortho(uint64_t *q)
{
#define SWAPN(cl, ch, s, x, y)   do { \
        uint64_t a, b; \
        a = (x); \
        b = (y); \
        (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \
        (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \
    } while (0)

#define SWAP2(x, y)    SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA,  1, x, y)
#define SWAP4(x, y)    SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC,  2, x, y)
#define SWAP8(x, y)    SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0,  4, x, y)

    SWAP2(q[0], q[1]);
    SWAP2(q[2], q[3]);
    SWAP2(q[4], q[5]);
    SWAP2(q[6], q[7]);

    SWAP4(q[0], q[2]);
    SWAP4(q[1], q[3]);
    SWAP4(q[4], q[6]);
    SWAP4(q[5], q[7]);

    SWAP8(q[0], q[4]);
    SWAP8(q[1], q[5]);
    SWAP8(q[2], q[6]);
    SWAP8(q[3], q[7]);
}


static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w)
{
    uint64_t x0, x1, x2, x3;

    x0 = w[0];
    x1 = w[1];
    x2 = w[2];
    x3 = w[3];
    x0 |= (x0 << 16);
    x1 |= (x1 << 16);
    x2 |= (x2 << 16);
    x3 |= (x3 << 16);
    x0 &= (uint64_t)0x0000FFFF0000FFFF;
    x1 &= (uint64_t)0x0000FFFF0000FFFF;
    x2 &= (uint64_t)0x0000FFFF0000FFFF;
    x3 &= (uint64_t)0x0000FFFF0000FFFF;
    x0 |= (x0 << 8);
    x1 |= (x1 << 8);
    x2 |= (x2 << 8);
    x3 |= (x3 << 8);
    x0 &= (uint64_t)0x00FF00FF00FF00FF;
    x1 &= (uint64_t)0x00FF00FF00FF00FF;
    x2 &= (uint64_t)0x00FF00FF00FF00FF;
    x3 &= (uint64_t)0x00FF00FF00FF00FF;
    *q0 = x0 | (x2 << 8);
    *q1 = x1 | (x3 << 8);
}


static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1)
{
    uint64_t x0, x1, x2, x3;

    x0 = q0 & (uint64_t)0x00FF00FF00FF00FF;
    x1 = q1 & (uint64_t)0x00FF00FF00FF00FF;
    x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF;
    x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF;
    x0 |= (x0 >> 8);
    x1 |= (x1 >> 8);
    x2 |= (x2 >> 8);
    x3 |= (x3 >> 8);
    x0 &= (uint64_t)0x0000FFFF0000FFFF;
    x1 &= (uint64_t)0x0000FFFF0000FFFF;
    x2 &= (uint64_t)0x0000FFFF0000FFFF;
    x3 &= (uint64_t)0x0000FFFF0000FFFF;
    w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16);
    w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16);
    w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16);
    w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16);
}

static inline void add_round_key(uint64_t *q, const uint64_t *sk)
{
    q[0] ^= sk[0];
    q[1] ^= sk[1];
    q[2] ^= sk[2];
    q[3] ^= sk[3];
    q[4] ^= sk[4];
    q[5] ^= sk[5];
    q[6] ^= sk[6];
    q[7] ^= sk[7];
}

static inline void shift_rows(uint64_t *q)
{
    int i;

    for (i = 0; i < 8; i++) {
        uint64_t x;

        x = q[i];
        q[i] = (x & (uint64_t)0x000000000000FFFF)
               | ((x & (uint64_t)0x00000000FFF00000) >> 4)
               | ((x & (uint64_t)0x00000000000F0000) << 12)
               | ((x & (uint64_t)0x0000FF0000000000) >> 8)
               | ((x & (uint64_t)0x000000FF00000000) << 8)
               | ((x & (uint64_t)0xF000000000000000) >> 12)
               | ((x & (uint64_t)0x0FFF000000000000) << 4);
    }
}

static inline uint64_t rotr32(uint64_t x)
{
    return (x << 32) | (x >> 32);
}

static inline void mix_columns(uint64_t *q)
{
    uint64_t q0, q1, q2, q3, q4, q5, q6, q7;
    uint64_t r0, r1, r2, r3, r4, r5, r6, r7;

    q0 = q[0];
    q1 = q[1];
    q2 = q[2];
    q3 = q[3];
    q4 = q[4];
    q5 = q[5];
    q6 = q[6];
    q7 = q[7];
    r0 = (q0 >> 16) | (q0 << 48);
    r1 = (q1 >> 16) | (q1 << 48);
    r2 = (q2 >> 16) | (q2 << 48);
    r3 = (q3 >> 16) | (q3 << 48);
    r4 = (q4 >> 16) | (q4 << 48);
    r5 = (q5 >> 16) | (q5 << 48);
    r6 = (q6 >> 16) | (q6 << 48);
    r7 = (q7 >> 16) | (q7 << 48);

    q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0);
    q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1);
    q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2);
    q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3);
    q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4);
    q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5);
    q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6);
    q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7);
}

static void interleave_constant(uint64_t *out, const unsigned char *in)
{
    uint32_t tmp_32_constant[16];
    int i;

    br_range_dec32le(tmp_32_constant, 16, in);
    for (i = 0; i < 4; i++) {
        br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2));
    }
    br_aes_ct64_ortho(out);
}

static void interleave_constant32(uint32_t *out, const unsigned char *in)
{
    int i;
    for (i = 0; i < 4; i++) {
        out[2*i] = br_dec32le(in + 4*i);
        out[2*i + 1] = br_dec32le(in + 4*i + 16);
    }
    br_aes_ct_ortho(out);
}

void tweak_constants(spx_ctx *ctx)
{
    unsigned char buf[40*16];
    int i;

    /* Use the standard constants to generate tweaked ones. */
    memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40*16);

    /* Constants for pk.seed */
    haraka_S(buf, 40*16, ctx->pub_seed, SPX_N, ctx);
    for (i = 0; i < 10; i++) {
        interleave_constant32(ctx->tweaked256_rc32[i], buf + 32*i);
        interleave_constant(ctx->tweaked512_rc64[i], buf + 64*i);
    }
}

static void haraka_S_absorb(unsigned char *s, unsigned int r,
                            const unsigned char *m, unsigned long long mlen,
                            unsigned char p, const spx_ctx *ctx)
{
    unsigned long long i;
    SPX_VLA(uint8_t, t, r);

    while (mlen >= r) {
        /* XOR block to state */
        for (i = 0; i < r; ++i) {
            s[i] ^= m[i];
        }
        haraka512_perm(s, s, ctx);
        mlen -= r;
        m += r;
    }

    for (i = 0; i < r; ++i) {
        t[i] = 0;
    }
    for (i = 0; i < mlen; ++i) {
        t[i] = m[i];
    }
    t[i] = p;
    t[r - 1] |= 128;
    for (i = 0; i < r; ++i) {
        s[i] ^= t[i];
    }
}

static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks,
                                   unsigned char *s, unsigned int r,
                                   const spx_ctx *ctx)
{
    while (nblocks > 0) {
        haraka512_perm(s, s, ctx);
        memcpy(h, s, HARAKAS_RATE);
        h += r;
        nblocks--;
    }
}

void haraka_S_inc_init(uint8_t *s_inc)
{
    size_t i;

    for (i = 0; i < 64; i++) {
        s_inc[i] = 0;
    }
    s_inc[64] = 0;
}

void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen,
        const spx_ctx *ctx)
{
    size_t i;

    /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */
    while (mlen + s_inc[64] >= HARAKAS_RATE) {
        for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) {
            /* Take the i'th byte from message
               xor with the s_inc[64] + i'th byte of the state */
            s_inc[s_inc[64] + i] ^= m[i];
        }
        mlen -= (size_t)(HARAKAS_RATE - s_inc[64]);
        m += HARAKAS_RATE - (uint8_t)s_inc[64];
        s_inc[64] = 0;

        haraka512_perm(s_inc, s_inc, ctx);
    }

    for (i = 0; i < mlen; i++) {
        s_inc[s_inc[64] + i] ^= m[i];
    }
    s_inc[64] += (uint8_t)mlen;
}

void haraka_S_inc_finalize(uint8_t *s_inc)
{
    /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE,
       so we can always use one more byte for p in the current state. */
    s_inc[s_inc[64]] ^= 0x1F;
    s_inc[HARAKAS_RATE - 1] ^= 128;
    s_inc[64] = 0;
}

void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc,
        const spx_ctx *ctx)
{
    size_t i;

    /* First consume any bytes we still have sitting around */
    for (i = 0; i < outlen && i < s_inc[64]; i++) {
        /* There are s_inc[64] bytes left, so r - s_inc[64] is the first
           available byte. We consume from there, i.e., up to r. */
        out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)];
    }
    out += i;
    outlen -= i;
    s_inc[64] -= (uint8_t)i;

    /* Then squeeze the remaining necessary blocks */
    while (outlen > 0) {
        haraka512_perm(s_inc, s_inc, ctx);

        for (i = 0; i < outlen && i < HARAKAS_RATE; i++) {
            out[i] = s_inc[i];
        }
        out += i;
        outlen -= i;
        s_inc[64] = (uint8_t)(HARAKAS_RATE - i);
    }
}

void haraka_S(unsigned char *out, unsigned long long outlen,
              const unsigned char *in, unsigned long long inlen,
              const spx_ctx *ctx)
{
    unsigned long long i;
    unsigned char s[64];
    unsigned char d[32];

    for (i = 0; i < 64; i++) {
        s[i] = 0;
    }
    haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx);

    haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx);
    out += (outlen / 32) * 32;

    if (outlen % 32) {
        haraka_S_squeezeblocks(d, 1, s, 32, ctx);
        for (i = 0; i < outlen % 32; i++) {
            out[i] = d[i];
        }
    }
}

void haraka512_perm(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx)
{
    uint32_t w[16];
    uint64_t q[8], tmp_q;
    unsigned int i, j;

    br_range_dec32le(w, 16, in);
    for (i = 0; i < 4; i++) {
        br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2));
    }
    br_aes_ct64_ortho(q);

    /* AES rounds */
    for (i = 0; i < 5; i++) {
        for (j = 0; j < 2; j++) {
            br_aes_ct64_bitslice_Sbox(q);
            shift_rows(q);
            mix_columns(q);
            add_round_key(q, ctx->tweaked512_rc64[2*i + j]);
        }
        /* Mix states */
        for (j = 0; j < 8; j++) {
            tmp_q = q[j];
            q[j] = (tmp_q & 0x0001000100010001) << 5 |
                   (tmp_q & 0x0002000200020002) << 12 |
                   (tmp_q & 0x0004000400040004) >> 1 |
                   (tmp_q & 0x0008000800080008) << 6 |
                   (tmp_q & 0x0020002000200020) << 9 |
                   (tmp_q & 0x0040004000400040) >> 4 |
                   (tmp_q & 0x0080008000800080) << 3 |
                   (tmp_q & 0x2100210021002100) >> 5 |
                   (tmp_q & 0x0210021002100210) << 2 |
                   (tmp_q & 0x0800080008000800) << 4 |
                   (tmp_q & 0x1000100010001000) >> 12 |
                   (tmp_q & 0x4000400040004000) >> 10 |
                   (tmp_q & 0x8400840084008400) >> 3;
        }
    }

    br_aes_ct64_ortho(q);
    for (i = 0; i < 4; i ++) {
        br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]);
    }
    br_range_enc32le(out, w, 16);
}

void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx)
{
    int i;

    unsigned char buf[64];

    haraka512_perm(buf, in, ctx);
    /* Feed-forward */
    for (i = 0; i < 64; i++) {
        buf[i] = buf[i] ^ in[i];
    }

    /* Truncated */
    memcpy(out,      buf + 8, 8);
    memcpy(out + 8,  buf + 24, 8);
    memcpy(out + 16, buf + 32, 8);
    memcpy(out + 24, buf + 48, 8);
}


void haraka256(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx)
{
    uint32_t q[8], tmp_q;
    int i, j;

    for (i = 0; i < 4; i++) {
        q[2*i] = br_dec32le(in + 4*i);
        q[2*i + 1] = br_dec32le(in + 4*i + 16);
    }
    br_aes_ct_ortho(q);

    /* AES rounds */
    for (i = 0; i < 5; i++) {
        for (j = 0; j < 2; j++) {
            br_aes_ct_bitslice_Sbox(q);
            shift_rows32(q);
            mix_columns32(q);
            add_round_key32(q, ctx->tweaked256_rc32[2*i + j]);
        }

        /* Mix states */
        for (j = 0; j < 8; j++) {
            tmp_q = q[j];
            q[j] = (tmp_q & 0x81818181) |
                   (tmp_q & 0x02020202) << 1 |
                   (tmp_q & 0x04040404) << 2 |
                   (tmp_q & 0x08080808) << 3 |
                   (tmp_q & 0x10101010) >> 3 |
                   (tmp_q & 0x20202020) >> 2 |
                   (tmp_q & 0x40404040) >> 1;
        }
    }

    br_aes_ct_ortho(q);
    for (i = 0; i < 4; i++) {
        br_enc32le(out + 4*i, q[2*i]);
        br_enc32le(out + 4*i + 16, q[2*i + 1]);
    }

    for (i = 0; i < 32; i++) {
        out[i] ^= in[i];
    }
}


================================================
FILE: ref/haraka.h
================================================
#ifndef SPX_HARAKA_H
#define SPX_HARAKA_H

#include "context.h"

/* Tweak constants with seed */
#define tweak_constants SPX_NAMESPACE(tweak_constants)
void tweak_constants(spx_ctx *ctx);

/* Haraka Sponge */
#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init)
void haraka_S_inc_init(uint8_t *s_inc);
#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb)
void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen,
        const spx_ctx *ctx);
#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize)
void haraka_S_inc_finalize(uint8_t *s_inc);
#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze)
void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc,
        const spx_ctx *ctx);
#define haraka_S SPX_NAMESPACE(haraka_S)
void haraka_S(unsigned char *out, unsigned long long outlen,
              const unsigned char *in, unsigned long long inlen,
              const spx_ctx *ctx);

/* Applies the 512-bit Haraka permutation to in. */
#define haraka512_perm SPX_NAMESPACE(haraka512_perm)
void haraka512_perm(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx);

/* Implementation of Haraka-512 */
#define haraka512 SPX_NAMESPACE(haraka512)
void haraka512(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx);

/* Implementation of Haraka-256 */
#define haraka256 SPX_NAMESPACE(haraka256)
void haraka256(unsigned char *out, const unsigned char *in,
        const spx_ctx *ctx);

#endif


================================================
FILE: ref/haraka_offsets.h
================================================
#if !defined( HARAKA_OFFSETS_H_ )
#define HARAKA_OFFSETS_H_

/*
 * Offsets of various fields in the address structure when we use Haraka as
 * the Sphincs+ hash function
 */

#define SPX_OFFSET_LAYER     3   /* The byte used to specify the Merkle tree layer */
#define SPX_OFFSET_TREE      8   /* The start of the 8 byte field used to specify the tree */
#define SPX_OFFSET_TYPE      19  /* The byte used to specify the hash type (reason) */
#define SPX_OFFSET_KP_ADDR   20  /* The start of the 4 byte field used to specify the key pair address */
#define SPX_OFFSET_CHAIN_ADDR 27  /* The byte used to specify the chain address (which Winternitz chain) */
#define SPX_OFFSET_HASH_ADDR 31  /* The byte used to specify the hash address (where in the Winternitz chain) */
#define SPX_OFFSET_TREE_HGT  27  /* The byte used to specify the height of this node in the FORS or Merkle tree */
#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */

#define SPX_HARAKA 1

#endif /* HARAKA_OFFSETS_H_ */


================================================
FILE: ref/hash.h
================================================
#ifndef SPX_HASH_H
#define SPX_HASH_H

#include <stdint.h>
#include "context.h"
#include "params.h"

#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function)
void initialize_hash_function(spx_ctx *ctx);

#define prf_addr SPX_NAMESPACE(prf_addr)
void prf_addr(unsigned char *out, const spx_ctx *ctx,
              const uint32_t addr[8]);

#define gen_message_random SPX_NAMESPACE(gen_message_random)
void gen_message_random(unsigned char *R, const unsigned char *sk_prf,
                        const unsigned char *optrand,
                        const unsigned char *m, unsigned long long mlen,
                        const spx_ctx *ctx);

#define hash_message SPX_NAMESPACE(hash_message)
void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
                  const unsigned char *R, const unsigned char *pk,
                  const unsigned char *m, unsigned long long mlen,
                  const spx_ctx *ctx);

#endif


================================================
FILE: ref/hash_haraka.c
================================================
#include <stdint.h>
#include <string.h>

#include "address.h"
#include "utils.h"
#include "params.h"

#include "haraka.h"
#include "hash.h"

void initialize_hash_function(spx_ctx* ctx)
{
    tweak_constants(ctx);
}

/*
 * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address
 */
void prf_addr(unsigned char *out, const spx_ctx *ctx,
              const uint32_t addr[8])
{
    /* Since SPX_N may be smaller than 32, we need temporary buffers. */
    unsigned char outbuf[32];
    unsigned char buf[64] = {0};

    memcpy(buf, addr, SPX_ADDR_BYTES);
    memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N);

    haraka512(outbuf, (const void *)buf, ctx);
    memcpy(out, outbuf, SPX_N);
}

/**
 * Computes the message-dependent randomness R, using a secret seed and an
 * optional randomization value as well as the message.
 */
void gen_message_random(unsigned char *R, const unsigned char* sk_prf,
                        const unsigned char *optrand,
                        const unsigned char *m, unsigned long long mlen,
                        const spx_ctx *ctx)
{
    uint8_t s_inc[65];

    haraka_S_inc_init(s_inc);
    haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx);
    haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx);
    haraka_S_inc_absorb(s_inc, m, mlen, ctx);
    haraka_S_inc_finalize(s_inc);
    haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx);
}

/**
 * Computes the message hash using R, the public key, and the message.
 * Outputs the message digest and the index of the leaf. The index is split in
 * the tree index and the leaf index, for convenient copying to an address.
 */
void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
                  const unsigned char *R, const unsigned char *pk,
                  const unsigned char *m, unsigned long long mlen,
                  const spx_ctx *ctx)
{
#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1))
#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8)
#define SPX_LEAF_BITS SPX_TREE_HEIGHT
#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8)
#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES)

    unsigned char buf[SPX_DGST_BYTES];
    unsigned char *bufp = buf;
    uint8_t s_inc[65];

    haraka_S_inc_init(s_inc);
    haraka_S_inc_absorb(s_inc, R, SPX_N, ctx);
    haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk
    haraka_S_inc_absorb(s_inc, m, mlen, ctx);
    haraka_S_inc_finalize(s_inc);
    haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx);

    memcpy(digest, bufp, SPX_FORS_MSG_BYTES);
    bufp += SPX_FORS_MSG_BYTES;

#if SPX_TREE_BITS > 64
    #error For given height and depth, 64 bits cannot represent all subtrees
#endif

    if (SPX_D == 1) {
	*tree = 0;
    } else {
        *tree = bytes_to_ull(bufp, SPX_TREE_BYTES);
        *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS);
    }
    bufp += SPX_TREE_BYTES;

    *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES);
    *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS);
}


================================================
FILE: ref/hash_sha2.c
================================================
#include <stdint.h>
#include <string.h>

#include "address.h"
#include "utils.h"
#include "params.h"
#include "hash.h"
#include "sha2.h"

#if SPX_N >= 24
#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES
#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES
#define shaX_inc_init sha512_inc_init
#define shaX_inc_blocks sha512_inc_blocks
#define shaX_inc_finalize sha512_inc_finalize
#define shaX sha512
#define mgf1_X mgf1_512
#else
#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES
#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES
#define shaX_inc_init sha256_inc_init
#define shaX_inc_blocks sha256_inc_blocks
#define shaX_inc_finalize sha256_inc_finalize
#define shaX sha256
#define mgf1_X mgf1_256
#endif


/* For SHA, there is no immediate reason to initialize at the start,
   so this function is an empty operation. */
void initialize_hash_function(spx_ctx *ctx)
{
    seed_state(ctx);
}

/*
 * Computes PRF(pk_seed, sk_seed, addr).
 */
void prf_addr(unsigned char *out, const spx_ctx *ctx,
              const uint32_t addr[8])
{
    uint8_t sha2_state[40];
    unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N];
    unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];

    /* Retrieve precomputed state containing pub_seed */
    memcpy(sha2_state, ctx->state_seeded, 40 * sizeof(uint8_t));

    /* Remainder: ADDR^c ‖ SK.seed */
    memcpy(buf, addr, SPX_SHA256_ADDR_BYTES);
    memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N);

    sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N);

    memcpy(out, outbuf, SPX_N);
}

/**
 * Computes the message-dependent randomness R, using a secret seed as a key
 * for HMAC, and an optional randomization value prefixed to the message.
 * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space
 * available in front of the pointer, i.e. before the message to use for the
 * prefix. This is necessary to prevent having to move the message around (and
 * allocate memory for it).
 */
void gen_message_random(unsigned char *R, const unsigned char *sk_prf,
                        const unsigned char *optrand,
                        const unsigned char *m, unsigned long long mlen,
                        const spx_ctx *ctx)
{
    (void)ctx;

    unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES];
    uint8_t state[8 + SPX_SHAX_OUTPUT_BYTES];
    int i;

#if SPX_N > SPX_SHAX_BLOCK_BYTES
    #error "Currently only supports SPX_N of at most SPX_SHAX_BLOCK_BYTES"
#endif

    /* This implements HMAC-SHA */
    for (i = 0; i < SPX_N; i++) {
        buf[i] = 0x36 ^ sk_prf[i];
    }
    memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N);

    shaX_inc_init(state);
    shaX_inc_blocks(state, buf, 1);

    memcpy(buf, optrand, SPX_N);

    /* If optrand + message cannot fill up an entire block */
    if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) {
        memcpy(buf + SPX_N, m, mlen);
        shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, state,
                            buf, mlen + SPX_N);
    }
    /* Otherwise first fill a block, so that finalize only uses the message */
    else {
        memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N);
        shaX_inc_blocks(state, buf, 1);

        m += SPX_SHAX_BLOCK_BYTES - SPX_N;
        mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N;
        shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, state, m, mlen);
    }

    for (i = 0; i < SPX_N; i++) {
        buf[i] = 0x5c ^ sk_prf[i];
    }
    memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N);

    shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES);
    memcpy(R, buf, SPX_N);
}

/**
 * Computes the message hash using R, the public key, and the message.
 * Outputs the message digest and the index of the leaf. The index is split in
 * the tree index and the leaf index, for convenient copying to an address.
 */
void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
                  const unsigned char *R, const unsigned char *pk,
                  const unsigned char *m, unsigned long long mlen,
                  const spx_ctx *ctx)
{
    (void)ctx;
#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1))
#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8)
#define SPX_LEAF_BITS SPX_TREE_HEIGHT
#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8)
#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES)

    unsigned char seed[2*SPX_N + SPX_SHAX_OUTPUT_BYTES];

    /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */
#if (SPX_SHAX_BLOCK_BYTES & (SPX_SHAX_BLOCK_BYTES-1)) != 0
    #error "Assumes that SPX_SHAX_BLOCK_BYTES is a power of 2"
#endif
#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \
                        -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES)
    unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES];

    unsigned char buf[SPX_DGST_BYTES];
    unsigned char *bufp = buf;
    uint8_t state[8 + SPX_SHAX_OUTPUT_BYTES];

    shaX_inc_init(state);

    // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M)
    memcpy(inbuf, R, SPX_N);
    memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES);

    /* If R + pk + message cannot fill up an entire block */
    if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) {
        memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen);
        shaX_inc_finalize(seed + 2*SPX_N, state, inbuf, SPX_N + SPX_PK_BYTES + mlen);
    }
    /* Otherwise first fill a block, so that finalize only uses the message */
    else {
        memcpy(inbuf + SPX_N + SPX_PK_BYTES, m,
               SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES);
        shaX_inc_blocks(state, inbuf, SPX_INBLOCKS);

        m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
        mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
        shaX_inc_finalize(seed + 2*SPX_N, state, m, mlen);
    }

    // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed)
    memcpy(seed, R, SPX_N);
    memcpy(seed + SPX_N, pk, SPX_N);

    /* By doing this in two steps, we prevent hashing the message twice;
       otherwise each iteration in MGF1 would hash the message again. */
    mgf1_X(bufp, SPX_DGST_BYTES, seed, 2*SPX_N + SPX_SHAX_OUTPUT_BYTES);

    memcpy(digest, bufp, SPX_FORS_MSG_BYTES);
    bufp += SPX_FORS_MSG_BYTES;

#if SPX_TREE_BITS > 64
    #error For given height and depth, 64 bits cannot represent all subtrees
#endif

    if (SPX_D == 1) {
	*tree = 0;
    } else {
        *tree = bytes_to_ull(bufp, SPX_TREE_BYTES);
        *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS);
    }
    bufp += SPX_TREE_BYTES;

    *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES);
    *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS);
}




================================================
FILE: ref/hash_shake.c
================================================
#include <stdint.h>
#include <string.h>

#include "address.h"
#include "utils.h"
#include "params.h"
#include "hash.h"
#include "fips202.h"

/* For SHAKE256, there is no immediate reason to initialize at the start,
   so this function is an empty operation. */
void initialize_hash_function(spx_ctx* ctx)
{
    (void)ctx; /* Suppress an 'unused parameter' warning. */
}

/*
 * Computes PRF(pk_seed, sk_seed, addr)
 */
void prf_addr(unsigned char *out, const spx_ctx *ctx,
              const uint32_t addr[8])
{
    unsigned char buf[2*SPX_N + SPX_ADDR_BYTES];

    memcpy(buf, ctx->pub_seed, SPX_N);
    memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES);
    memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N);

    shake256(out, SPX_N, buf, 2*SPX_N + SPX_ADDR_BYTES);
}

/**
 * Computes the message-dependent randomness R, using a secret seed and an
 * optional randomization value as well as the message.
 */
void gen_message_random(unsigned char *R, const unsigned char *sk_prf,
                        const unsigned char *optrand,
                        const unsigned char *m, unsigned long long mlen,
                        const spx_ctx *ctx)
{
    (void)ctx;
    uint64_t s_inc[26];

    shake256_inc_init(s_inc);
    shake256_inc_absorb(s_inc, sk_prf, SPX_N);
    shake256_inc_absorb(s_inc, optrand, SPX_N);
    shake256_inc_absorb(s_inc, m, mlen);
    shake256_inc_finalize(s_inc);
    shake256_inc_squeeze(R, SPX_N, s_inc);
}

/**
 * Computes the message hash using R, the public key, and the message.
 * Outputs the message digest and the index of the leaf. The index is split in
 * the tree index and the leaf index, for convenient copying to an address.
 */
void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
                  const unsigned char *R, const unsigned char *pk,
                  const unsigned char *m, unsigned long long mlen,
                  const spx_ctx *ctx)
{
    (void)ctx;
#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1))
#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8)
#define SPX_LEAF_BITS SPX_TREE_HEIGHT
#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8)
#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES)

    unsigned char buf[SPX_DGST_BYTES];
    unsigned char *bufp = buf;
    uint64_t s_inc[26];

    shake256_inc_init(s_inc);
    shake256_inc_absorb(s_inc, R, SPX_N);
    shake256_inc_absorb(s_inc, pk, SPX_PK_BYTES);
    shake256_inc_absorb(s_inc, m, mlen);
    shake256_inc_finalize(s_inc);
    shake256_inc_squeeze(buf, SPX_DGST_BYTES, s_inc);

    memcpy(digest, bufp, SPX_FORS_MSG_BYTES);
    bufp += SPX_FORS_MSG_BYTES;

#if SPX_TREE_BITS > 64
    #error For given height and depth, 64 bits cannot represent all subtrees
#endif

    if (SPX_D == 1) {
        *tree = 0;
    } else {
        *tree = bytes_to_ull(bufp, SPX_TREE_BYTES);
        *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS);
    }
    bufp += SPX_TREE_BYTES;

    *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES);
    *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS);
}


================================================
FILE: ref/merkle.c
================================================
#include <stdint.h>
#include <string.h>

#include "utils.h"
#include "utilsx1.h"
#include "wots.h"
#include "wotsx1.h"
#include "merkle.h"
#include "address.h"
#include "params.h"

/*
 * This generates a Merkle signature (WOTS signature followed by the Merkle
 * authentication path).  This is in this file because most of the complexity
 * is involved with the WOTS signature; the Merkle authentication path logic
 * is mostly hidden in treehashx4
 */
void merkle_sign(uint8_t *sig, unsigned char *root,
                 const spx_ctx *ctx,
                 uint32_t wots_addr[8], uint32_t tree_addr[8],
                 uint32_t idx_leaf)
{
    unsigned char *auth_path = sig + SPX_WOTS_BYTES;
    struct leaf_info_x1 info = { 0 };
    unsigned steps[ SPX_WOTS_LEN ];

    info.wots_sig = sig;
    chain_lengths(steps, root);
    info.wots_steps = steps;

    set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE);
    set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK);
    copy_subtree_addr(&info.leaf_addr[0], wots_addr);
    copy_subtree_addr(&info.pk_addr[0], wots_addr);

    info.wots_sign_leaf = idx_leaf;

    treehashx1(root, auth_path, ctx,
                idx_leaf, 0,
                SPX_TREE_HEIGHT,
                wots_gen_leafx1,
                tree_addr, &info);
}

/* Compute root node of the top-most subtree. */
void merkle_gen_root(unsigned char *root, const spx_ctx *ctx)
{
    /* We do not need the auth path in key generation, but it simplifies the
       code to have just one treehash routine that computes both root and path
       in one function. */
    unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES];
    uint32_t top_tree_addr[8] = {0};
    uint32_t wots_addr[8] = {0};

    set_layer_addr(top_tree_addr, SPX_D - 1);
    set_layer_addr(wots_addr, SPX_D - 1);

    merkle_sign(auth_path, root, ctx,
                wots_addr, top_tree_addr,
                (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ );
}


================================================
FILE: ref/merkle.h
================================================
#if !defined( MERKLE_H_ )
#define MERKLE_H_

#include <stdint.h>

/* Generate a Merkle signature (WOTS signature followed by the Merkle */
/* authentication path) */
#define merkle_sign SPX_NAMESPACE(merkle_sign)
void merkle_sign(uint8_t *sig, unsigned char *root,
        const spx_ctx* ctx,
        uint32_t wots_addr[8], uint32_t tree_addr[8],
        uint32_t idx_leaf);

/* Compute the root node of the top-most subtree. */
#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root)
void merkle_gen_root(unsigned char *root, const spx_ctx* ctx);

#endif /* MERKLE_H_ */


================================================
FILE: ref/params/params-sphincs-haraka-128f.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 16
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 66
/* Number of subtree layer. */
#define SPX_D 22
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 6
#define SPX_FORS_TREES 33
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../haraka_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-haraka-128s.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 16
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 63
/* Number of subtree layer. */
#define SPX_D 7
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 12
#define SPX_FORS_TREES 14
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../haraka_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-haraka-192f.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 24
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 66
/* Number of subtree layer. */
#define SPX_D 22
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 8
#define SPX_FORS_TREES 33
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../haraka_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-haraka-192s.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 24
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 63
/* Number of subtree layer. */
#define SPX_D 7
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 14
#define SPX_FORS_TREES 17
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../haraka_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-haraka-256f.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 32
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 68
/* Number of subtree layer. */
#define SPX_D 17
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 9
#define SPX_FORS_TREES 35
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../haraka_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-haraka-256s.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 32
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 64
/* Number of subtree layer. */
#define SPX_D 8
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 14
#define SPX_FORS_TREES 22
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../haraka_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-sha2-128f.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 16
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 66
/* Number of subtree layer. */
#define SPX_D 22
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 6
#define SPX_FORS_TREES 33
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* This is a SHA2-based parameter set, hence whether we use SHA-256
 * exclusively or we use both SHA-256 and SHA-512 is controlled by
 * the following #define */
#define SPX_SHA512 0  /* Use SHA-256 for all hashes */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../sha2_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-sha2-128s.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 16
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 63
/* Number of subtree layer. */
#define SPX_D 7
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 12
#define SPX_FORS_TREES 14
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* This is a SHA2-based parameter set, hence whether we use SHA-256
 * exclusively or we use both SHA-256 and SHA-512 is controlled by
 * the following #define */
#define SPX_SHA512 0  /* Use SHA-256 for all hashes */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../sha2_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-sha2-192f.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 24
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 66
/* Number of subtree layer. */
#define SPX_D 22
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 8
#define SPX_FORS_TREES 33
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* This is a SHA2-based parameter set, hence whether we use SHA-256
 * exclusively or we use both SHA-256 and SHA-512 is controlled by
 * the following #define */
#define SPX_SHA512 1  /* Use SHA-512 for H and T_l, l >= 2 */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../sha2_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-sha2-192s.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 24
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 63
/* Number of subtree layer. */
#define SPX_D 7
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 14
#define SPX_FORS_TREES 17
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* This is a SHA2-based parameter set, hence whether we use SHA-256
 * exclusively or we use both SHA-256 and SHA-512 is controlled by
 * the following #define */
#define SPX_SHA512 1  /* Use SHA-512 for H and T_l, l >= 2 */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../sha2_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-sha2-256f.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 32
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 68
/* Number of subtree layer. */
#define SPX_D 17
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 9
#define SPX_FORS_TREES 35
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* This is a SHA2-based parameter set, hence whether we use SHA-256
 * exclusively or we use both SHA-256 and SHA-512 is controlled by
 * the following #define */
#define SPX_SHA512 1  /* Use SHA-512 for H and T_l, l >= 2 */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../sha2_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-sha2-256s.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 32
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 64
/* Number of subtree layer. */
#define SPX_D 8
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 14
#define SPX_FORS_TREES 22
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* This is a SHA2-based parameter set, hence whether we use SHA-256
 * exclusively or we use both SHA-256 and SHA-512 is controlled by
 * the following #define */
#define SPX_SHA512 1  /* Use SHA-512 for H and T_l, l >= 2 */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../sha2_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-shake-128f.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 16
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 66
/* Number of subtree layer. */
#define SPX_D 22
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 6
#define SPX_FORS_TREES 33
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../shake_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-shake-128s.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 16
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 63
/* Number of subtree layer. */
#define SPX_D 7
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 12
#define SPX_FORS_TREES 14
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../shake_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-shake-192f.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 24
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 66
/* Number of subtree layer. */
#define SPX_D 22
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 8
#define SPX_FORS_TREES 33
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../shake_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-shake-192s.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 24
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 63
/* Number of subtree layer. */
#define SPX_D 7
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 14
#define SPX_FORS_TREES 17
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../shake_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-shake-256f.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 32
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 68
/* Number of subtree layer. */
#define SPX_D 17
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 9
#define SPX_FORS_TREES 35
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../shake_offsets.h"

#endif


================================================
FILE: ref/params/params-sphincs-shake-256s.h
================================================
#ifndef SPX_PARAMS_H
#define SPX_PARAMS_H

#define SPX_NAMESPACE(s) SPX_##s

/* Hash output length in bytes. */
#define SPX_N 32
/* Height of the hypertree. */
#define SPX_FULL_HEIGHT 64
/* Number of subtree layer. */
#define SPX_D 8
/* FORS tree dimensions. */
#define SPX_FORS_HEIGHT 14
#define SPX_FORS_TREES 22
/* Winternitz parameter, */
#define SPX_WOTS_W 16

/* The hash function is defined by linking a different hash.c file, as opposed
   to setting a #define constant. */

/* For clarity */
#define SPX_ADDR_BYTES 32

/* WOTS parameters. */
#if SPX_WOTS_W == 256
    #define SPX_WOTS_LOGW 8
#elif SPX_WOTS_W == 16
    #define SPX_WOTS_LOGW 4
#else
    #error SPX_WOTS_W assumed 16 or 256
#endif

#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)

/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
#if SPX_WOTS_W == 256
    #if SPX_N <= 1
        #define SPX_WOTS_LEN2 1
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 2
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#elif SPX_WOTS_W == 16
    #if SPX_N <= 8
        #define SPX_WOTS_LEN2 2
    #elif SPX_N <= 136
        #define SPX_WOTS_LEN2 3
    #elif SPX_N <= 256
        #define SPX_WOTS_LEN2 4
    #else
        #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256}
    #endif
#endif

#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES

/* Subtree size. */
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)

#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT
    #error SPX_D should always divide SPX_FULL_HEIGHT
#endif

/* FORS parameters. */
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
#define SPX_FORS_PK_BYTES SPX_N

/* Resulting SPX sizes. */
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
                   SPX_FULL_HEIGHT * SPX_N)
#define SPX_PK_BYTES (2 * SPX_N)
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)

#include "../shake_offsets.h"

#endif


================================================
FILE: ref/params.h
================================================
#define str(s) #s
#define xstr(s) str(s)

#include xstr(params/params-PARAMS.h)



================================================
FILE: ref/randombytes.c
================================================
/*
This code was taken from the SPHINCS reference implementation and is public domain.
*/

#include <fcntl.h>
#include <unistd.h>

#include "randombytes.h"

static int fd = -1;

void randombytes(unsigned char *x, unsigned long long xlen)
{
    unsigned long long i;

    if (fd == -1) {
        for (;;) {
            fd = open("/dev/urandom", O_RDONLY);
            if (fd != -1) {
                break;
            }
            sleep(1);
        }
    }

    while (xlen > 0) {
        if (xlen < 1048576) {
            i = xlen;
        }
        else {
            i = 1048576;
        }

        i = (unsigned long long)read(fd, x, i);
        if (i < 1) {
            sleep(1);
            continue;
        }

        x += i;
        xlen -= i;
    }
}


================================================
FILE: ref/randombytes.h
================================================
#ifndef SPX_RANDOMBYTES_H
#define SPX_RANDOMBYTES_H

extern void randombytes(unsigned char * x,unsigned long long xlen);

#endif


================================================
FILE: ref/rng.c
================================================
//
//  rng.c
//
//  Created by Bassham, Lawrence E (Fed) on 8/29/17.
//  Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
//

#include <string.h>
#include "rng.h"
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>

AES256_CTR_DRBG_struct  DRBG_ctx;

void    AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer);

/*
 seedexpander_init()
 ctx            - stores the current state of an instance of the seed expander
 seed           - a 32 byte random value
 diversifier    - an 8 byte diversifier
 maxlen         - maximum number of bytes (less than 2**32) generated under this seed and diversifier
 */
int
seedexpander_init(AES_XOF_struct *ctx,
                  unsigned char *seed,
                  unsigned char *diversifier,
                  unsigned long maxlen)
{
    if ( maxlen >= 0x100000000 )
        return RNG_BAD_MAXLEN;
    
    ctx->length_remaining = maxlen;
    
    memcpy(ctx->key, seed, 32);
    
    memcpy(ctx->ctr, diversifier, 8);
    ctx->ctr[11] = (unsigned char)(maxlen % 256);
    maxlen >>= 8;
    ctx->ctr[10] = (unsigned char)(maxlen % 256);
    maxlen >>= 8;
    ctx->ctr[9] = (unsigned char)(maxlen % 256);
    maxlen >>= 8;
    ctx->ctr[8] = (unsigned char)(maxlen % 256);
    memset(ctx->ctr+12, 0x00, 4);
    
    ctx->buffer_pos = 16;
    memset(ctx->buffer, 0x00, 16);
    
    return RNG_SUCCESS;
}

/*
 seedexpander()
    ctx  - stores the current state of an instance of the seed expander
    x    - returns the XOF data
    xlen - number of bytes to return
 */
int
seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen)
{
    unsigned long   offset;
    
    if ( x == NULL )
        return RNG_BAD_OUTBUF;
    if ( xlen >= ctx->length_remaining )
        return RNG_BAD_REQ_LEN;
    
    ctx->length_remaining -= xlen;
    
    offset = 0;
    while ( xlen > 0 ) {
        if ( xlen <= (16-ctx->buffer_pos) ) { // buffer has what we need
            memcpy(x+offset, ctx->buffer+ctx->buffer_pos, xlen);
            ctx->buffer_pos += xlen;
            
            return RNG_SUCCESS;
        }
        
        // take what's in the buffer
        memcpy(x+offset, ctx->buffer+ctx->buffer_pos, 16-ctx->buffer_pos);
        xlen -= 16-ctx->buffer_pos;
        offset += 16-ctx->buffer_pos;
        
        AES256_ECB(ctx->key, ctx->ctr, ctx->buffer);
        ctx->buffer_pos = 0;
        
        //increment the counter
        for (int i=15; i>=12; i--) {
            if ( ctx->ctr[i] == 0xff )
                ctx->ctr[i] = 0x00;
            else {
                ctx->ctr[i]++;
                break;
            }
        }
        
    }
    
    return RNG_SUCCESS;
}


static void handleErrors(void)
{
    ERR_print_errors_fp(stderr);
    abort();
}

// Use whatever AES implementation you have. This uses AES from openSSL library
//    key - 256-bit AES key
//    ctr - a 128-bit plaintext value
//    buffer - a 128-bit ciphertext value
void
AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer)
{
    EVP_CIPHER_CTX *ctx;
    
    int len;
    
    /* Create and initialise the context */
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
    
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
        handleErrors();
    
    if(1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16))
        handleErrors();
    
    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);
}

void
randombytes_init(unsigned char *entropy_input,
                 unsigned char *per
Download .txt
gitextract_8vizip4a/

├── .github/
│   └── workflows/
│       ├── test-haraka-aesni.yml
│       ├── test-ref.yml
│       ├── test-sha2-avx2.yml
│       └── test-shake-avx2.yml
├── .reuse/
│   └── dep5
├── LICENSE
├── LICENSES/
│   ├── 0BSD.txt
│   ├── CC0-1.0.txt
│   ├── LicenseRef-SPHINCS-PLUS-Public-Domain.txt
│   ├── MIT-0.txt
│   └── MIT.txt
├── README.md
├── SHA256SUMS
├── benchmark.py
├── haraka-aesni/
│   ├── .gitignore
│   ├── Makefile
│   ├── context.h
│   ├── haraka.c
│   ├── harakax4.h
│   ├── hash_harakax4.c
│   ├── test/
│   │   └── benchmark.c
│   ├── thash_haraka_robustx4.c
│   └── thash_haraka_simplex4.c
├── ref/
│   ├── .gitignore
│   ├── Makefile
│   ├── PQCgenKAT_sign.c
│   ├── address.c
│   ├── address.h
│   ├── api.h
│   ├── context.h
│   ├── fips202.c
│   ├── fips202.h
│   ├── fors.c
│   ├── fors.h
│   ├── haraka.c
│   ├── haraka.h
│   ├── haraka_offsets.h
│   ├── hash.h
│   ├── hash_haraka.c
│   ├── hash_sha2.c
│   ├── hash_shake.c
│   ├── merkle.c
│   ├── merkle.h
│   ├── params/
│   │   ├── params-sphincs-haraka-128f.h
│   │   ├── params-sphincs-haraka-128s.h
│   │   ├── params-sphincs-haraka-192f.h
│   │   ├── params-sphincs-haraka-192s.h
│   │   ├── params-sphincs-haraka-256f.h
│   │   ├── params-sphincs-haraka-256s.h
│   │   ├── params-sphincs-sha2-128f.h
│   │   ├── params-sphincs-sha2-128s.h
│   │   ├── params-sphincs-sha2-192f.h
│   │   ├── params-sphincs-sha2-192s.h
│   │   ├── params-sphincs-sha2-256f.h
│   │   ├── params-sphincs-sha2-256s.h
│   │   ├── params-sphincs-shake-128f.h
│   │   ├── params-sphincs-shake-128s.h
│   │   ├── params-sphincs-shake-192f.h
│   │   ├── params-sphincs-shake-192s.h
│   │   ├── params-sphincs-shake-256f.h
│   │   └── params-sphincs-shake-256s.h
│   ├── params.h
│   ├── randombytes.c
│   ├── randombytes.h
│   ├── rng.c
│   ├── rng.h
│   ├── sha2.c
│   ├── sha2.h
│   ├── sha2_offsets.h
│   ├── shake_offsets.h
│   ├── sign.c
│   ├── test/
│   │   ├── benchmark.c
│   │   ├── cycles.c
│   │   ├── cycles.h
│   │   ├── fors.c
│   │   ├── haraka.c
│   │   └── spx.c
│   ├── thash.h
│   ├── thash_haraka_robust.c
│   ├── thash_haraka_simple.c
│   ├── thash_sha2_robust.c
│   ├── thash_sha2_simple.c
│   ├── thash_shake_robust.c
│   ├── thash_shake_simple.c
│   ├── utils.c
│   ├── utils.h
│   ├── utilsx1.c
│   ├── utilsx1.h
│   ├── wots.c
│   ├── wots.h
│   ├── wotsx1.c
│   └── wotsx1.h
├── sha2-avx2/
│   ├── .gitignore
│   ├── Makefile
│   ├── context.h
│   ├── fors.c
│   ├── hash_sha2x8.c
│   ├── hashx8.h
│   ├── merkle.c
│   ├── sha256avx.c
│   ├── sha256avx.h
│   ├── sha256x8.c
│   ├── sha256x8.h
│   ├── sha512x4.c
│   ├── sha512x4.h
│   ├── test/
│   │   ├── benchmark.c
│   │   └── thashx8.c
│   ├── thash_sha2_robustx8.c
│   ├── thash_sha2_simplex8.c
│   ├── thashx8.h
│   ├── utilsx8.c
│   ├── utilsx8.h
│   ├── wots.c
│   └── wotsx8.h
├── shake-a64/
│   ├── .gitignore
│   ├── Makefile
│   ├── context.h
│   ├── f1600x2.h
│   ├── f1600x2.s
│   ├── f1600x2_const.c
│   ├── fips202x2.c
│   ├── fips202x2.h
│   ├── fors.c
│   ├── hash_shakex2.c
│   ├── hashx2.h
│   ├── merkle.c
│   ├── test/
│   │   ├── benchmark.c
│   │   └── thashx2.c
│   ├── thash.h
│   ├── thash_shake_robustx2.c
│   ├── thash_shake_simplex2.c
│   ├── thashx2.h
│   ├── utilsx2.c
│   ├── utilsx2.h
│   ├── wots.c
│   └── wotsx2.h
├── shake-avx2/
│   ├── .gitignore
│   ├── Makefile
│   ├── context.h
│   ├── fips202x4.c
│   ├── fips202x4.h
│   ├── fors.c
│   ├── hash_shakex4.c
│   ├── hashx4.h
│   ├── keccak4x/
│   │   ├── KeccakP-1600-times4-SIMD256.c
│   │   ├── KeccakP-1600-times4-SnP.h
│   │   ├── KeccakP-1600-unrolling.macros
│   │   ├── SIMD256-config.h
│   │   ├── align.h
│   │   └── brg_endian.h
│   ├── merkle.c
│   ├── test/
│   │   ├── benchmark.c
│   │   └── thashx4.c
│   ├── thash_shake_robustx4.c
│   ├── thash_shake_simplex4.c
│   ├── thashx4.h
│   ├── utilsx4.c
│   ├── utilsx4.h
│   ├── wots.c
│   └── wotsx4.h
└── vectors.py
Download .txt
SYMBOL INDEX (349 symbols across 79 files)

FILE: haraka-aesni/context.h
  type spx_ctx (line 9) | typedef struct {

FILE: haraka-aesni/haraka.c
  function load_haraka_constants (line 73) | static void load_haraka_constants(u128 *rc)
  function tweak_constants (line 117) | void tweak_constants(spx_ctx *ctx)
  function haraka_S_absorb (line 134) | static void haraka_S_absorb(unsigned char *s, unsigned int r,
  function haraka_S_absorb4x (line 162) | static void haraka_S_absorb4x(unsigned char *s,
  function haraka_S_squeezeblocks (line 230) | static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long ...
  function haraka_S_squeezeblocks4x (line 243) | static void haraka_S_squeezeblocks4x(unsigned char *h0,
  function haraka_S_inc_init (line 270) | void haraka_S_inc_init(uint8_t *s_inc)
  function haraka_S_inc_absorb (line 280) | void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen,
  function haraka_S_inc_finalize (line 305) | void haraka_S_inc_finalize(uint8_t *s_inc)
  function haraka_S_inc_squeeze (line 314) | void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc,
  function haraka_S (line 342) | void haraka_S(unsigned char *out, unsigned long long outlen,
  function haraka_Sx4 (line 366) | void haraka_Sx4(unsigned char *out0,
  function haraka512_perm (line 408) | void haraka512_perm(unsigned char *out, const unsigned char *in,
  function haraka512_perm_x4 (line 439) | void haraka512_perm_x4(unsigned char *out, const unsigned char *in,
  function haraka512 (line 509) | void haraka512(unsigned char *out, const unsigned char *in,
  function haraka512x4 (line 543) | void haraka512x4(unsigned char *out, const unsigned char *in,
  function haraka256 (line 618) | void haraka256(unsigned char *out, const unsigned char *in,
  function haraka256x4 (line 648) | void haraka256x4(unsigned char *out, const unsigned char *in,

FILE: haraka-aesni/hash_harakax4.c
  function prf_addrx4 (line 13) | void prf_addrx4(unsigned char *out0,

FILE: haraka-aesni/test/benchmark.c
  function cmp_llu (line 19) | static int cmp_llu(const void *a, const void*b)
  function median (line 26) | static unsigned long long median(unsigned long long *l, size_t llen)
  function delta (line 34) | static void delta(unsigned long long *l, size_t llen)
  function cpucycles (line 42) | static unsigned long long cpucycles(void)
  function printfcomma (line 50) | static void printfcomma (unsigned long long n)
  function printfalignedcomma (line 60) | static void printfalignedcomma (unsigned long long n, int len)
  function display_result (line 77) | static void display_result(double result, unsigned long long *l, size_t ...
  function main (line 103) | int main(void)
  function wots_gen_pkx4 (line 156) | static void wots_gen_pkx4(unsigned char *pk, const spx_ctx *ctx,

FILE: haraka-aesni/thash_haraka_robustx4.c
  function thashx4 (line 15) | void thashx4(unsigned char *out0,

FILE: haraka-aesni/thash_haraka_simplex4.c
  function thashx4 (line 15) | void thashx4(unsigned char *out0,

FILE: ref/PQCgenKAT_sign.c
  function main (line 28) | int
  function FindMarker (line 163) | int
  function ReadHex (line 203) | int
  function fprintBstr (line 247) | void

FILE: ref/address.c
  function set_layer_addr (line 11) | void set_layer_addr(uint32_t addr[8], uint32_t layer)
  function set_tree_addr (line 19) | void set_tree_addr(uint32_t addr[8], uint64_t tree)
  function set_type (line 33) | void set_type(uint32_t addr[8], uint32_t type)
  function copy_subtree_addr (line 42) | void copy_subtree_addr(uint32_t out[8], const uint32_t in[8])
  function set_keypair_addr (line 53) | void set_keypair_addr(uint32_t addr[8], uint32_t keypair)
  function copy_keypair_addr (line 62) | void copy_keypair_addr(uint32_t out[8], const uint32_t in[8])
  function set_chain_addr (line 72) | void set_chain_addr(uint32_t addr[8], uint32_t chain)
  function set_hash_addr (line 81) | void set_hash_addr(uint32_t addr[8], uint32_t hash)
  function set_tree_height (line 92) | void set_tree_height(uint32_t addr[8], uint32_t tree_height)
  function set_tree_index (line 101) | void set_tree_index(uint32_t addr[8], uint32_t tree_index)

FILE: ref/context.h
  type spx_ctx (line 8) | typedef struct {

FILE: ref/fips202.c
  function load64 (line 25) | static uint64_t load64(const uint8_t *x) {
  function store64 (line 42) | static void store64(uint8_t *x, uint64_t u) {
  function KeccakF1600_StatePermute (line 71) | static void KeccakF1600_StatePermute(uint64_t *state) {
  function keccak_absorb (line 347) | static void keccak_absorb(uint64_t *s, uint32_t r, const uint8_t *m,
  function keccak_squeezeblocks (line 393) | static void keccak_squeezeblocks(uint8_t *h, size_t nblocks,
  function keccak_inc_init (line 415) | static void keccak_inc_init(uint64_t *s_inc) {
  function keccak_inc_absorb (line 438) | static void keccak_inc_absorb(uint64_t *s_inc, uint32_t r, const uint8_t...
  function keccak_inc_finalize (line 475) | static void keccak_inc_finalize(uint64_t *s_inc, uint32_t r, uint8_t p) {
  function keccak_inc_squeeze (line 496) | static void keccak_inc_squeeze(uint8_t *h, size_t outlen,
  function shake256_inc_init (line 523) | void shake256_inc_init(uint64_t *s_inc) {
  function shake256_inc_absorb (line 527) | void shake256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t i...
  function shake256_inc_finalize (line 531) | void shake256_inc_finalize(uint64_t *s_inc) {
  function shake256_inc_squeeze (line 535) | void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_in...
  function shake256_absorb (line 550) | void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen) {
  function shake256_squeezeblocks (line 566) | void shake256_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s) {
  function shake256 (line 580) | void shake256(uint8_t *output, size_t outlen,

FILE: ref/fors.c
  function fors_gen_sk (line 12) | static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx,
  function fors_sk_to_leaf (line 18) | static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
  type fors_gen_leaf_info (line 25) | struct fors_gen_leaf_info {
  function fors_gen_leafx1 (line 29) | static void fors_gen_leafx1(unsigned char *leaf,
  function message_to_indices (line 51) | static void message_to_indices(uint32_t *indices, const unsigned char *m)
  function fors_sign (line 69) | void fors_sign(unsigned char *sig, unsigned char *pk,
  function fors_pk_from_sig (line 122) | void fors_pk_from_sig(unsigned char *pk,

FILE: ref/haraka.c
  function br_dec32le (line 54) | static inline uint32_t br_dec32le(const unsigned char *src)
  function br_range_dec32le (line 62) | static void br_range_dec32le(uint32_t *v, size_t num, const unsigned cha...
  function br_enc32le (line 70) | static inline void br_enc32le(unsigned char *dst, uint32_t x)
  function br_range_enc32le (line 79) | static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size...
  function br_aes_ct64_bitslice_Sbox (line 87) | static void br_aes_ct64_bitslice_Sbox(uint64_t *q) {
  function br_aes_ct_bitslice_Sbox (line 261) | static void br_aes_ct_bitslice_Sbox(uint32_t *q)
  function br_aes_ct_ortho (line 436) | static void br_aes_ct_ortho(uint32_t *q)
  function add_round_key32 (line 466) | static inline void add_round_key32(uint32_t *q, const uint32_t *sk)
  function shift_rows32 (line 478) | static inline void shift_rows32(uint32_t *q)
  function rotr16 (line 493) | static inline uint32_t rotr16(uint32_t x)
  function mix_columns32 (line 498) | static inline void mix_columns32(uint32_t *q)
  function br_aes_ct64_ortho (line 530) | static void br_aes_ct64_ortho(uint64_t *q)
  function br_aes_ct64_interleave_in (line 561) | static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const ...
  function br_aes_ct64_interleave_out (line 590) | static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_...
  function add_round_key (line 612) | static inline void add_round_key(uint64_t *q, const uint64_t *sk)
  function shift_rows (line 624) | static inline void shift_rows(uint64_t *q)
  function rotr32 (line 642) | static inline uint64_t rotr32(uint64_t x)
  function mix_columns (line 647) | static inline void mix_columns(uint64_t *q)
  function interleave_constant (line 679) | static void interleave_constant(uint64_t *out, const unsigned char *in)
  function interleave_constant32 (line 691) | static void interleave_constant32(uint32_t *out, const unsigned char *in)
  function tweak_constants (line 701) | void tweak_constants(spx_ctx *ctx)
  function haraka_S_absorb (line 717) | static void haraka_S_absorb(unsigned char *s, unsigned int r,
  function haraka_S_squeezeblocks (line 747) | static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long ...
  function haraka_S_inc_init (line 759) | void haraka_S_inc_init(uint8_t *s_inc)
  function haraka_S_inc_absorb (line 769) | void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen,
  function haraka_S_inc_finalize (line 794) | void haraka_S_inc_finalize(uint8_t *s_inc)
  function haraka_S_inc_squeeze (line 803) | void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc,
  function haraka_S (line 831) | void haraka_S(unsigned char *out, unsigned long long outlen,
  function haraka512_perm (line 855) | void haraka512_perm(unsigned char *out, const unsigned char *in,
  function haraka512 (line 902) | void haraka512(unsigned char *out, const unsigned char *in, const spx_ct...
  function haraka256 (line 922) | void haraka256(unsigned char *out, const unsigned char *in,

FILE: ref/hash_haraka.c
  function initialize_hash_function (line 11) | void initialize_hash_function(spx_ctx* ctx)
  function prf_addr (line 19) | void prf_addr(unsigned char *out, const spx_ctx *ctx,
  function gen_message_random (line 37) | void gen_message_random(unsigned char *R, const unsigned char* sk_prf,
  function hash_message (line 57) | void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_...

FILE: ref/hash_sha2.c
  function initialize_hash_function (line 31) | void initialize_hash_function(spx_ctx *ctx)
  function prf_addr (line 39) | void prf_addr(unsigned char *out, const spx_ctx *ctx,
  function gen_message_random (line 66) | void gen_message_random(unsigned char *R, const unsigned char *sk_prf,
  function hash_message (line 122) | void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_...

FILE: ref/hash_shake.c
  function initialize_hash_function (line 12) | void initialize_hash_function(spx_ctx* ctx)
  function prf_addr (line 20) | void prf_addr(unsigned char *out, const spx_ctx *ctx,
  function gen_message_random (line 36) | void gen_message_random(unsigned char *R, const unsigned char *sk_prf,
  function hash_message (line 57) | void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_...

FILE: ref/merkle.c
  function merkle_sign (line 18) | void merkle_sign(uint8_t *sig, unsigned char *root,
  function merkle_gen_root (line 46) | void merkle_gen_root(unsigned char *root, const spx_ctx *ctx)

FILE: ref/randombytes.c
  function randombytes (line 12) | void randombytes(unsigned char *x, unsigned long long xlen)

FILE: ref/rng.c
  function seedexpander_init (line 25) | int
  function seedexpander (line 60) | int
  function handleErrors (line 105) | static void handleErrors(void)
  function AES256_ECB (line 115) | void
  function randombytes_init (line 135) | void
  function randombytes (line 151) | int
  function AES256_CTR_DRBG_Update (line 184) | void

FILE: ref/rng.h
  type AES_XOF_struct (line 18) | typedef struct {
  type AES256_CTR_DRBG_struct (line 26) | typedef struct {

FILE: ref/sha2.c
  function load_bigendian_32 (line 12) | static uint32_t load_bigendian_32(const uint8_t *x) {
  function load_bigendian_64 (line 17) | static uint64_t load_bigendian_64(const uint8_t *x) {
  function store_bigendian_32 (line 24) | static void store_bigendian_32(uint8_t *x, uint64_t u) {
  function store_bigendian_64 (line 34) | static void store_bigendian_64(uint8_t *x, uint64_t u) {
  function crypto_hashblocks_sha256 (line 132) | static size_t crypto_hashblocks_sha256(uint8_t *statebytes,
  function crypto_hashblocks_sha512 (line 289) | static int crypto_hashblocks_sha512(unsigned char *statebytes,const unsi...
  function sha256_inc_init (line 474) | void sha256_inc_init(uint8_t *state) {
  function sha512_inc_init (line 483) | void sha512_inc_init(uint8_t *state) {
  function sha256_inc_blocks (line 492) | void sha256_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblock...
  function sha512_inc_blocks (line 501) | void sha512_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblock...
  function sha256_inc_finalize (line 510) | void sha256_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in...
  function sha512_inc_finalize (line 558) | void sha512_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in...
  function sha256 (line 607) | void sha256(uint8_t *out, const uint8_t *in, size_t inlen) {
  function sha512 (line 614) | void sha512(uint8_t *out, const uint8_t *in, size_t inlen) {
  function mgf1_256 (line 627) | void mgf1_256(unsigned char *out, unsigned long outlen,
  function mgf1_512 (line 653) | void mgf1_512(unsigned char *out, unsigned long outlen,
  function seed_state (line 682) | void seed_state(spx_ctx *ctx) {

FILE: ref/sign.c
  function crypto_sign_secretkeybytes (line 19) | unsigned long long crypto_sign_secretkeybytes(void)
  function crypto_sign_publickeybytes (line 27) | unsigned long long crypto_sign_publickeybytes(void)
  function crypto_sign_bytes (line 35) | unsigned long long crypto_sign_bytes(void)
  function crypto_sign_seedbytes (line 43) | unsigned long long crypto_sign_seedbytes(void)
  function crypto_sign_seed_keypair (line 53) | int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk,
  function crypto_sign_keypair (line 83) | int crypto_sign_keypair(unsigned char *pk, unsigned char *sk)
  function crypto_sign_signature (line 95) | int crypto_sign_signature(uint8_t *sig, size_t *siglen,
  function crypto_sign_verify (line 163) | int crypto_sign_verify(const uint8_t *sig, size_t siglen,
  function crypto_sign (line 246) | int crypto_sign(unsigned char *sm, unsigned long long *smlen,
  function crypto_sign_open (line 263) | int crypto_sign_open(unsigned char *m, unsigned long long *mlen,

FILE: ref/test/benchmark.c
  function cmp_llu (line 21) | static int cmp_llu(const void *a, const void*b)
  function median (line 28) | static unsigned long long median(unsigned long long *l, size_t llen)
  function delta (line 36) | static void delta(unsigned long long *l, size_t llen)
  function printfcomma (line 45) | static void printfcomma (unsigned long long n)
  function printfalignedcomma (line 55) | static void printfalignedcomma (unsigned long long n, int len)
  function display_result (line 72) | static void display_result(double result, unsigned long long *l, size_t ...
  function main (line 109) | int main(void)
  function wots_gen_pkx1 (line 166) | static void wots_gen_pkx1(unsigned char *pk, const spx_ctx *ctx,

FILE: ref/test/cycles.c
  function configure_rdtsc (line 30) | static void configure_rdtsc(void) {
  function init_cpucycles (line 52) | void init_cpucycles(void) {
  function cpucycles (line 86) | unsigned long long cpucycles(void) {
  function init_cpucycles (line 100) | void init_cpucycles(void) {
  function cpucycles (line 103) | unsigned long long cpucycles(void)

FILE: ref/test/fors.c
  function main (line 10) | int main(void)

FILE: ref/test/haraka.c
  function test_haraka_S_incremental (line 9) | static int test_haraka_S_incremental(void) {
  function main (line 147) | int main(void) {

FILE: ref/test/spx.c
  function main (line 12) | int main(void)

FILE: ref/thash_haraka_robust.c
  function thash (line 14) | void thash(unsigned char *out, const unsigned char *in, unsigned int inb...

FILE: ref/thash_haraka_simple.c
  function thash (line 14) | void thash(unsigned char *out, const unsigned char *in, unsigned int inb...

FILE: ref/thash_sha2_robust.c
  function thash (line 18) | void thash(unsigned char *out, const unsigned char *in, unsigned int inb...
  function thash_512 (line 50) | static void thash_512(unsigned char *out, const unsigned char *in, unsig...

FILE: ref/thash_sha2_simple.c
  function thash (line 18) | void thash(unsigned char *out, const unsigned char *in, unsigned int inb...
  function thash_512 (line 43) | static void thash_512(unsigned char *out, const unsigned char *in, unsig...

FILE: ref/thash_shake_robust.c
  function thash (line 14) | void thash(unsigned char *out, const unsigned char *in, unsigned int inb...

FILE: ref/thash_shake_simple.c
  function thash (line 14) | void thash(unsigned char *out, const unsigned char *in, unsigned int inb...

FILE: ref/utils.c
  function ull_to_bytes (line 12) | void ull_to_bytes(unsigned char *out, unsigned int outlen,
  function u32_to_bytes (line 24) | void u32_to_bytes(unsigned char *out, uint32_t in)
  function bytes_to_ull (line 35) | unsigned long long bytes_to_ull(const unsigned char *in, unsigned int in...
  function compute_root (line 50) | void compute_root(unsigned char *root, const unsigned char *leaf,
  function treehash (line 105) | void treehash(unsigned char *root, unsigned char *auth_path, const spx_c...

FILE: ref/utilsx1.c
  function treehashx1 (line 23) | void treehashx1(unsigned char *root, unsigned char *auth_path,

FILE: ref/wots.c
  function gen_chain (line 24) | static void gen_chain(unsigned char *out, const unsigned char *in,
  function base_w (line 45) | static void base_w(unsigned int *output, const int out_len,
  function wots_checksum (line 67) | static void wots_checksum(unsigned int *csum_base_w,
  function chain_lengths (line 87) | void chain_lengths(unsigned int *lengths, const unsigned char *msg)
  function wots_pk_from_sig (line 98) | void wots_pk_from_sig(unsigned char *pk,

FILE: ref/wotsx1.c
  function wots_gen_leafx1 (line 17) | void wots_gen_leafx1(unsigned char *dest,

FILE: ref/wotsx1.h
  type leaf_info_x1 (line 12) | struct leaf_info_x1 {

FILE: sha2-avx2/context.h
  type spx_ctx (line 8) | typedef struct {

FILE: sha2-avx2/fors.c
  function fors_gen_sk (line 14) | static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx,
  function fors_gen_skx8 (line 20) | static void fors_gen_skx8(unsigned char *sk0,
  function fors_sk_to_leaf (line 34) | static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
  function fors_sk_to_leafx8 (line 41) | static void fors_sk_to_leafx8(unsigned char *leaf0,
  type fors_gen_leaf_info (line 65) | struct fors_gen_leaf_info {
  function fors_gen_leafx8 (line 69) | static void fors_gen_leafx8(unsigned char *leaf,
  function message_to_indices (line 121) | static void message_to_indices(uint32_t *indices, const unsigned char *m)
  function fors_sign (line 139) | void fors_sign(unsigned char *sig, unsigned char *pk,
  function fors_pk_from_sig (line 194) | void fors_pk_from_sig(unsigned char *pk,

FILE: sha2-avx2/hash_sha2x8.c
  function prf_addrx8 (line 15) | void prf_addrx8(unsigned char *out0,

FILE: sha2-avx2/merkle.c
  function merkle_sign (line 17) | void merkle_sign(uint8_t *sig, unsigned char *root,
  function merkle_gen_root (line 52) | void merkle_gen_root(unsigned char *root, const spx_ctx *ctx)

FILE: sha2-avx2/sha256avx.c
  function transpose (line 8) | void transpose(u256 s[8]) {
  function sha256_init8x (line 37) | void sha256_init8x(sha256ctx *ctx) {
  function sha256_final8x (line 51) | void sha256_final8x(sha256ctx *ctx,
  function sha256_transform8x (line 130) | void sha256_transform8x(sha256ctx *ctx,

FILE: sha2-avx2/sha256avx.h
  type sha256ctx (line 66) | typedef struct SHA256state {

FILE: sha2-avx2/sha256x8.c
  function load_bigendian_32 (line 7) | static uint32_t load_bigendian_32(const uint8_t *x) {
  function _sha256x8 (line 13) | static void _sha256x8(
  function sha256x8_seeded (line 61) | void sha256x8_seeded(
  function sha256x8 (line 97) | void sha256x8(unsigned char *out0,
  function mgf1x8 (line 126) | void mgf1x8(unsigned char *outx8, unsigned long outlen,

FILE: sha2-avx2/sha512x4.c
  type u64 (line 10) | typedef uint64_t u64;
  type __m256i (line 11) | typedef __m256i u256;
  function transpose (line 36) | static void transpose(u256 s[4]) {
  function sha512_init4x (line 54) | static void sha512_init4x(sha512ctx4x *ctx) {
  function u256 (line 82) | static u256 XOR3(u256 a, u256 b, u256 c) {
  function u256 (line 90) | static u256 MAJ_AVX(u256 a, u256 b, u256 c) {
  function u256 (line 93) | static u256 CH_AVX(u256 a, u256 b, u256 c) {
  function u256 (line 96) | static u256 SIGMA0_AVX(u256 x) {
  function u256 (line 99) | static u256 SIGMA1_AVX(u256 x) {
  function u256 (line 102) | static u256 GAMMA0_AVX(u256 x) {
  function u256 (line 105) | static u256 GAMMA1_AVX(u256 x) {
  function sha512_transform4x (line 158) | static void sha512_transform4x(
  function _sha512x4 (line 271) | static void _sha512x4(
  function mgf1x4_512 (line 380) | void mgf1x4_512(unsigned char *outx4, unsigned long outlen,
  function sha512x4_seeded (line 431) | void sha512x4_seeded(

FILE: sha2-avx2/sha512x4.h
  type sha512ctx4x (line 8) | typedef struct SHA512state4x {

FILE: sha2-avx2/test/benchmark.c
  function cmp_llu (line 20) | static int cmp_llu(const void *a, const void*b)
  function median (line 27) | static unsigned long long median(unsigned long long *l, size_t llen)
  function delta (line 35) | static void delta(unsigned long long *l, size_t llen)
  function cpucycles (line 43) | static unsigned long long cpucycles(void)
  function printfcomma (line 51) | static void printfcomma (unsigned long long n)
  function printfalignedcomma (line 61) | static void printfalignedcomma (unsigned long long n, int len)
  function display_result (line 78) | static void display_result(double result, unsigned long long *l, size_t ...
  function main (line 104) | int main(void)
  function wots_gen_pkx8 (line 156) | static void wots_gen_pkx8(unsigned char *pk, const spx_ctx *ctx,

FILE: sha2-avx2/test/thashx8.c
  function main (line 16) | int main(void)

FILE: sha2-avx2/thash_sha2_robustx8.c
  function thashx8 (line 41) | void thashx8(unsigned char *out0,
  function thashx8_512 (line 160) | static void thashx8_512(

FILE: sha2-avx2/thash_sha2_simplex8.c
  function thashx8 (line 41) | void thashx8(unsigned char *out0,
  function thashx8_512 (line 135) | static void thashx8_512(

FILE: sha2-avx2/utilsx8.c
  function treehashx8 (line 38) | void treehashx8(unsigned char *root, unsigned char *auth_path,

FILE: sha2-avx2/wots.c
  function gen_chains (line 22) | static void gen_chains(
  function base_w (line 112) | static void base_w(unsigned int *output, const int out_len,
  function wots_checksum (line 134) | static void wots_checksum(unsigned int *csum_base_w,
  function chain_lengths (line 154) | void chain_lengths(unsigned int *lengths, const unsigned char *msg)
  function wots_pk_from_sig (line 165) | void wots_pk_from_sig(unsigned char *pk,
  function wots_gen_leafx8 (line 187) | void wots_gen_leafx8(unsigned char *dest,

FILE: sha2-avx2/wotsx8.h
  type leaf_info_x8 (line 13) | struct leaf_info_x8 {

FILE: shake-a64/context.h
  type spx_ctx (line 8) | typedef struct {

FILE: shake-a64/fips202x2.c
  function load64 (line 8) | uint64_t load64(const unsigned char *x)
  function store64 (line 18) | void store64(uint8_t *x, uint64_t u)
  function keccak_absorb2x (line 28) | static void keccak_absorb2x(uint64_t *s,
  function keccak_squeezeblocks2x (line 78) | static void keccak_squeezeblocks2x(unsigned char *h0,
  function shake128x2 (line 102) | void shake128x2(unsigned char *out0,
  function shake256x2 (line 135) | void shake256x2(unsigned char *out0,

FILE: shake-a64/fors.c
  function fors_gen_sk (line 14) | static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx,
  function fors_gen_skx2 (line 20) | static void fors_gen_skx2(unsigned char *sk0,
  function fors_sk_to_leaf (line 29) | static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
  function fors_sk_to_leafx2 (line 36) | static void fors_sk_to_leafx2(unsigned char *leaf0,
  type fors_gen_leaf_info (line 48) | struct fors_gen_leaf_info {
  function fors_gen_leafx2 (line 52) | static void fors_gen_leafx2(unsigned char *leaf,
  function message_to_indices (line 86) | static void message_to_indices(uint32_t *indices, const unsigned char *m)
  function fors_sign (line 104) | void fors_sign(unsigned char *sig, unsigned char *pk,
  function fors_pk_from_sig (line 159) | void fors_pk_from_sig(unsigned char *pk,

FILE: shake-a64/hash_shakex2.c
  function prf_addrx2 (line 13) | void prf_addrx2(unsigned char *out0,

FILE: shake-a64/merkle.c
  function merkle_sign (line 16) | void merkle_sign(uint8_t *sig, unsigned char *root,
  function merkle_gen_root (line 50) | void merkle_gen_root(unsigned char *root, const spx_ctx *ctx)

FILE: shake-a64/test/benchmark.c
  function cmp_llu (line 25) | static int cmp_llu(const void *a, const void*b)
  function median (line 32) | static unsigned long long median(unsigned long long *l, size_t llen)
  function delta (line 40) | static void delta(unsigned long long *l, size_t llen)
  function printfcomma (line 48) | static void printfcomma (unsigned long long n)
  function printfalignedcomma (line 58) | static void printfalignedcomma (unsigned long long n, int len)
  function display_result (line 75) | static void display_result(double result, unsigned long long *l, size_t ...
  function main (line 112) | int main(void)
  function wots_gen_pkx2 (line 170) | static void wots_gen_pkx2(unsigned char *pk, const spx_ctx *ctx, uint32_...

FILE: shake-a64/test/thashx2.c
  function main (line 9) | int main(void)

FILE: shake-a64/thash_shake_robustx2.c
  function thash (line 14) | void thash(unsigned char *out,
  function thashx2 (line 28) | void thashx2(unsigned char *out0,

FILE: shake-a64/thash_shake_simplex2.c
  function thash (line 14) | void thash(unsigned char *out,
  function thashx2 (line 28) | void thashx2(unsigned char *out0,

FILE: shake-a64/utilsx2.c
  function treehashx2 (line 34) | void treehashx2(unsigned char *root, unsigned char *auth_path,

FILE: shake-a64/wots.c
  function gen_chains (line 21) | static void gen_chains(
  function base_w (line 109) | static void base_w(unsigned int *output, const int out_len,
  function wots_checksum (line 131) | static void wots_checksum(unsigned int *csum_base_w,
  function chain_lengths (line 151) | void chain_lengths(unsigned int *lengths, const unsigned char *msg)
  function wots_pk_from_sig (line 162) | void wots_pk_from_sig(unsigned char *pk,
  function wots_gen_leafx2 (line 184) | void wots_gen_leafx2(unsigned char *dest,

FILE: shake-a64/wotsx2.h
  type leaf_info_x2 (line 13) | struct leaf_info_x2 {

FILE: shake-avx2/context.h
  type spx_ctx (line 8) | typedef struct {

FILE: shake-avx2/fips202x4.c
  function load64 (line 11) | static uint64_t load64(const unsigned char *x)
  function store64 (line 21) | static void store64(uint8_t *x, uint64_t u)
  function keccak_absorb4x (line 35) | static void keccak_absorb4x(__m256i *s,
  function keccak_squeezeblocks4x (line 106) | static void keccak_squeezeblocks4x(unsigned char *h0,
  function shake128x4 (line 138) | void shake128x4(unsigned char *out0,
  function shake256x4 (line 183) | void shake256x4(unsigned char *out0,

FILE: shake-avx2/fors.c
  function fors_gen_sk (line 14) | static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx,
  function fors_gen_skx4 (line 20) | static void fors_gen_skx4(unsigned char *sk0,
  function fors_sk_to_leaf (line 30) | static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
  function fors_sk_to_leafx4 (line 37) | static void fors_sk_to_leafx4(unsigned char *leaf0,
  type fors_gen_leaf_info (line 53) | struct fors_gen_leaf_info {
  function fors_gen_leafx4 (line 57) | static void fors_gen_leafx4(unsigned char *leaf,
  function message_to_indices (line 97) | static void message_to_indices(uint32_t *indices, const unsigned char *m)
  function fors_sign (line 115) | void fors_sign(unsigned char *sig, unsigned char *pk,
  function fors_pk_from_sig (line 170) | void fors_pk_from_sig(unsigned char *pk,

FILE: shake-avx2/hash_shakex4.c
  function prf_addrx4 (line 14) | void prf_addrx4(unsigned char *out0,

FILE: shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c
  type UINT8 (line 32) | typedef unsigned char UINT8;
  type UINT64 (line 33) | typedef unsigned long long int UINT64;
  type __m128i (line 34) | typedef __m128i V128;
  type __m256i (line 35) | typedef __m256i V256;
  function KeccakP1600times4_InitializeAll (line 83) | void KeccakP1600times4_InitializeAll(void *states)
  function KeccakP1600times4_AddBytes (line 88) | void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex...
  function KeccakP1600times4_AddLanesAll (line 123) | void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *da...
  function KeccakP1600times4_OverwriteBytes (line 168) | void KeccakP1600times4_OverwriteBytes(void *states, unsigned int instanc...
  function KeccakP1600times4_OverwriteLanesAll (line 199) | void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned ch...
  function KeccakP1600times4_OverwriteWithZeroes (line 244) | void KeccakP1600times4_OverwriteWithZeroes(void *states, unsigned int in...
  function KeccakP1600times4_ExtractBytes (line 261) | void KeccakP1600times4_ExtractBytes(const void *states, unsigned int ins...
  function KeccakP1600times4_ExtractLanesAll (line 291) | void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char...
  function KeccakP1600times4_ExtractAndAddBytes (line 341) | void KeccakP1600times4_ExtractAndAddBytes(const void *states, unsigned i...
  function KeccakP1600times4_ExtractAndAddLanesAll (line 380) | void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const u...
  function KeccakP1600times4_PermuteAll_24rounds (line 802) | void KeccakP1600times4_PermuteAll_24rounds(void *states)

FILE: shake-avx2/merkle.c
  function merkle_sign (line 16) | void merkle_sign(uint8_t *sig, unsigned char *root,
  function merkle_gen_root (line 50) | void merkle_gen_root(unsigned char *root, const spx_ctx *ctx)

FILE: shake-avx2/test/benchmark.c
  function cmp_llu (line 20) | static int cmp_llu(const void *a, const void*b)
  function median (line 27) | static unsigned long long median(unsigned long long *l, size_t llen)
  function delta (line 35) | static void delta(unsigned long long *l, size_t llen)
  function cpucycles (line 43) | static unsigned long long cpucycles(void)
  function printfcomma (line 51) | static void printfcomma (unsigned long long n)
  function printfalignedcomma (line 61) | static void printfalignedcomma (unsigned long long n, int len)
  function display_result (line 78) | static void display_result(double result, unsigned long long *l, size_t ...
  function main (line 104) | int main(void)
  function wots_gen_pkx4 (line 156) | static void wots_gen_pkx4(unsigned char *pk, const spx_ctx *ctx, uint32_...

FILE: shake-avx2/test/thashx4.c
  function main (line 9) | int main(void)

FILE: shake-avx2/thash_shake_robustx4.c
  function thashx4 (line 16) | void thashx4(unsigned char *out0,

FILE: shake-avx2/thash_shake_simplex4.c
  function thashx4 (line 16) | void thashx4(unsigned char *out0,

FILE: shake-avx2/utilsx4.c
  function treehashx4 (line 38) | void treehashx4(unsigned char *root, unsigned char *auth_path,

FILE: shake-avx2/wots.c
  function gen_chains (line 22) | static void gen_chains(
  function base_w (line 110) | static void base_w(unsigned int *output, const int out_len,
  function wots_checksum (line 132) | static void wots_checksum(unsigned int *csum_base_w,
  function chain_lengths (line 152) | void chain_lengths(unsigned int *lengths, const unsigned char *msg)
  function wots_pk_from_sig (line 163) | void wots_pk_from_sig(unsigned char *pk,
  function wots_gen_leafx4 (line 185) | void wots_gen_leafx4(unsigned char *dest,

FILE: shake-avx2/wotsx4.h
  type leaf_info_x4 (line 13) | struct leaf_info_x4 {

FILE: vectors.py
  function nameFor (line 25) | def nameFor(fn, opt, size, thash):
  function make (line 28) | def make(fn, opt, size, thash, bindir, impl):
  function run (line 47) | def run(name_size, bindir):
  function generate_sums (line 62) | def generate_sums():
  function check_sum (line 74) | def check_sum(name, impl):
Condensed preview — 161 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (567K chars).
[
  {
    "path": ".github/workflows/test-haraka-aesni.yml",
    "chars": 1019,
    "preview": "name: Tests for haraka-aesni implementation\n\non:\n  - push\n  - pull_request\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n  "
  },
  {
    "path": ".github/workflows/test-ref.yml",
    "chars": 1080,
    "preview": "name: Tests for ref implementation\n\non:\n  - push\n  - pull_request\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strateg"
  },
  {
    "path": ".github/workflows/test-sha2-avx2.yml",
    "chars": 993,
    "preview": "name: Tests for sha2-avx2 implementation\n\non:\n  - push\n  - pull_request\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    s"
  },
  {
    "path": ".github/workflows/test-shake-avx2.yml",
    "chars": 1003,
    "preview": "name: Tests for shake-avx2 implementation\n\non:\n  - push\n  - pull_request\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    "
  },
  {
    "path": ".reuse/dep5",
    "chars": 563,
    "preview": "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: SPHINCS+\nUpstream-Contact: con"
  },
  {
    "path": "LICENSE",
    "chars": 102,
    "preview": "SPDX-License-Identifier: (LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0) AND MIT\n\n"
  },
  {
    "path": "LICENSES/0BSD.txt",
    "chars": 632,
    "preview": "BSD Zero Clause License\n\nPermission to use, copy, modify, and/or distribute this software for\nany purpose with or withou"
  },
  {
    "path": "LICENSES/CC0-1.0.txt",
    "chars": 7049,
    "preview": "Creative Commons Legal Code\n\nCC0 1.0 Universal\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE\n"
  },
  {
    "path": "LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt",
    "chars": 52,
    "preview": "This work is hereby placed into the public domain.\n\n"
  },
  {
    "path": "LICENSES/MIT-0.txt",
    "chars": 879,
    "preview": "MIT No Attribution\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this\nsoftware and as"
  },
  {
    "path": "LICENSES/MIT.txt",
    "chars": 1068,
    "preview": "MIT License\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associate"
  },
  {
    "path": "README.md",
    "chars": 3108,
    "preview": "## SPHINCS+\n\nThis repository contains the software that accompanies the [SPHINCS+ submission](https://sphincs.org/) to ["
  },
  {
    "path": "SHA256SUMS",
    "chars": 3276,
    "preview": "9e1b3168520c917b6de676caa7a5799ec972e55caa150090e8452c80c299545e sphincs-haraka-128f-robust\nc6a28dcf0667bd91c7bb46814ac7"
  },
  {
    "path": "benchmark.py",
    "chars": 1333,
    "preview": "#! /usr/bin/env python3\nimport fileinput\nimport itertools\nimport os\nimport sys\nfrom subprocess import DEVNULL, run\n\nimpl"
  },
  {
    "path": "haraka-aesni/.gitignore",
    "chars": 66,
    "preview": "test/*\n!test/*.c\nPQCsignKAT_*.rsp\nPQCsignKAT_*.req\nPQCgenKAT_sign\n"
  },
  {
    "path": "haraka-aesni/Makefile",
    "chars": 1214,
    "preview": "PARAMS = sphincs-haraka-128f\nTHASH = robust\n\nCC = /usr/bin/gcc\nCFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O"
  },
  {
    "path": "haraka-aesni/context.h",
    "chars": 224,
    "preview": "#ifndef SPX_CONTEXT_H\n#define SPX_CONTEXT_H\n\n#include <stdint.h>\n\n#include \"params.h\"\n#include \"immintrin.h\"\n\ntypedef st"
  },
  {
    "path": "haraka-aesni/haraka.c",
    "chars": 22888,
    "preview": "/*\nPlain C implementation of the Haraka256 and Haraka512 permutations.\n*/\n#include <immintrin.h>\n#include <stdio.h>\n#inc"
  },
  {
    "path": "haraka-aesni/harakax4.h",
    "chars": 1165,
    "preview": "#ifndef SPX_HARAKAX4_H\n#define SPX_HARAKAX4_H\n\n#include \"context.h\"\n#include \"params.h\"\n\n/* Haraka Sponge */\n#define har"
  },
  {
    "path": "haraka-aesni/hash_harakax4.c",
    "chars": 999,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"params.h\"\n#include \"harakax4.h\"\n#include \"hashx4"
  },
  {
    "path": "haraka-aesni/test/benchmark.c",
    "chars": 4607,
    "preview": "#define _POSIX_C_SOURCE 199309L\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"../api.h\"\n#include "
  },
  {
    "path": "haraka-aesni/thash_haraka_robustx4.c",
    "chars": 3506,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thashx4.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h"
  },
  {
    "path": "haraka-aesni/thash_haraka_simplex4.c",
    "chars": 2307,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thashx4.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h"
  },
  {
    "path": "ref/.gitignore",
    "chars": 66,
    "preview": "test/*\n!test/*.c\nPQCsignKAT_*.rsp\nPQCsignKAT_*.req\nPQCgenKAT_sign\n"
  },
  {
    "path": "ref/Makefile",
    "chars": 1731,
    "preview": "PARAMS = sphincs-haraka-128f\nTHASH = robust\n\nCC=/usr/bin/gcc\nCFLAGS=-Wall -Wextra -Wpedantic -O3 -std=c99 -Wconversion -"
  },
  {
    "path": "ref/PQCgenKAT_sign.c",
    "chars": 7000,
    "preview": "\n//\n//  PQCgenKAT_sign.c\n//\n//  Created by Bassham, Lawrence E (Fed) on 8/29/17.\n//  Copyright © 2017 Bassham, Lawrence "
  },
  {
    "path": "ref/address.c",
    "chars": 2957,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h\"\n\n/*\n * Specify whic"
  },
  {
    "path": "ref/address.h",
    "chars": 1683,
    "preview": "#ifndef SPX_ADDRESS_H\n#define SPX_ADDRESS_H\n\n#include <stdint.h>\n#include \"params.h\"\n\n/* The hash types that are passed "
  },
  {
    "path": "ref/api.h",
    "chars": 2116,
    "preview": "#ifndef SPX_API_H\n#define SPX_API_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"params.h\"\n\n#define CRYPTO_ALGNAM"
  },
  {
    "path": "ref/context.h",
    "chars": 479,
    "preview": "#ifndef SPX_CONTEXT_H\n#define SPX_CONTEXT_H\n\n#include <stdint.h>\n\n#include \"params.h\"\n\ntypedef struct {\n    uint8_t pub_"
  },
  {
    "path": "ref/fips202.c",
    "chars": 19100,
    "preview": "/* Based on the public domain implementation in\n * crypto_hash/keccakc512/simple/ from http://bench.cr.yp.to/supercop.ht"
  },
  {
    "path": "ref/fips202.h",
    "chars": 1676,
    "preview": "#ifndef SPX_FIPS202_H\n#define SPX_FIPS202_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#define SHAKE128_RATE 168\n#define "
  },
  {
    "path": "ref/fors.c",
    "chars": 5301,
    "preview": "#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"fors.h\"\n#include \"utils.h\"\n#include \"utilsx1.h\"\n#"
  },
  {
    "path": "ref/fors.h",
    "chars": 1104,
    "preview": "#ifndef SPX_FORS_H\n#define SPX_FORS_H\n\n#include <stdint.h>\n\n#include \"params.h\"\n#include \"context.h\"\n\n/**\n * Signs a mes"
  },
  {
    "path": "ref/haraka.c",
    "chars": 26095,
    "preview": "/*\n * Constant time implementation of the Haraka hash function.\n *\n * The bit-sliced implementation of the AES round fun"
  },
  {
    "path": "ref/haraka.h",
    "chars": 1494,
    "preview": "#ifndef SPX_HARAKA_H\n#define SPX_HARAKA_H\n\n#include \"context.h\"\n\n/* Tweak constants with seed */\n#define tweak_constants"
  },
  {
    "path": "ref/haraka_offsets.h",
    "chars": 1059,
    "preview": "#if !defined( HARAKA_OFFSETS_H_ )\n#define HARAKA_OFFSETS_H_\n\n/*\n * Offsets of various fields in the address structure wh"
  },
  {
    "path": "ref/hash.h",
    "chars": 967,
    "preview": "#ifndef SPX_HASH_H\n#define SPX_HASH_H\n\n#include <stdint.h>\n#include \"context.h\"\n#include \"params.h\"\n\n#define initialize_"
  },
  {
    "path": "ref/hash_haraka.c",
    "chars": 3032,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"utils.h\"\n#include \"params.h\"\n\n#include \"haraka.h"
  },
  {
    "path": "ref/hash_sha2.c",
    "chars": 6702,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"utils.h\"\n#include \"params.h\"\n#include \"hash.h\"\n#"
  },
  {
    "path": "ref/hash_shake.c",
    "chars": 3063,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"utils.h\"\n#include \"params.h\"\n#include \"hash.h\"\n#"
  },
  {
    "path": "ref/merkle.c",
    "chars": 1973,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx1.h\"\n#include \"wots.h\"\n#include \"wotsx1.h\"\n#"
  },
  {
    "path": "ref/merkle.h",
    "chars": 571,
    "preview": "#if !defined( MERKLE_H_ )\n#define MERKLE_H_\n\n#include <stdint.h>\n\n/* Generate a Merkle signature (WOTS signature followe"
  },
  {
    "path": "ref/params/params-sphincs-haraka-128f.h",
    "chars": 2131,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-haraka-128s.h",
    "chars": 2131,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-haraka-192f.h",
    "chars": 2131,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-haraka-192s.h",
    "chars": 2131,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-haraka-256f.h",
    "chars": 2131,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-haraka-256s.h",
    "chars": 2131,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-sha2-128f.h",
    "chars": 2348,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-sha2-128s.h",
    "chars": 2348,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-sha2-192f.h",
    "chars": 2355,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-sha2-192s.h",
    "chars": 2355,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-sha2-256f.h",
    "chars": 2355,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-sha2-256s.h",
    "chars": 2355,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-shake-128f.h",
    "chars": 2130,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-shake-128s.h",
    "chars": 2130,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-shake-192f.h",
    "chars": 2130,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-shake-192s.h",
    "chars": 2130,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-shake-256f.h",
    "chars": 2130,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params/params-sphincs-shake-256s.h",
    "chars": 2130,
    "preview": "#ifndef SPX_PARAMS_H\n#define SPX_PARAMS_H\n\n#define SPX_NAMESPACE(s) SPX_##s\n\n/* Hash output length in bytes. */\n#define "
  },
  {
    "path": "ref/params.h",
    "chars": 81,
    "preview": "#define str(s) #s\n#define xstr(s) str(s)\n\n#include xstr(params/params-PARAMS.h)\n\n"
  },
  {
    "path": "ref/randombytes.c",
    "chars": 762,
    "preview": "/*\nThis code was taken from the SPHINCS reference implementation and is public domain.\n*/\n\n#include <fcntl.h>\n#include <"
  },
  {
    "path": "ref/randombytes.h",
    "chars": 129,
    "preview": "#ifndef SPX_RANDOMBYTES_H\n#define SPX_RANDOMBYTES_H\n\nextern void randombytes(unsigned char * x,unsigned long long xlen);"
  },
  {
    "path": "ref/rng.c",
    "chars": 5362,
    "preview": "//\n//  rng.c\n//\n//  Created by Bassham, Lawrence E (Fed) on 8/29/17.\n//  Copyright © 2017 Bassham, Lawrence E (Fed). All"
  },
  {
    "path": "ref/rng.h",
    "chars": 1215,
    "preview": "//\n//  rng.h\n//\n//  Created by Bassham, Lawrence E (Fed) on 8/29/17.\n//  Copyright © 2017 Bassham, Lawrence E (Fed). All"
  },
  {
    "path": "ref/sha2.c",
    "chars": 21257,
    "preview": "/* Based on the public domain implementation in\n * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html\n * b"
  },
  {
    "path": "ref/sha2.h",
    "chars": 1368,
    "preview": "#ifndef SPX_SHA2_H\n#define SPX_SHA2_H\n\n#include \"params.h\"\n\n#define SPX_SHA256_BLOCK_BYTES 64\n#define SPX_SHA256_OUTPUT_"
  },
  {
    "path": "ref/sha2_offsets.h",
    "chars": 1042,
    "preview": "#ifndef SHA2_OFFSETS_H_\n#define SHA2_OFFSETS_H_\n\n/*\n * Offsets of various fields in the address structure when we use SH"
  },
  {
    "path": "ref/shake_offsets.h",
    "chars": 1055,
    "preview": "#if !defined( SHAKE_OFFSETS_H_ )\n#define SHAKE_OFFSETS_H_\n\n/*\n * Offsets of various fields in the address structure when"
  },
  {
    "path": "ref/sign.c",
    "chars": 8147,
    "preview": "#include <stddef.h>\n#include <string.h>\n#include <stdint.h>\n\n#include \"api.h\"\n#include \"params.h\"\n#include \"wots.h\"\n#inc"
  },
  {
    "path": "ref/test/benchmark.c",
    "chars": 4933,
    "preview": "#define _POSIX_C_SOURCE 199309L\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"../thash.h\"\n#includ"
  },
  {
    "path": "ref/test/cycles.c",
    "chars": 3202,
    "preview": "#include \"cycles.h\"\n\n#if defined(__aarch64__) && defined(__APPLE__)\n// Adapted from\n// https://github.com/lemire/Code-us"
  },
  {
    "path": "ref/test/cycles.h",
    "chars": 114,
    "preview": "#ifndef SPX_CYCLES_H\n#define SPX_CYCLES_H\n\nvoid init_cpucycles(void);\nunsigned long long cpucycles(void);\n\n#endif\n"
  },
  {
    "path": "ref/test/fors.c",
    "chars": 968,
    "preview": "#include <stdio.h>\n#include <string.h>\n\n#include \"../context.h\"\n#include \"../hash.h\"\n#include \"../fors.h\"\n#include \"../r"
  },
  {
    "path": "ref/test/haraka.c",
    "chars": 4332,
    "preview": "#include <stdio.h>\n#include <stdint.h>\n#include <string.h>\n#include <inttypes.h>\n\n#include \"../haraka.c\"\n#include \"../ra"
  },
  {
    "path": "ref/test/spx.c",
    "chars": 3438,
    "preview": "#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n\n#include \"../api.h\"\n#include \"../params.h\"\n#include \"../rand"
  },
  {
    "path": "ref/thash.h",
    "chars": 276,
    "preview": "#ifndef SPX_THASH_H\n#define SPX_THASH_H\n\n#include \"context.h\"\n#include \"params.h\"\n\n#include <stdint.h>\n\n#define thash SP"
  },
  {
    "path": "ref/thash_haraka_robust.c",
    "chars": 1324,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thash.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h\"\n"
  },
  {
    "path": "ref/thash_haraka_simple.c",
    "chars": 1020,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thash.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h\"\n"
  },
  {
    "path": "ref/thash_sha2_robust.c",
    "chars": 2376,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thash.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h\"\n"
  },
  {
    "path": "ref/thash_sha2_simple.c",
    "chars": 1793,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thash.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h\"\n"
  },
  {
    "path": "ref/thash_shake_robust.c",
    "chars": 831,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thash.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h\"\n"
  },
  {
    "path": "ref/thash_shake_simple.c",
    "chars": 641,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thash.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h\"\n"
  },
  {
    "path": "ref/utils.c",
    "chars": 5332,
    "preview": "#include <string.h>\n\n#include \"utils.h\"\n#include \"params.h\"\n#include \"hash.h\"\n#include \"thash.h\"\n#include \"address.h\"\n\n/"
  },
  {
    "path": "ref/utils.h",
    "chars": 2378,
    "preview": "#ifndef SPX_UTILS_H\n#define SPX_UTILS_H\n\n#include <stdint.h>\n#include \"params.h\"\n#include \"context.h\"\n\n\n/* To support MS"
  },
  {
    "path": "ref/utilsx1.c",
    "chars": 3787,
    "preview": "#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx1.h\"\n#include \"params.h\"\n#include \"thash.h\"\n#include \"address.h\""
  },
  {
    "path": "ref/utilsx1.h",
    "chars": 1009,
    "preview": "#ifndef SPX_UTILSX4_H\n#define SPX_UTILSX4_H\n\n#include <stdint.h>\n#include \"params.h\"\n#include \"context.h\"\n\n/**\n * For a "
  },
  {
    "path": "ref/wots.c",
    "chars": 3225,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx1.h\"\n#include \"hash.h\"\n#include \"thash.h\"\n#i"
  },
  {
    "path": "ref/wots.h",
    "chars": 663,
    "preview": "#ifndef SPX_WOTS_H\n#define SPX_WOTS_H\n\n#include <stdint.h>\n\n#include \"params.h\"\n#include \"context.h\"\n\n/**\n * Takes a WOT"
  },
  {
    "path": "ref/wotsx1.c",
    "chars": 2269,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"hash.h\"\n#include \"thash.h\"\n#include \"wots.h\"\n#incl"
  },
  {
    "path": "ref/wotsx1.h",
    "chars": 1190,
    "preview": "#if !defined( WOTSX1_H_ )\n#define WOTSX1_H_ \n\n#include <string.h>\n\n/*\n * This is here to provide an interface to the int"
  },
  {
    "path": "sha2-avx2/.gitignore",
    "chars": 104,
    "preview": "test/*\n!test/*.c\nPQCsignKAT_*.rsp\nPQCsignKAT_*.req\nPQCgenKAT_sign\nkeccak4x/KeccakP-1600-times4-SIMD256.o"
  },
  {
    "path": "sha2-avx2/Makefile",
    "chars": 1327,
    "preview": "PARAMS = sphincs-sha2-128f\nTHASH = robust\n\nCC = /usr/bin/gcc\nCFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 "
  },
  {
    "path": "sha2-avx2/context.h",
    "chars": 267,
    "preview": "#ifndef SPX_CONTEXT_H\n#define SPX_CONTEXT_H\n\n#include <stdint.h>\n\n#include \"params.h\"\n\ntypedef struct {\n    uint8_t pub_"
  },
  {
    "path": "sha2-avx2/fors.c",
    "chars": 8069,
    "preview": "#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"fors.h\"\n#include \"utils.h\"\n#include \"utilsx8.h\"\n#"
  },
  {
    "path": "sha2-avx2/hash_sha2x8.c",
    "chars": 2538,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"utils.h\"\n#include \"params.h\"\n#include \"hashx8.h\""
  },
  {
    "path": "sha2-avx2/hashx8.h",
    "chars": 514,
    "preview": "#ifndef SPX_HASHX8_H\n#define SPX_HASHX8_H\n\n#include <stdint.h>\n#include \"params.h\"\n\n#define prf_addrx8 SPX_NAMESPACE(prf"
  },
  {
    "path": "sha2-avx2/merkle.c",
    "chars": 2115,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx8.h\"\n#include \"wots.h\"\n#include \"wotsx8.h\"\n#"
  },
  {
    "path": "sha2-avx2/sha256avx.c",
    "chars": 15421,
    "preview": "#include <stdio.h>\n#include <string.h>\n#include <stdint.h>\n\n#include \"sha256avx.h\"\n\n// Transpose 8 vectors containing 32"
  },
  {
    "path": "sha2-avx2/sha256avx.h",
    "chars": 3512,
    "preview": "#ifndef SHA256AVX_H\n#define SHA256AVX_H\n#include \"immintrin.h\"\n#include <stdint.h>\n\nstatic const unsigned int RC[] = {\n "
  },
  {
    "path": "sha2-avx2/sha256x8.c",
    "chars": 7040,
    "preview": "#include <string.h>\n\n#include \"sha256x8.h\"\n#include \"sha256avx.h\"\n#include \"utils.h\"\n\nstatic uint32_t load_bigendian_32("
  },
  {
    "path": "sha2-avx2/sha256x8.h",
    "chars": 2465,
    "preview": "#ifndef SPX_SHA256X8_H\n#define SPX_SHA256X8_H\n\n#include \"params.h\"\n\n#define SPX_SHA256_BLOCK_BYTES 64\n#define SPX_SHA256"
  },
  {
    "path": "sha2-avx2/sha512x4.c",
    "chars": 15546,
    "preview": "#include <stdio.h>\n#include <string.h>\n#include <stdint.h>\n\n#define SPX_SHA512_OUTPUT_BYTES 64  /* In sha256.h, but we d"
  },
  {
    "path": "sha2-avx2/sha512x4.h",
    "chars": 1137,
    "preview": "#ifndef SHA512AVX_H\n#define SHA512AVX_H\n#include <stdint.h>\n#include \"immintrin.h\"\n\n#include \"params.h\"\n\ntypedef struct "
  },
  {
    "path": "sha2-avx2/test/benchmark.c",
    "chars": 4636,
    "preview": "#define _POSIX_C_SOURCE 199309L\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"../api.h\"\n#include "
  },
  {
    "path": "sha2-avx2/test/thashx8.c",
    "chars": 2299,
    "preview": "#include <stdio.h>\n#include <string.h>\n\n#include \"../thashx8.h\"\n#include \"../thash.h\"\n#include \"../randombytes.h\"\n#inclu"
  },
  {
    "path": "sha2-avx2/thash_sha2_robustx8.c",
    "chars": 11408,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"utils.h\"\n#include \"params.h\"\n#include \"thashx8.h"
  },
  {
    "path": "sha2-avx2/thash_sha2_simplex8.c",
    "chars": 8176,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"utils.h\"\n#include \"params.h\"\n#include \"thashx8.h"
  },
  {
    "path": "sha2-avx2/thashx8.h",
    "chars": 817,
    "preview": "#ifndef SPX_THASHX8_H\n#define SPX_THASHX8_H\n\n#include <stdint.h>\n#include \"context.h\"\n#include \"params.h\"\n\n#define thash"
  },
  {
    "path": "sha2-avx2/utilsx8.c",
    "chars": 6238,
    "preview": "#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx8.h\"\n#include \"params.h\"\n#include \"thashx8.h\"\n#include \"address."
  },
  {
    "path": "sha2-avx2/utilsx8.h",
    "chars": 1084,
    "preview": "#ifndef SPX_UTILSX8_H\n#define SPX_UTILSX8_H\n\n#include <stdint.h>\n#include \"params.h\"\n\n/**\n * For a given leaf index, com"
  },
  {
    "path": "sha2-avx2/wots.c",
    "chars": 9351,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx8.h\"\n#include \"hash.h\"\n#include \"hashx8.h\"\n#"
  },
  {
    "path": "sha2-avx2/wotsx8.h",
    "chars": 1307,
    "preview": "#if !defined( WOTSX8_H_ )\n#define WOTSX8_H_ \n\n#include <string.h>\n#include \"params.h\"\n\n/*\n * This is here to provide an "
  },
  {
    "path": "shake-a64/.gitignore",
    "chars": 66,
    "preview": "test/*\n!test/*.c\nPQCsignKAT_*.rsp\nPQCsignKAT_*.req\nPQCgenKAT_sign\n"
  },
  {
    "path": "shake-a64/Makefile",
    "chars": 1411,
    "preview": "PARAMS = sphincs-shake-128f\nTHASH = robust\n\nCFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -fomit-f"
  },
  {
    "path": "shake-a64/context.h",
    "chars": 180,
    "preview": "#ifndef SPX_CONTEXT_H\n#define SPX_CONTEXT_H\n\n#include <stdint.h>\n\n#include \"params.h\"\n\ntypedef struct {\n    uint8_t pub_"
  },
  {
    "path": "shake-a64/f1600x2.h",
    "chars": 212,
    "preview": "#ifndef SPX_F1600X2_H\n#define SPX_F1600X2_H\n\n#include <stdint.h>\n\nextern uint64_t f1600_RC[24];\nextern void _f1600x2(uin"
  },
  {
    "path": "shake-a64/f1600x2.s",
    "chars": 3689,
    "preview": "# From https://github.com/bwesterb/armed-keccak\n\n.macro round\n    # Execute theta, but without xoring into the state yet"
  },
  {
    "path": "shake-a64/f1600x2_const.c",
    "chars": 557,
    "preview": "#include \"f1600x2.h\"\n\nuint64_t f1600_RC[24] = {\n\t0x0000000000000001,\n\t0x0000000000008082,\n\t0x800000000000808A,\n\t0x800000"
  },
  {
    "path": "shake-a64/fips202x2.c",
    "chars": 3478,
    "preview": "#include <stdint.h>\n#include <assert.h>\n\n#include \"fips202x2.h\"\n#include \"fips202.h\"\n#include \"f1600x2.h\"\n\nuint64_t load"
  },
  {
    "path": "shake-a64/fips202x2.h",
    "chars": 624,
    "preview": "#ifndef SPX_FIPS202X2_H\n#define SPX_FIPS202X2_H\n\n#include <stdint.h>\n\nuint64_t load64(const unsigned char *x);\nvoid stor"
  },
  {
    "path": "shake-a64/fors.c",
    "chars": 6457,
    "preview": "#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"thash.h\"\n#include \"fors.h\"\n#include \"utils.h\"\n#in"
  },
  {
    "path": "shake-a64/hash_shakex2.c",
    "chars": 1470,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"params.h\"\n#include \"fips202x2.h\"\n#include \"f1600"
  },
  {
    "path": "shake-a64/hashx2.h",
    "chars": 313,
    "preview": "#ifndef SPX_HASHX2_H\n#define SPX_HASHX2_H\n\n#include <stdint.h>\n#include \"context.h\"\n#include \"params.h\"\n\n#define prf_add"
  },
  {
    "path": "shake-a64/merkle.c",
    "chars": 2027,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx2.h\"\n#include \"wots.h\"\n#include \"wotsx2.h\"\n#"
  },
  {
    "path": "shake-a64/test/benchmark.c",
    "chars": 5176,
    "preview": "#define _POSIX_C_SOURCE 199309L\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"../thash.h\"\n#includ"
  },
  {
    "path": "shake-a64/test/thashx2.c",
    "chars": 987,
    "preview": "#include <stdio.h>\n#include <string.h>\n\n#include \"../thashx2.h\"\n#include \"../thash.h\"\n#include \"../randombytes.h\"\n#inclu"
  },
  {
    "path": "shake-a64/thash.h",
    "chars": 236,
    "preview": "#ifndef SPX_THASHX2_AS_ONE\n#define SPX_THASHX2_AS_ONE\n\n#include <stdint.h>\n#include \"context.h\"\n\nvoid thash(unsigned cha"
  },
  {
    "path": "shake-a64/thash_shake_robustx2.c",
    "chars": 4069,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thash.h\"\n#include \"thashx2.h\"\n#include \"address.h\"\n#include \"params.h"
  },
  {
    "path": "shake-a64/thash_shake_simplex2.c",
    "chars": 2815,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thash.h\"\n#include \"thashx2.h\"\n#include \"address.h\"\n#include \"params.h"
  },
  {
    "path": "shake-a64/thashx2.h",
    "chars": 392,
    "preview": "#ifndef SPX_THASHX2_H\n#define SPX_THASHX2_H\n\n#include <stdint.h>\n#include \"context.h\"\n#include \"params.h\"\n\n#define thash"
  },
  {
    "path": "shake-a64/utilsx2.c",
    "chars": 5458,
    "preview": "#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx2.h\"\n#include \"params.h\"\n#include \"thashx2.h\"\n#include \"address."
  },
  {
    "path": "shake-a64/utilsx2.h",
    "chars": 1085,
    "preview": "#ifndef SPX_UTILSX2_H\n#define SPX_UTILSX2_H\n\n#include <stdint.h>\n#include \"params.h\"\n\n/**\n * For a given leaf index, com"
  },
  {
    "path": "shake-a64/wots.c",
    "chars": 8017,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx2.h\"\n#include \"hash.h\"\n#include \"hashx2.h\"\n#"
  },
  {
    "path": "shake-a64/wotsx2.h",
    "chars": 1307,
    "preview": "#if !defined( WOTSX2_H_ )\n#define WOTSX2_H_ \n\n#include <string.h>\n#include \"params.h\"\n\n/*\n * This is here to provide an "
  },
  {
    "path": "shake-avx2/.gitignore",
    "chars": 104,
    "preview": "test/*\n!test/*.c\nPQCsignKAT_*.rsp\nPQCsignKAT_*.req\nPQCgenKAT_sign\nkeccak4x/KeccakP-1600-times4-SIMD256.o"
  },
  {
    "path": "shake-avx2/Makefile",
    "chars": 1729,
    "preview": "PARAMS = sphincs-shake-128f\nTHASH = robust\n\nCC = /usr/bin/gcc\nCFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3"
  },
  {
    "path": "shake-avx2/context.h",
    "chars": 180,
    "preview": "#ifndef SPX_CONTEXT_H\n#define SPX_CONTEXT_H\n\n#include <stdint.h>\n\n#include \"params.h\"\n\ntypedef struct {\n    uint8_t pub_"
  },
  {
    "path": "shake-avx2/fips202x4.c",
    "chars": 5440,
    "preview": "#include <immintrin.h>\n#include <stdint.h>\n#include <assert.h>\n\n#include \"fips202.h\"\n#include \"fips202x4.h\"\n\n#define NRO"
  },
  {
    "path": "shake-avx2/fips202x4.h",
    "chars": 774,
    "preview": "#ifndef SPX_FIPS202X4_H\n#define SPX_FIPS202X4_H\n\n#include <immintrin.h>\n\nvoid shake128x4(unsigned char *out0,\n          "
  },
  {
    "path": "shake-avx2/fors.c",
    "chars": 6977,
    "preview": "#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"fors.h\"\n#include \"utils.h\"\n#include \"utilsx4.h\"\n#"
  },
  {
    "path": "shake-avx2/hash_shakex4.c",
    "chars": 1981,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"address.h\"\n#include \"params.h\"\n#include \"fips202x4.h\"\n#include \"hashx"
  },
  {
    "path": "shake-avx2/hashx4.h",
    "chars": 387,
    "preview": "#ifndef SPX_HASHX4_H\n#define SPX_HASHX4_H\n\n#include <stdint.h>\n#include \"context.h\"\n#include \"params.h\"\n\n#define prf_add"
  },
  {
    "path": "shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c",
    "chars": 40005,
    "preview": "/*\nImplementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,\nJoan Daemen, Michaël Peeters, Gilles Van "
  },
  {
    "path": "shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h",
    "chars": 3113,
    "preview": "/*\nImplementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,\nJoan Daemen, Michaël Peeters, Gilles Van "
  },
  {
    "path": "shake-avx2/keccak4x/KeccakP-1600-unrolling.macros",
    "chars": 6643,
    "preview": "/*\nImplementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,\nJoan Daemen, Michaël Peeters, Gilles Van "
  },
  {
    "path": "shake-avx2/keccak4x/SIMD256-config.h",
    "chars": 150,
    "preview": "#define KeccakP1600times4_implementation_config \"AVX2, all rounds unrolled\"\n#define KeccakP1600times4_fullUnrolling\n#def"
  },
  {
    "path": "shake-avx2/keccak4x/align.h",
    "chars": 938,
    "preview": "/*\nImplementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,\nJoan Daemen, Michaël Peeters, Gilles Van "
  },
  {
    "path": "shake-avx2/keccak4x/brg_endian.h",
    "chars": 5546,
    "preview": "/*\n ---------------------------------------------------------------------------\n Copyright (c) 1998-2008, Brian Gladman,"
  },
  {
    "path": "shake-avx2/merkle.c",
    "chars": 2027,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx4.h\"\n#include \"wots.h\"\n#include \"wotsx4.h\"\n#"
  },
  {
    "path": "shake-avx2/test/benchmark.c",
    "chars": 4619,
    "preview": "#define _POSIX_C_SOURCE 199309L\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"../api.h\"\n#include "
  },
  {
    "path": "shake-avx2/test/thashx4.c",
    "chars": 1105,
    "preview": "#include <stdio.h>\n#include <string.h>\n\n#include \"../thashx4.h\"\n#include \"../thash.h\"\n#include \"../randombytes.h\"\n#inclu"
  },
  {
    "path": "shake-avx2/thash_shake_robustx4.c",
    "chars": 5199,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thashx4.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h"
  },
  {
    "path": "shake-avx2/thash_shake_simplex4.c",
    "chars": 3746,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"thashx4.h\"\n#include \"address.h\"\n#include \"params.h\"\n#include \"utils.h"
  },
  {
    "path": "shake-avx2/thashx4.h",
    "chars": 525,
    "preview": "#ifndef SPX_THASHX4_H\n#define SPX_THASHX4_H\n\n#include <stdint.h>\n#include \"context.h\"\n#include \"params.h\"\n\n#define thash"
  },
  {
    "path": "shake-avx2/utilsx4.c",
    "chars": 5872,
    "preview": "#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx4.h\"\n#include \"params.h\"\n#include \"thashx4.h\"\n#include \"address."
  },
  {
    "path": "shake-avx2/utilsx4.h",
    "chars": 1084,
    "preview": "#ifndef SPX_UTILSX4_H\n#define SPX_UTILSX4_H\n\n#include <stdint.h>\n#include \"params.h\"\n\n/**\n * For a given leaf index, com"
  },
  {
    "path": "shake-avx2/wots.c",
    "chars": 8464,
    "preview": "#include <stdint.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"utilsx4.h\"\n#include \"hash.h\"\n#include \"hashx4.h\"\n#"
  },
  {
    "path": "shake-avx2/wotsx4.h",
    "chars": 1306,
    "preview": "#if !defined( WOTSX4_H_ )\n#define WOTSX4_H_\n\n#include <string.h>\n#include \"params.h\"\n\n/*\n * This is here to provide an i"
  },
  {
    "path": "vectors.py",
    "chars": 3266,
    "preview": "#! /usr/bin/env python3\n\n# Without arguments, generates sha256 sums of NIST KAT response files\n# for each of the instanc"
  }
]

About this extraction

This page contains the full source code of the sphincs/sphincsplus GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 161 files (526.4 KB), approximately 182.2k tokens, and a symbol index with 349 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!