Perform various reformatting / renaming
This commit is contained in:
parent
998137622a
commit
305bd614bb
@ -4,9 +4,15 @@
|
|||||||
#define SHAKE128_RATE 168
|
#define SHAKE128_RATE 168
|
||||||
#define SHAKE256_RATE 136
|
#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,
|
void shake128(unsigned char *out, unsigned long long outlen,
|
||||||
const unsigned char *in, unsigned long long inlen);
|
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,
|
void shake256(unsigned char *out, unsigned long long outlen,
|
||||||
const unsigned char *in, unsigned long long inlen);
|
const unsigned char *in, unsigned long long inlen);
|
||||||
|
|
||||||
|
41
hash.c
41
hash.c
@ -5,16 +5,14 @@
|
|||||||
#include "fips202.h"
|
#include "fips202.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
|
||||||
#include <openssl/sha.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;
|
int i;
|
||||||
for (i = 0; i < 8; 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,
|
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 long long i = 0;
|
||||||
unsigned char buf[inlen + n + keylen];
|
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++) {
|
for (i=0; i < keylen; i++) {
|
||||||
buf[i+n] = key[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 buf[2*params->n];
|
||||||
unsigned char key[params->n];
|
unsigned char key[params->n];
|
||||||
unsigned char bitmask[2*params->n];
|
unsigned char bitmask[2*params->n];
|
||||||
unsigned char byte_addr[32];
|
unsigned char addr_as_bytes[32];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Generate the n-byte key. */
|
||||||
set_key_and_mask(addr, 0);
|
set_key_and_mask(addr, 0);
|
||||||
addr_to_byte(byte_addr, addr);
|
addr_to_bytes(addr_as_bytes, addr);
|
||||||
prf(params, key, byte_addr, pub_seed, params->n);
|
prf(params, key, addr_as_bytes, pub_seed, params->n);
|
||||||
|
|
||||||
|
/* Generate the 2n-byte mask. */
|
||||||
set_key_and_mask(addr, 1);
|
set_key_and_mask(addr, 1);
|
||||||
addr_to_byte(byte_addr, addr);
|
addr_to_bytes(addr_as_bytes, addr);
|
||||||
prf(params, bitmask, byte_addr, pub_seed, params->n);
|
prf(params, bitmask, addr_as_bytes, pub_seed, params->n);
|
||||||
|
|
||||||
set_key_and_mask(addr, 2);
|
set_key_and_mask(addr, 2);
|
||||||
addr_to_byte(byte_addr, addr);
|
addr_to_bytes(addr_as_bytes, addr);
|
||||||
prf(params, bitmask+params->n, byte_addr, pub_seed, params->n);
|
prf(params, bitmask + params->n, addr_as_bytes, pub_seed, params->n);
|
||||||
|
|
||||||
for (i = 0; i < 2*params->n; i++) {
|
for (i = 0; i < 2*params->n; i++) {
|
||||||
buf[i] = in[i] ^ bitmask[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 buf[params->n];
|
||||||
unsigned char key[params->n];
|
unsigned char key[params->n];
|
||||||
unsigned char bitmask[params->n];
|
unsigned char bitmask[params->n];
|
||||||
unsigned char byte_addr[32];
|
unsigned char addr_as_bytes[32];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
set_key_and_mask(addr, 0);
|
set_key_and_mask(addr, 0);
|
||||||
addr_to_byte(byte_addr, addr);
|
addr_to_bytes(addr_as_bytes, addr);
|
||||||
prf(params, key, byte_addr, pub_seed, params->n);
|
prf(params, key, addr_as_bytes, pub_seed, params->n);
|
||||||
|
|
||||||
set_key_and_mask(addr, 1);
|
set_key_and_mask(addr, 1);
|
||||||
addr_to_byte(byte_addr, addr);
|
addr_to_bytes(addr_as_bytes, addr);
|
||||||
prf(params, bitmask, byte_addr, pub_seed, params->n);
|
prf(params, bitmask, addr_as_bytes, pub_seed, params->n);
|
||||||
|
|
||||||
for (i = 0; i < params->n; i++) {
|
for (i = 0; i < params->n; i++) {
|
||||||
buf[i] = in[i] ^ bitmask[i];
|
buf[i] = in[i] ^ bitmask[i];
|
||||||
|
2
hash.h
2
hash.h
@ -4,7 +4,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "params.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,
|
int prf(const xmss_params *params,
|
||||||
unsigned char *out, const unsigned char *in,
|
unsigned char *out, const unsigned char *in,
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
#include <stdint.h>
|
#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;
|
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[1] = (uint32_t) (tree >> 32);
|
||||||
addr[2] = (uint32_t) tree;
|
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;
|
int i;
|
||||||
|
|
||||||
addr[3] = type;
|
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;
|
addr[7] = key_and_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These functions are used for OTS addresses. */
|
/* 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;
|
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;
|
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;
|
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;
|
addr[4] = ltree;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These functions are used for hash tree addresses. */
|
/* 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;
|
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;
|
addr[6] = treeIndex;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
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);
|
void set_ltree_addr(uint32_t addr[8], uint32_t ltree);
|
||||||
|
|
||||||
|
26
params.h
26
params.h
@ -3,14 +3,14 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#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_SHA2 0
|
||||||
#define XMSS_SHAKE 1
|
#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
|
#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 {
|
typedef struct {
|
||||||
unsigned int func;
|
unsigned int func;
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
@ -30,10 +30,30 @@ typedef struct {
|
|||||||
unsigned int bds_k;
|
unsigned int bds_k;
|
||||||
} xmss_params;
|
} 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);
|
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);
|
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);
|
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);
|
int xmssmt_parse_oid(xmss_params *params, const uint32_t oid);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#ifndef XMSS_RANDOMBYTES_H
|
#ifndef XMSS_RANDOMBYTES_H
|
||||||
#define 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
|
#endif
|
||||||
|
@ -24,13 +24,13 @@ int main(int argc, char **argv) {
|
|||||||
return -1;
|
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);
|
fread(&oid_pk, 1, XMSS_OID_LEN, keypair);
|
||||||
xmss_parse_oid(¶ms, oid_pk);
|
xmss_parse_oid(¶ms, oid_pk);
|
||||||
|
|
||||||
// fseek past the public key
|
/* fseek past the public key */
|
||||||
fseek(keypair, params.publickey_bytes, SEEK_CUR);
|
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);
|
fread(&oid_sk, 1, XMSS_OID_LEN, keypair);
|
||||||
xmss_parse_oid(¶ms, oid_sk);
|
xmss_parse_oid(¶ms, oid_sk);
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ int main(int argc, char **argv) {
|
|||||||
return -1;
|
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);
|
fread(&oid_pk, 1, XMSS_OID_LEN, keypair);
|
||||||
xmssmt_parse_oid(¶ms, oid_pk);
|
xmssmt_parse_oid(¶ms, oid_pk);
|
||||||
|
|
||||||
// fseek past the public key
|
/* fseek past the public key. */
|
||||||
fseek(keypair, params.publickey_bytes, SEEK_CUR);
|
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);
|
fread(&oid_sk, 1, XMSS_OID_LEN, keypair);
|
||||||
xmssmt_parse_oid(¶ms, oid_sk);
|
xmssmt_parse_oid(¶ms, oid_sk);
|
||||||
|
|
||||||
|
18
wots.c
18
wots.c
@ -6,9 +6,8 @@
|
|||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method for pseudorandom key generation
|
* Helper method for pseudorandom key generation.
|
||||||
* Expands an n-byte array into a len*n byte array
|
* Expands an n-byte array into a len*n byte array using the `prf` function.
|
||||||
* this is done using PRF
|
|
||||||
*/
|
*/
|
||||||
static void expand_seed(const xmss_params *params,
|
static void expand_seed(const xmss_params *params,
|
||||||
unsigned char *outseeds, const unsigned char *inseed)
|
unsigned char *outseeds, const unsigned char *inseed)
|
||||||
@ -17,17 +16,17 @@ static void expand_seed(const xmss_params *params,
|
|||||||
unsigned char ctr[32];
|
unsigned char ctr[32];
|
||||||
|
|
||||||
for (i = 0; i < params->wots_len; i++) {
|
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);
|
prf(params, outseeds + i*params->n, ctr, inseed, params->n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the chaining function.
|
* 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
|
* Interprets in as start-th value of the chain.
|
||||||
* addr has to contain the address of the chain
|
* addr has to contain the address of the chain.
|
||||||
*/
|
*/
|
||||||
static void gen_chain(const xmss_params *params,
|
static void gen_chain(const xmss_params *params,
|
||||||
unsigned char *out, const unsigned char *in,
|
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.
|
* 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,
|
static void base_w(const xmss_params *params,
|
||||||
int *output, const int out_len, const unsigned char *input)
|
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));
|
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);
|
base_w(params, csum_basew, params->wots_len2, csum_bytes);
|
||||||
|
|
||||||
for (i = 0; i < params->wots_len2; i++) {
|
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));
|
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);
|
base_w(params, csum_basew, params->wots_len2, csum_bytes);
|
||||||
|
|
||||||
for (i = 0; i < params->wots_len2; i++) {
|
for (i = 0; i < params->wots_len2; i++) {
|
||||||
|
15
wots.h
15
wots.h
@ -5,17 +5,20 @@
|
|||||||
#include "params.h"
|
#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.
|
* WOTS key generation. Takes a 32 byte seed for the secret key, expands it to
|
||||||
* 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
|
* 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,
|
void wots_pkgen(const xmss_params *params,
|
||||||
unsigned char *pk, const unsigned char *sk,
|
unsigned char *pk, const unsigned char *sk,
|
||||||
const unsigned char *pub_seed, uint32_t addr[8]);
|
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,
|
void wots_sign(const xmss_params *params,
|
||||||
unsigned char *sig, const unsigned char *msg,
|
unsigned char *sig, const unsigned char *msg,
|
||||||
@ -23,7 +26,9 @@ void wots_sign(const xmss_params *params,
|
|||||||
uint32_t addr[8]);
|
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,
|
void wots_pk_from_sig(const xmss_params *params, unsigned char *pk,
|
||||||
const unsigned char *sig, const unsigned char *msg,
|
const unsigned char *sig, const unsigned char *msg,
|
||||||
|
24
xmss.h
24
xmss.h
@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a XMSS key pair for a given parameter set.
|
* Generates a XMSS key pair for a given parameter set.
|
||||||
* Format sk: [oid || (32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
|
* Format sk: [OID || (32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
|
||||||
* Format pk: [oid || root || PUB_SEED]
|
* Format pk: [OID || root || PUB_SEED]
|
||||||
*/
|
*/
|
||||||
int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid);
|
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
|
* Returns
|
||||||
* 1. an array containing the signature followed by the message AND
|
* 1. an array containing the signature followed by the message AND
|
||||||
* 2. an updated secret key!
|
* 2. an updated secret key!
|
||||||
@ -21,9 +21,11 @@ int xmss_sign(unsigned char *sk,
|
|||||||
const unsigned char *m, unsigned long long mlen);
|
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,
|
int xmss_sign_open(unsigned char *m, unsigned long long *mlen,
|
||||||
const unsigned char *sm, unsigned long long smlen,
|
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.
|
* 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 sk: [OID || (ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
|
||||||
* Format pk: [oid || root || PUB_SEED]
|
* Format pk: [OID || root || PUB_SEED]
|
||||||
*/
|
*/
|
||||||
int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid);
|
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
|
* Returns
|
||||||
* 1. an array containing the signature followed by the message AND
|
* 1. an array containing the signature followed by the message AND
|
||||||
* 2. an updated secret key!
|
* 2. an updated secret key!
|
||||||
@ -47,7 +49,11 @@ int xmssmt_sign(unsigned char *sk,
|
|||||||
const unsigned char *m, unsigned long long mlen);
|
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,
|
int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen,
|
||||||
const unsigned char *sm, unsigned long long smlen,
|
const unsigned char *sm, unsigned long long smlen,
|
||||||
|
@ -8,18 +8,23 @@
|
|||||||
#include "wots.h"
|
#include "wots.h"
|
||||||
#include "xmss_commons.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;
|
int i;
|
||||||
|
|
||||||
for (i = bytes-1; i >= 0; i--) {
|
for (i = len - 1; i >= 0; i--) {
|
||||||
out[i] = in & 0xff;
|
out[i] = in & 0xff;
|
||||||
in = in >> 8;
|
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,
|
void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
|
||||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
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,
|
* Used for pseudo-random key generation.
|
||||||
* generates the seed for the WOTS keypair at address addr
|
* 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,
|
void get_seed(const xmss_params *params, unsigned char *seed,
|
||||||
const unsigned char *sk_seed, uint32_t addr[8])
|
const unsigned char *sk_seed, uint32_t addr[8])
|
||||||
{
|
{
|
||||||
unsigned char bytes[32];
|
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_chain_addr(addr, 0);
|
||||||
set_hash_addr(addr, 0);
|
set_hash_addr(addr, 0);
|
||||||
set_key_and_mask(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);
|
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])
|
const unsigned char *pub_seed, uint32_t addr[8])
|
||||||
{
|
{
|
||||||
unsigned int l = params->wots_len;
|
unsigned int l = params->wots_len;
|
||||||
uint32_t i = 0;
|
unsigned int parent_nodes;
|
||||||
|
uint32_t i;
|
||||||
uint32_t height = 0;
|
uint32_t height = 0;
|
||||||
uint32_t bound;
|
|
||||||
|
|
||||||
set_tree_height(addr, height);
|
set_tree_height(addr, height);
|
||||||
|
|
||||||
while (l > 1) {
|
while (l > 1) {
|
||||||
bound = l >> 1;
|
parent_nodes = l >> 1;
|
||||||
for (i = 0; i < bound; i++) {
|
for (i = 0; i < parent_nodes; i++) {
|
||||||
set_tree_index(addr, 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) {
|
if (l & 1) {
|
||||||
memcpy(wots_pk + (l >> 1)*params->n, wots_pk + (l - 1)*params->n, params->n);
|
memcpy(wots_pk + (l >> 1)*params->n, wots_pk + (l - 1)*params->n, params->n);
|
||||||
l = (l >> 1) + 1;
|
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,
|
static void validate_authpath(const xmss_params *params, unsigned char *root,
|
||||||
const unsigned char *leaf, unsigned long leafidx,
|
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;
|
uint32_t i, j;
|
||||||
unsigned char buffer[2*params->n];
|
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.
|
/* If leafidx is odd (last bit = 1), current path element is a right child
|
||||||
// Otherwise, it is the other way around
|
and authpath has to go left. Otherwise it is the other way around. */
|
||||||
if (leafidx & 1) {
|
if (leafidx & 1) {
|
||||||
for (j = 0; j < params->n; j++) {
|
for (j = 0; j < params->n; j++) {
|
||||||
buffer[params->n + j] = leaf[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);
|
set_tree_height(addr, i);
|
||||||
leafidx >>= 1;
|
leafidx >>= 1;
|
||||||
set_tree_index(addr, leafidx);
|
set_tree_index(addr, leafidx);
|
||||||
|
/* Pick the right or left neighbor, depending on parity of the node. */
|
||||||
if (leafidx & 1) {
|
if (leafidx & 1) {
|
||||||
hash_h(params, buffer + params->n, buffer, pub_seed, addr);
|
hash_h(params, buffer + params->n, buffer, pub_seed, addr);
|
||||||
for (j = 0; j < params->n; j++) {
|
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.
|
* 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,
|
int xmss_core_sign_open(const xmss_params *params,
|
||||||
unsigned char *m, unsigned long long *mlen,
|
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];
|
unsigned char pub_seed[params->n];
|
||||||
memcpy(pub_seed, pk + params->n, params->n);
|
memcpy(pub_seed, pk + params->n, params->n);
|
||||||
|
|
||||||
// Init addresses
|
|
||||||
uint32_t ots_addr[8] = {0};
|
uint32_t ots_addr[8] = {0};
|
||||||
uint32_t ltree_addr[8] = {0};
|
uint32_t ltree_addr[8] = {0};
|
||||||
uint32_t node_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;
|
*mlen = smlen - params->bytes;
|
||||||
|
|
||||||
// Extract index
|
/* Convert the index bytes from the signature to an integer. */
|
||||||
for (i = 0; i < params->index_len; i++) {
|
for (i = 0; i < params->index_len; i++) {
|
||||||
idx |= ((unsigned long long)sm[i]) << (8*(params->index_len - 1 - 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, sm + params->index_len, params->n);
|
||||||
memcpy(hash_key + params->n, pk, 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);
|
h_msg(params, msg_h, sm + params->bytes, *mlen, hash_key, 3*params->n);
|
||||||
sm += params->index_len + 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);
|
set_ots_addr(ots_addr, idx);
|
||||||
// Check WOTS signature
|
|
||||||
wots_pk_from_sig(params, wots_pk, sm, msg_h, pub_seed, ots_addr);
|
wots_pk_from_sig(params, wots_pk, sm, msg_h, pub_seed, ots_addr);
|
||||||
sm += params->wots_keysize;
|
sm += params->wots_keysize;
|
||||||
|
|
||||||
// Compute Ltree
|
/* Compute the leaf node using the WOTS public key. */
|
||||||
set_ltree_addr(ltree_addr, idx);
|
set_ltree_addr(ltree_addr, idx);
|
||||||
l_tree(params, pkhash, wots_pk, pub_seed, ltree_addr);
|
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);
|
validate_authpath(params, root, pkhash, idx, sm, pub_seed, node_addr);
|
||||||
sm += params->tree_height*params->n;
|
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++) {
|
for (i = 0; i < params->n; i++) {
|
||||||
if (root[i] != pk[i]) {
|
if (root[i] != pk[i]) {
|
||||||
for (i = 0; i < *mlen; 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++) {
|
for (i = 0; i < *mlen; i++) {
|
||||||
m[i] = sm[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.
|
* 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,
|
int xmssmt_core_sign_open(const xmss_params *params,
|
||||||
unsigned char *m, unsigned long long *mlen,
|
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];
|
unsigned char hash_key[3*params->n];
|
||||||
const unsigned char *pub_seed = pk + params->n;
|
const unsigned char *pub_seed = pk + params->n;
|
||||||
|
|
||||||
// Init addresses
|
|
||||||
uint32_t ots_addr[8] = {0};
|
uint32_t ots_addr[8] = {0};
|
||||||
uint32_t ltree_addr[8] = {0};
|
uint32_t ltree_addr[8] = {0};
|
||||||
uint32_t node_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;
|
*mlen = smlen - params->bytes;
|
||||||
|
|
||||||
// Extract index
|
/* Convert the index bytes from the signature to an integer. */
|
||||||
for (i = 0; i < params->index_len; i++) {
|
for (i = 0; i < params->index_len; i++) {
|
||||||
idx |= ((unsigned long long)sm[i]) << (8*(params->index_len - 1 - 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, sm + params->index_len, params->n);
|
||||||
memcpy(hash_key + params->n, pk, 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);
|
h_msg(params, msg_h, sm + params->bytes, *mlen, hash_key, 3*params->n);
|
||||||
sm += params->index_len + params->n;
|
sm += params->index_len + params->n;
|
||||||
|
|
||||||
|
/* For each subtree.. */
|
||||||
for (i = 0; i < params->d; i++) {
|
for (i = 0; i < params->d; i++) {
|
||||||
// Prepare Address
|
|
||||||
idx_leaf = (idx & ((1 << params->tree_height)-1));
|
idx_leaf = (idx & ((1 << params->tree_height)-1));
|
||||||
idx = idx >> params->tree_height;
|
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(ots_addr, idx);
|
||||||
set_tree_addr(node_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);
|
set_ots_addr(ots_addr, idx_leaf);
|
||||||
|
/* Initially, root = msg_h, but on subsequent iterations it is the root
|
||||||
// Check WOTS signature
|
of the subtree below the currently processed subtree. */
|
||||||
wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr);
|
wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr);
|
||||||
sm += params->wots_keysize;
|
sm += params->wots_keysize;
|
||||||
|
|
||||||
// Compute Ltree
|
/* Compute the leaf node using the WOTS public key. */
|
||||||
set_ltree_addr(ltree_addr, idx_leaf);
|
set_ltree_addr(ltree_addr, idx_leaf);
|
||||||
l_tree(params, pkhash, wots_pk, pub_seed, ltree_addr);
|
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);
|
validate_authpath(params, root, pkhash, idx_leaf, sm, pub_seed, node_addr);
|
||||||
sm += params->tree_height*params->n;
|
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++) {
|
for (i = 0; i < params->n; i++) {
|
||||||
if (root[i] != pk[i]) {
|
if (root[i] != pk[i]) {
|
||||||
for (i = 0; i < *mlen; 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++) {
|
for (i = 0; i < *mlen; i++) {
|
||||||
m[i] = sm[i];
|
m[i] = sm[i];
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,50 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "params.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,
|
void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
|
||||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||||
uint32_t ltree_addr[8], uint32_t ots_addr[8]);
|
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,
|
void get_seed(const xmss_params *params, unsigned char *seed,
|
||||||
const unsigned char *sk_seed, uint32_t addr[8]);
|
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]);
|
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,
|
int xmss_core_sign_open(const xmss_params *params,
|
||||||
unsigned char *m, unsigned long long *mlen,
|
unsigned char *m, unsigned long long *mlen,
|
||||||
const unsigned char *sm, unsigned long long smlen,
|
const unsigned char *sm, unsigned long long smlen,
|
||||||
const unsigned char *pk);
|
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,
|
int xmssmt_core_sign_open(const xmss_params *params,
|
||||||
unsigned char *m, unsigned long long *mlen,
|
unsigned char *m, unsigned long long *mlen,
|
||||||
const unsigned char *sm, unsigned long long smlen,
|
const unsigned char *sm, unsigned long long smlen,
|
||||||
|
34
xmss_core.c
34
xmss_core.c
@ -11,14 +11,14 @@
|
|||||||
#include "xmss_core.h"
|
#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.
|
* 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])
|
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;
|
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 ots_addr[8];
|
||||||
uint32_t ltree_addr[8];
|
uint32_t ltree_addr[8];
|
||||||
uint32_t node_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.
|
* Computes the authpath and the root. This method is using a lot of space as we
|
||||||
* For more efficient algorithms see e.g. the chapter on hash-based signatures in Bernstein, Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009.
|
* build the whole tree and then select the authpath nodes. For more efficient
|
||||||
* It returns the authpath in "authpath" with the node on level 0 at index 0.
|
* 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])
|
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
|
// index as 32 bytes string
|
||||||
unsigned char idx_bytes_32[32];
|
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_seed, sk+4, params->n);
|
||||||
memcpy(sk_prf, sk+4+params->n, 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[1] = ((idx + 1) >> 16) & 255;
|
||||||
sk[2] = ((idx + 1) >> 8) & 255;
|
sk[2] = ((idx + 1) >> 8) & 255;
|
||||||
sk[3] = (idx + 1) & 255;
|
sk[3] = (idx + 1) & 255;
|
||||||
// -- Secret key for this non-forward-secure version is now updated.
|
// 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!
|
// A production implementation should consider using a file handle instead,
|
||||||
|
// and write the updated secret key at this point!
|
||||||
|
|
||||||
// Init working params
|
// Init working params
|
||||||
unsigned char R[params->n];
|
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)
|
// Generate hash key (R || root || idx)
|
||||||
memcpy(hash_key, R, params->n);
|
memcpy(hash_key, R, params->n);
|
||||||
memcpy(hash_key+params->n, sk+4+3*params->n, 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
|
// Then use it for message digest
|
||||||
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
|
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++) {
|
for (i = 0; i < params->index_len; i++) {
|
||||||
sk[i] = ((idx + 1) >> 8*(params->index_len - 1 - i)) & 255;
|
sk[i] = ((idx + 1) >> 8*(params->index_len - 1 - i)) & 255;
|
||||||
}
|
}
|
||||||
// -- Secret key for this non-forward-secure version is now updated.
|
// 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!
|
// A production implementation should consider using a file handle instead,
|
||||||
|
// and write the updated secret key at this point!
|
||||||
|
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
// Message Hashing
|
// Message Hashing
|
||||||
@ -312,12 +316,12 @@ int xmssmt_core_sign(const xmss_params *params, unsigned char *sk, unsigned char
|
|||||||
|
|
||||||
// Message Hash:
|
// Message Hash:
|
||||||
// First compute pseudorandom value
|
// 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);
|
prf(params, R, idx_bytes_32, sk_prf, params->n);
|
||||||
// Generate hash key (R || root || idx)
|
// Generate hash key (R || root || idx)
|
||||||
memcpy(hash_key, R, params->n);
|
memcpy(hash_key, R, params->n);
|
||||||
memcpy(hash_key+params->n, sk+params->index_len+3*params->n, 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
|
// Then use it for message digest
|
||||||
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
|
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
|
||||||
|
@ -14,13 +14,14 @@ int xmss_core_keypair(const xmss_params *params, unsigned char *pk, unsigned cha
|
|||||||
* Returns
|
* Returns
|
||||||
* 1. an array containing the signature followed by the message AND
|
* 1. an array containing the signature followed by the message AND
|
||||||
* 2. an updated secret key!
|
* 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);
|
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.
|
* 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);
|
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);
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ int xmss_core_sign(const xmss_params *params,
|
|||||||
|
|
||||||
// index as 32 bytes string
|
// index as 32 bytes string
|
||||||
unsigned char idx_bytes_32[32];
|
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];
|
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[1] = ((idx + 1) >> 16) & 255;
|
||||||
sk[2] = ((idx + 1) >> 8) & 255;
|
sk[2] = ((idx + 1) >> 8) & 255;
|
||||||
sk[3] = (idx + 1) & 255;
|
sk[3] = (idx + 1) & 255;
|
||||||
// -- Secret key for this non-forward-secure version is now updated.
|
// 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!
|
// A production implementation should consider using a file handle instead,
|
||||||
|
// and write the updated secret key at this point!
|
||||||
|
|
||||||
// Init working params
|
// Init working params
|
||||||
unsigned char R[params->n];
|
unsigned char R[params->n];
|
||||||
@ -424,7 +425,7 @@ int xmss_core_sign(const xmss_params *params,
|
|||||||
// Generate hash key (R || root || idx)
|
// Generate hash key (R || root || idx)
|
||||||
memcpy(hash_key, R, params->n);
|
memcpy(hash_key, R, params->n);
|
||||||
memcpy(hash_key+params->n, sk+4+3*params->n, 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
|
// Then use it for message digest
|
||||||
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
|
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++) {
|
for (i = 0; i < params->index_len; i++) {
|
||||||
sk[i] = ((idx + 1) >> 8*(params->index_len - 1 - i)) & 255;
|
sk[i] = ((idx + 1) >> 8*(params->index_len - 1 - i)) & 255;
|
||||||
}
|
}
|
||||||
// -- Secret key for this non-forward-secure version is now updated.
|
// 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!
|
// A production implementation should consider using a file handle instead,
|
||||||
|
// and write the updated secret key at this point!
|
||||||
|
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
// Message Hashing
|
// Message Hashing
|
||||||
@ -576,12 +577,12 @@ int xmssmt_core_sign(const xmss_params *params,
|
|||||||
|
|
||||||
// Message Hash:
|
// Message Hash:
|
||||||
// First compute pseudorandom value
|
// 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);
|
prf(params, R, idx_bytes_32, sk_prf, params->n);
|
||||||
// Generate hash key (R || root || idx)
|
// Generate hash key (R || root || idx)
|
||||||
memcpy(hash_key, R, params->n);
|
memcpy(hash_key, R, params->n);
|
||||||
memcpy(hash_key+params->n, sk+params->index_len+3*params->n, 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
|
// Then use it for message digest
|
||||||
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
|
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
|
||||||
|
Loading…
Reference in New Issue
Block a user