From 7793c40c07483dd3efed0a27a85922ed5c7f0cee Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 14 Apr 2020 15:18:01 -0400 Subject: [PATCH] Separate definition of padding length The reference implemention of XMSS currently assumes that n bytes of padding is used for the prefix in the functions prf, hash_message, thash_h, and thash_f. While this is the case for all of the parameter sets in RFC 8391, the draft version of NIST Special Publication 800-208 specifies paramter sets in which the amount of padding is different than n. This commit allows for the padding length for a parameter set to be specified separately from n. --- hash.c | 40 ++++++++++++++++++++-------------------- params.c | 4 ++++ params.h | 1 + 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/hash.c b/hash.c index ec804ac..7b49f6a 100644 --- a/hash.c +++ b/hash.c @@ -50,13 +50,13 @@ int prf(const xmss_params *params, unsigned char *out, const unsigned char in[32], const unsigned char *key) { - unsigned char buf[2*params->n + 32]; + unsigned char buf[params->padding_len + params->n + 32]; - ull_to_bytes(buf, params->n, XMSS_HASH_PADDING_PRF); - memcpy(buf + params->n, key, params->n); - memcpy(buf + 2*params->n, in, 32); + ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF); + memcpy(buf + params->padding_len, key, params->n); + memcpy(buf + params->padding_len + params->n, in, 32); - return core_hash(params, out, buf, 2*params->n + 32); + return core_hash(params, out, buf, params->padding_len + params->n + 32); } /* @@ -72,12 +72,12 @@ int hash_message(const xmss_params *params, unsigned char *out, { /* 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, XMSS_HASH_PADDING_HASH); - 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); + ull_to_bytes(m_with_prefix, params->padding_len, XMSS_HASH_PADDING_HASH); + memcpy(m_with_prefix + params->padding_len, R, params->n); + memcpy(m_with_prefix + params->padding_len + params->n, root, params->n); + ull_to_bytes(m_with_prefix + params->padding_len + 2*params->n, params->n, idx); - return core_hash(params, out, m_with_prefix, mlen + 4*params->n); + return core_hash(params, out, m_with_prefix, mlen + params->padding_len + 3*params->n); } /** @@ -87,18 +87,18 @@ int thash_h(const xmss_params *params, unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8]) { - unsigned char buf[4 * params->n]; + unsigned char buf[params->padding_len + 3 * params->n]; unsigned char bitmask[2 * params->n]; unsigned char addr_as_bytes[32]; unsigned int i; /* Set the function padding. */ - ull_to_bytes(buf, params->n, XMSS_HASH_PADDING_H); + ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_H); /* Generate the n-byte key. */ set_key_and_mask(addr, 0); addr_to_bytes(addr_as_bytes, addr); - prf(params, buf + params->n, addr_as_bytes, pub_seed); + prf(params, buf + params->padding_len, addr_as_bytes, pub_seed); /* Generate the 2n-byte mask. */ set_key_and_mask(addr, 1); @@ -110,27 +110,27 @@ int thash_h(const xmss_params *params, prf(params, bitmask + params->n, addr_as_bytes, pub_seed); for (i = 0; i < 2 * params->n; i++) { - buf[2*params->n + i] = in[i] ^ bitmask[i]; + buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i]; } - return core_hash(params, out, buf, 4 * params->n); + return core_hash(params, out, buf, params->padding_len + 3 * params->n); } int thash_f(const xmss_params *params, unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8]) { - unsigned char buf[3 * params->n]; + unsigned char buf[params->padding_len + 2 * params->n]; unsigned char bitmask[params->n]; unsigned char addr_as_bytes[32]; unsigned int i; /* Set the function padding. */ - ull_to_bytes(buf, params->n, XMSS_HASH_PADDING_F); + ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_F); /* Generate the n-byte key. */ set_key_and_mask(addr, 0); addr_to_bytes(addr_as_bytes, addr); - prf(params, buf + params->n, addr_as_bytes, pub_seed); + prf(params, buf + params->padding_len, addr_as_bytes, pub_seed); /* Generate the n-byte mask. */ set_key_and_mask(addr, 1); @@ -138,7 +138,7 @@ int thash_f(const xmss_params *params, prf(params, bitmask, addr_as_bytes, pub_seed); for (i = 0; i < params->n; i++) { - buf[2*params->n + i] = in[i] ^ bitmask[i]; + buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i]; } - return core_hash(params, out, buf, 3 * params->n); + return core_hash(params, out, buf, params->padding_len + 2 * params->n); } diff --git a/params.c b/params.c index bc4c87f..a1bb69f 100644 --- a/params.c +++ b/params.c @@ -185,6 +185,7 @@ int xmss_parse_oid(xmss_params *params, const uint32_t oid) case 0x00000008: case 0x00000009: params->n = 32; + params->padding_len = 32; break; case 0x00000004: @@ -195,6 +196,7 @@ int xmss_parse_oid(xmss_params *params, const uint32_t oid) case 0x0000000b: case 0x0000000c: params->n = 64; + params->padding_len = 64; break; default: @@ -298,6 +300,7 @@ int xmssmt_parse_oid(xmss_params *params, const uint32_t oid) case 0x00000017: case 0x00000018: params->n = 32; + params->padding_len = 32; break; case 0x00000009: @@ -318,6 +321,7 @@ int xmssmt_parse_oid(xmss_params *params, const uint32_t oid) case 0x0000001f: case 0x00000020: params->n = 64; + params->padding_len = 64; break; default: diff --git a/params.h b/params.h index 5c8094b..3778fbb 100644 --- a/params.h +++ b/params.h @@ -14,6 +14,7 @@ typedef struct { unsigned int func; unsigned int n; + unsigned int padding_len; unsigned int wots_w; unsigned int wots_log_w; unsigned int wots_len1;