Browse Source

Perform various reformatting / renaming

master
Joost Rijneveld 7 years ago
parent
commit
305bd614bb
No known key found for this signature in database GPG Key ID: A4FE39CF49CBC553
17 changed files with 234 additions and 130 deletions
  1. +6
    -0
      fips202.h
  2. +23
    -18
      hash.c
  3. +1
    -1
      hash.h
  4. +21
    -11
      hash_address.c
  5. +1
    -1
      hash_address.h
  6. +23
    -3
      params.h
  7. +4
    -1
      randombytes.h
  8. +3
    -3
      test/xmss_sign.c
  9. +3
    -3
      test/xmssmt_sign.c
  10. +9
    -9
      wots.c
  11. +10
    -5
      wots.h
  12. +15
    -9
      xmss.h
  13. +54
    -38
      xmss_commons.c
  14. +29
    -2
      xmss_commons.h
  15. +19
    -15
      xmss_core.c
  16. +3
    -2
      xmss_core.h
  17. +10
    -9
      xmss_core_fast.c

+ 6
- 0
fips202.h View File

@@ -4,9 +4,15 @@
#define SHAKE128_RATE 168
#define SHAKE256_RATE 136

/* Evaluates SHAKE-128 on `inlen' bytes in `in', according to FIPS-202.
* Writes the first `outlen` bytes of output to `out`.
*/
void shake128(unsigned char *out, unsigned long long outlen,
const unsigned char *in, unsigned long long inlen);

/* Evaluates SHAKE-256 on `inlen' bytes in `in', according to FIPS-202.
* Writes the first `outlen` bytes of output to `out`.
*/
void shake256(unsigned char *out, unsigned long long outlen,
const unsigned char *in, unsigned long long inlen);



+ 23
- 18
hash.c View File

@@ -5,16 +5,14 @@
#include "fips202.h"

#include <stdint.h>
#include <string.h>
#include <openssl/sha.h>

unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8])
void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8])
{
int i;
for (i = 0; i < 8; i++) {
to_byte(bytes + i*4, addr[i], 4);
ull_to_bytes(bytes + i*4, addr[i], 4);
}
return bytes;
}

