Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

Revision 81a0bf97e2012c369f800f26e2e3d3651cde7a35 authored by Matthias J. Kannwischer on 29 July 2021, 07:22:18 UTC, committed by Matthias J. Kannwischer on 02 August 2021, 03:06:46 UTC
Update NTRU Prime; add new round 3 parameter sets
1 parent 819f906
  • Files
  • Changes
  • b53fadd
  • /
  • crypto_sign
  • /
  • sphincs-shake256-256s-simple
  • /
  • avx2
  • /
  • wots.c
Raw File Download
Permalinks

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • revision
  • directory
  • content
revision badge
swh:1:rev:81a0bf97e2012c369f800f26e2e3d3651cde7a35
directory badge Iframe embedding
swh:1:dir:228f9241d780f7e1061c8459aa4c0d9a28d87f7e
content badge Iframe embedding
swh:1:cnt:1d05315afa43704967460209dcdec569e703be69
Citations

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • revision
  • directory
  • content
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
wots.c
#include <stdint.h>
#include <string.h>

#include "address.h"
#include "hash.h"
#include "hash_state.h"
#include "hashx4.h"
#include "params.h"
#include "thash.h"
#include "thashx4.h"
#include "utils.h"
#include "wots.h"

// TODO clarify address expectations, and make them more uniform.
// TODO i.e. do we expect types to be set already?
// TODO and do we expect modifications or copies?

/**
 * Computes the starting value for a chain, i.e. the secret key.
 * Expects the address to be complete up to the chain address.
 */
static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
                        uint32_t wots_addr[8], const hash_state *state_seeded) {
    /* Make sure that the hash address is actually zeroed. */
    PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr(wots_addr, 0);

    /* Generate sk element. */
    PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded);
}

/**
 * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk
 */
static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed,
                          uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) {
    unsigned int j;

    /* Make sure that the hash address is actually zeroed. */
    for (j = 0; j < 4; j++) {
        PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0);
    }

    /* Generate sk element. */
    PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
            skx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
            skx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
            skx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
            sk_seed, wots_addrx4,
            state_seeded);
}

/**
 * Computes the chaining function.
 * out and in have to be n-byte arrays.
 *
 * Interprets in as start-th value of the chain.
 * addr has to contain the address of the chain.
 */
static void gen_chain(unsigned char *out, const unsigned char *in,
                      unsigned int start, unsigned int steps,
                      const unsigned char *pub_seed, uint32_t addr[8],
                      const hash_state *state_seeded) {
    uint32_t i;

    /* Initialize out with the value at position 'start'. */
    memcpy(out, in, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N);

    /* Iterate 'steps' calls to the hash function. */
    for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W; i++) {
        PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr(addr, i);
        PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded);
    }
}

/**
 * 4-way parallel version of gen_chain; expects 4x as much space in out, and
 * 4x as much space in inx4. Assumes start and step identical across chains.
 */
static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4,
                        unsigned int start, unsigned int steps,
                        const unsigned char *pub_seed, uint32_t addrx4[4 * 8],
                        const hash_state *state_seeded) {
    uint32_t i;
    unsigned int j;

    /* Initialize outx4 with the value at position 'start'. */
    memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N);

    /* Iterate 'steps' calls to the hash function. */
    for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W; i++) {
        for (j = 0; j < 4; j++) {
            PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr(addrx4 + j * 8, i);
        }
        PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
                outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
                outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
                outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
                outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
                outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
                outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
                outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
                pub_seed, addrx4,
                state_seeded);
    }
}

/**
 * base_w algorithm as described in draft.
 * Interprets an array of bytes as integers in base w.
 * This only works when log_w is a divisor of 8.
 */
static void base_w(unsigned int *output, const int out_len, const unsigned char *input) {
    int in = 0;
    int out = 0;
    unsigned char total = 0;
    int bits = 0;
    int consumed;

    for (consumed = 0; consumed < out_len; consumed++) {
        if (bits == 0) {
            total = input[in];
            in++;
            bits += 8;
        }
        bits -= PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LOGW;
        output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W - 1);
        out++;
    }
}

/* Computes the WOTS+ checksum over a message (in base_w). */
static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) {
    unsigned int csum = 0;
    unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LOGW + 7) / 8];
    unsigned int i;

    /* Compute checksum. */
    for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN1; i++) {
        csum += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i];
    }

    /* Convert checksum to base_w. */
    /* Make sure expected empty zero bits are the least significant bits. */
    csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LOGW) % 8));
    PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum);
    base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN2, csum_bytes);
}

/* Takes a message and derives the matching chain lengths. */
static void chain_lengths(unsigned int *lengths, const unsigned char *msg) {
    base_w(lengths, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN1, msg);
    wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN1, lengths);
}

/**
 * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key
 * elements and computes the corresponding public key.
 * It requires the seed pub_seed (used to generate bitmasks and hash keys)
 * and the address of this WOTS key pair.
 *
 * Writes the computed public key to 'pk'.
 */
void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed,
        const unsigned char *pub_seed, uint32_t addr[8],
        const hash_state *state_seeded) {
    uint32_t i;
    unsigned int j;

    uint32_t addrx4[4 * 8];
    unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N];

    for (j = 0; j < 4; j++) {
        memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8);
    }

    /* The last iteration typically does not have complete set of 4 chains,
       but because we use pkbuf, this is not an issue -- we still do as many
       in parallel as possible. */
    for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) {
        for (j = 0; j < 4; j++) {
            PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_chain_addr(addrx4 + j * 8, i + j);
        }
        wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded);
        gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded);
        for (j = 0; j < 4; j++) {
            if (i + j < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN) {
                memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N);
            }
        }
    }

    // Get rid of unused argument variable.
    (void)state_seeded;
}

/**
 * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'.
 */
void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg,
        const unsigned char *sk_seed, const unsigned char *pub_seed,
        uint32_t addr[8], const hash_state *state_seeded) {
    unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN];
    uint32_t i;

    chain_lengths(lengths, msg);

    for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN; i++) {
        PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_chain_addr(addr, i);
        wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sk_seed, addr, state_seeded);
        gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded);
    }

    // avoid unused argument
    (void)state_seeded;
}

/**
 * Takes a WOTS signature and an n-byte message, computes a WOTS public key.
 *
 * Writes the computed public key to 'pk'.
 */
void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk,
        const unsigned char *sig, const unsigned char *msg,
        const unsigned char *pub_seed, uint32_t addr[8],
        const hash_state *state_seeded) {
    unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN];
    uint32_t i;

    chain_lengths(lengths, msg);

    for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN; i++) {
        PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_chain_addr(addr, i);
        gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N,
                  lengths[i], PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr,
                  state_seeded);
    }

    // avoid unused argument
    (void)state_seeded;
}
The diff you're trying to view is too large. Only the first 1000 changed files have been loaded.
Showing with 0 additions and 0 deletions (0 / 0 diffs computed)
swh spinner

Computing file changes ...

back to top

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Contact— JavaScript license information— Web API