Ver código fonte

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.
master
Joost Rijneveld 7 anos atrás
pai
commit
384b228c58
Nenhuma chave conhecida encontrada para esta assinatura no banco de dados ID da chave GPG: A4FE39CF49CBC553
9 arquivos alterados com 108 adições e 72 exclusões
  1. +45
    -15
      hash.c
  2. +5
    -0
      hash.h
  3. +11
    -3
      test/xmss.c
  4. +6
    -2
      ui/open.c
  5. +8
    -2
      ui/sign.c
  6. +5
    -20
      xmss_commons.c
  7. +0
    -8
      xmss_commons.h
  8. +9
    -7
      xmss_core.c
  9. +19
    -15
      xmss_core_fast.c

+ 45
- 15
hash.c Ver arquivo

@@ -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
- 0
hash.h Ver arquivo

@@ -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

+ 11
- 3
test/xmss.c Ver arquivo

@@ -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;
}

+ 6
- 2
ui/open.c Ver arquivo

@@ -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(&params, 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;
}

+ 8
- 2
ui/sign.c Ver arquivo

@@ -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(&params, 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;
}

+ 5
- 20
xmss_commons.c Ver arquivo

@@ -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.. */


+ 0
- 8
xmss_commons.h Ver arquivo

@@ -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]


+ 9
- 7
xmss_core.c Ver arquivo

@@ -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;
}

+ 19
- 15
xmss_core_fast.c Ver arquivo

@@ -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;


Carregando…
Cancelar
Salvar