Skip to content

Commit

Permalink
Add XMSS parameter xmss_sha256_h10 (#1482)
Browse files Browse the repository at this point in the history
* init external and parameters

* fix the size of pk and sk

* add cmakelist for xmss_sha256_h10

* add comment

* fix format err

* fix compiler warning of size_t

* update to match local

* add remain and total API

* add sigs_remaining and sigs_total

* add const to API

* add kat_sig_stfl

* to pass the format test

* fix typo

* verbose error

* let's see if this work

* use UINT64_MAX constant

* goto err to avoid memory leaks

* safe arithmetic using unsigned int and initialize lengths array

* fix iteration type to match its comparison

* using unsigned int instead of uint32_t to match with comparison

* use memset to initialize default value

* convert to unsigned int

* propagate unsigned int

* clean up

* remove randombytes, use OQS_randombytes instead.

* use calloc instead of malloc for secret_key memory initialization

* remove randombytes from CMakeLists.txt

* remove makefile

* using namespace to separate core_hash.c

* rename katfile

* add test and kats for test_kat.py

* add compile definition for core_hash.c

* add type for t

* fix typo
  • Loading branch information
ducnguyen-sb authored and SWilson4 committed May 14, 2024
1 parent 8e1dd5c commit 244288f
Show file tree
Hide file tree
Showing 37 changed files with 4,484 additions and 70 deletions.
16 changes: 16 additions & 0 deletions src/sig_stfl/sig_stfl.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,22 @@ OQS_API OQS_STATUS OQS_SIG_STFL_verify(const OQS_SIG_STFL *sig, const uint8_t *m
}
}

OQS_API OQS_STATUS OQS_SIG_STFL_sigs_remaining(const OQS_SIG_STFL *sig, size_t *remain, const uint8_t *secret_key) {
if (sig == NULL || sig->sigs_remaining == NULL || sig->sigs_remaining(remain, secret_key) != 0) {
return OQS_ERROR;
} else {
return OQS_SUCCESS;
}
}

OQS_API OQS_STATUS OQS_SIG_STFL_sigs_total(const OQS_SIG_STFL *sig, size_t *max, const uint8_t *secret_key) {
if (sig == NULL || sig->sigs_total == NULL || sig->sigs_total(max, secret_key) != 0) {
return OQS_ERROR;
} else {
return OQS_SUCCESS;
}
}

OQS_API void OQS_SIG_STFL_free(OQS_SIG_STFL *sig) {
OQS_MEM_insecure_free(sig);
}
38 changes: 38 additions & 0 deletions src/sig_stfl/sig_stfl.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,24 @@ typedef struct OQS_SIG_STFL {
*/
OQS_STATUS (*verify)(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);

/**
* Query number of remaining signatures
*
* @param[out] remain The number of remaining signatures
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*sigs_remaining)(size_t *remain, const uint8_t *secret_key);

/**
* Total number of signatures
*
* @param[out] total The total number of signatures
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*sigs_total)(size_t *total, const uint8_t *secret_key);

} OQS_SIG_STFL;

/**
Expand Down Expand Up @@ -183,6 +201,26 @@ OQS_API OQS_STATUS OQS_SIG_STFL_sign(const OQS_SIG_STFL *sig, uint8_t *signature
*/
OQS_API OQS_STATUS OQS_SIG_STFL_verify(const OQS_SIG_STFL *sig, const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);

/**
* Query number of remaining signatures
*
* @param[in] sig The OQS_SIG_STFL object representing the signature scheme.
* @param[out] remain The number of remaining signatures
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_SIG_STFL_sigs_remaining(const OQS_SIG_STFL *sig, size_t *remain, const uint8_t *secret_key);

/**
* * Total number of signatures
*
* @param[in] sig The OQS_SIG_STFL object representing the signature scheme.
* @param[out] max The number of remaining signatures
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_SIG_STFL_sigs_total(const OQS_SIG_STFL *sig, size_t *max, const uint8_t *secret_key);

/**
* Frees an OQS_SIG_STFL object that was constructed by OQS_SIG_STFL_new.
*
Expand Down
16 changes: 14 additions & 2 deletions src/sig_stfl/xmss/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,20 @@

set(_XMSS_OBJS "")

set(SRCS sig_stfl_xmss_sha256.c
)
set(SRCS external/hash.c
external/hash_address.c
external/params.c
external/utils.c
external/wots.c
external/xmss.c
external/xmss_commons.c
)

if (OQS_ENABLE_SIG_STFL_xmss_sha256_h10)
add_compile_definitions(OQS_ENABLE_SIG_STFL_xmss_sha256_h10)
set (SRCS ${SRCS} sig_stfl_xmss_sha256_h10.c external/core_hash.c external/xmss_core.c)
endif()


add_library(xmss OBJECT ${SRCS})
set(_XMSS_OBJS ${_XMSS_OBJS} $<TARGET_OBJECTS:xmss>)
Expand Down
14 changes: 14 additions & 0 deletions src/sig_stfl/xmss/external/core_hash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <oqs/sha2.h>
#include <oqs/sha3.h>
#include "hash.h"

int core_hash(const xmss_params *params,
unsigned char *out,
const unsigned char *in, unsigned long long inlen)
{
#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h10
(void)params;
OQS_SHA2_sha256(out, in, inlen);
return 0;
#endif
}
142 changes: 142 additions & 0 deletions src/sig_stfl/xmss/external/hash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#include <stdint.h>
#include <string.h>

#include <oqs/sha2.h>
#include <oqs/sha3.h>

#include "hash_address.h"
#include "utils.h"
#include "params.h"
#include "hash.h"

#define XMSS_HASH_PADDING_F 0
#define XMSS_HASH_PADDING_H 1
#define XMSS_HASH_PADDING_HASH 2
#define XMSS_HASH_PADDING_PRF 3
#define XMSS_HASH_PADDING_PRF_KEYGEN 4

void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8])
{
int i;
for (i = 0; i < 8; i++) {
ull_to_bytes(bytes + i*4, 4, addr[i]);
}
}

/*
* Computes PRF(key, in), for a key of params->n bytes, and a 32-byte input.
*/
int prf(const xmss_params *params,
unsigned char *out, const unsigned char in[32],
const unsigned char *key)
{
unsigned char buf[params->padding_len + params->n + 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, params->padding_len + params->n + 32);
}

/*
* Computes PRF_keygen(key, in), for a key of params->n bytes, and an input
* of 32 + params->n bytes
*/
int prf_keygen(const xmss_params *params,
unsigned char *out, const unsigned char *in,
const unsigned char *key)
{
unsigned char buf[params->padding_len + 2*params->n + 32];

ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF_KEYGEN);
memcpy(buf + params->padding_len, key, params->n);
memcpy(buf + params->padding_len + params->n, in, params->n + 32);

return core_hash(params, out, buf, params->padding_len + 2*params->n + 32);
}