static int core_hash(const xmss_params *params,
@@ -25,9 +23,11 @@ static int core_hash(const xmss_params *params,
unsigned long long i = 0;
unsigned char buf[inlen + n + keylen];

/* Input is of the form (toByte(X, 32) || KEY || M). */
/* We arrange the input into the hash function to be of the form:
* toByte(X, 32) || KEY || M
*/

to_byte(buf, type, n);
ull_to_bytes(buf, type, n);

for (i=0; i < keylen; i++) {
buf[i+n] = key[i];
@@ -80,18 +80,23 @@ int hash_h(const xmss_params *params,
unsigned char buf[2*params->n];
unsigned char key[params->n];
unsigned char bitmask[2*params->n];
unsigned char byte_addr[32];
unsigned char addr_as_bytes[32];
unsigned int i;

/* Generate the n-byte key. */
set_key_and_mask(addr, 0);
addr_to_byte(byte_addr, addr);
prf(params, key, byte_addr, pub_seed, params->n);
addr_to_bytes(addr_as_bytes, addr);
prf(params, key, addr_as_bytes, pub_seed, params->n);

/* Generate the 2n-byte mask. */
set_key_and_mask(addr, 1);
addr_to_byte(byte_addr, addr);
prf(params, bitmask, byte_addr, pub_seed, params->n);
addr_to_bytes(addr_as_bytes, addr);
prf(params, bitmask, addr_as_bytes, pub_seed, params->n);

set_key_and_mask(addr, 2);
addr_to_byte(byte_addr, addr);
prf(params, bitmask+params->n, byte_addr, pub_seed, params->n);
addr_to_bytes(addr_as_bytes, addr);
prf(params, bitmask + params->n, addr_as_bytes, pub_seed, params->n);

for (i = 0; i < 2*params->n; i++) {
buf[i] = in[i] ^ bitmask[i];
}
@@ -105,16 +110,16 @@ int hash_f(const xmss_params *params,
unsigned char buf[params->n];
unsigned char key[params->n];
unsigned char bitmask[params->n];
unsigned char byte_addr[32];
unsigned char addr_as_bytes[32];
unsigned int i;

set_key_and_mask(addr, 0);
addr_to_byte(byte_addr, addr);
prf(params, key, byte_addr, pub_seed, params->n);
addr_to_bytes(addr_as_bytes, addr);
prf(params, key, addr_as_bytes, pub_seed, params->n);

set_key_and_mask(addr, 1);
addr_to_byte(byte_addr, addr);
prf(params, bitmask, byte_addr, pub_seed, params->n);
addr_to_bytes(addr_as_bytes, addr);
prf(params, bitmask, addr_as_bytes, pub_seed, params->n);

for (i = 0; i < params->n; i++) {
buf[i] = in[i] ^ bitmask[i];


+ 1
- 1
hash.h View File

@@ -4,7 +4,7 @@
#include <stdint.h>
#include "params.h"

unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]);
void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8]);

int prf(const xmss_params *params,
unsigned char *out, const unsigned char *in,


+ 21
- 11
hash_address.c View File

@@ -1,15 +1,18 @@
#include <stdint.h>

void set_layer_addr(uint32_t addr[8], uint32_t layer) {
void set_layer_addr(uint32_t addr[8], uint32_t layer)
{
addr[0] = layer;
}

void set_tree_addr(uint32_t addr[8], uint64_t tree) {
void set_tree_addr(uint32_t addr[8], uint64_t tree)
{
addr[1] = (uint32_t) (tree >> 32);
addr[2] = (uint32_t) tree;
}

void set_type(uint32_t addr[8], uint32_t type) {
void set_type(uint32_t addr[8], uint32_t type)
{
int i;

addr[3] = type;
@@ -18,36 +21,43 @@ void set_type(uint32_t addr[8], uint32_t type) {
}
}

void set_key_and_mask(uint32_t addr[8], uint32_t key_and_mask) {
void set_key_and_mask(uint32_t addr[8], uint32_t key_and_mask)
{
addr[7] = key_and_mask;
}

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

void set_ots_addr(uint32_t addr[8], uint32_t ots) {
void set_ots_addr(uint32_t addr[8], uint32_t ots)
{
addr[4] = ots;
}

void set_chain_addr(uint32_t addr[8], uint32_t chain) {
void set_chain_addr(uint32_t addr[8], uint32_t chain)
{
addr[5] = chain;
}

void set_hash_addr(uint32_t addr[8], uint32_t hash) {
void set_hash_addr(uint32_t addr[8], uint32_t hash)
{
addr[6] = hash;
}

/* This function is used for L-trees. */
/* This function is used for L-tree addresses. */

void set_ltree_addr(uint32_t addr[8], uint32_t ltree) {
void set_ltree_addr(uint32_t addr[8], uint32_t ltree)
{
addr[4] = ltree;
}

/* These functions are used for hash tree addresses. */

void set_tree_height(uint32_t addr[8], uint32_t treeHeight) {
void set_tree_height(uint32_t addr[8], uint32_t treeHeight)
{
addr[5] = treeHeight;
}

void set_tree_index(uint32_t addr[8], uint32_t treeIndex) {
void set_tree_index(uint32_t addr[8], uint32_t treeIndex)
{
addr[6] = treeIndex;
}

+ 1
- 1
hash_address.h View File

@@ -19,7 +19,7 @@ void set_chain_addr(uint32_t addr[8], uint32_t chain);

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

/* This function is used for L-trees. */
/* This function is used for L-tree addresses. */

void set_ltree_addr(uint32_t addr[8], uint32_t ltree);



+ 23
- 3
params.h View File

@@ -3,14 +3,14 @@

#include <stdint.h>

// These are merely internal identifiers for the supported hash functions
/* These are merely internal identifiers for the supported hash functions. */
#define XMSS_SHA2 0
#define XMSS_SHAKE 1

// This is a consequence of the OID definitions in the draft, used for parsing
/* This is a result of the OID definitions in the draft; needed for parsing. */
#define XMSS_OID_LEN 4

// This structure will be populated when calling xmss[mt]_parse_oid
/* This structure will be populated when calling xmss[mt]_parse_oid. */
typedef struct {
unsigned int func;
unsigned int n;
@@ -30,10 +30,30 @@ typedef struct {
unsigned int bds_k;
} xmss_params;

/**
* Accepts strings such as "XMSS-SHA2_10_256"
* and outputs OIDs such as 0x01000001.
* Returns 1 when the parameter set is not found, 0 otherwise
*/
int xmss_str_to_oid(uint32_t *oid, const char* s);

/**
* Accepts takes strings such as "XMSSMT-SHA2_20/2_256"
* and outputs OIDs such as 0x01000001.
* Returns 1 when the parameter set is not found, 0 otherwise
*/
int xmssmt_str_to_oid(uint32_t *oid, const char* s);

/**
* Accepts OIDs such as 0x01000001, and configures params accordingly.
* Returns 1 when the OID is not found, 0 otherwise.
*/
int xmss_parse_oid(xmss_params *params, const uint32_t oid);

/**
* Accepts OIDs such as 0x01000001, and configures params accordingly.
* Returns 1 when the OID is not found, 0 otherwise.
*/
int xmssmt_parse_oid(xmss_params *params, const uint32_t oid);

#endif

+ 4
- 1
randombytes.h View File

@@ -1,6 +1,9 @@
#ifndef XMSS_RANDOMBYTES_H
#define XMSS_RANDOMBYTES_H

extern void randombytes(unsigned char * x,unsigned long long xlen);
/**
* Tries to read xlen bytes from a source of randomness, and writes them to x.
*/
void randombytes(unsigned char *x, unsigned long long xlen);

#endif

+ 3
- 3
test/xmss_sign.c View File

@@ -24,13 +24,13 @@ int main(int argc, char **argv) {
return -1;
}

// Read the OID from the public key, as we need its length to seek past it
/* Read the OID from the public key, as we need its length to seek past it */
fread(&oid_pk, 1, XMSS_OID_LEN, keypair);
xmss_parse_oid(&params, oid_pk);

// fseek past the public key
/* fseek past the public key */
fseek(keypair, params.publickey_bytes, SEEK_CUR);
// This is the OID we're actually going to use. Likely the same, but still.
/* This is the OID we're actually going to use. Likely the same, but still. */
fread(&oid_sk, 1, XMSS_OID_LEN, keypair);
xmss_parse_oid(&params, oid_sk);



+ 3
- 3
test/xmssmt_sign.c View File

@@ -24,13 +24,13 @@ int main(int argc, char **argv) {
return -1;
}

// Read the OID from the public key, as we need its length to seek past it
/* Read the OID from the public key, as we need its length to seek past it. */
fread(&oid_pk, 1, XMSS_OID_LEN, keypair);
xmssmt_parse_oid(&params, oid_pk);

// fseek past the public key
/* fseek past the public key. */
fseek(keypair, params.publickey_bytes, SEEK_CUR);
// This is the OID we're actually going to use. Likely the same, but still.
/* This is the OID we're actually going to use. Likely the same, but still.. */
fread(&oid_sk, 1, XMSS_OID_LEN, keypair);
xmssmt_parse_oid(&params, oid_sk);



+ 9
- 9
wots.c View File

@@ -6,9 +6,8 @@
#include "params.h"

/**
* Helper method for pseudorandom key generation
* Expands an n-byte array into a len*n byte array
* this is done using PRF
* Helper method for pseudorandom key generation.
* Expands an n-byte array into a len*n byte array using the `prf` function.
*/
static void expand_seed(const xmss_params *params,
unsigned char *outseeds, const unsigned char *inseed)
@@ -17,17 +16,17 @@ static void expand_seed(const xmss_params *params,
unsigned char ctr[32];

for (i = 0; i < params->wots_len; i++) {
to_byte(ctr, i, 32);
ull_to_bytes(ctr, i, 32);
prf(params, outseeds + i*params->n, ctr, inseed, params->n);
}
}

/**
* Computes the chaining function.
* out and in have to be n-byte arrays
* out and in have to be n-byte arrays.
*
* interpretes in as start-th value of the chain
* addr has to contain the address of the chain
* Interprets in as start-th value of the chain.
* addr has to contain the address of the chain.
*/
static void gen_chain(const xmss_params *params,
unsigned char *out, const unsigned char *in,
@@ -48,6 +47,7 @@ static void gen_chain(const xmss_params *params,

/**
* base_w algorithm as described in draft.
* Interprets an array of bytes as integers in base w.
*/
static void base_w(const xmss_params *params,
int *output, const int out_len, const unsigned char *input)
@@ -104,7 +104,7 @@ void wots_sign(const xmss_params *params,

csum = csum << (8 - ((params->wots_len2 * params->wots_log_w) % 8));

to_byte(csum_bytes, csum, ((params->wots_len2 * params->wots_log_w) + 7) / 8);
ull_to_bytes(csum_bytes, csum, ((params->wots_len2 * params->wots_log_w) + 7) / 8);
base_w(params, csum_basew, params->wots_len2, csum_bytes);

for (i = 0; i < params->wots_len2; i++) {
@@ -138,7 +138,7 @@ void wots_pk_from_sig(const xmss_params *params, unsigned char *pk,

csum = csum << (8 - ((params->wots_len2 * params->wots_log_w) % 8));

to_byte(csum_bytes, csum, ((params->wots_len2 * params->wots_log_w) + 7) / 8);
ull_to_bytes(csum_bytes, csum, ((params->wots_len2 * params->wots_log_w) + 7) / 8);
base_w(params, csum_basew, params->wots_len2, csum_bytes);

for (i = 0; i < params->wots_len2; i++) {


+ 10
- 5
wots.h View File

@@ -5,17 +5,20 @@
#include "params.h"

/**
* WOTS key generation. Takes a 32byte seed for the secret key, expands it to a full WOTS secret key and computes the corresponding public key.
* For this it takes the seed pub_seed which is used to generate bitmasks and hash keys and the address of this WOTS key pair addr
* WOTS key generation. Takes a 32 byte seed for the secret key, expands it to
* a full WOTS secret key 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.
*
* Places the computed public key at address pk.
* Writes the computed public key to 'pk'.
*/
void wots_pkgen(const xmss_params *params,
unsigned char *pk, const unsigned char *sk,
const unsigned char *pub_seed, uint32_t addr[8]);

/**
* Takes a m-byte message and the 32-byte seed for the secret key to compute a signature that is placed at "sig".
* Takes a m-byte message and the 32-byte seed for the secret key to compute a
* signature that is placed at 'sig'.
*/
void wots_sign(const xmss_params *params,
unsigned char *sig, const unsigned char *msg,
@@ -23,7 +26,9 @@ void wots_sign(const xmss_params *params,
uint32_t addr[8]);

/**
* Takes a WOTS signature, a m-byte message and computes a WOTS public key that it places at pk.
* Takes a WOTS signature and an m-byte message, computes a WOTS public key.
*
* Writes the computed public key to 'pk'.
*/
void wots_pk_from_sig(const xmss_params *params, unsigned char *pk,
const unsigned char *sig, const unsigned char *msg,


+ 15
- 9
xmss.h View File

@@ -5,13 +5,13 @@

/**
* Generates a XMSS key pair for a given parameter set.
* Format sk: [oid || (32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
* Format pk: [oid || root || PUB_SEED]
* Format sk: [OID || (32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
* Format pk: [OID || root || PUB_SEED]
*/
int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid);

/**
* Signs a message.
* Signs a message using an XMSS secret key.
* Returns
* 1. an array containing the signature followed by the message AND
* 2. an updated secret key!
@@ -21,9 +21,11 @@ int xmss_sign(unsigned char *sk,
const unsigned char *m, unsigned long long mlen);

/**
* Verifies a given message signature pair under a given public key.
* Verifies a given message signature pair using a given public key.
*
* Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg).
* Note: m and mlen are pure outputs which carry the message in case
* verification succeeds. The (input) message is assumed to be contained in sm
* which has the form [signature || message].
*/
int xmss_sign_open(unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
@@ -31,13 +33,13 @@ int xmss_sign_open(unsigned char *m, unsigned long long *mlen,

/*
* Generates a XMSSMT key pair for a given parameter set.
* Format sk: [oid || (ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
* Format pk: [oid || root || PUB_SEED]
* Format sk: [OID || (ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
* Format pk: [OID || root || PUB_SEED]
*/
int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid);

/**
* Signs a message.
* Signs a message using an XMSSMT secret key.
* Returns
* 1. an array containing the signature followed by the message AND
* 2. an updated secret key!
@@ -47,7 +49,11 @@ int xmssmt_sign(unsigned char *sk,
const unsigned char *m, unsigned long long mlen);

/**
* Verifies a given message signature pair under a given public key.
* Verifies a given message signature pair using a given public key.
*
* Note: m and mlen are pure outputs which carry the message in case
* verification succeeds. The (input) message is assumed to be contained in sm
* which has the form [signature || message].
*/
int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,


+ 54
- 38
xmss_commons.c View File

@@ -8,18 +8,23 @@
#include "wots.h"
#include "xmss_commons.h"

void to_byte(unsigned char *out, unsigned long long in, uint32_t bytes)
/**
* Converts the value of 'in' to 'len' bytes in big-endian byte order.
*/
void ull_to_bytes(unsigned char *out, unsigned long long in, uint32_t len)
{
int i;

for (i = bytes-1; i >= 0; i--) {
for (i = len - 1; i >= 0; i--) {
out[i] = in & 0xff;
in = in >> 8;
}
}

/**
* Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address.
* Computes the leaf at a given address. First generates the WOTS key pair,
* then computes leaf using l_tree. As this happens position independent, we
* only require that addr encodes the right ltree-address.
*/
void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
const unsigned char *sk_seed, const unsigned char *pub_seed,
@@ -35,44 +40,50 @@ void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
}

/**
* Used for pseudorandom keygeneration,
* generates the seed for the WOTS keypair at address addr
* Used for pseudo-random key generation.
* Generates the seed for the WOTS key pair at address 'addr'.
*
* takes params->n byte sk_seed and returns params->n byte seed using 32 byte address addr.
* Takes n-byte sk_seed and returns n-byte seed using 32 byte address 'addr'.
*/
void get_seed(const xmss_params *params, unsigned char *seed,
const unsigned char *sk_seed, uint32_t addr[8])
{
unsigned char bytes[32];

// Make sure that chain addr, hash addr, and key bit are 0!
/* Make sure that chain addr, hash addr, and key bit are zeroed. */
set_chain_addr(addr, 0);
set_hash_addr(addr, 0);
set_key_and_mask(addr, 0);
// Generate pseudorandom value
addr_to_byte(bytes, addr);

/* Generate seed. */
addr_to_bytes(bytes, addr);
prf(params, seed, bytes, sk_seed, params->n);
}

/**
* Computes a leaf from a WOTS public key using an L-tree.
* Computes a leaf node from a WOTS public key using an L-tree.
* Note that this destroys the used WOTS public key.
*/
void l_tree(const xmss_params *params, unsigned char *leaf, unsigned char *wots_pk,
void l_tree(const xmss_params *params,
unsigned char *leaf, unsigned char *wots_pk,
const unsigned char *pub_seed, uint32_t addr[8])
{
unsigned int l = params->wots_len;
uint32_t i = 0;
unsigned int parent_nodes;
uint32_t i;
uint32_t height = 0;
uint32_t bound;

set_tree_height(addr, height);

while (l > 1) {
bound = l >> 1;
for (i = 0; i < bound; i++) {
parent_nodes = l >> 1;
for (i = 0; i < parent_nodes; i++) {
set_tree_index(addr, i);
hash_h(params, wots_pk + i*params->n, wots_pk + i*2*params->n, pub_seed, addr);
/* Hashes the nodes at (i*2)*params->n and (i*2)*params->n + 1 */
hash_h(params, wots_pk + i*params->n, wots_pk + (i*2)*params->n, pub_seed, addr);
}
/* If the row contained an odd number of nodes, the last node was not hashed.
Instead, we pull it up to the next layer. */
if (l & 1) {
memcpy(wots_pk + (l >> 1)*params->n, wots_pk + (l - 1)*params->n, params->n);
l = (l >> 1) + 1;
@@ -87,7 +98,7 @@ void l_tree(const xmss_params *params, unsigned char *leaf, unsigned char *wots_
}

/**
* Computes a root node given a leaf and an authapth
* Computes a root node given a leaf and an auth path
*/
static void validate_authpath(const xmss_params *params, unsigned char *root,
const unsigned char *leaf, unsigned long leafidx,
@@ -97,8 +108,8 @@ static void validate_authpath(const xmss_params *params, unsigned char *root,
uint32_t i, j;
unsigned char buffer[2*params->n];

// If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left.
// Otherwise, it is the other way around
/* If leafidx is odd (last bit = 1), current path element is a right child
and authpath has to go left. Otherwise it is the other way around. */
if (leafidx & 1) {
for (j = 0; j < params->n; j++) {
buffer[params->n + j] = leaf[j];
@@ -117,6 +128,7 @@ static void validate_authpath(const xmss_params *params, unsigned char *root,
set_tree_height(addr, i);
leafidx >>= 1;
set_tree_index(addr, leafidx);
/* Pick the right or left neighbor, depending on parity of the node. */
if (leafidx & 1) {
hash_h(params, buffer + params->n, buffer, pub_seed, addr);
for (j = 0; j < params->n; j++) {
@@ -139,6 +151,7 @@ static void validate_authpath(const xmss_params *params, unsigned char *root,

/**
* Verifies a given message signature pair under a given public key.
* Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
*/
int xmss_core_sign_open(const xmss_params *params,
unsigned char *m, unsigned long long *mlen,
@@ -156,7 +169,6 @@ int xmss_core_sign_open(const xmss_params *params,
unsigned char pub_seed[params->n];
memcpy(pub_seed, pk + params->n, params->n);

// Init addresses
uint32_t ots_addr[8] = {0};
uint32_t ltree_addr[8] = {0};
uint32_t node_addr[8] = {0};
@@ -167,34 +179,34 @@ int xmss_core_sign_open(const xmss_params *params,

*mlen = smlen - params->bytes;

// Extract index
/* Convert the index bytes from the signature to an integer. */
for (i = 0; i < params->index_len; i++) {
idx |= ((unsigned long long)sm[i]) << (8*(params->index_len - 1 - i));
}

// Generate hash key (R || root || idx)
/* Prepare the hash key, of the form [R || root || idx]. */
memcpy(hash_key, sm + params->index_len, params->n);
memcpy(hash_key + params->n, pk, params->n);
to_byte(hash_key + 2*params->n, idx, params->n);
ull_to_bytes(hash_key + 2*params->n, idx, params->n);

// hash message
/* Compute the message hash. */
h_msg(params, msg_h, sm + params->bytes, *mlen, hash_key, 3*params->n);
sm += params->index_len + params->n;

// Prepare Address
/* The WOTS public key is only correct if the signature was correct. */
set_ots_addr(ots_addr, idx);
// Check WOTS signature
wots_pk_from_sig(params, wots_pk, sm, msg_h, pub_seed, ots_addr);
sm += params->wots_keysize;

// Compute Ltree
/* Compute the leaf node using the WOTS public key. */
set_ltree_addr(ltree_addr, idx);
l_tree(params, pkhash, wots_pk, pub_seed, ltree_addr);

// Compute root
/* Compute the root node. */
validate_authpath(params, root, pkhash, idx, sm, pub_seed, node_addr);
sm += params->tree_height*params->n;

/* Check if the root node equals the root node in the public key. */
for (i = 0; i < params->n; i++) {
if (root[i] != pk[i]) {
for (i = 0; i < *mlen; i++) {
@@ -205,6 +217,7 @@ int xmss_core_sign_open(const xmss_params *params,
}
}

/* If verification was successful, copy the message from the signature. */
for (i = 0; i < *mlen; i++) {
m[i] = sm[i];
}
@@ -214,6 +227,7 @@ int xmss_core_sign_open(const xmss_params *params,

/**
* Verifies a given message signature pair under a given public key.
* Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
*/
int xmssmt_core_sign_open(const xmss_params *params,
unsigned char *m, unsigned long long *mlen,
@@ -230,7 +244,6 @@ int xmssmt_core_sign_open(const xmss_params *params,
unsigned char hash_key[3*params->n];
const unsigned char *pub_seed = pk + params->n;

// Init addresses
uint32_t ots_addr[8] = {0};
uint32_t ltree_addr[8] = {0};
uint32_t node_addr[8] = {0};
@@ -241,22 +254,22 @@ int xmssmt_core_sign_open(const xmss_params *params,

*mlen = smlen - params->bytes;

// Extract index
/* Convert the index bytes from the signature to an integer. */
for (i = 0; i < params->index_len; i++) {
idx |= ((unsigned long long)sm[i]) << (8*(params->index_len - 1 - i));
}

// Generate hash key (R || root || idx)
/* Prepare the hash key, of the form [R || root || idx]. */
memcpy(hash_key, sm + params->index_len, params->n);
memcpy(hash_key + params->n, pk, params->n);
to_byte(hash_key + 2*params->n, idx, params->n);
ull_to_bytes(hash_key + 2*params->n, idx, params->n);

// hash message
/* Compute the message hash. */
h_msg(params, msg_h, sm + params->bytes, *mlen, hash_key, 3*params->n);
sm += params->index_len + params->n;

/* For each subtree.. */
for (i = 0; i < params->d; i++) {
// Prepare Address
idx_leaf = (idx & ((1 << params->tree_height)-1));
idx = idx >> params->tree_height;

@@ -268,21 +281,23 @@ int xmssmt_core_sign_open(const xmss_params *params,
set_tree_addr(ots_addr, idx);
set_tree_addr(node_addr, idx);

/* The WOTS public key is only correct if the signature was correct. */
set_ots_addr(ots_addr, idx_leaf);
// Check WOTS signature
/* Initially, root = msg_h, but on subsequent iterations it is the root
of the subtree below the currently processed subtree. */
wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr);
sm += params->wots_keysize;

// Compute Ltree
/* Compute the leaf node using the WOTS public key. */
set_ltree_addr(ltree_addr, idx_leaf);
l_tree(params, pkhash, wots_pk, pub_seed, ltree_addr);

// Compute root
/* Compute the root node of this subtree. */
validate_authpath(params, root, pkhash, idx_leaf, sm, pub_seed, node_addr);
sm += params->tree_height*params->n;
}

/* Check if the final root node equals the root node in the public key. */
for (i = 0; i < params->n; i++) {
if (root[i] != pk[i]) {
for (i = 0; i < *mlen; i++) {
@@ -293,6 +308,7 @@ int xmssmt_core_sign_open(const xmss_params *params,
}
}

/* If verification was successful, copy the message from the signature. */
for (i = 0; i < *mlen; i++) {
m[i] = sm[i];
}


+ 29
- 2
xmss_commons.h View File

@@ -4,23 +4,50 @@
#include <stdint.h>
#include "params.h"

void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes);
/**
* Converts the value of 'in' to 'len' bytes in big-endian byte order.
*/
void ull_to_bytes(unsigned char *output, unsigned long long in, uint32_t bytes);

/**
* Computes the leaf at a given address. First generates the WOTS key pair,
* then computes leaf using l_tree. As this happens position independent, we
* only require that addr encodes the right ltree-address.
*/
void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
const unsigned char *sk_seed, const unsigned char *pub_seed,
uint32_t ltree_addr[8], uint32_t ots_addr[8]);

/**
* Used for pseudo-random key generation.
* Generates the seed for the WOTS key pair at address 'addr'.
*
* Takes n-byte sk_seed and returns n-byte seed using 32 byte address 'addr'.
*/
void get_seed(const xmss_params *params, unsigned char *seed,
const unsigned char *sk_seed, uint32_t addr[8]);

void l_tree(const xmss_params *params, unsigned char *leaf, unsigned char *wots_pk,
/**
* Computes a leaf node from a WOTS public key using an L-tree.
* Note that the WOTS public key is destroyed.
*/
void l_tree(const xmss_params *params,
unsigned char *leaf, unsigned char *wots_pk,
const unsigned char *pub_seed, uint32_t addr[8]);

/**
* Verifies a given message signature pair under a given public key.
* Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
*/
int xmss_core_sign_open(const xmss_params *params,
unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk);

/**
* Verifies a given message signature pair under a given public key.
* Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
*/
int xmssmt_core_sign_open(const xmss_params *params,
unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,


+ 19
- 15
xmss_core.c View File

@@ -11,14 +11,14 @@
#include "xmss_core.h"

/**
* Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash.
* Merkle's TreeHash algorithm. The address only needs to initialize the first
* 78 bits of addr. Everything else will be set by treehash.
* Currently only used for key generation.
*
*/
static void treehash(const xmss_params *params, unsigned char *node, uint32_t index, const unsigned char *sk_seed, const unsigned char *pub_seed, const uint32_t addr[8])
{
uint32_t idx = index;
// use three different addresses because at this point we use all three formats in parallel
// Use three different addresses because at this point we use all three formats in parallel
uint32_t ots_addr[8];
uint32_t ltree_addr[8];
uint32_t node_addr[8];
@@ -58,9 +58,12 @@ static void treehash(const xmss_params *params, unsigned char *node, uint32_t in
}

/**
* Computes the authpath and the root. This method is using a lot of space as we build the whole tree and then select the authpath nodes.
* For more efficient algorithms see e.g. the chapter on hash-based signatures in Bernstein, Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009.
* It returns the authpath in "authpath" with the node on level 0 at index 0.
* Computes the authpath and the root. This method is using a lot of space as we
* build the whole tree and then select the authpath nodes. For more efficient
* algorithms see e.g. the chapter on hash-based signatures in Bernstein,
* Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009.
*
* Returns the authpath in "authpath" with the node on level 0 at index 0.
*/
static void compute_authpath_wots(const xmss_params *params, unsigned char *root, unsigned char *authpath, unsigned long leaf_idx, const unsigned char *sk_seed, unsigned char *pub_seed, uint32_t addr[8])
{
@@ -155,7 +158,7 @@ int xmss_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *

// index as 32 bytes string
unsigned char idx_bytes_32[32];
to_byte(idx_bytes_32, idx, 32);
ull_to_bytes(idx_bytes_32, idx, 32);

memcpy(sk_seed, sk+4, params->n);
memcpy(sk_prf, sk+4+params->n, params->n);
@@ -166,8 +169,9 @@ int xmss_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *
sk[1] = ((idx + 1) >> 16) & 255;
sk[2] = ((idx + 1) >> 8) & 255;
sk[3] = (idx + 1) & 255;
// -- Secret key for this non-forward-secure version is now updated.
// -- A productive implementation should use a file handle instead and write the updated secret key at this point!
// Secret key for this non-forward-secure version is now updated.
// A production implementation should consider using a file handle instead,
// and write the updated secret key at this point!

// Init working params
unsigned char R[params->n];
@@ -186,7 +190,7 @@ int xmss_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *
// Generate hash key (R || root || idx)
memcpy(hash_key, R, params->n);
memcpy(hash_key+params->n, sk+4+3*params->n, params->n);
to_byte(hash_key+2*params->n, idx, params->n);
ull_to_bytes(hash_key+2*params->n, idx, params->n);
// Then use it for message digest
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);

@@ -302,9 +306,9 @@ int xmssmt_core_sign(const xmss_params *params, unsigned char *sk, unsigned char
for (i = 0; i < params->index_len; i++) {
sk[i] = ((idx + 1) >> 8*(params->index_len - 1 - i)) & 255;
}
// -- Secret key for this non-forward-secure version is now updated.
// -- A productive implementation should use a file handle instead and write the updated secret key at this point!
// Secret key for this non-forward-secure version is now updated.
// A production implementation should consider using a file handle instead,
// and write the updated secret key at this point!

// ---------------------------------
// Message Hashing
@@ -312,12 +316,12 @@ int xmssmt_core_sign(const xmss_params *params, unsigned char *sk, unsigned char

// Message Hash:
// First compute pseudorandom value
to_byte(idx_bytes_32, idx, 32);
ull_to_bytes(idx_bytes_32, idx, 32);
prf(params, R, idx_bytes_32, sk_prf, params->n);
// Generate hash key (R || root || idx)
memcpy(hash_key, R, params->n);
memcpy(hash_key+params->n, sk+params->index_len+3*params->n, params->n);
to_byte(hash_key+2*params->n, idx, params->n);
ull_to_bytes(hash_key+2*params->n, idx, params->n);

// Then use it for message digest
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);


+ 3
- 2
xmss_core.h View File

@@ -14,13 +14,14 @@ int xmss_core_keypair(const xmss_params *params, unsigned char *pk, unsigned cha
* Returns
* 1. an array containing the signature followed by the message AND
* 2. an updated secret key!
*
*/
int xmss_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen);
/**
* Verifies a given message signature pair under a given public key.
*
* Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg).
* Note: msg and msglen are pure outputs which carry the message in case
* verification succeeds. The (input) message is assumed to be within sig_msg
* which has the form (sig||msg).
*/
int xmss_core_sign_open(const xmss_params *params, unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk);



+ 10
- 9
xmss_core_fast.c View File

@@ -396,7 +396,7 @@ int xmss_core_sign(const xmss_params *params,

// index as 32 bytes string
unsigned char idx_bytes_32[32];
to_byte(idx_bytes_32, idx, 32);
ull_to_bytes(idx_bytes_32, idx, 32);

unsigned char hash_key[3*params->n];

@@ -405,8 +405,9 @@ int xmss_core_sign(const xmss_params *params,
sk[1] = ((idx + 1) >> 16) & 255;
sk[2] = ((idx + 1) >> 8) & 255;
sk[3] = (idx + 1) & 255;
// -- Secret key for this non-forward-secure version is now updated.
// -- A productive implementation should use a file handle instead and write the updated secret key at this point!
// Secret key for this non-forward-secure version is now updated.
// A production implementation should consider using a file handle instead,
// and write the updated secret key at this point!

// Init working params
unsigned char R[params->n];
@@ -424,7 +425,7 @@ int xmss_core_sign(const xmss_params *params,
// Generate hash key (R || root || idx)
memcpy(hash_key, R, params->n);
memcpy(hash_key+params->n, sk+4+3*params->n, params->n);
to_byte(hash_key+2*params->n, idx, params->n);
ull_to_bytes(hash_key+2*params->n, idx, params->n);
// Then use it for message digest
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);

@@ -566,9 +567,9 @@ int xmssmt_core_sign(const xmss_params *params,
for (i = 0; i < params->index_len; i++) {
sk[i] = ((idx + 1) >> 8*(params->index_len - 1 - i)) & 255;
}
// -- Secret key for this non-forward-secure version is now updated.
// -- A productive implementation should use a file handle instead and write the updated secret key at this point!
// Secret key for this non-forward-secure version is now updated.
// A production implementation should consider using a file handle instead,
// and write the updated secret key at this point!

// ---------------------------------
// Message Hashing
@@ -576,12 +577,12 @@ int xmssmt_core_sign(const xmss_params *params,

// Message Hash:
// First compute pseudorandom value
to_byte(idx_bytes_32, idx, 32);
ull_to_bytes(idx_bytes_32, idx, 32);
prf(params, R, idx_bytes_32, sk_prf, params->n);
// Generate hash key (R || root || idx)
memcpy(hash_key, R, params->n);
memcpy(hash_key+params->n, sk+params->index_len+3*params->n, params->n);
to_byte(hash_key+2*params->n, idx, params->n);
ull_to_bytes(hash_key+2*params->n, idx, params->n);

// Then use it for message digest
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);


Loading…
Cancel
Save