LMS, XMSS: move code into wolfCrypt

Move implementations of LMS and XMSS into wolfCrypt and use by default.
pull/7500/head
Sean Parkinson 2024-05-03 10:58:54 +10:00
parent 51b85ee1e3
commit e47f1d4190
7 changed files with 10887 additions and 55 deletions

View File

@ -1229,7 +1229,6 @@ AC_ARG_ENABLE([xmss],
[ ENABLED_XMSS=no ]
)
ENABLED_WC_XMSS=no
for v in `echo $ENABLED_XMSS | tr "," " "`
do
case $v in
@ -1238,15 +1237,9 @@ do
no)
;;
verify-only)
XMSS_VERIFY_ONLY=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_XMSS_VERIFY_ONLY -DXMSS_VERIFY_ONLY"
;;
wolfssl)
ENABLED_WC_XMSS=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_XMSS"
;;
small)
ENABLED_WC_XMSS=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_XMSS_SMALL"
;;
*)
@ -1255,20 +1248,6 @@ do
esac
done
if test "$ENABLED_XMSS" != "no"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_XMSS"
if test "$ENABLED_WC_XMSS" = "no";
then
# Default is to use hash-sigs XMSS lib. Make sure it's enabled.
if test "$ENABLED_LIBXMSS" = "no"; then
AC_MSG_ERROR([The default implementation for XMSS is the xmss-reference lib.
Please use --with-libxmss.])
fi
fi
fi
# libxmss
# Get the path to xmss-reference.
ENABLED_LIBXMSS="no"
@ -1321,6 +1300,19 @@ AC_ARG_WITH([libxmss],
[XMSS_ROOT=""]
)
if test "$ENABLED_XMSS" != "no"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_XMSS"
# Use hash-sigs XMSS lib if enabled.
if test "$ENABLED_LIBXMSS" = "yes"; then
ENABLED_WC_XMSS=no
else
ENABLED_WC_XMSS=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_XMSS"
fi
fi
# LMS
AC_ARG_ENABLE([lms],
[AS_HELP_STRING([--enable-lms],[Enable stateful LMS/HSS signatures (default: disabled)])],
@ -1328,7 +1320,6 @@ AC_ARG_ENABLE([lms],
[ ENABLED_LMS=no ]
)
ENABLED_WC_LMS=no
for v in `echo $ENABLED_LMS | tr "," " "`
do
case $v in
@ -1337,37 +1328,17 @@ do
no)
;;
verify-only)
LMS_VERIFY_ONLY=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LMS_VERIFY_ONLY"
;;
small)
ENABLED_WC_LMS=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_LMS_SMALL"
;;
wolfssl)
ENABLED_WC_LMS=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_LMS"
;;
*)
AC_MSG_ERROR([Invalid choice for LMS []: $ENABLED_LMS.])
break;;
esac
done
if test "$ENABLED_LMS" != "no"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_LMS"
if test "$ENABLED_WC_LMS" = "no";
then
# Default is to use hash-sigs LMS lib. Make sure it's enabled.
if test "$ENABLED_LIBLMS" = "no"; then
AC_MSG_ERROR([The default implementation for LMS is the hash-sigs LMS/HSS lib.
Please use --with-liblms.])
fi
fi
fi
# liblms
# Get the path to the hash-sigs LMS HSS lib.
ENABLED_LIBLMS="no"
@ -1436,6 +1407,19 @@ AC_ARG_WITH([liblms],
]
)
if test "$ENABLED_LMS" != "no"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_LMS"
# Use hash-sigs LMS lib if enabled.
if test "$ENABLED_LIBLMS" = "yes"; then
ENABLED_WC_LMS=no
else
ENABLED_WC_LMS=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_LMS"
fi
fi
# SINGLE THREADED
AC_ARG_ENABLE([singlethreaded],
[AS_HELP_STRING([--enable-singlethreaded],[Enable wolfSSL single threaded (default: disabled)])],

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -19,5 +19,452 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#error "Contact wolfSSL to get the implementation of this file"
/* Implementation based on:
* RFC 8554: Leighton-Micali Hash-Based Signatures
* https://datatracker.ietf.org/doc/html/rfc8554
* Implementation by Sean Parkinson.
*/
/* Possible LMS options:
*
* WOLFSSL_LMS_LARGE_CACHES Default: OFF
* Authentication path caches are large and signing faster.
* WOLFSSL_LMS_ROOT_LEVELS Default: 5 (Large: 7)
* Number of levels of interior nodes from the to to cached.
* Valid value are: 1..height of subtree.
* The bigger the number, the larger the LmsKey but faster signing.
* Only applies when !WOLFSSL_WC_LMS_SMALL.
* WOLFSSL_LMS_CACHE_BITS Default: 5 (Large: 7)
* 2 to the power of the value is the number of leaf nodes to cache.
* Maximum valid value is height of subtree.
* Valid value are: 0..height of subtree.
* The bigger the number, the larger the LmsKey but faster signing.
* Only applies when !WOLFSSL_WC_LMS_SMALL.
*
* Memory/Level | R/C | Approx. Time (% of 5/5)
* (Bytes) | | H=10 | H=15 | H=20
* -------------+--------------+--------+--------
* 2016 | 5/5 | 100.0% | 100.0% | 100.0%
* 3040 | 5/6 | 75.5% | 89.2% |
* 4064 | 6/6 | 75.3% | 78.8% |
* 4576 | 4/7 | 72.4% | 87.6% |
* 6112 | 6/7 | 72.1% | 67.5% |
* 8160 | 7/7 | 72.2% | 56.8% |
* 8416 | 3/8 | 66.4% | 84.9% |
* 12256 | 7/8 | 66.5% | 45.9% |
* 16352 | 8/8 | 66.0% | 35.0% |
* 16416 | 1/9 | 54.1% | 79.5% |
* R = Root levels
* C = Cache bits
* To mimic the dynamic memory usage of XMSS, use 3/3.
*
* WOLFSSL_LMS_NO_SIGN SMOOTHING Default: OFF
* Disable precalculation of next subtree.
* Use less dynamic memory.
* At certain indexes, signing will take a long time compared to the mean.
* When OFF, the private key holds a second copy of caches.
*
* WOLFSSL_LMS_NO_SIG_CACHE Default: OFF
* Signature cache is disabled.
* This will use less dynamic memory and make signing slower when multiple
* levels.
*
* Sig cache holds the C and y hashes for a tree that is not the lowest.
* Sig cache size = (levels - 1) * (1 + p) * 32 bytes
* p is the number of y terms based on Winternitz width.
*
* w | p | l | Bytes
* ---+----+---+------
* 4 | 67 | 2 | 2176
* 4 | 67 | 3 | 4353
* 4 | 67 | 4 | 6528
* 8 | 34 | 2 | 1120
* 8 | 34 | 3 | 2240
* 8 | 34 | 4 | 3360
* w = Winternitz width
* l = #levels
*/
#ifndef WC_LMS_H
#define WC_LMS_H
#if defined(WOLFSSL_HAVE_LMS) && defined(WOLFSSL_WC_LMS)
#include <wolfssl/wolfcrypt/lms.h>
#include <wolfssl/wolfcrypt/sha256.h>
#ifdef WOLFSSL_LMS_MAX_LEVELS
/* Maximum number of levels of trees supported by implementation. */
#define LMS_MAX_LEVELS WOLFSSL_LMS_MAX_LEVELS
#else
/* Maximum number of levels of trees supported by implementation. */
#define LMS_MAX_LEVELS 4
#endif
#if (LMS_MAX_LEVELS < 1) || (LMS_MAX_LEVELS > 4)
#error "LMS parameters only support heights 1-4."
#endif
/* Smoothing is only used when there are 2 or more levels. */
#if LMS_MAX_LEVELS == 1 && !defined(WOLFSSL_LMS_NO_SIGN_SMOOTHING)
#define WOLFSSL_LMS_NO_SIGN_SMOOTHING
#endif
#ifdef WOLFSSL_LMS_MAX_HEIGHT
/* Maximum height of a tree supported by implementation. */
#define LMS_MAX_HEIGHT WOLFSSL_LMS_MAX_HEIGHT
#else
/* Maximum height of a tree supported by implementation. */
#define LMS_MAX_HEIGHT 20
#endif
#if (LMS_MAX_HEIGHT < 5) || (LMS_MAX_HEIGHT > 20)
#error "LMS parameters only support heights 5-20."
#endif
/* Length of I in bytes. */
#define LMS_I_LEN 16
/* Length of L in bytes. */
#define LMS_L_LEN 4
/* Length of Q for a level. */
#define LMS_Q_LEN 4
/* Length of P in bytes. */
#define LMS_P_LEN 2
/* Length of W in bytes. */
#define LMS_W_LEN 1
/* Length of numeric types when encoding. */
#define LMS_TYPE_LEN 4
/* Maximum size of a node hash. */
#define LMS_MAX_NODE_LEN WC_SHA256_DIGEST_SIZE
/* Maximum size of SEED (produced by hash). */
#define LMS_SEED_LEN WC_SHA256_DIGEST_SIZE
/* Maximum number of P, number of n-byte string elements in LM-OTS signature.
* Value of P when N=32 and W=1.
*/
#define LMS_MAX_P 265
/* Length of SEED and I in bytes. */
#define LMS_SEED_I_LEN (LMS_SEED_LEN + LMS_I_LEN)
#ifndef WOLFSSL_LMS_ROOT_LEVELS
#ifdef WOLFSSL_LMS_LARGE_CACHES
/* Number of root levels of interior nodes to store. */
#define LMS_ROOT_LEVELS 7
#else
/* Number of root levels of interior nodes to store. */
#define LMS_ROOT_LEVELS 5
#endif
#else
#define LMS_ROOT_LEVELS WOLFSSL_LMS_ROOT_LEVELS
#endif
#if LMS_ROOT_LEVELS <= 0
#error "LMS_ROOT_LEVELS must be greater than 0."
#endif
/* Count of root nodes to store per level. */
#define LMS_ROOT_COUNT ((1 << (LMS_ROOT_LEVELS)) - 1)
#ifndef WOLFSSL_LMS_CACHE_BITS
#ifdef WOLFSSL_LMS_LARGE_CACHES
/* 2 to the power of the value is the number of leaf nodes to cache. */
#define LMS_CACHE_BITS 7
#else
/* 2 to the power of the value is the number of leaf nodes to cache. */
#define LMS_CACHE_BITS 5
#endif
#else
#define LMS_CACHE_BITS WOLFSSL_LMS_CACHE_BITS
#endif
#if LMS_CACHE_BITS < 0
#error "LMS_CACHE_BITS must be greater than or equal to 0."
#endif
/* Number of leaf nodes to cache. */
#define LMS_LEAF_CACHE (1 << LMS_CACHE_BITS)
/* Maximum number of levels of trees described in private key. */
#define HSS_MAX_LEVELS 8
/* Length of full Q in bytes. Q from all levels combined. */
#define HSS_Q_LEN 8
/* Compressed parameter set length in bytes. */
#define HSS_COMPRESS_PARAM_SET_LEN 1
/* Total compressed parameter set length for private key in bytes. */
#define HSS_PRIV_KEY_PARAM_SET_LEN \
(HSS_COMPRESS_PARAM_SET_LEN * HSS_MAX_LEVELS)
/* Private key length for one level. */
#define LMS_PRIV_LEN \
(LMS_Q_LEN + LMS_SEED_LEN + LMS_I_LEN)
/* Public key length in signature. */
#define LMS_PUBKEY_LEN \
(LMS_TYPE_LEN + LMS_TYPE_LEN + LMS_I_LEN + LMS_MAX_NODE_LEN)
/* LMS signature data length. */
#define LMS_SIG_LEN(h, p) \
(LMS_Q_LEN + LMS_TYPE_LEN + LMS_MAX_NODE_LEN + (p) * LMS_MAX_NODE_LEN + \
LMS_TYPE_LEN + (h) * LMS_MAX_NODE_LEN)
/* Length of public key. */
#define HSS_PUBLIC_KEY_LEN (LMS_L_LEN + LMS_PUBKEY_LEN)
/* Length of private key. */
#define HSS_PRIVATE_KEY_LEN \
(HSS_Q_LEN + HSS_PRIV_KEY_PARAM_SET_LEN + LMS_SEED_LEN + LMS_I_LEN)
/* Maximum public key length - length is constant for all parameters. */
#define HSS_MAX_PRIVATE_KEY_LEN HSS_PRIVATE_KEY_LEN
/* Maximum private key length - length is constant for all parameters. */
#define HSS_MAX_PUBLIC_KEY_LEN HSS_PUBLIC_KEY_LEN
/* Maximum signature length. */
#define HSS_MAX_SIG_LEN \
(LMS_TYPE_LEN + \
LMS_MAX_LEVELS * (LMS_Q_LEN + LMS_TYPE_LEN + LMS_TYPE_LEN + \
LMS_MAX_NODE_LEN * (1 + LMS_MAX_P + LMS_MAX_HEIGHT)) + \
(LMS_MAX_LEVELS - 1) * LMS_PUBKEY_LEN \
)
/* Maximum buffer length required for use when hashing. */
#define LMS_MAX_BUFFER_LEN \
(LMS_I_LEN + LMS_Q_LEN + LMS_P_LEN + LMS_W_LEN + 2 * LMS_MAX_NODE_LEN)
/* Private key data length.
*
* HSSPrivKey.priv
*/
#define LMS_PRIV_KEY_LEN(l) \
((l) * LMS_PRIV_LEN)
/* Stack of nodes. */
#define LMS_STACK_CACHE_LEN(h) \
(((h) + 1) * LMS_MAX_NODE_LEN)
/* Root cache length. */
#define LMS_ROOT_CACHE_LEN(rl) \
(((1 << (rl)) - 1) * LMS_MAX_NODE_LEN)
/* Leaf cache length. */
#define LMS_LEAF_CACHE_LEN(cb) \
((1 << (cb)) * LMS_MAX_NODE_LEN)
/* Length of LMS private key state.
*
* LmsPrivState
* auth_path +
* root +
* stack.stack + stack.offset +
* cache.leaf + cache.index + cache.offset
*/
#define LMS_PRIV_STATE_LEN(h, rl, cb) \
(((h) * LMS_MAX_NODE_LEN) + \
LMS_STACK_CACHE_LEN(h) + 4 + \
LMS_ROOT_CACHE_LEN(rl) + \
LMS_LEAF_CACHE_LEN(cb) + 4 + 4)
#ifndef WOLFSSL_WC_LMS_SMALL
/* Private key data state for all levels. */
#define LMS_PRIV_STATE_ALL_LEN(l, h, rl, cb) \
((l) * LMS_PRIV_STATE_LEN(h, rl, cb))
#else
/* Private key data state for all levels. */
#define LMS_PRIV_STATE_ALL_LEN(l, h, rl, cb) 0
#endif
#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING
/* Extra private key data for smoothing. */
#define LMS_PRIV_SMOOTH_LEN(l, h, rl, cb) \
(LMS_PRIV_KEY_LEN(l) + \
((l) - 1) * LMS_PRIV_STATE_LEN(h, rl, cb))
#else
/* Extra private key data for smoothing. */
#define LMS_PRIV_SMOOTH_LEN(l, h, rl, cb) 0
#endif
#ifndef WOLFSSL_LMS_NO_SIG_CACHE
#define LMS_PRIV_Y_TREE_LEN(p) \
(LMS_MAX_NODE_LEN + (p) * LMS_MAX_NODE_LEN)
/* Length of the y data cached in private key data. */
#define LMS_PRIV_Y_LEN(l, p) \
(((l) - 1) * (LMS_MAX_NODE_LEN + (p) * LMS_MAX_NODE_LEN))
#else
/* Length of the y data cached in private key data. */
#define LMS_PRIV_Y_LEN(l, p) 0
#endif
#ifndef WOLFSSL_WC_LMS_SMALL
/* Length of private key data. */
#define LMS_PRIV_DATA_LEN(l, h, p, rl, cb) \
(LMS_PRIV_KEY_LEN(l) + \
LMS_PRIV_STATE_ALL_LEN(l, h, rl, cb) + \
LMS_PRIV_SMOOTH_LEN(l, h, rl, cb) + \
LMS_PRIV_Y_LEN(l, p))
#else
#define LMS_PRIV_DATA_LEN(l, h, p, rl, cb) \
LMS_PRIV_KEY_LEN(l)
#endif
/* LMS Parameters. */
/* SHA-256 hash, 32-bytes of hash used, tree height of 5. */
#define LMS_SHA256_M32_H5 5
/* SHA-256 hash, 32-bytes of hash used, tree height of 10. */
#define LMS_SHA256_M32_H10 6
/* SHA-256 hash, 32-bytes of hash used, tree height of 15. */
#define LMS_SHA256_M32_H15 7
/* SHA-256 hash, 32-bytes of hash used, tree height of 20. */
#define LMS_SHA256_M32_H20 8
/* SHA-256 hash, 32-bytes of hash used, tree height of 25. */
#define LMS_SHA256_M32_H25 9
/* SHA-256 hash, 32-bytes of hash used, Winternitz width of 1 bit. */
#define LMOTS_SHA256_N32_W1 1
/* SHA-256 hash, 32-bytes of hash used, Winternitz width of 2 bits. */
#define LMOTS_SHA256_N32_W2 2
/* SHA-256 hash, 32-bytes of hash used, Winternitz width of 4 bits. */
#define LMOTS_SHA256_N32_W4 3
/* SHA-256 hash, 32-bytes of hash used, Winternitz width of 8 bits. */
#define LMOTS_SHA256_N32_W8 4
typedef struct LmsParams {
/* Number of tree levels. */
word8 levels;
/* Height of each tree. */
word8 height;
/* Width or Winternitz coefficient. */
word8 width;
/* Number of left-shift bits used in checksum calculation. */
word8 ls;
/* Number of n-byte string elements in LM-OTS signature. */
word16 p;
/* LMS type. */
word16 lmsType;
/* LMOTS type. */
word16 lmOtsType;
/* Length of LM-OTS signature. */
word16 sig_len;
#ifndef WOLFSSL_WC_LMS_SMALL
/* Number of root levels of interior nodes to store. */
word8 rootLevels;
/* 2 to the power of the value is the number of leaf nodes to cache. */
word8 cacheBits;
#endif
} LmsParams;
/* Mapping of id and string to parameters. */
typedef struct wc_LmsParamsMap {
/* Identifier of parameters. */
enum wc_LmsParm id;
/* String representation of identifier of parameters. */
const char* str;
/* LMS parameter set. */
LmsParams params;
} wc_LmsParamsMap;
typedef struct LmsState {
/* Buffer to hold data to hash. */
ALIGN16 byte buffer[LMS_MAX_BUFFER_LEN];
#ifdef WOLFSSL_SMALL_STACK
/* Buffer to hold expanded Q coefficients. */
ALIGN16 byte a[LMS_MAX_P];
#endif
/* LMS parameters. */
const LmsParams* params;
/* Hash algorithm. */
wc_Sha256 hash;
/* Hash algorithm for calculating K. */
wc_Sha256 hash_k;
} LmsState;
#ifndef WOLFSSL_WC_LMS_SMALL
/* Stack of interior node hashes. */
typedef struct LmsStack {
/* Stack nodes. */
byte* stack;
/* Top of stack offset. */
word32 offset;
} LmsStack;
/* Cache of leaf hashes. */
typedef struct HssLeafCache {
/* Cache of leaf nodes. Circular queue. */
byte* cache;
/* Start index of cached leaf nodes. */
word32 idx;
/* Index into cache of first leaf node. */
word32 offset;
} HssLeafCache;
typedef struct LmsPrivState {
/* Authentication path for current index. */
byte* auth_path;
/* Stack nodes. */
LmsStack stack;
/* Root nodes. */
byte* root;
/* Cache of leaf nodes. */
HssLeafCache leaf;
} LmsPrivState;
#endif /* WOLFSSL_WC_LMS_SMALL */
typedef struct HssPrivKey {
/* Private key. */
byte* priv;
#ifndef WOLFSSL_WC_LMS_SMALL
/* Per level state of the private key. */
LmsPrivState state[LMS_MAX_LEVELS];
#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING
/* Next private key. */
byte* next_priv;
/* Next private state. */
LmsPrivState next_state[LMS_MAX_LEVELS - 1];
#endif
#ifndef WOLFSSL_LMS_NO_SIG_CACHE
/* Per level state of the private key. */
byte* y;
#endif
/* Indicates the key has all levels initialized. */
word8 inited:1;
#endif
} HssPrivKey;
struct LmsKey {
/* Public key. */
ALIGN16 byte pub[HSS_PUBLIC_KEY_LEN];
#ifndef WOLFSSL_LMS_VERIFY_ONLY
/* Encoded private key. */
ALIGN16 byte priv_raw[HSS_PRIVATE_KEY_LEN];
/* Packed private key data. */
byte* priv_data;
/* HSS Private key. */
HssPrivKey priv;
/* Callback to write/update key. */
wc_lms_write_private_key_cb write_private_key;
/* Callback to read key. */
wc_lms_read_private_key_cb read_private_key;
/* Context arg passed to callbacks. */
void* context;
/* Dynamic memory hint. */
void* heap;
#endif /* !WOLFSSL_LMS_VERIFY_ONLY */
/* Parameters of key. */
const LmsParams* params;
/* Current state of key. */
enum wc_LmsState state;
#ifdef WOLF_CRYPTO_CB
/* Device Identifier. */
int devId;
#endif
};
int wc_hss_make_key(LmsState* state, WC_RNG* rng, byte* priv_raw,
HssPrivKey* priv_key, byte* priv_data, byte* pub);
int wc_hss_reload_key(LmsState* state, const byte* priv_raw,
HssPrivKey* priv_key, byte* priv_data, byte* pub_root);
int wc_hss_sign(LmsState* state, byte* priv_raw, HssPrivKey* priv_key,
byte* priv_data, const byte* msg, word32 msgSz, byte* sig);
int wc_hss_sigsleft(const LmsParams* params, const byte* priv_raw);
int wc_hss_verify(LmsState* state, const byte* pub, const byte* msg,
word32 msgSz, const byte* sig);
#endif /* WOLFSSL_HAVE_LMS && WOLFSSL_WC_LMS */
#endif /* WC_LMS_H */

View File

@ -19,5 +19,267 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#error "Contact wolfSSL to get the implementation of this file"
/* Based on:
* o RFC 8391 - XMSS: eXtended Merkle Signature Scheme
* o [HDSS] "Hash-based Digital Signature Schemes", Buchmann, Dahmen and Szydlo
* from "Post Quantum Cryptography", Springer 2009.
*/
#ifndef WC_XMSS_H
#define WC_XMSS_H
#ifdef WOLFSSL_HAVE_XMSS
#include <wolfssl/wolfcrypt/xmss.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/sha512.h>
#include <wolfssl/wolfcrypt/sha3.h>
#if !defined(WOLFSSL_WC_XMSS)
#error "This code is incompatible with external implementation of XMSS."
#endif
#if (defined(WC_XMSS_SHA512) || defined(WC_XMSS_SHAKE256)) && \
(WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512)
#define WC_XMSS_MAX_N 64
#define WC_XMSS_MAX_PADDING_LEN 64
#else
#define WC_XMSS_MAX_N 32
#define WC_XMSS_MAX_PADDING_LEN 32
#endif
#define WC_XMSS_MAX_MSG_PRE_LEN \
(WC_XMSS_MAX_PADDING_LEN + 3 * WC_XMSS_MAX_N)
#define WC_XMSS_MAX_TREE_HEIGHT 20
#define WC_XMSS_MAX_CSUM_BYTES 4
#define WC_XMSS_MAX_WOTS_LEN (8 * WC_XMSS_MAX_N / 4 + 3)
#define WC_XMSS_MAX_WOTS_SIG_LEN (WC_XMSS_MAX_WOTS_LEN * WC_XMSS_MAX_N)
#define WC_XMSS_MAX_STACK_LEN \
((WC_XMSS_MAX_TREE_HEIGHT + 1) * WC_XMSS_MAX_N)
#define WC_XMSS_MAX_D 12
#define WC_XMSS_MAX_BDS_STATES (2 * WC_XMSS_MAX_D - 1)
#define WC_XMSS_MAX_TREE_HASH \
((2 * WC_XMSS_MAX_D - 1) * WC_XMSS_MAX_TREE_HEIGHT)
#define WC_XMSS_MAX_BDS_K 0
#define WC_XMSS_ADDR_LEN 32
#define WC_XMSS_HASH_PRF_MAX_DATA_LEN \
(WC_XMSS_MAX_PADDING_LEN + 2 * WC_XMSS_MAX_N + WC_XMSS_ADDR_LEN)
#define WC_XMSS_HASH_MAX_DATA_LEN \
(WC_XMSS_MAX_PADDING_LEN + 3 * WC_XMSS_MAX_N)
#define WC_XMSS_SHA256_N 32
#define WC_XMSS_SHA256_PADDING_LEN 32
#define WC_XMSS_SHA256_WOTS_LEN 67
#define XMSS_OID_LEN 4
#define XMSS_MAX_HASH_LEN WC_SHA256_DIGEST_SIZE
#define XMSS_RETAIN_LEN(k, n) ((!!(k)) * ((1 << (k)) - (k) - 1) * (n))
/* XMMS Algorithm OIDs
* Note: values are used in mathematical calculations in OID to parames. */
#define WC_XMSS_OID_SHA2_10_256 0x01
#define WC_XMSS_OID_SHA2_16_256 0x02
#define WC_XMSS_OID_SHA2_20_256 0x03
#define WC_XMSS_OID_SHA2_10_512 0x04
#define WC_XMSS_OID_SHA2_16_512 0x05
#define WC_XMSS_OID_SHA2_20_512 0x06
#define WC_XMSS_OID_SHAKE_10_256 0x07
#define WC_XMSS_OID_SHAKE_16_256 0x08
#define WC_XMSS_OID_SHAKE_20_256 0x09
#define WC_XMSS_OID_SHAKE_10_512 0x0a
#define WC_XMSS_OID_SHAKE_16_512 0x0b
#define WC_XMSS_OID_SHAKE_20_512 0x0c
#define WC_XMSS_OID_SHA2_10_192 0x0d
#define WC_XMSS_OID_SHA2_16_192 0x0e
#define WC_XMSS_OID_SHA2_20_192 0x0f
#define WC_XMSS_OID_SHAKE256_10_256 0x10
#define WC_XMSS_OID_SHAKE256_16_256 0x11
#define WC_XMSS_OID_SHAKE256_20_256 0x12
#define WC_XMSS_OID_SHAKE256_10_192 0x13
#define WC_XMSS_OID_SHAKE256_16_192 0x14
#define WC_XMSS_OID_SHAKE256_20_192 0x15
#define WC_XMSS_OID_FIRST WC_XMSS_OID_SHA2_10_256
#define WC_XMSS_OID_LAST WC_XMSS_OID_SHAKE256_20_192
/* XMMS^MT Algorithm OIDs
* Note: values are used in mathematical calculations in OID to parames. */
#define WC_XMSSMT_OID_SHA2_20_2_256 0x01
#define WC_XMSSMT_OID_SHA2_20_4_256 0x02
#define WC_XMSSMT_OID_SHA2_40_2_256 0x03
#define WC_XMSSMT_OID_SHA2_40_4_256 0x04
#define WC_XMSSMT_OID_SHA2_40_8_256 0x05
#define WC_XMSSMT_OID_SHA2_60_3_256 0x06
#define WC_XMSSMT_OID_SHA2_60_6_256 0x07
#define WC_XMSSMT_OID_SHA2_60_12_256 0x08
#define WC_XMSSMT_OID_SHA2_20_2_512 0x09
#define WC_XMSSMT_OID_SHA2_20_4_512 0x0a
#define WC_XMSSMT_OID_SHA2_40_2_512 0x0b
#define WC_XMSSMT_OID_SHA2_40_4_512 0x0c
#define WC_XMSSMT_OID_SHA2_40_8_512 0x0d
#define WC_XMSSMT_OID_SHA2_60_3_512 0x0e
#define WC_XMSSMT_OID_SHA2_60_6_512 0x0f
#define WC_XMSSMT_OID_SHA2_60_12_512 0x10
#define WC_XMSSMT_OID_SHAKE_20_2_256 0x11
#define WC_XMSSMT_OID_SHAKE_20_4_256 0x12
#define WC_XMSSMT_OID_SHAKE_40_2_256 0x13
#define WC_XMSSMT_OID_SHAKE_40_4_256 0x14
#define WC_XMSSMT_OID_SHAKE_40_8_256 0x15
#define WC_XMSSMT_OID_SHAKE_60_3_256 0x16
#define WC_XMSSMT_OID_SHAKE_60_6_256 0x17
#define WC_XMSSMT_OID_SHAKE_60_12_256 0x18
#define WC_XMSSMT_OID_SHAKE_20_2_512 0x19
#define WC_XMSSMT_OID_SHAKE_20_4_512 0x1a
#define WC_XMSSMT_OID_SHAKE_40_2_512 0x1b
#define WC_XMSSMT_OID_SHAKE_40_4_512 0x1c
#define WC_XMSSMT_OID_SHAKE_40_8_512 0x1d
#define WC_XMSSMT_OID_SHAKE_60_3_512 0x1e
#define WC_XMSSMT_OID_SHAKE_60_6_512 0x1f
#define WC_XMSSMT_OID_SHAKE_60_12_512 0x20
#define WC_XMSSMT_OID_SHA2_20_2_192 0x21
#define WC_XMSSMT_OID_SHA2_20_4_192 0x22
#define WC_XMSSMT_OID_SHA2_40_2_192 0x23
#define WC_XMSSMT_OID_SHA2_40_4_192 0x24
#define WC_XMSSMT_OID_SHA2_40_8_192 0x25
#define WC_XMSSMT_OID_SHA2_60_3_192 0x26
#define WC_XMSSMT_OID_SHA2_60_6_192 0x27
#define WC_XMSSMT_OID_SHA2_60_12_192 0x28
#define WC_XMSSMT_OID_SHAKE256_20_2_256 0x29
#define WC_XMSSMT_OID_SHAKE256_20_4_256 0x2a
#define WC_XMSSMT_OID_SHAKE256_40_2_256 0x2b
#define WC_XMSSMT_OID_SHAKE256_40_4_256 0x2c
#define WC_XMSSMT_OID_SHAKE256_40_8_256 0x2d
#define WC_XMSSMT_OID_SHAKE256_60_3_256 0x2e
#define WC_XMSSMT_OID_SHAKE256_60_6_256 0x2f
#define WC_XMSSMT_OID_SHAKE256_60_12_256 0x30
#define WC_XMSSMT_OID_SHAKE256_20_2_192 0x31
#define WC_XMSSMT_OID_SHAKE256_20_4_192 0x32
#define WC_XMSSMT_OID_SHAKE256_40_2_192 0x33
#define WC_XMSSMT_OID_SHAKE256_40_4_192 0x34
#define WC_XMSSMT_OID_SHAKE256_40_8_192 0x35
#define WC_XMSSMT_OID_SHAKE256_60_3_192 0x36
#define WC_XMSSMT_OID_SHAKE256_60_6_192 0x37
#define WC_XMSSMT_OID_SHAKE256_60_12_192 0x38
#define WC_XMSSMT_OID_FIRST WC_XMSSMT_OID_SHA2_20_2_256
#define WC_XMSSMT_OID_LAST WC_XMSSMT_OID_SHAKE256_60_12_192
/* Type for hash address. */
typedef word32 HashAddress[8];
/* XMSS/XMSS^MT fixed parameters. */
typedef struct XmssParams {
/* Hash algorithm to use. */
word8 hash;
/* Size of hash output. */
word8 n;
/* Number of bytes of padding before rest of hash data. */
word8 pad_len;
/* Number of values to chain = 2 * n + 3. */
word8 wots_len;
/* Number of bytes in each WOTS+ signature. */
word16 wots_sig_len;
/* Full height of tree. */
word8 h;
/* Height of tree each subtree. */
word8 sub_h;
/* Number of subtrees = h / sub_h. */
word8 d;
/* Number of bytes to encode index into in private/secret key. */
word8 idx_len;
/* Number of bytes in a signature. */
word32 sig_len;
/* Number of bytes in a secret/private key. */
word32 sk_len;
/* Number of bytes in a public key. */
word8 pk_len;
/* BDS parameter for fast C implementation. */
word8 bds_k;
} XmssParams;
struct XmssKey {
/* Public key. */
unsigned char pk[2 * WC_XMSS_MAX_N];
/* OID that identifies parameters. */
word32 oid;
/* Indicates whether the parameters are for XMSS^MT. */
int is_xmssmt;
/* XMSS/XMSS^MT parameters. */
const XmssParams* params;
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
/* Secret/private key. */
unsigned char* sk;
/* Length of secret key. */
word32 sk_len;
/* Callback to write/update key. */
wc_xmss_write_private_key_cb write_private_key;
/* Callback to read key. */
wc_xmss_read_private_key_cb read_private_key;
/* Context arg passed to callbacks. */
void* context;
#endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
/* State of key. */
enum wc_XmssState state;
};
typedef struct XmssState {
const XmssParams* params;
/* Digest is assumed to be at the end. */
union {
#ifdef WC_XMSS_SHA256
wc_Sha256 sha256;
#endif
#ifdef WC_XMSS_SHA512
wc_Sha512 sha512;
#endif
#if defined(WC_XMSS_SHAKE128) || defined(WC_XMSS_SHAKE256)
wc_Shake shake;
#endif
} digest;
#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) && \
!defined(WC_XMSS_FULL_HASH)
ALIGN16 word32 dgst_state[WC_SHA256_DIGEST_SIZE / sizeof(word32)];
#endif
ALIGN16 byte prf_buf[WC_XMSS_HASH_PRF_MAX_DATA_LEN];
ALIGN16 byte buf[WC_XMSS_HASH_MAX_DATA_LEN];
ALIGN16 byte pk[WC_XMSS_MAX_WOTS_SIG_LEN];
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
ALIGN16 byte stack[WC_XMSS_MAX_STACK_LEN];
#else
ALIGN16 byte stack[WC_XMSS_ADDR_LEN];
#endif
byte encMsg[WC_XMSS_MAX_WOTS_LEN];
HashAddress addr;
int ret;
} XmssState;
#ifdef __cplusplus
extern "C" {
#endif
WOLFSSL_LOCAL int wc_xmssmt_keygen(XmssState *state, const unsigned char* seed,
unsigned char *sk, unsigned char *pk);
WOLFSSL_LOCAL int wc_xmss_keygen(XmssState *state, const unsigned char* seed,
unsigned char *sk, unsigned char *pk);
WOLFSSL_LOCAL int wc_xmssmt_sign(XmssState *state, const unsigned char *m,
word32 mlen, unsigned char *sk, unsigned char *sm);
WOLFSSL_LOCAL int wc_xmss_sign(XmssState *state, const unsigned char *m,
word32 mlen, unsigned char *sk, unsigned char *sm);
WOLFSSL_LOCAL int wc_xmss_sigsleft(const XmssParams* params, unsigned char* sk);
WOLFSSL_LOCAL int wc_xmssmt_verify(XmssState *state, const unsigned char *m,
word32 mlen, const unsigned char *sm, const unsigned char *pk);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WOLFSSL_HAVE_XMSS */
#endif /* WC_XMSS_H */