/*
* 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 3*n plus
* the length of the padding as free space available 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->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 + params->padding_len + 3*params->n);
}

/**
* We assume the left half is in in[0]...in[n-1]
*/
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[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->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->padding_len, addr_as_bytes, pub_seed);

/* Generate the 2n-byte mask. */
set_key_and_mask(addr, 1);
addr_to_bytes(addr_as_bytes, addr);
prf(params, bitmask, addr_as_bytes, pub_seed);

set_key_and_mask(addr, 2);
addr_to_bytes(addr_as_bytes, addr);
prf(params, bitmask + params->n, addr_as_bytes, pub_seed);

for (i = 0; i < 2 * params->n; i++) {
buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i];
}
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[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->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->padding_len, addr_as_bytes, pub_seed);

/* Generate the n-byte mask. */
set_key_and_mask(addr, 1);
addr_to_bytes(addr_as_bytes, addr);
prf(params, bitmask, addr_as_bytes, pub_seed);

for (i = 0; i < params->n; i++) {
buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i];
}
return core_hash(params, out, buf, params->padding_len + 2 * params->n);
}
47 changes: 47 additions & 0 deletions src/sig_stfl/xmss/external/hash.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef XMSS_HASH_H
#define XMSS_HASH_H

#include <stdint.h>
#include "params.h"

#define addr_to_bytes XMSS_INNER_NAMESPACE(addr_to_bytes)
void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8]);

#define core_hash XMSS_INNER_NAMESPACE(core_hash)
int core_hash(const xmss_params *params,
unsigned char *out,
const unsigned char *in, unsigned long long inlen);

#define prf XMSS_INNER_NAMESPACE(prf)
int prf(const xmss_params *params,
unsigned char *out, const unsigned char in[32],
const unsigned char *key);

#define prf_keygen XMSS_INNER_NAMESPACE(prf_keygen)
int prf_keygen(const xmss_params *params,
unsigned char *out, const unsigned char *in,
const unsigned char *key);

#define h_msg XMSS_INNER_NAMESPACE(h_msg)
int h_msg(const xmss_params *params,
unsigned char *out,
const unsigned char *in, unsigned long long inlen,
const unsigned char *key, const unsigned int keylen);

#define thash_h XMSS_INNER_NAMESPACE(thash_h)
int thash_h(const xmss_params *params,
unsigned char *out, const unsigned char *in,
const unsigned char *pub_seed, uint32_t addr[8]);

#define thash_f XMSS_INNER_NAMESPACE(thash_f)
int thash_f(const xmss_params *params,
unsigned char *out, const unsigned char *in,
const unsigned char *pub_seed, uint32_t addr[8]);

#define hash_message XMSS_INNER_NAMESPACE(hash_message)
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
66 changes: 66 additions & 0 deletions src/sig_stfl/xmss/external/hash_address.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include <stdint.h>
#include "hash_address.h"

void set_layer_addr(uint32_t addr[8], uint32_t layer)
{
addr[0] = layer;
}

void set_tree_addr(uint32_t addr[8], uint64_t tree)
{
addr[1] = (uint32_t) (tree >> 32);
addr[2] = (uint32_t) tree;
}

void set_type(uint32_t addr[8], uint32_t type)
{
addr[3] = type;
}

void set_key_and_mask(uint32_t addr[8], uint32_t key_and_mask)
{
addr[7] = key_and_mask;
}

void copy_subtree_addr(uint32_t out[8], const uint32_t in[8])
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
}

/* These functions are used for OTS addresses. */

void set_ots_addr(uint32_t addr[8], uint32_t ots)
{
addr[4] = ots;
}

void set_chain_addr(uint32_t addr[8], uint32_t chain)
{
addr[5] = chain;
}

void set_hash_addr(uint32_t addr[8], uint32_t hash)
{
addr[6] = hash;
}

/* This function is used for L-tree addresses. */

void set_ltree_addr(uint32_t addr[8], uint32_t ltree)
{
addr[4] = ltree;
}

/* These functions are used for hash tree addresses. */

void set_tree_height(uint32_t addr[8], uint32_t tree_height)
{
addr[5] = tree_height;
}

void set_tree_index(uint32_t addr[8], uint32_t tree_index)
{
addr[6] = tree_index;
}
Loading

0 comments on commit 244288f

Please sign in to comment.