@@ -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); | ||||
@@ -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); | |||||
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); | 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); | 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++) { | 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); | |||||
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); | 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++) { | for (i = 0; i < params->n; i++) { | ||||
buf[i] = in[i] ^ bitmask[i]; | buf[i] = in[i] ^ bitmask[i]; | ||||
@@ -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); | ||||
@@ -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); | ||||
@@ -6,9 +6,8 @@ | |||||
#include "params.h" | #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, | 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 | |||||
* 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, | 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++) { | ||||
@@ -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. | |||||
* 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, | 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, | ||||
@@ -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 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); | 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 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); | 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, | |||||
* 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, | 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; | |||||
for (i = 0; i < bound; i++) { | |||||
parent_nodes = l >> 1; | |||||
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. | |||||
// 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) { | 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); | ||||
// 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); | 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, | ||||
@@ -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. | |||||
* 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]) | 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. | |||||
// -- 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 | // 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. | |||||
// -- 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 | // 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. | |||||
// -- 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 | // 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. | |||||
// -- 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 | // 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); | ||||