Support messages that exceed the stack size
Previous code allocated an array on the stack of mlen bytes, but it should be possible to also sign heap-space messages. By relying on the fact that sm and m fit the message + signature, we move the message so that 4*n bytes of prefix can be added.
This commit is contained in:
parent
f5d53b252e
commit
384b228c58
60
hash.c
60
hash.c
@ -1,12 +1,13 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "hash_address.h"
|
||||
#include "xmss_commons.h"
|
||||
#include "params.h"
|
||||
#include "hash.h"
|
||||
#include "fips202.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8])
|
||||
{
|
||||
int i;
|
||||
@ -20,22 +21,13 @@ static int core_hash(const xmss_params *params,
|
||||
const unsigned char *key, unsigned int keylen,
|
||||
const unsigned char *in, unsigned long long inlen, int n)
|
||||
{
|
||||
unsigned long long i = 0;
|
||||
unsigned char buf[inlen + n + keylen];
|
||||
|
||||
/* We arrange the input into the hash function to be of the form:
|
||||
* toByte(X, 32) || KEY || M
|
||||
*/
|
||||
|
||||
* toByte(X, 32) || KEY || M */
|
||||
ull_to_bytes(buf, n, type);
|
||||
|
||||
for (i=0; i < keylen; i++) {
|
||||
buf[i+n] = key[i];
|
||||
}
|
||||
|
||||
for (i=0; i < inlen; i++) {
|
||||
buf[keylen + n + i] = in[i];
|
||||
}
|
||||
memcpy(buf + n, key, keylen);
|
||||
memcpy(buf + keylen + n, in, inlen);
|
||||
|
||||
if (n == 32 && params->func == XMSS_SHA2) {
|
||||
SHA256(buf, inlen + keylen + n, out);
|
||||
@ -70,6 +62,44 @@ int h_msg(const xmss_params *params,
|
||||
return core_hash(params, out, 2, key, keylen, in, inlen, params->n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes the message hash using R, the public root, the index of the leaf
|
||||
* node, and the message. Notably, it requires m_with_prefix to have 4*n bytes
|
||||
* of space before the message, to use for the prefix. This is necessary to
|
||||
* prevent having to move the message around (and thus allocate memory for it).
|
||||
*/
|
||||
int hash_message(const xmss_params *params, unsigned char *out,
|
||||
const unsigned char *R, const unsigned char *root,
|
||||
unsigned long long idx,
|
||||
unsigned char *m_with_prefix, unsigned long long mlen)
|
||||
{
|
||||
/* We're creating a hash using input of the form:
|
||||
toByte(X, 32) || R || root || index || M */
|
||||
ull_to_bytes(m_with_prefix, params->n, 2);
|
||||
memcpy(m_with_prefix + params->n, R, params->n);
|
||||
memcpy(m_with_prefix + 2 * params->n, root, params->n);
|
||||
ull_to_bytes(m_with_prefix + 3 * params->n, params->n, idx);
|
||||
|
||||
/* Since the message can be bigger than the stack, this cannot use the
|
||||
* core_hash function. */
|
||||
if (params->n == 32 && params->func == XMSS_SHA2) {
|
||||
SHA256(m_with_prefix, mlen + 4*params->n, out);
|
||||
}
|
||||
else if (params->n == 32 && params->func == XMSS_SHAKE) {
|
||||
shake128(out, 32, m_with_prefix, mlen + 4*params->n);
|
||||
}
|
||||
else if (params->n == 64 && params->func == XMSS_SHA2) {
|
||||
SHA512(m_with_prefix, mlen + 4*params->n, out);
|
||||
}
|
||||
else if (params->n == 64 && params->func == XMSS_SHAKE) {
|
||||
shake256(out, 64, m_with_prefix, mlen + 4*params->n);
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* We assume the left half is in in[0]...in[n-1]
|
||||
*/
|
||||
|
5
hash.h
5
hash.h
@ -23,4 +23,9 @@ int hash_f(const xmss_params *params,
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8]);
|
||||
|
||||
int hash_message(const xmss_params *params, unsigned char *out,
|
||||
const unsigned char *R, const unsigned char *root,
|
||||
unsigned long long idx,
|
||||
unsigned char *m_with_prefix, unsigned long long mlen);
|
||||
|
||||
#endif
|
||||
|
14
test/xmss.c
14
test/xmss.c
@ -1,9 +1,11 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../xmss.h"
|
||||
#include "../params.h"
|
||||
#include "../randombytes.h"
|
||||
|
||||
#define MLEN 32
|
||||
#define SIGNATURES 16
|
||||
@ -33,12 +35,14 @@ int main()
|
||||
|
||||
unsigned char pk[XMSS_OID_LEN + params.pk_bytes];
|
||||
unsigned char sk[XMSS_OID_LEN + params.sk_bytes];
|
||||
unsigned char m[MLEN];
|
||||
unsigned char sm[params.sig_bytes + MLEN];
|
||||
unsigned char mout[params.sig_bytes + MLEN];
|
||||
unsigned char *m = malloc(MLEN);
|
||||
unsigned char *sm = malloc(params.sig_bytes + MLEN);
|
||||
unsigned char *mout = malloc(params.sig_bytes + MLEN);
|
||||
unsigned long long smlen;
|
||||
unsigned long long mlen;
|
||||
|
||||
randombytes(m, MLEN);
|
||||
|
||||
XMSS_KEYPAIR(pk, sk, oid);
|
||||
|
||||
printf("Testing %d %s signatures.. \n", SIGNATURES, XMSS_VARIANT);
|
||||
@ -106,5 +110,9 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
free(m);
|
||||
free(sm);
|
||||
free(mout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../params.h"
|
||||
#include "../xmss.h"
|
||||
@ -49,8 +50,8 @@ int main(int argc, char **argv) {
|
||||
XMSS_PARSE_OID(¶ms, oid);
|
||||
|
||||
unsigned char pk[XMSS_OID_LEN + params.pk_bytes];
|
||||
unsigned char sm[smlen];
|
||||
unsigned char m[smlen];
|
||||
unsigned char *sm = malloc(smlen);
|
||||
unsigned char *m = malloc(smlen);
|
||||
unsigned long long mlen;
|
||||
|
||||
fseek(keypair_file, 0, SEEK_SET);
|
||||
@ -70,5 +71,8 @@ int main(int argc, char **argv) {
|
||||
fclose(keypair_file);
|
||||
fclose(sm_file);
|
||||
|
||||
free(m);
|
||||
free(sm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
10
ui/sign.c
10
ui/sign.c
@ -1,4 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../params.h"
|
||||
#include "../xmss.h"
|
||||
@ -56,8 +57,8 @@ int main(int argc, char **argv) {
|
||||
XMSS_PARSE_OID(¶ms, oid_sk);
|
||||
|
||||
unsigned char sk[XMSS_OID_LEN + params.sk_bytes];
|
||||
unsigned char m[mlen];
|
||||
unsigned char sm[params.sig_bytes + mlen];
|
||||
unsigned char *m = malloc(mlen);
|
||||
unsigned char *sm = malloc(params.sig_bytes + mlen);
|
||||
unsigned long long smlen;
|
||||
|
||||
/* fseek back to start of sk. */
|
||||
@ -74,4 +75,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
fclose(keypair_file);
|
||||
fclose(m_file);
|
||||
|
||||
free(m);
|
||||
free(sm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -115,25 +115,6 @@ void l_tree(const xmss_params *params,
|
||||
memcpy(leaf, wots_pk, params->n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the randomized message hash.
|
||||
*/
|
||||
void hash_message(const xmss_params *params, unsigned char *mhash,
|
||||
const unsigned char *R, const unsigned char *root,
|
||||
unsigned long long idx,
|
||||
const unsigned char *m, unsigned long long mlen)
|
||||
{
|
||||
unsigned char hash_key[3*params->n];
|
||||
|
||||
/* Compute hash key. */
|
||||
memcpy(hash_key, R, params->n);
|
||||
memcpy(hash_key + params->n, root, params->n);
|
||||
ull_to_bytes(hash_key + 2*params->n, params->n, idx);
|
||||
|
||||
/* Hash the message using the randomized hash key. */
|
||||
h_msg(params, mhash, m, mlen, hash_key, 3*params->n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a root node given a leaf and an auth path
|
||||
*/
|
||||
@ -228,9 +209,13 @@ int xmssmt_core_sign_open(const xmss_params *params,
|
||||
/* Convert the index bytes from the signature to an integer. */
|
||||
idx = bytes_to_ull(sm, params->index_bytes);
|
||||
|
||||
/* Put the message all the way at the end of the m buffer, so that we can
|
||||
* prepend the required other inputs for the hash function. */
|
||||
memcpy(m + params->sig_bytes, sm + params->sig_bytes, *mlen);
|
||||
|
||||
/* Compute the message hash. */
|
||||
hash_message(params, mhash, sm + params->index_bytes, pk, idx,
|
||||
sm + params->sig_bytes, *mlen);
|
||||
m + params->sig_bytes - 4*params->n, *mlen);
|
||||
sm += params->index_bytes + params->n;
|
||||
|
||||
/* For each subtree.. */
|
||||
|
@ -41,14 +41,6 @@ void l_tree(const xmss_params *params,
|
||||
unsigned char *leaf, unsigned char *wots_pk,
|
||||
const unsigned char *pub_seed, uint32_t addr[8]);
|
||||
|
||||
/**
|
||||
* Computes the randomized message hash.
|
||||
*/
|
||||
void hash_message(const xmss_params *params, unsigned char *mhash,
|
||||
const unsigned char *R, const unsigned char *root,
|
||||
unsigned long long idx,
|
||||
const unsigned char *m, unsigned long long mlen);
|
||||
|
||||
/**
|
||||
* 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]
|
||||
|
16
xmss_core.c
16
xmss_core.c
@ -189,10 +189,14 @@ int xmssmt_core_sign(const xmss_params *params,
|
||||
uint32_t ots_addr[8] = {0};
|
||||
set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
|
||||
|
||||
/* Already put the message in the right place, to make it easier to prepend
|
||||
* things when computing the hash over the message. */
|
||||
memcpy(sm + params->sig_bytes, m, mlen);
|
||||
*smlen = params->sig_bytes + mlen;
|
||||
|
||||
/* Read and use the current index from the secret key. */
|
||||
idx = (unsigned long)bytes_to_ull(sk, params->index_bytes);
|
||||
memcpy(sm, sk, params->index_bytes);
|
||||
sm += params->index_bytes;
|
||||
|
||||
/*************************************************************************
|
||||
* THIS IS WHERE PRODUCTION IMPLEMENTATIONS WOULD UPDATE THE SECRET KEY. *
|
||||
@ -202,11 +206,12 @@ int xmssmt_core_sign(const xmss_params *params,
|
||||
|
||||
/* Compute the digest randomization value. */
|
||||
ull_to_bytes(idx_bytes_32, 32, idx);
|
||||
prf(params, sm, idx_bytes_32, sk_prf, params->n);
|
||||
prf(params, sm + params->index_bytes, idx_bytes_32, sk_prf, params->n);
|
||||
|
||||
/* Compute the message hash. */
|
||||
hash_message(params, mhash, sm, pub_root, idx, m, mlen);
|
||||
sm += params->n;
|
||||
hash_message(params, mhash, sm + params->index_bytes, pub_root, idx,
|
||||
sm + params->sig_bytes - 4*params->n, mlen);
|
||||
sm += params->index_bytes + params->n;
|
||||
|
||||
set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
|
||||
|
||||
@ -232,8 +237,5 @@ int xmssmt_core_sign(const xmss_params *params,
|
||||
sm += params->tree_height*params->n;
|
||||
}
|
||||
|
||||
memcpy(sm, m, mlen);
|
||||
*smlen = params->sig_bytes + mlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -393,6 +393,8 @@ int xmss_core_sign(const xmss_params *params,
|
||||
unsigned char *sm, unsigned long long *smlen,
|
||||
const unsigned char *m, unsigned long long mlen)
|
||||
{
|
||||
const unsigned char *pub_root = sk + params->index_bytes + 3*params->n;
|
||||
|
||||
uint16_t i = 0;
|
||||
|
||||
// Extract SK
|
||||
@ -408,8 +410,6 @@ int xmss_core_sign(const xmss_params *params,
|
||||
unsigned char idx_bytes_32[32];
|
||||
ull_to_bytes(idx_bytes_32, 32, idx);
|
||||
|
||||
unsigned char hash_key[3*params->n];
|
||||
|
||||
// Update SK
|
||||
sk[0] = ((idx + 1) >> 24) & 255;
|
||||
sk[1] = ((idx + 1) >> 16) & 255;
|
||||
@ -432,12 +432,14 @@ int xmss_core_sign(const xmss_params *params,
|
||||
// Message Hash:
|
||||
// First compute pseudorandom value
|
||||
prf(params, R, idx_bytes_32, sk_prf, params->n);
|
||||
// Generate hash key (R || root || idx)
|
||||
memcpy(hash_key, R, params->n);
|
||||
memcpy(hash_key+params->n, sk+4+3*params->n, params->n);
|
||||
ull_to_bytes(hash_key+2*params->n, params->n, idx);
|
||||
// Then use it for message digest
|
||||
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
|
||||
|
||||
/* Already put the message in the right place, to make it easier to prepend
|
||||
* things when computing the hash over the message. */
|
||||
memcpy(sm + params->sig_bytes, m, mlen);
|
||||
|
||||
/* Compute the message hash. */
|
||||
hash_message(params, msg_h, R, pub_root, idx,
|
||||
sm + params->sig_bytes - 4*params->n, mlen);
|
||||
|
||||
// Start collecting signature
|
||||
*smlen = 0;
|
||||
@ -554,6 +556,8 @@ int xmssmt_core_sign(const xmss_params *params,
|
||||
unsigned char *sm, unsigned long long *smlen,
|
||||
const unsigned char *m, unsigned long long mlen)
|
||||
{
|
||||
const unsigned char *pub_root = sk + params->index_bytes + 3*params->n;
|
||||
|
||||
uint64_t idx_tree;
|
||||
uint32_t idx_leaf;
|
||||
uint64_t i, j;
|
||||
@ -566,7 +570,6 @@ int xmssmt_core_sign(const xmss_params *params,
|
||||
// Init working params
|
||||
unsigned char R[params->n];
|
||||
unsigned char msg_h[params->n];
|
||||
unsigned char hash_key[3*params->n];
|
||||
unsigned char ots_seed[params->n];
|
||||
uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
@ -599,13 +602,14 @@ int xmssmt_core_sign(const xmss_params *params,
|
||||
// First compute pseudorandom value
|
||||
ull_to_bytes(idx_bytes_32, 32, idx);
|
||||
prf(params, R, idx_bytes_32, sk_prf, params->n);
|
||||
// Generate hash key (R || root || idx)
|
||||
memcpy(hash_key, R, params->n);
|
||||
memcpy(hash_key+params->n, sk+params->index_bytes+3*params->n, params->n);
|
||||
ull_to_bytes(hash_key+2*params->n, params->n, idx);
|
||||
|
||||
// Then use it for message digest
|
||||
h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
|
||||
/* Already put the message in the right place, to make it easier to prepend
|
||||
* things when computing the hash over the message. */
|
||||
memcpy(sm + params->sig_bytes, m, mlen);
|
||||
|
||||
/* Compute the message hash. */
|
||||
hash_message(params, msg_h, R, pub_root, idx,
|
||||
sm + params->sig_bytes - 4*params->n, mlen);
|
||||
|
||||
// Start collecting signature
|
||||
*smlen = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user