From 8ff6df538c506bfcd83d9e4ab8bfaf2f4e671d11 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 21 Jul 2021 12:42:15 +0100 Subject: [PATCH 001/104] Add LMS implementation Also an LM-OTS implementation as one is required for LMS. Signed-off-by: Raef Coles --- ChangeLog.d/LMS.txt | 12 + include/mbedtls/check_config.h | 10 + include/mbedtls/error.h | 2 + include/mbedtls/lmots.h | 292 ++++++++++ include/mbedtls/lms.h | 254 +++++++++ include/mbedtls/mbedtls_config.h | 28 + library/CMakeLists.txt | 2 + library/Makefile | 2 + library/lmots.c | 684 +++++++++++++++++++++++ library/lms.c | 718 +++++++++++++++++++++++++ scripts/generate_errors.pl | 2 +- tests/suites/test_suite_lmots.data | 29 + tests/suites/test_suite_lmots.function | 108 ++++ tests/suites/test_suite_lms.data | 32 ++ tests/suites/test_suite_lms.function | 85 +++ 15 files changed, 2259 insertions(+), 1 deletion(-) create mode 100644 ChangeLog.d/LMS.txt create mode 100644 include/mbedtls/lmots.h create mode 100644 include/mbedtls/lms.h create mode 100644 library/lmots.c create mode 100644 library/lms.c create mode 100644 tests/suites/test_suite_lmots.data create mode 100644 tests/suites/test_suite_lmots.function create mode 100644 tests/suites/test_suite_lms.data create mode 100644 tests/suites/test_suite_lms.function diff --git a/ChangeLog.d/LMS.txt b/ChangeLog.d/LMS.txt new file mode 100644 index 0000000000..0f09f01860 --- /dev/null +++ b/ChangeLog.d/LMS.txt @@ -0,0 +1,12 @@ +Features + * Add the LMS post-quantum-safe stateful-hash asymmetric signature scheme + as defined in RFC8554 and NIST.SP.200-208. This currently only supports + one parameter set (LMS_SHA256_M32_H10), meaning that each private key can + be used to sign 1024 messages. As such, it is not intended for use in TLS, + but instead for verification of assets transmitted over an insecure + channel, particularly firmware images. This is one of the signature + schemes recommended by the IETF draft SUIT standard for IOT firmware + upgrades (RFC9019). + * Add the LM-OTS post-quantum-safe one-time signature scheme, which is + required for LMS. This can be used independently, but each key can only be + used to sign one message so is impractical for most circumstances. diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 6b330a75ba..37253ab525 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -353,6 +353,16 @@ #error "MBEDTLS_MD_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_LMOTS_C) && \ + ( !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_LMOTS_C requires MBEDTLS_MD_C" +#endif + +#if defined(MBEDTLS_LMS_C) && \ + ( !defined(MBEDTLS_LMOTS_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_LMS_C requires MBEDTLS_LMOTS_C and MBEDTLS_MD_C" +#endif + #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) #error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 8b2b9ea580..73d61dbc63 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -82,6 +82,8 @@ * POLY1305 3 0x0057-0x005B * CHACHAPOLY 2 0x0054-0x0056 * PLATFORM 2 0x0070-0x0072 + * LMOTS 2 0x0076-0x0078 + * LMS 2 0x0011-0x0017 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors diff --git a/include/mbedtls/lmots.h b/include/mbedtls/lmots.h new file mode 100644 index 0000000000..a177ad4a57 --- /dev/null +++ b/include/mbedtls/lmots.h @@ -0,0 +1,292 @@ +/** + * \file lmots.h + * + * \brief This file provides an API for the LM-OTS post-quantum-safe one-time + * public-key signature scheme. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_LMOTS_H +#define MBEDTLS_LMOTS_H + +#include "mbedtls/private_access.h" + +#include +#include + +#define MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA -0x0076 /**< Bad data has been input to an LMOTS function */ +#define MBEDTLS_ERR_LMOTS_VERIFY_FAILED -0x0078 /**< LMOTS signature verification failed */ + +#define MBEDTLS_LMOTS_N_HASH_LEN (32) +#define MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN (34) +#define MBEDTLS_LMOTS_TYPE_LEN (4) +#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN (MBEDTLS_LMOTS_N_HASH_LEN) +#define MBEDTLS_LMOTS_I_KEY_ID_LEN (16) +#define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4) + +#define MBEDTLS_LMOTS_SIG_LEN (MBEDTLS_LMOTS_TYPE_LEN + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN + \ + (MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN * MBEDTLS_LMOTS_N_HASH_LEN)) + +#define MBEDTLS_LMOTS_PUBKEY_LEN (MBEDTLS_LMOTS_TYPE_LEN + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN + MBEDTLS_LMOTS_N_HASH_LEN) + +#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0) +#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN) + +#define MBEDTLS_LMOTS_PUBKEY_TYPE_OFFSET (0) +#define MBEDTLS_LMOTS_PUBKEY_I_KEY_ID_OFFSET (MBEDTLS_LMOTS_PUBKEY_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMOTS_PUBKEY_Q_LEAF_ID_OFFSET (MBEDTLS_LMOTS_PUBKEY_I_KEY_ID_OFFSET + MBEDTLS_LMOTS_I_KEY_ID_LEN) +#define MBEDTLS_LMOTS_PUBKEY_KEY_HASH_OFFSET (MBEDTLS_LMOTS_PUBKEY_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* We are only implementing a subset of the types, particularly n32_w8, for the + * sake of simplicty + */ +typedef enum { + MBEDTLS_LMOTS_SHA256_N32_W8 = 4 +} mbedtls_lmots_algorithm_type_t; + + +typedef struct { + unsigned char MBEDTLS_PRIVATE(have_privkey); + unsigned char MBEDTLS_PRIVATE(have_pubkey); + unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); + unsigned int MBEDTLS_PRIVATE(q_leaf_identifier); + unsigned char MBEDTLS_PRIVATE(q_leaf_identifier_bytes)[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]; + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); + unsigned char MBEDTLS_PRIVATE(priv_key[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32]); + unsigned char MBEDTLS_PRIVATE(pub_key[32]); +} mbedtls_lmots_context; + + +/** + * \brief This function initializes an LMOTS context + * + * \param ctx The uninitialized LMOTS context that will then be + * initialized. + */ +void mbedtls_lmots_init( mbedtls_lmots_context *ctx ); + +/** + * \brief This function uninitializes an LMOTS context + * + * \param ctx The initialized LMOTS context that will then be + * uninitialized. + */ +void mbedtls_lmots_free( mbedtls_lmots_context *ctx ); + +/** + * \brief This function sets the type of an LMOTS context + * + * \note The parameter set in the context will then be used + * for keygen operations etc. + * + * \param ctx The initialized LMOTS context. + * \param type The type that will be set in the context. + */ +int mbedtls_lmots_set_algorithm_type( mbedtls_lmots_context *ctx, + mbedtls_lmots_algorithm_type_t type ); + +/** + * \brief This function creates a candidate public key from + * an LMOTS signature. This can then be compared to + * the real public key to determine the validity of + * the signature. + * + * \note This function is exposed publicly to be used in LMS + * signature verification, it is expected that + * mbedtls_lmots_verify will be used for LMOTS + * signature verification. + * + * \param I_key_identifier The key identifier of the key, as a 16 byte + * bytestring. + * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is + * not being used as part of an LMS key, this should + * be set to 0. + * \param msg The buffer from which the message will be read. + * \param msg_len The size of the message that will be read. + * \param sig The buff from which the signature will be read. + * MBEDTLS_LMOTS_SIG_LEN bytes will be read from this. + * \param out The buffer where the candidate public key will be + * stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN + * bytes in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_generate_pub_key_candidate( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], + const unsigned char *msg, + size_t msg_len, + const unsigned char *sig, + unsigned char *out ); + +/** + * \brief This function creates a LMOTS signature, using a + * LMOTS context that contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and must contain a private + * key. + * + * \note LMOTS private keys can only be used once, otherwise + * attackers may be able to create forged signatures. + * If the signing operation is successful, the private + * key in the context will be erased, and no further + * signing will be possible until another private key + * is loaded + * + * \param ctx The initialized LMOTS context from which the + * private key will be read. + * \param f_rng The RNG function to be used for signature + * generation. + * \param p_rng The RNG context to be passed to f_rng + * \param msg The buffer from which the message will be read. + * \param msg_len The size of the message that will be read. + * \param sig The buf into which the signature will be stored. + * Must be at least #MBEDTLS_LMOTS_SIG_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_sign( mbedtls_lmots_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, size_t msg_len, + unsigned char *sig ); + +/** + * \brief This function verifies a LMOTS signature, using a + * LMOTS context that contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and must contain a public key + * (either by import or generation). + * + * \param ctx The initialized LMOTS context from which the public + * key will be read. + * \param msg The buffer from which the message will be read. + * \param msg_len The size of the message that will be read. + * \param sig The buf from which the signature will be read. + * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from + * this. + * + * \return \c 0 on successful verification. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_verify( mbedtls_lmots_context *ctx, const unsigned char *msg, + size_t msg_len, const unsigned char *sig ); + +/** + * \brief This function imports an LMOTS public key into a + * LMOTS context. + * + * \note Before this function is called, the context must + * have been initialized. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMOTS context store the key in. + * \param key The buffer from which the key will be read. + * #MBEDTLS_LMOTS_PUBKEY_LEN bytes will be read from + * this. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_import_pubkey( mbedtls_lmots_context *ctx, + const unsigned char *key ); + +/** + * \brief This function exports an LMOTS public key from a + * LMOTS context that already contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMOTS context that contains the + * publc key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMOTS_PUBKEY_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_export_pubkey( mbedtls_lmots_context *ctx, + unsigned char *key ); + +/** + * \brief This function generates an LMOTS public key from a + * LMOTS context that already contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a private key. + * + * \param ctx The initialized LMOTS context to generate the key + * from and store it into. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_gen_pubkey( mbedtls_lmots_context *ctx ); + +/** + * \brief This function generates an LMOTS private key, and + * stores in into an LMOTS context. + * + * \note Before this function is called, the context must + * have been initialized and the type of the LMOTS + * context set using mbedtls_lmots_set_algorithm_type + * + * \note The seed must have at least 256 bits of entropy. + * + * \param ctx The initialized LMOTS context to generate the key + * into. + * \param I_key_identifier The key identifier of the key, as a 16 byte + * bytestring. + * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is + * not being used as part of an LMS key, this should + * be set to 0. + * \param seed The seed used to deterministically generate the + * key. + * \param seed_len The length of the seed. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_gen_privkey( mbedtls_lmots_context *ctx, + const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + unsigned int q_leaf_identifier, + const unsigned char *seed, + size_t seed_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_LMOTS_H */ diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h new file mode 100644 index 0000000000..868a667e6a --- /dev/null +++ b/include/mbedtls/lms.h @@ -0,0 +1,254 @@ +/** + * \file lms.h + * + * \brief This file provides an API for the LMS post-quantum-safe stateful-hash + * public-key signature scheme. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_LMS_H +#define MBEDTLS_LMS_H + +#include +#include + +#include "mbedtls/private_access.h" +#include "mbedtls/lmots.h" + +#define MBEDTLS_ERR_LMS_BAD_INPUT_DATA -0x0011 /**< Bad data has been input to an LMS function */ +#define MBEDTLS_ERR_LMS_OUT_OF_PRIV_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */ +#define MBEDTLS_ERR_LMS_VERIFY_FAILED -0x0015 /**< LMS signature verification failed */ +#define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ + +#define MBEDTLS_LMS_TYPE_LEN (4) +#define MBEDTLS_LMS_H_TREE_HEIGHT (10) +#define MBEDTLS_LMS_M_NODE_BYTES (32) + +#define MBEDTLS_LMS_SIG_LEN (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + MBEDTLS_LMOTS_SIG_LEN + \ + MBEDTLS_LMS_TYPE_LEN + MBEDTLS_LMS_H_TREE_HEIGHT * MBEDTLS_LMS_M_NODE_BYTES) + +#define MBEDTLS_LMS_PUBKEY_LEN (MBEDTLS_LMS_TYPE_LEN + MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN + MBEDTLS_LMS_M_NODE_BYTES) + +#define MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET (0) +#define MBEDTLS_LMS_SIG_OTS_SIG_OFFSET (MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) +#define MBEDTLS_LMS_SIG_TYPE_OFFSET (MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_LEN) +#define MBEDTLS_LMS_SIG_PATH_OFFSET (MBEDTLS_LMS_SIG_TYPE_OFFSET + MBEDTLS_LMS_TYPE_LEN) + +#define MBEDTLS_LMS_PUBKEY_TYPE_OFFSET (0) +#define MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET (MBEDTLS_LMS_PUBKEY_TYPE_OFFSET + MBEDTLS_LMS_TYPE_LEN) +#define MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET (MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMS_PUBKEY_ROOT_NODE_OFFSET (MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET + MBEDTLS_LMOTS_I_KEY_ID_LEN) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + MBEDTLS_LMS_SHA256_M32_H10 = 0x6, +} mbedtls_lms_algorithm_type_t; + + +typedef struct { + unsigned char MBEDTLS_PRIVATE(have_privkey); + unsigned char MBEDTLS_PRIVATE(have_pubkey); + unsigned char MBEDTLS_PRIVATE(I_key_identifier)[MBEDTLS_LMOTS_I_KEY_ID_LEN]; + mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); + unsigned int MBEDTLS_PRIVATE(q_next_usable_key); + mbedtls_lmots_context *MBEDTLS_PRIVATE(priv_keys); + unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES]; +} mbedtls_lms_context; + + +/** + * \brief This function initializes an LMS context + * + * \param ctx The uninitialized LMS context that will then be + * initialized. + */ +void mbedtls_lms_init( mbedtls_lms_context *ctx ); + +/** + * \brief This function uninitializes an LMS context + * + * \param ctx The initialized LMS context that will then be + * uninitialized. + */ +void mbedtls_lms_free( mbedtls_lms_context *ctx ); + +/** + * \brief This function sets the type of an LMS context + * + * \note The parameter set in the context will then be used + * for keygen operations etc. + * + * \param ctx The initialized LMS context. + * \param type The type that will be set in the context. + * \param otstype The type of the LMOTS implementation used by this + * context. + */ +int mbedtls_lms_set_algorithm_type( mbedtls_lms_context *ctx, + mbedtls_lms_algorithm_type_t type, + mbedtls_lmots_algorithm_type_t otstype); + +/** + * \brief This function creates a LMS signature, using a + * LMOTS context that contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and must contain a private + * key. + * + * \note Each of the LMOTS private keys inside a LMS private + * key can only be used once. If they are reused, then + * attackers may be able to forge signatures with that + * key. This is all handled transparently, but it is + * important to not perform copy operations on LMS + * contexts that contain private key material. + * + * \param ctx The initialized LMS context from which the + * private key will be read. + * \param f_rng The RNG function to be used for signature + * generation. + * \param p_rng The RNG context to be passed to f_rng + * \param msg The buffer from which the message will be read. + * \param msg_len The size of the message that will be read. + * \param sig The buf into which the signature will be stored. + * Must be at least #MBEDTLS_LMOTS_SIG_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_sign( mbedtls_lms_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void* p_rng, unsigned char *msg, unsigned int msg_len, + unsigned char *sig); + +/** + * \brief This function verifies a LMS signature, using a + * LMS context that contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and must contain a public key + * (either by import or generation). + * + * \param ctx The initialized LMS context from which the public + * key will be read. + * \param msg The buffer from which the message will be read. + * \param msg_len The size of the message that will be read. + * \param sig The buf from which the signature will be read. + * #MBEDTLS_LMS_SIG_LEN bytes will be read from + * this. + * + * \return \c 0 on successful verification. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_verify( const mbedtls_lms_context *ctx, + const unsigned char *msg, unsigned int msg_len, + const unsigned char *sig ); + +/** + * \brief This function imports an LMOTS public key into a + * LMS context. + * + * \note Before this function is called, the context must + * have been initialized. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMS context store the key in. + * \param key The buffer from which the key will be read. + * #MBEDTLS_LMS_PUBKEY_LEN bytes will be read from + * this. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_import_pubkey( mbedtls_lms_context *ctx, + const unsigned char *key ); + +/** + * \brief This function exports an LMOTS public key from a + * LMS context that already contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMS context that contains the + * publc key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMS_PUBKEY_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_export_pubkey( mbedtls_lms_context *ctx, + unsigned char *key ); + +/** + * \brief This function generates an LMS public key from a + * LMS context that already contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a private key. + * + * \param ctx The initialized LMS context to generate the key + * from and store it into. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_gen_pubkey( mbedtls_lms_context *ctx ); + +/** + * \brief This function generates an LMS private key, and + * stores in into an LMS context. + * + * \note Before this function is called, the context must + * have been initialized and the type of the LMS + * context set using mbedtls_lmots_set_algorithm_type + * + * \note The seed must have at least 256 bits of entropy. + * + * \param ctx The initialized LMOTS context to generate the key + * into. + * \param f_rng The RNG function to be used to generate the key ID. + * \param p_rng The RNG context to be passed to f_rng + * \param seed The seed used to deterministically generate the + * key. + * \param seed_len The length of the seed. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_gen_privkey( mbedtls_lms_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void* p_rng, unsigned char *seed, + size_t seed_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_LMS_H */ diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 23e601b32d..1da395b5c3 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2461,6 +2461,34 @@ */ #define MBEDTLS_HMAC_DRBG_C +/** + * \def MBEDTLS_LMOTS_C + * + * Enable the LMOTS one-time asymmetric hash signature algorithm. + * + * Module: library/lm_ots.c + * Caller: + * + * Requires: MBEDTLS_SHA256_C + * + * Uncomment to enable the LMOTS signature algorithm. + */ +#define MBEDTLS_LMOTS_C + +/** + * \def MBEDTLS_LMS_C + * + * Enable the LMS stateful-hash asymmetric signature algorithm. + * + * Module: library/lms.c + * Caller: + * + * Requires: MBEDTLS_LMS_C + * + * Uncomment to enable the LMS signature algorithm. + */ +#define MBEDTLS_LMS_C + /** * \def MBEDTLS_NIST_KW_C * diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 951381475e..7c325f7bae 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -44,6 +44,8 @@ set(src_crypto hash_info.c hkdf.c hmac_drbg.c + lmots.c + lms.c md.c md5.c memory_buffer_alloc.c diff --git a/library/Makefile b/library/Makefile index 9c3af3b9b5..624773dc19 100644 --- a/library/Makefile +++ b/library/Makefile @@ -109,6 +109,8 @@ OBJS_CRYPTO= \ hash_info.o \ hkdf.o \ hmac_drbg.o \ + lmots.o \ + lms.o \ md.o \ md5.o \ memory_buffer_alloc.o \ diff --git a/library/lmots.c b/library/lmots.c new file mode 100644 index 0000000000..7319d29be7 --- /dev/null +++ b/library/lmots.c @@ -0,0 +1,684 @@ +/* + * The LM-OTS one-time public-key signature scheme + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The following sources were referenced in the design of this implementation + * of the LM-OTS algorithm: + * + * [1] IETF RFC8554 + * D. McGrew, M. Curcio, S.Fluhrer + * https://datatracker.ietf.org/doc/html/rfc8554 + * + * [2] NIST Special Publication 800-208 + * David A. Cooper et. al. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf + */ + +#include "common.h" + +#ifdef MBEDTLS_LMOTS_C + +#include + +#include "mbedtls/lmots.h" +#include "mbedtls/md.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#define W_SYMBOL_BIT_LEN (8) +#define CHECKSUM_LEN (2) +#define I_SYMBOL_IDX_LEN (2) +#define J_HASH_IDX_LEN (1) +#define D_CONST_LEN (2) + +#define SYMBOL_MAX_VAL ((1 << W_SYMBOL_BIT_LEN) - 1) + +#define D_PBLC_CONSTANT (0x8080) +#define D_MESG_CONSTANT (0x8181) + +static void val_to_network_bytes(unsigned int val, size_t len, unsigned char *bytes) +{ + size_t idx; + + for (idx = 0; idx < len; idx++) { + bytes[idx] = (val >> ((len - 1 - idx) * 8)) & 0xFF; + } +} + +static unsigned int network_bytes_to_val(size_t len, const unsigned char *bytes) +{ + size_t idx; + unsigned int val = 0; + + for (idx = 0; idx < len; idx++) { + val |= ((unsigned int)bytes[idx]) << (8 * (len - 1 - idx)); + } + + return val; +} + +static unsigned short lmots_checksum_generate( const unsigned char* digest ) +{ + size_t idx; + unsigned short sum = 0; + + for ( idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN; idx++ ) + { + sum += ( 1 << W_SYMBOL_BIT_LEN ) - 1 - digest[idx]; + } + + return sum; +} + +static int create_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], + const unsigned char *msg, + size_t msg_len, + const unsigned char C_random_value[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN], + unsigned char out[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN] ) +{ + mbedtls_md_context_t hash_ctx; + unsigned char D_MESG_BYTES[D_CONST_LEN]; + unsigned short checksum; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &hash_ctx ); + ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); + if( ret ) + { + goto out; + } + ret = mbedtls_md_starts( &hash_ctx ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + if ( ret ) + { + goto out; + } + + val_to_network_bytes( D_MESG_CONSTANT, D_CONST_LEN, D_MESG_BYTES ); + ret = mbedtls_md_update( &hash_ctx, D_MESG_BYTES, sizeof( D_MESG_BYTES ) ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, C_random_value, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, msg, msg_len ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_finish( &hash_ctx, out ); + if ( ret ) + { + goto out; + } + + checksum = lmots_checksum_generate( out ); + val_to_network_bytes( checksum, CHECKSUM_LEN, out + MBEDTLS_LMOTS_N_HASH_LEN ); + +out: + mbedtls_md_free( &hash_ctx ); + + return( ret ); +} + +static int hash_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], + const unsigned char x_symbol_array[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32], + const unsigned char hash_idx_min_values[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN], + const unsigned char hash_idx_max_values[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN], + unsigned char output[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32] ) +{ + unsigned char i_symbol_idx; + unsigned char j_hash_idx; + unsigned char i_symbol_idx_bytes[I_SYMBOL_IDX_LEN]; + unsigned char j_hash_idx_bytes[1]; + unsigned short j_hash_idx_min; + unsigned short j_hash_idx_max; + mbedtls_md_context_t hash_ctx; + unsigned char tmp_hash[32]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + for ( i_symbol_idx = 0; i_symbol_idx < MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN; i_symbol_idx++ ) + { + + memcpy( tmp_hash, &x_symbol_array[i_symbol_idx], MBEDTLS_LMOTS_N_HASH_LEN ); + + j_hash_idx_min = hash_idx_min_values != NULL ? hash_idx_min_values[i_symbol_idx] : 0; + j_hash_idx_max = hash_idx_max_values != NULL ? hash_idx_max_values[i_symbol_idx] : SYMBOL_MAX_VAL; + + for ( j_hash_idx = (unsigned char)j_hash_idx_min; j_hash_idx < j_hash_idx_max; j_hash_idx++ ) + { + mbedtls_md_init( &hash_ctx ); + ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); + if( ret ) + { + goto out; + } + ret = mbedtls_md_starts( &hash_ctx ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + if ( ret ) + { + goto out; + } + + val_to_network_bytes( i_symbol_idx, I_SYMBOL_IDX_LEN, i_symbol_idx_bytes ); + ret = mbedtls_md_update( &hash_ctx, i_symbol_idx_bytes, I_SYMBOL_IDX_LEN ); + if ( ret ) + { + goto out; + } + + val_to_network_bytes( j_hash_idx, J_HASH_IDX_LEN, j_hash_idx_bytes ); + ret = mbedtls_md_update( &hash_ctx, j_hash_idx_bytes, J_HASH_IDX_LEN ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_finish( &hash_ctx, tmp_hash ); + if ( ret ) + { + goto out; + } + + mbedtls_md_free( &hash_ctx ); + } + + memcpy( &output[i_symbol_idx], tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); + } + +out: + if( ret ) + { + mbedtls_md_free( &hash_ctx ); + return( ret ); + } + + return ret; +} + +static int public_key_from_hashed_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], + const unsigned char y_hashed_symbols[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32], + unsigned char *pub_key ) +{ + unsigned char D_PBLC_bytes[D_CONST_LEN]; + mbedtls_md_context_t hash_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &hash_ctx ); + ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); + if( ret ) + { + goto out; + } + ret = mbedtls_md_starts( &hash_ctx ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + if ( ret ) + { + goto out; + } + + val_to_network_bytes( D_PBLC_CONSTANT, D_CONST_LEN, D_PBLC_bytes ); + ret = mbedtls_md_update( &hash_ctx, D_PBLC_bytes, D_CONST_LEN ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, ( unsigned char * )y_hashed_symbols, + MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN * MBEDTLS_LMOTS_N_HASH_LEN ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_finish( &hash_ctx, pub_key ); + +out: + mbedtls_md_free( &hash_ctx ); + return( ret ); +} + +void mbedtls_lmots_init( mbedtls_lmots_context *ctx ) +{ + if( ctx == NULL ) { + return; + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_context ) ) ; +} + +void mbedtls_lmots_free( mbedtls_lmots_context *ctx ) +{ + if( ctx == NULL ) + { + return; + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_context ) ) ; +} + +int mbedtls_lmots_set_algorithm_type( mbedtls_lmots_context *ctx, + mbedtls_lmots_algorithm_type_t type ) +{ + if( ctx == NULL ) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + ctx->MBEDTLS_PRIVATE(type) = type; + + return( 0 ); +} + +int mbedtls_lmots_generate_pub_key_candidate( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], + const unsigned char *msg, + size_t msg_len, + const unsigned char *sig, + unsigned char *out ) +{ + unsigned char tmp_symbol_array[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN]; + unsigned char y_hashed_symbols[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (I_key_identifier == NULL || msg == NULL || sig == NULL || out == NULL) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + ret = create_symbol_array( I_key_identifier, q_leaf_identifier, msg, msg_len, + sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_symbol_array ); + if ( ret ) + { + return ( ret ); + } + + ret = hash_symbol_array( I_key_identifier, q_leaf_identifier, + ( const unsigned char( *)[32] )(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET), + tmp_symbol_array, NULL, y_hashed_symbols ); + if ( ret ) + { + return ( ret ); + } + + ret = public_key_from_hashed_symbol_array( I_key_identifier, q_leaf_identifier, + ( const unsigned char( *)[32] )y_hashed_symbols, + out ); + if ( ret ) + { + return ( ret ); + } + + return( 0 ); +} + +int mbedtls_lmots_sign( mbedtls_lmots_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, size_t msg_len, + unsigned char *sig ) +{ + unsigned char tmp_symbol_array[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN]; + unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][MBEDTLS_LMOTS_N_HASH_LEN]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx == NULL || f_rng == NULL || p_rng == NULL || msg == NULL || sig == NULL) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + /* Check that a private key is loaded */ + if ( !ctx->MBEDTLS_PRIVATE(have_privkey) ) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + ret = f_rng( p_rng, sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN ); + if ( ret ) + { + return( ret ); + } + + ret = create_symbol_array( ctx->MBEDTLS_PRIVATE(I_key_identifier), + ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), + msg, msg_len, sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, + tmp_symbol_array ); + if ( ret ) + { + return( ret ); + } + + ret = hash_symbol_array( ctx->MBEDTLS_PRIVATE(I_key_identifier), + ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), + ( const unsigned char( *)[32] )(ctx->MBEDTLS_PRIVATE(priv_key)), + NULL, tmp_symbol_array, tmp_sig ); + if ( ret ) + { + return( ret ); + } + + val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), MBEDTLS_LMOTS_TYPE_LEN, + sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + + /* We've got a valid signature now, so it's time to make sure the private + * key can't be reused. + */ + ctx->MBEDTLS_PRIVATE(have_privkey) = 0; + mbedtls_platform_zeroize(ctx->MBEDTLS_PRIVATE(priv_key), + sizeof(ctx->MBEDTLS_PRIVATE(priv_key))); + + memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET, tmp_sig, + MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN * MBEDTLS_LMOTS_N_HASH_LEN); + + return( 0 ); +} + +int mbedtls_lmots_verify( mbedtls_lmots_context *ctx, const unsigned char *msg, + size_t msg_len, const unsigned char *sig ) +{ + unsigned char Kc_public_key_candidate[32]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx == NULL || msg == NULL || sig == NULL) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + if ( !ctx->MBEDTLS_PRIVATE(have_pubkey) ) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(type ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + if ( network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, + sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMOTS_VERIFY_FAILED ); + } + + ret = mbedtls_lmots_generate_pub_key_candidate( ctx->MBEDTLS_PRIVATE(I_key_identifier), + ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), + msg, msg_len, sig, + Kc_public_key_candidate ); + if ( ret ) + { + return( ret ); + } + + if ( memcmp( &Kc_public_key_candidate, ctx->MBEDTLS_PRIVATE(pub_key), + sizeof( ctx->MBEDTLS_PRIVATE(pub_key) ) ) ) + { + return( MBEDTLS_ERR_LMOTS_VERIFY_FAILED ); + } + + return( 0 ); +} + +int mbedtls_lmots_import_pubkey( mbedtls_lmots_context *ctx, + const unsigned char *key ) +{ + if ( ctx == NULL || key == NULL) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + ctx->MBEDTLS_PRIVATE(type) = network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + + memcpy( ctx->MBEDTLS_PRIVATE(I_key_identifier), key + MBEDTLS_LMOTS_PUBKEY_I_KEY_ID_OFFSET, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + + memcpy( ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), key + MBEDTLS_LMOTS_PUBKEY_Q_LEAF_ID_OFFSET, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + ctx->MBEDTLS_PRIVATE(q_leaf_identifier) = network_bytes_to_val( MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes) ); + + memcpy( ctx->MBEDTLS_PRIVATE(pub_key), key + MBEDTLS_LMOTS_PUBKEY_KEY_HASH_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN ); + + ctx->MBEDTLS_PRIVATE(have_pubkey) = 1; + + return( 0 ); +} + +int mbedtls_lmots_export_pubkey( mbedtls_lmots_context *ctx, + unsigned char *key ) +{ + if ( ctx == NULL || key == NULL) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + if ( ! ctx->MBEDTLS_PRIVATE(have_pubkey) ) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + + memcpy( key + MBEDTLS_LMOTS_PUBKEY_I_KEY_ID_OFFSET, ctx->MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + + memcpy( key + MBEDTLS_LMOTS_PUBKEY_Q_LEAF_ID_OFFSET, ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + + memcpy( key + MBEDTLS_LMOTS_PUBKEY_KEY_HASH_OFFSET, ctx->MBEDTLS_PRIVATE(pub_key), + MBEDTLS_LMOTS_N_HASH_LEN ); + + return( 0 ); +} + + +int mbedtls_lmots_gen_pubkey( mbedtls_lmots_context *ctx ) +{ + unsigned char y_hashed_symbols[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + /* Check that a private key is loaded */ + if ( !ctx->MBEDTLS_PRIVATE(have_privkey) ) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + ret = hash_symbol_array( ctx->MBEDTLS_PRIVATE(I_key_identifier), + ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), + ( const unsigned char( *)[32] )(ctx->MBEDTLS_PRIVATE(priv_key)), + NULL, NULL, y_hashed_symbols ); + if ( ret ) + { + return( ret ); + } + + ret = public_key_from_hashed_symbol_array( ctx->MBEDTLS_PRIVATE(I_key_identifier), + ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), + ( const unsigned char( *)[32] )y_hashed_symbols, + ctx->MBEDTLS_PRIVATE(pub_key) ); + if ( ret ) + { + return( ret ); + } + + ctx->MBEDTLS_PRIVATE(have_pubkey = 1); + + return( ret ); +} + +int mbedtls_lmots_gen_privkey( mbedtls_lmots_context *ctx, + const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + unsigned int q_leaf_identifier, + const unsigned char *seed, + size_t seed_len ) +{ + mbedtls_md_context_t hash_ctx; + unsigned int i_symbol_idx; + unsigned char i_symbol_idx_bytes[2]; + unsigned char const_bytes[1]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx == NULL || I_key_identifier == NULL || seed == NULL) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + if ( ctx->MBEDTLS_PRIVATE(have_privkey) ) + { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + if ( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { + return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + } + + memcpy( ctx->MBEDTLS_PRIVATE(I_key_identifier), I_key_identifier, + sizeof( ctx->MBEDTLS_PRIVATE(I_key_identifier) ) ); + + ctx->MBEDTLS_PRIVATE(q_leaf_identifier) = q_leaf_identifier; + + val_to_network_bytes( ctx->MBEDTLS_PRIVATE(q_leaf_identifier), MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes) ); + + val_to_network_bytes( 0xFF, sizeof( const_bytes ), const_bytes ); + + for ( i_symbol_idx = 0; i_symbol_idx < MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN; i_symbol_idx++ ) + { + mbedtls_md_init( &hash_ctx ); + ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); + if( ret ) + { + goto out; + } + ret = mbedtls_md_starts( &hash_ctx ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, ctx->MBEDTLS_PRIVATE(I_key_identifier), + sizeof( ctx->MBEDTLS_PRIVATE(I_key_identifier) ) ); + if ( ret ) { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), + sizeof( ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes) ) ); + if ( ret ) + { + goto out; + } + + val_to_network_bytes( i_symbol_idx, I_SYMBOL_IDX_LEN, i_symbol_idx_bytes ); + ret = mbedtls_md_update( &hash_ctx, i_symbol_idx_bytes, I_SYMBOL_IDX_LEN ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, const_bytes, sizeof( const_bytes) ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, seed, seed_len ); + if ( ret ) + { + goto out; + } + + ret = mbedtls_md_finish( &hash_ctx, ctx->MBEDTLS_PRIVATE(priv_key)[i_symbol_idx] ); + if ( ret ) + { + goto out; + } + + mbedtls_md_free( &hash_ctx); + } + + ctx->MBEDTLS_PRIVATE(have_privkey) = 1; + +out: + if( ret ) + { + mbedtls_md_free( &hash_ctx ); + return( ret ); + } + + return ret; +} + +#endif /* MBEDTLS_LMOTS_C */ diff --git a/library/lms.c b/library/lms.c new file mode 100644 index 0000000000..e1ac7b9353 --- /dev/null +++ b/library/lms.c @@ -0,0 +1,718 @@ +/* + * The LMS stateful-hash public-key signature scheme + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The following sources were referenced in the design of this implementation + * of the LMS algorithm: + * + * [1] IETF RFC8554 + * D. McGrew, M. Curcio, S.Fluhrer + * https://datatracker.ietf.org/doc/html/rfc8554 + * + * [2] NIST Special Publication 800-208 + * David A. Cooper et. al. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf + */ + +#include "common.h" + +#ifdef MBEDTLS_LMS_C + +#include + +#include "mbedtls/lms.h" +#include "mbedtls/lmots.h" +#include "mbedtls/md.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define MERKLE_TREE_NODE_AM (1 << (MBEDTLS_LMS_H_TREE_HEIGHT + 1)) +#define MERKLE_TREE_LEAF_AM (1 << MBEDTLS_LMS_H_TREE_HEIGHT) +#define MERKLE_TREE_INTR_AM (1 << MBEDTLS_LMS_H_TREE_HEIGHT) + +#define D_CONST_LEN (2) + +#define D_LEAF_CONSTANT (0x8282) +#define D_INTR_CONSTANT (0x8383) + +static void val_to_network_bytes(unsigned int val, size_t len, unsigned char *bytes) +{ + size_t idx; + + for (idx = 0; idx < len; idx++) { + bytes[idx] = (val >> ((len - 1 - idx) * 8)) & 0xFF; + } +} + +static unsigned int network_bytes_to_val(size_t len, const unsigned char *bytes) +{ + size_t idx; + unsigned int val = 0; + + for (idx = 0; idx < len; idx++) { + val |= ((unsigned int)bytes[idx]) << (8 * (len - 1 - idx)); + } + + return val; +} + +static int create_merkle_leaf_node( const mbedtls_lms_context *ctx, + unsigned char pub_key[MBEDTLS_LMOTS_N_HASH_LEN], + unsigned int r_node_idx, + unsigned char out[32] ) +{ + mbedtls_md_context_t hash_ctx; + unsigned char D_LEAF_bytes[D_CONST_LEN]; + unsigned char r_node_idx_bytes[4]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &hash_ctx ); + ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); + if( ret ) + { + goto out; + } + ret = mbedtls_md_starts( &hash_ctx ); + if( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, + ctx->MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + if( ret ) + { + goto out; + } + + val_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); + ret = mbedtls_md_update( &hash_ctx, r_node_idx_bytes, 4 ); + if( ret ) + { + goto out; + } + + val_to_network_bytes( D_LEAF_CONSTANT, D_CONST_LEN, D_LEAF_bytes ); + ret = mbedtls_md_update( &hash_ctx, D_LEAF_bytes, D_CONST_LEN ); + if( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, pub_key, MBEDTLS_LMOTS_N_HASH_LEN ); + if( ret ) + { + goto out; + } + + ret = mbedtls_md_finish( &hash_ctx, out ); + if( ret ) + { + goto out; + } + +out: + mbedtls_md_free( &hash_ctx ); + + return( ret ); +} + +static int create_merkle_intr_node( const mbedtls_lms_context *ctx, + const unsigned char left_node[32], + const unsigned char rght_node[32], + unsigned int r_node_idx, + unsigned char out[32] ) +{ + mbedtls_md_context_t hash_ctx; + unsigned char D_INTR_bytes[D_CONST_LEN]; + unsigned char r_node_idx_bytes[4]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &hash_ctx ); + ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); + if( ret ) + { + goto out; + } + ret = mbedtls_md_starts( &hash_ctx ); + if( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, ctx->MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + if( ret ) + { + goto out; + } + + val_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); + ret = mbedtls_md_update( &hash_ctx, r_node_idx_bytes, 4 ); + if( ret ) + { + goto out; + } + + val_to_network_bytes( D_INTR_CONSTANT, D_CONST_LEN, D_INTR_bytes ); + ret = mbedtls_md_update( &hash_ctx, D_INTR_bytes, D_CONST_LEN ); + if( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, left_node, MBEDTLS_LMOTS_N_HASH_LEN ); + if( ret ) + { + goto out; + } + + ret = mbedtls_md_update( &hash_ctx, rght_node, MBEDTLS_LMOTS_N_HASH_LEN ); + if( ret ) + { + goto out; + } + + ret = mbedtls_md_finish( &hash_ctx, out ); + if( ret ) + { + goto out; + } + +out: + mbedtls_md_free( &hash_ctx ); + + return ret; +} + +static int generate_merkle_tree( mbedtls_lms_context *ctx, + unsigned char tree[MERKLE_TREE_NODE_AM][32] ) +{ + unsigned int priv_key_idx; + unsigned int r_node_idx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* First create the leaf nodes, in ascending order */ + for( priv_key_idx = 0; priv_key_idx < MERKLE_TREE_INTR_AM; priv_key_idx++ ) + { + r_node_idx = MERKLE_TREE_INTR_AM + priv_key_idx; + + ret = create_merkle_leaf_node( ctx, ctx->MBEDTLS_PRIVATE(priv_keys)[priv_key_idx].pub_key, + r_node_idx, tree[r_node_idx] ); + if( ret ) + { + return( ret ); + } + } + + /* Then the internal nodes, in reverse order so that we can guarantee the + * parent has been created */ + for( r_node_idx = MERKLE_TREE_INTR_AM - 1; r_node_idx > 0; r_node_idx-- ) + { + ret = create_merkle_intr_node( ctx, tree[(r_node_idx * 2)], + tree[(r_node_idx * 2 + 1)], + r_node_idx, tree[r_node_idx] ); + if( ret ) + { + return( ret ); + } + } + + return( 0 ); +} + +static int get_merkle_path( mbedtls_lms_context *ctx, + unsigned int leaf_node_id, unsigned char path[MBEDTLS_LMS_H_TREE_HEIGHT][32] ) +{ + unsigned char tree[MERKLE_TREE_NODE_AM][32]; + unsigned int curr_node_id = leaf_node_id; + unsigned int parent_node_id; + unsigned char sibling_relative_id; + unsigned int adjacent_node_id; + unsigned int height; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = generate_merkle_tree( ctx, tree); + if( ret ) + { + return( ret ); + } + + for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ ) + { + parent_node_id = ( curr_node_id / 2 ); + + /* 0 if the node is a left child, 1 if the node is a right child */ + sibling_relative_id = curr_node_id & 1; + + adjacent_node_id = ( parent_node_id * 2 ) + ( 1 - sibling_relative_id ); + + memcpy( &path[height], &tree[adjacent_node_id], MBEDTLS_LMOTS_N_HASH_LEN ); + + curr_node_id = parent_node_id; + } + + return( 0 ); +} + +void mbedtls_lms_init( mbedtls_lms_context *ctx ) +{ + if( ctx == NULL ) + { + return; + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_context ) ) ; +} + +void mbedtls_lms_free( mbedtls_lms_context *ctx ) +{ + unsigned int idx; + + if( ctx == NULL ) + { + return; + } + + if( ctx->MBEDTLS_PRIVATE(have_privkey) ) + { + for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ ) + { + mbedtls_lmots_free( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx] ); + } + + mbedtls_free( ctx->MBEDTLS_PRIVATE(priv_keys) ); + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_context ) ); +} + +int mbedtls_lms_set_algorithm_type( mbedtls_lms_context *ctx, + mbedtls_lms_algorithm_type_t type, + mbedtls_lmots_algorithm_type_t otstype ) +{ + if( ctx == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + ctx->MBEDTLS_PRIVATE(type) = type; + ctx->MBEDTLS_PRIVATE(otstype) = otstype; + + return( 0 ); +} + +int mbedtls_lms_sign( mbedtls_lms_context *ctx, + int ( *f_rng)(void *, unsigned char *, size_t), + void* p_rng, unsigned char *msg, unsigned int msg_len, + unsigned char *sig ) +{ + unsigned int q_leaf_identifier; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ! ctx->MBEDTLS_PRIVATE(have_privkey) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( msg == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( sig == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + + if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + + if( ctx->MBEDTLS_PRIVATE(q_next_usable_key) >= MERKLE_TREE_LEAF_AM ) + { + return( MBEDTLS_ERR_LMS_OUT_OF_PRIV_KEYS ); + } + + + q_leaf_identifier = ctx->MBEDTLS_PRIVATE(q_next_usable_key); + /* This new value must _always_ be written back to the disk before the + * signature is returned. + */ + ctx->MBEDTLS_PRIVATE(q_next_usable_key) += 1; + + ret = mbedtls_lmots_sign( &ctx->MBEDTLS_PRIVATE(priv_keys)[q_leaf_identifier], + f_rng, p_rng, msg, msg_len, + sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET ); + if( ret ) + { + return( ret ); + } + + val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), MBEDTLS_LMS_TYPE_LEN, + sig + MBEDTLS_LMS_SIG_TYPE_OFFSET ); + val_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET); + + ret = get_merkle_path( ctx, MERKLE_TREE_INTR_AM + q_leaf_identifier, + ( unsigned char( * )[32] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) ); + if( ret ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_lms_verify( const mbedtls_lms_context *ctx, + const unsigned char *msg, unsigned int msg_len, + const unsigned char *sig ) +{ + unsigned int q_leaf_identifier; + unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN]; + unsigned char Tc_candidate_root_node[32]; + unsigned int height; + unsigned int curr_node_id; + unsigned int parent_node_id; + const unsigned char* left_node; + const unsigned char* rght_node; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ! ctx->MBEDTLS_PRIVATE(have_pubkey) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( msg == NULL) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( sig == NULL) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + + if( network_bytes_to_val( MBEDTLS_LMS_TYPE_LEN, + sig + MBEDTLS_LMS_SIG_TYPE_OFFSET) != MBEDTLS_LMS_SHA256_M32_H10 ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + + if( network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, + sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) + != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + + + q_leaf_identifier = network_bytes_to_val( MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); + + if( q_leaf_identifier >= MERKLE_TREE_LEAF_AM ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + + ret = mbedtls_lmots_generate_pub_key_candidate( ctx->MBEDTLS_PRIVATE(I_key_identifier), + sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET, + msg, msg_len, + sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, + Kc_candidate_ots_pub_key ); + if( ret ) + { + return( ret ); + } + + create_merkle_leaf_node( ctx, Kc_candidate_ots_pub_key, + MERKLE_TREE_INTR_AM + q_leaf_identifier, + Tc_candidate_root_node ); + + curr_node_id = MERKLE_TREE_INTR_AM + q_leaf_identifier; + + for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ ) + { + parent_node_id = curr_node_id / 2; + + /* Left/right node ordering matters for the hash */ + if( curr_node_id & 1 ) + { + left_node = ( ( const unsigned char( * )[32] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height]; + rght_node = Tc_candidate_root_node; + } + else + { + left_node = Tc_candidate_root_node; + rght_node = ( ( const unsigned char( * )[32] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height]; + } + + create_merkle_intr_node( ctx, left_node, rght_node, parent_node_id, + Tc_candidate_root_node); + + curr_node_id /= 2; + } + + if( memcmp( Tc_candidate_root_node, ctx->MBEDTLS_PRIVATE(T_1_pub_key), + MBEDTLS_LMOTS_N_HASH_LEN) ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + + return( 0 ); +} + +int mbedtls_lms_import_pubkey( mbedtls_lms_context *ctx, + const unsigned char *key ) +{ + mbedtls_lms_algorithm_type_t type; + mbedtls_lmots_algorithm_type_t otstype; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( key == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + type = network_bytes_to_val( MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBKEY_TYPE_OFFSET ); + if( type != MBEDTLS_LMS_SHA256_M32_H10 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + ctx->MBEDTLS_PRIVATE(type) = type; + + otstype = network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET ); + if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + ctx->MBEDTLS_PRIVATE(otstype) = otstype; + + memcpy( ctx->MBEDTLS_PRIVATE(I_key_identifier), key + MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + memcpy( ctx->MBEDTLS_PRIVATE(T_1_pub_key), key + MBEDTLS_LMS_PUBKEY_ROOT_NODE_OFFSET, + MBEDTLS_LMOTS_N_HASH_LEN ); + + ctx->MBEDTLS_PRIVATE(have_pubkey) = 1; + + return( 0 ); +} + +int mbedtls_lms_export_pubkey( mbedtls_lms_context *ctx, + unsigned char *key ) +{ + if( ctx == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( key == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ! ctx->MBEDTLS_PRIVATE(have_pubkey) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), + MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBKEY_TYPE_OFFSET ); + val_to_network_bytes( ctx->MBEDTLS_PRIVATE(otstype), + MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET ); + memcpy( key + MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET, + ctx->MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + memcpy( key + MBEDTLS_LMS_PUBKEY_ROOT_NODE_OFFSET, + ctx->MBEDTLS_PRIVATE(T_1_pub_key), + MBEDTLS_LMOTS_N_HASH_LEN ); + + return( 0 ); +} + +int mbedtls_lms_gen_pubkey( mbedtls_lms_context *ctx ) +{ + unsigned char tree[MERKLE_TREE_NODE_AM][32]; + unsigned int idx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ! ctx->MBEDTLS_PRIVATE( have_privkey ) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ ) + { + ret = mbedtls_lmots_gen_pubkey( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx] ); + if( ret ) + { + return( ret ); + } + } + + ret = generate_merkle_tree( ctx, tree); + if( ret ) + { + return( ret ); + } + + /* Root node is always at position 1, due to 1-based indexing */ + memcpy( ctx->MBEDTLS_PRIVATE(T_1_pub_key), &tree[1], MBEDTLS_LMOTS_N_HASH_LEN ); + + ctx->MBEDTLS_PRIVATE(have_pubkey) = 1; + + return( 0 ); +} + +int mbedtls_lms_gen_privkey( mbedtls_lms_context *ctx, + int ( *f_rng)(void *, unsigned char *, size_t), + void* p_rng, unsigned char *seed, + size_t seed_len ) +{ + unsigned int idx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(have_privkey) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + f_rng( p_rng, ctx->MBEDTLS_PRIVATE(I_key_identifier), + sizeof( ctx->MBEDTLS_PRIVATE(I_key_identifier) ) ); + + ctx->MBEDTLS_PRIVATE(priv_keys) = mbedtls_calloc( MERKLE_TREE_LEAF_AM, + sizeof( mbedtls_lmots_context)); + if( ctx->MBEDTLS_PRIVATE(priv_keys) == NULL ) + { + ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; + goto out; + } + + for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ ) + { + mbedtls_lmots_init( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx] ); + ret = mbedtls_lmots_set_algorithm_type( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx], + ctx->MBEDTLS_PRIVATE(otstype) ); + if( ret) + { + goto out; + } + } + + + for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ ) + { + ret = mbedtls_lmots_gen_privkey( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx], + ctx->MBEDTLS_PRIVATE(I_key_identifier), + idx, seed, seed_len ); + if( ret) + { + goto out; + } + } + + ctx->MBEDTLS_PRIVATE(q_next_usable_key) = 0; + ctx->MBEDTLS_PRIVATE(have_privkey) = 1; + +out: + if( ret ) + { + mbedtls_free( ctx->MBEDTLS_PRIVATE(priv_keys) ); + return( ret ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_LMS_C */ diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index 0a03f02e96..d333f6590f 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -47,7 +47,7 @@ my $error_format_file = $data_dir.'/error.fmt'; my @low_level_modules = qw( AES ARIA ASN1 BASE64 BIGNUM CAMELLIA CCM CHACHA20 CHACHAPOLY CMAC CTR_DRBG DES - ENTROPY ERROR GCM HKDF HMAC_DRBG MD5 + ENTROPY ERROR GCM HKDF HMAC_DRBG LMS LMOTS MD5 NET OID PADLOCK PBKDF2 PLATFORM POLY1305 RIPEMD160 SHA1 SHA256 SHA512 THREADING ); my @high_level_modules = qw( CIPHER DHM ECP MD diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data new file mode 100644 index 0000000000..ed192bf7d7 --- /dev/null +++ b/tests/suites/test_suite_lmots.data @@ -0,0 +1,29 @@ +LMOTS sign-verify test #1 +lmots_sign_verify_test:"c41ba177a0ca1ec31dfb2e145237e65b" + +LMOTS sign-verify test #2 +lmots_sign_verify_test:"55a6647a581004306792b653a561d9f3" + +LMOTS hash-sigs interop test #1 +lmots_verify_test:"C80B24A82D52963AB241C84DCF0EEE55BB24F9F0":"00000004DB3B6B24FD191CE8894AE3C4E2CE2DE0C3F5D508691A9162F37704E07838488466CCD746E55BC8E3055C7A4D4DA2E10775DAFA2E8E5FEFB1CEB25973BC3323B61DE5E2EA7DCFF15DA482320F958023CA2E718C69B977019E8F2FCD47151388E2E5E11170AFE93BDEB508362B3A317835A9DDEB18F0CDCCC0731902DB3D37F441C93A490DE53962A915AB5060A1C157D61DDF061F272362AB7FD9EE95AE48D3448F204C81A3F260792784E1BFB49871A27C09CC549A406520F0B40BC74CAAD082EAAB12C994B8495B8C80E96384FF2222255BE6C4EE5AF439534E616F9C0B53E951F69D59BD0506C0C0366A679A8329ACF6E2D1D4E4EF49D35375A8EA46FCF3C9B2F8E033C242EC61B796E43B901407077A2AF3F0AABD2D0CB9004F10D91B57C2D5E8BA7BA9268FF94962CC102F55B5120D7D2F7A3BE281BA01D78895ADA2F05B77967EDA0E1EDEAFBB9BBC3D68DCBF682FBC70467FA2BEE5DE65F54247C4BE5BEF41F5108B6CD09E7698E3AAEA04B60746EDD0E2623B66B092DDA21EFA5A0D36805D101D805CC06F0E818B46059B3984C8B8A526C4239F66ED34B8CA57E178DC5E7B8D2BE029114B4CE466E2B5A081729B3F3A3F3845DDE177062F201C09125ED3CC381AF35EAD795440C421A136F941F09F3E4BA9E0203CBA875AF477AB0246342700F323E65DC327D27966377D871FD9C58BEC8797DEF35E1D0751A554719828B87332F601884EBFECB63A8D4F390785B3826BFA384BE502D2322C919ABD12A486C2AB124DCB7B74DE91241A30EF0388411E52145A88971C6C0A4E7C4F23EDD8D6008065A3D108C6B1EC5219BB0DFDBD37EE3A7A8DD37E3563A5777838FCA61E9E744813F39CF70B5A0F50E1BD4FF8733A3BDA76D2135969809D91A9786F22DC2ACBA4E0164C411019EC77A0BD253A42AC7528FC7C0DA1711FBD6C23825207060463080F9E04B7D819C8B150C22B8BA87C6277696EC409369C48AC0E3233DE52D31EF6D2207D2B57DFC2D0C43BE8212EAE6CB1BACBC2D3568E5527A14065D5F1F56AAE2AFB5FB1CEFFC228A30692BD030C71F4872DB54F2632CD919DA61576CF58D1EBE3D7988183A9C789EB74A3D7F6BBEBAC035A43397BF684C9E1130B252940DBA4454311A6A3D54D9386D48E1D5A3E70944EDF725AEDC5440CD610F79AB05A43C917FFC15213295EB8CB8432B6554A47C2AD419ADD52E0F5E0BD7A1E0F873257E69F8647F3A07093387B7A64C4812CDBEE536E45D531F89653AC5F14A4715CFF40692346FE6CBF2F9B92D9F1101C379AFD5E6154605059C1DA463B407E79C139396623DC7F15EEFCE424C8E214C6A645EF002F90A230D8F62177CBCF2A688D4F822B119835AD3D3A619F46230257A5AD59CB0924B2584DBA96AADE0A2487E7409EE5993A4F0E3DC46C10B96595CDD17D72C35EF4A52C5906655B0AE649B5DE03B7D46F3839E808761EE05E9300050647593C048669A952324B0188ED225AD11BED3FD94E44E134FB9D6DAD53CC34ECF62695E30637C4528C450D62174E2F8ABA2C09F134412EF889C24B36224BE4259B363A9D8EB89BAEE16BE1898D46":"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A":0 + +LMOTS hash-sigs interop test #2 +lmots_verify_test:"85A77D026E8C704B14EF665DEB0A648350FA8859":"00000004BEEF900CA9A14982E011A5A94503D566288932AD4B9CB85D1551C766A56F788B0D223FBA0E1AD722BE48365B4CE5DA21051B3A79EAD8C1046944192EE51E162DE1E9AE9B13DD8FA90867A17666CB8967F7CD7F4F5383703CCFF555EEBDC8123AF3C4E39D0A5D61725B6A7F23CE587D256C08D31510BCD895106CD524B432A9211CDCBDF5ADDAD5F1D76D428A76DF2556FFA8AB546CFAAA7F2FE86164B976FDA2940498DB0D1A2DE29972FFD55D83E7CA3318DBAC31670565A1E5F59E36342F887E0EF7855AD93CA5F1951307D79EEA375168BC35A3A0B053AEBDB4D7157AD929B0D7DE9FC1E8C32C9A2D679843CBC77560EEDA5959D0AC8407648344C6952649A303E7B6FCC2EE979E1B2786B898A01E2918894DB4E37A0ED79A30260A45959B4BB3016F081181190CB740376389827B2D56DF7EC00871DC9A198B74C7C6086C940A845D54198F2D5DD7A47F97A192F33A85AAA1304A3251B82AC33C5E7B3BA20D2A9BD49BBEE0B2DA2338E578E6F139BB7596DC3BD89E86CB393C42765B9FE85457116906C3F9A8499CF5E539A5CCB3F6D1F36CA209DE6942F807E579AF0EBF072EA110A812C9E420647CE7C8B2BDBB5F56C5B3B7EA80A53C3574F4ED32E4708DFEED60280ABBE2021B3791B0CB09C1F0731353234A6A327CDDFD4E3E2D9DD5A16FCDE3EEF09C67065BD702C07B53A005D3FE7D23FFD77D40E49C82165EB104343A166E808A3CAEDE1A43AE3A82E1788B49C565CF88A2AB8E2FD37657D53E3679D7A818D864F55144011AB498A4A985C46342F3562FD80ECB86497C3DBB759006E5FFFDC01CAA15C69B716174EDCB6E9870CF391003D3826451D1BEFDCC84C093428EE01DAF883190F5D2542B36A7DE44A453AECD5E93B768ACEE75076BE3D73A66F17CFD8E4A49B1F61CE9446815A86FF5FB0EA070A751893C85360C038A161D3DD4D2C66F440E7265153AB346EF620156605C028DD9636FAE0C9A20DF09303ECC5E57A6424505530F70D25F1C95FE51CBD82C2AD0015EB9AD5379CEC463FA0331A14DD971B7C2311FC45979C531653E7252884BAB7C49F8CD652BDF6FDFA76984445C63B54ED22B4A8A267D091381BE7B9B7608133968BA46106BF42B9091F78C085E674D1F70FB91C68D07733F6412B1583DD2F37C6ECAD6BCCE1A1C7D0A7CA80677F679A5AFE08D15427E5C78CE6EB9AA90F51F40343DC9FD1316DCEB2C1EF8EA217B714B0DE1AEECE04D19D0D7757481EDA6E8C51BE85B7B24720E8D62B8AEC56C1A1B9D278B874AACC0B492CF44ED4E7B1200C82323C1AFA0FC776E92B227E8979E3A92EAB05FCF18A43AE648397088F4991F73ECE22C03B3F42F51C0C0FE0DF37919D048FB473F7AB0E33310B9782DE56384BD888CE5E2A644E20A52DD47F710DB0D3169991E29E716ABFD84CA4850080B6C252CB96CD8979189819E532DF56ECB172F773919733BF4D442901EBFB656EBFED4C6D83FAFF288279779499091C94432ECDF83188048AB596D65BC48FA708D485F9CDC50C8B470DFE22157E8F5EE366722A04E8CE7B861573E5FC97D34055BB50B562738F803B202F7F8":"00000004DE9CE10EA7125AC6399B6B3C7EE24224000000161D61E675F3EA19C5B95DA4EE2E35BA061B39E7639F3989F8AE4B0696B3F87E4E":0 + +LMOTS hash-sigs interop test #3 +lmots_verify_test:"C32F83EFBFD87F386A6C0850CBB93A75F2506A35":"00000004BD2D174BEBEEF1CAF06E4BF1088DE2AAB17C0528579BD4E1C4A1ED583C36BDACA49798373961B605EAEFAEFC0B4BC39C7AD30572CD29BEBE9AEE503CA2D8BF8C31C8A1B71CF67A18EE01A8A878699F22A1AEE32731E51E3EAD3775EFD8339E263C5A4544559506BA5502B9AEF59217ABC24923EC5E28D18BA18B0D964DB277007A76B8075B39F48CDA92148C9BAE1C7E5421CA753FA2D6BEAE8F49977E4E5B6F38D35BA28A526A53061E57BB92DA0EBBD4AE01AE9FADBED74F503DC39FA2E10C20B47DFB3DFBE25EC35618D2307D21716B10F8FB5095B42C289D1847E5D6F9988C6763D288667D3B658A4F3613E084DAE8B78E0B295A6ED28E88C676995AA5EB1533CDF8EB6F95A5E5117F06B1759495A9CB6E40FBF1F97FF73FDCBFD315C48DA631AB0425CA0633817C46F25E84AEEA37DD77310EE56815E83F862EF14E15FC1246243AA02F40EA32567237D5ADC2944BD63CF55FA4F0DE251B3F5C067D9EC396D5E20F9CEF2C555D89DA721D91D6D607653B97636AB10B74F39FA984D23A3D276EFF5F49C336274A66AC491EDE34686C6CFC17F5312FD3E3E5749A2E472011FA391A5ACF09D918B01704B447FD5E3EA6BB726A3475775DFE6A98CE5473CDEDB630EA4D604BAF36A8B8A8E567F05929E8A74970AA742FBC945021017E464E753D5AC497925AA4AECA0CBF562B2E39F891E177FD8E4E61A698B099D21F13EFD0DE5357A1970314D8E3AA1D2A84D3BCF75A7876C16F585322CC4C613FE3AC8FEA5F258FC9C7200765E9209378C362AFC1A478A117D913CE2BEFEB51103E48D0802618C50918005F1AA4228B67BA1A1B001A91A032019A135B8AEEE3D0158A602C8DCCE5A6580DECC16204E410CBB15FCF36704BB2ECB826A229E45C454B4A5DFC12796E636B300C624DB4E6EAB424B17A18A5A5F52399F247A1507A5985D06F90889FE381129148AF8447B392D4EC0775D91502B48D9F212FCE3F81639901C462F752E27FBEEC9E2B7F8CCD16053FB839E8ADF8CD3E8FF8AF3B3E884F4F524C2026BD3B337B7058B53CFC7596F9C813FFD746B8AC0012C60E96140934B4EED1D8602E57A1A6EBC01FCFD66053AF9614FAF0D0F7320D50D440F2A3148A0DAEF5E2FA31F854D56045065AFAA52A60DC3321E2D7C104FF505057D55CD94C53C31C14DB0DAA4D55C4065CD9BCD78E1B8532A680F7DC3544021346CC59ADEC061DDA1B7606BAF28AD87C39AB8AF3D03E981EFFE50B4D5347175517EF212E61F02B594A96492091AC82625D334504EF19BEEE52E01B111D43313F35EC69C88EF38926071506AB3A5B372DD6F2B901AC1E12E61CCB3ACD3D0777A7A10F137126DAD0D1970D369A067C3A1F19D9CB8756D7130B7EB0C08CF725EB2ADFAD61204195CE14F3C99A88A9B8FA2FDCBD612DF9266614DEA073C9EDABE07B3793048167D4DA49B305AE27974D48A296871350DE036CAA348D2F9A9CB19DC094E5904E25DDCF5657227DCD2A4E620121FBDA032A58836EDC14F3A7C4E51319A60F91F941CC61757498B769799394574C9D198426AC3499F0D0BA1770AD6BAA0D3716333F785A9D7D":"00000004DA66203A7E7BCA2362DB3C8E897A84B10000000D1BD4EE08FAA341C2CE018BD12776E1B8E6B8B2C1EEDAE6BD0998E52F089936FE":0 + +LMOTS hash-sigs interop negative test (altered random value) +lmots_verify_test:"C80B24A82D52963AB241C84DCF0EEE55BB24F9F0":"00000004CB3B6B24FD191CE8894AE3C4E2CE2DE0C3F5D508691A9162F37704E07838488466CCD746E55BC8E3055C7A4D4DA2E10775DAFA2E8E5FEFB1CEB25973BC3323B61DE5E2EA7DCFF15DA482320F958023CA2E718C69B977019E8F2FCD47151388E2E5E11170AFE93BDEB508362B3A317835A9DDEB18F0CDCCC0731902DB3D37F441C93A490DE53962A915AB5060A1C157D61DDF061F272362AB7FD9EE95AE48D3448F204C81A3F260792784E1BFB49871A27C09CC549A406520F0B40BC74CAAD082EAAB12C994B8495B8C80E96384FF2222255BE6C4EE5AF439534E616F9C0B53E951F69D59BD0506C0C0366A679A8329ACF6E2D1D4E4EF49D35375A8EA46FCF3C9B2F8E033C242EC61B796E43B901407077A2AF3F0AABD2D0CB9004F10D91B57C2D5E8BA7BA9268FF94962CC102F55B5120D7D2F7A3BE281BA01D78895ADA2F05B77967EDA0E1EDEAFBB9BBC3D68DCBF682FBC70467FA2BEE5DE65F54247C4BE5BEF41F5108B6CD09E7698E3AAEA04B60746EDD0E2623B66B092DDA21EFA5A0D36805D101D805CC06F0E818B46059B3984C8B8A526C4239F66ED34B8CA57E178DC5E7B8D2BE029114B4CE466E2B5A081729B3F3A3F3845DDE177062F201C09125ED3CC381AF35EAD795440C421A136F941F09F3E4BA9E0203CBA875AF477AB0246342700F323E65DC327D27966377D871FD9C58BEC8797DEF35E1D0751A554719828B87332F601884EBFECB63A8D4F390785B3826BFA384BE502D2322C919ABD12A486C2AB124DCB7B74DE91241A30EF0388411E52145A88971C6C0A4E7C4F23EDD8D6008065A3D108C6B1EC5219BB0DFDBD37EE3A7A8DD37E3563A5777838FCA61E9E744813F39CF70B5A0F50E1BD4FF8733A3BDA76D2135969809D91A9786F22DC2ACBA4E0164C411019EC77A0BD253A42AC7528FC7C0DA1711FBD6C23825207060463080F9E04B7D819C8B150C22B8BA87C6277696EC409369C48AC0E3233DE52D31EF6D2207D2B57DFC2D0C43BE8212EAE6CB1BACBC2D3568E5527A14065D5F1F56AAE2AFB5FB1CEFFC228A30692BD030C71F4872DB54F2632CD919DA61576CF58D1EBE3D7988183A9C789EB74A3D7F6BBEBAC035A43397BF684C9E1130B252940DBA4454311A6A3D54D9386D48E1D5A3E70944EDF725AEDC5440CD610F79AB05A43C917FFC15213295EB8CB8432B6554A47C2AD419ADD52E0F5E0BD7A1E0F873257E69F8647F3A07093387B7A64C4812CDBEE536E45D531F89653AC5F14A4715CFF40692346FE6CBF2F9B92D9F1101C379AFD5E6154605059C1DA463B407E79C139396623DC7F15EEFCE424C8E214C6A645EF002F90A230D8F62177CBCF2A688D4F822B119835AD3D3A619F46230257A5AD59CB0924B2584DBA96AADE0A2487E7409EE5993A4F0E3DC46C10B96595CDD17D72C35EF4A52C5906655B0AE649B5DE03B7D46F3839E808761EE05E9300050647593C048669A952324B0188ED225AD11BED3FD94E44E134FB9D6DAD53CC34ECF62695E30637C4528C450D62174E2F8ABA2C09F134412EF889C24B36224BE4259B363A9D8EB89BAEE16BE1898D46":"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A":MBEDTLS_ERR_LMOTS_VERIFY_FAILED + +LMOTS negative test (invalid type) #1 +lmots_verify_test:"0000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA + +LMOTS negative test (invalid type) #2 +lmots_verify_test:"0000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA + +LMOTS key import / export test +lmots_import_export_test:"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A" + +LMOTS key reuse test +lmots_reuse_test:"cfcd1e81193e310c9d931d1b00818d14" diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function new file mode 100644 index 0000000000..6de94d1247 --- /dev/null +++ b/tests/suites/test_suite_lmots.function @@ -0,0 +1,108 @@ +/* BEGIN_HEADER */ +#include "mbedtls/lmots.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES + * depends_on:MBEDTLS_LMOTS_C:MBEDTLS_SHA256_C:MBEDTLS_CTR_DRBG_C + * END_DEPENDENCIES + */ + +/* BEGIN_CASE */ +void lmots_sign_verify_test ( data_t * msg ) +{ + mbedtls_lmots_context ctx; + unsigned char sig[MBEDTLS_LMOTS_SIG_LEN]; + mbedtls_entropy_context entropy_ctx; + mbedtls_ctr_drbg_context drbg_ctx; + uint8_t seed[16]; + + mbedtls_entropy_init( &entropy_ctx ); + mbedtls_ctr_drbg_init( &drbg_ctx ); + mbedtls_lmots_init( &ctx ); + + TEST_ASSERT( mbedtls_ctr_drbg_seed( &drbg_ctx, mbedtls_entropy_func, + &entropy_ctx, (uint8_t*)"", 0 ) == 0 ); + TEST_ASSERT( mbedtls_ctr_drbg_random( &drbg_ctx, seed, sizeof( seed ) ) == 0 ); + + TEST_ASSERT( mbedtls_lmots_set_algorithm_type(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8) == 0 ); + TEST_ASSERT( mbedtls_lmots_gen_privkey(&ctx, (uint8_t[16]){0}, 0x12, seed, sizeof( seed ) ) == 0 ); + TEST_ASSERT( mbedtls_lmots_gen_pubkey(&ctx) == 0 ); + TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, msg->x, msg->len, sig ) == 0 ); + TEST_ASSERT( mbedtls_lmots_verify(&ctx, msg->x, msg->len, sig) == 0 ); + +exit: + mbedtls_entropy_free( &entropy_ctx ); + mbedtls_ctr_drbg_free( &drbg_ctx ); + mbedtls_lmots_free( &ctx ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void lmots_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, + int expected_rc ) +{ + mbedtls_lmots_context ctx; + + mbedtls_lmots_init( &ctx ); + + mbedtls_lmots_import_pubkey( &ctx, pub_key->x ); + + TEST_ASSERT(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x ) == expected_rc ); + +exit: + mbedtls_lmots_free( &ctx ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void lmots_import_export_test ( data_t * pub_key ) +{ + mbedtls_lmots_context ctx; + uint8_t exported_pub_key[MBEDTLS_LMOTS_PUBKEY_LEN]; + + mbedtls_lmots_init( &ctx ); + TEST_ASSERT( mbedtls_lmots_import_pubkey( &ctx, pub_key->x ) == 0 ); + TEST_ASSERT( mbedtls_lmots_export_pubkey( &ctx, exported_pub_key ) == 0 ); + + TEST_ASSERT( memcmp( pub_key->x, exported_pub_key, MBEDTLS_LMOTS_PUBKEY_LEN ) == 0 ); + +exit: + mbedtls_lmots_free( &ctx ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void lmots_reuse_test ( data_t * msg ) +{ + mbedtls_lmots_context ctx; + unsigned char sig[MBEDTLS_LMOTS_SIG_LEN]; + mbedtls_entropy_context entropy_ctx; + mbedtls_ctr_drbg_context drbg_ctx; + uint8_t seed[16]; + + mbedtls_entropy_init( &entropy_ctx ); + mbedtls_ctr_drbg_init( &drbg_ctx ); + TEST_ASSERT( mbedtls_ctr_drbg_seed(&drbg_ctx, mbedtls_entropy_func, + &entropy_ctx, (uint8_t*)"", 0 ) == 0 ); + + mbedtls_ctr_drbg_random( &drbg_ctx, seed, sizeof( seed ) ); + + mbedtls_lmots_init( &ctx ); + TEST_ASSERT( mbedtls_lmots_set_algorithm_type( &ctx, MBEDTLS_LMOTS_SHA256_N32_W8 ) == 0 ); + TEST_ASSERT( mbedtls_lmots_gen_privkey(&ctx, (uint8_t[16]){0}, 0x12, seed, sizeof( seed ) ) == 0 ); + TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, msg->x, msg->len, sig ) == 0 ); + + /* Running another sign operation should fail, since the key should now have + * been erased. + */ + TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, msg->x, msg->len, sig ) != 0 ); + +exit: + mbedtls_entropy_free( &entropy_ctx ); + mbedtls_ctr_drbg_free( &drbg_ctx ); + mbedtls_lmots_free( &ctx ); +} +/* END_CASE */ diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data new file mode 100644 index 0000000000..b17fddc153 --- /dev/null +++ b/tests/suites/test_suite_lms.data @@ -0,0 +1,32 @@ +LMS sign-verify test +lms_sign_verify_test:"c41ba177a0ca1ec31dfb2e145237e65b" + +LMS hash-sigs interop test #1 +lms_verify_test:"D5557C719EBB0DBECF563E5CDB16568BB11CD779":"0000000000000004C167A9AC495BD4EA34CD8EE5AAA2A656D518C33612FD87171421BFC3977CFA99765C6D496499C72A1DE21360DA57EB96BC83DB8AA92E560054C7805B04E336162FB4C411B509F76959F2458B0E53CF830E0145CCD439D494259EA4818CA68924A7E8B9DD36D6A9C7849B72F9338ED6C80A3E70B717E8E65B991B2FF9D8B49820E8ABC9E2ECC17DB38E855DA75D84DF9885C7F9DFB4ABC209CFF1D37D66595371D688A203CB89168945200C39169F784B19665CE1FB47D58BFA734C3E0E7E31D1206A033C6D8E25B7E45CA779A5FDE00C6B1CAC44884F2B52A380E1F6D8753549F7F4948A95AEA83703CF3AA108FA4F735AFC0DA1A03C378033D8B5959E7BE05D3C5070E709181AC09EFEC04128ABD7E8F37304FAD4B66373D4A83CFC1EF632DF6DB95577C2C6101CBDC807109ED8AE831FFB73DBC80942C58F334663B980F982C74B943BF7C57147250AADE595310387E3BB1A2705E9EC73DE7FABDA5EC0B1141A18798215B9A70F8D688357C833ED869059A2AA3360155EF84426288198D0FBB78223816B17093684C48942ED18FCD351C34E108E5B71D1CE39E318B5D991B650C46A91112E013E1180F2054C7A22429CAB31512BA34EA3AD9B68C5001EB70C993297CCF11914ECAF059922DAEE7D90ACE2567495ADA066E7DA1679CA45DAC1990B17184E7BE2E6A0F26AD77F19855D074F5B37372277484CE30B80A0540173C1B310C3E7B683A487B5D0676218EA1F65FEA444C493FC535E948EAB62252DCC90516BB45B60D4253DB6979FE342DC5CA1B86B01B2D8EBA79B0BC7B6984535616B792BB45F3C0E20B506E0694E1D5BA28FE96D34FE2BE354777D090404DD3508E9F7918FF5593ADB468478CA8A1F6AF752CC76F401E373B71471D9D70F455C8A73E4E7B6714394B1DD0E2A816AF3D5149835DAE477A70DEE0BDAC22F99A04BFB7C2D4AD53079C326F620DFD3F7CED4AB7F2E291507AA046331050F9E2205C52B36CBAEE817C5C3B1FBCDE61C54C8CB7B67E0570FA44728EC8FD091D5CEDC19C6B99840F7A0E49086F707E959D34B30E255B67BBAA24FADE532BF3D21825626E114BD8213170B0C2F01733D4ED420D01EE3ACD5F84DACE674AE7127DB0A80ACE252CAD9ADADDAFAB27281AFD6DDD72DB5AF878326C45D7DB1EFF8BC40895A3473A52461D076881310AD9937307217B5C0448B509EF9BA075936CC09E11B8838D3A6BC5EF9FAEA85A3EC87EEFDF2E38CD9732730085375A4FFC4E0A213B0E1FC3DE2D37F1EDACC3030F617F3459A03BFCF776A05FD3B7FD135782F6D6E7C5E92B56A1316525B26D3AE1CEA3C0C7CF3AA7B1E72B7599A31B50837D79A7AB61B9A9E2B7AABD2D605C97E302EB4B66C0588C24147955EA0892A54D42843568FE0863E7EFEAE336D302E672EA62689B4DAA02DD5BC99D93886EC7F411C53CE1CAEAB59FBC0B06E0E294F1900F8C626C6FF520AE2323DA797CDC120DBC19F7FEBA0E13429508C5B838A0F8B9B28A069C5DD40E2F6CC2C95FC6ACE7E1351516817BD2DC1AE08D498AD2B0BD1D8374942FF31FC6A4689C592244C919C3561E73DD4986FA500000006BBF34F6EE152B64FCDD1CB6848D2DA761798707060431761006E2EBD9312851F4F3DF3C46E10F643DDD58CB3D9F4D371F655EE26271F2DDE84A14CAA6A077DD96AF83849DE6CA8F2F3248902CBF49630C18C3EE3123D951CE9162D0E742B899AF9E5DA8D28A41C7CADF0194CDB09418BF48BF322F8C5E9563524196FA8AB785B43C4EA41A36148028D2F4C7356CDEEB09532CD7F2C80FC36589FF7A9954100C8697AEB014997C3088C242B4F70D26CE7F7E77384A9CF536EC5C5329E08BD6C1D65EFEFC1389A42D16FFB43A0E1D7661220E92A4A59703FB28410E73A677E803D4441929DFD7269E6F77AE8CA8C70B67B250A8728291EA5D4E3F03D505639408C88156DCBECC137142FA3585C09D99B84D8C380A5D29CE2ADA10A25F7CF939FE23288551F37FE2B7233BF97C0F5726B972E087BCBA095957CCD794794A4F50027":"00000006000000046B0927585C8547228D495361D73B970C287A2254BF8F1B170E55ACC9520A56CE5D2C711B6617718B49247D28CCC6D11D":0 + +LMS hash-sigs interop test #2 +lms_verify_test:"DA16BE0B8FB691248486ACAFD531BE6EE4C362E0":"000000000000000484FCD0D791D175A0F86D64B2E8949F793CA9FFDC0347DE125DDB2F895BB9D2B43740B9B326B24F934D67586812BE6F3FB57E76FB12FBAD60A685F22A82C95C84AFAE63F47BB3CD951D483F61F5626B2B5FB6FDCA0CF02293EFDE1EB0AF6712D635678E825099E95435B43EF83C49C6589054D0905D82D597FB11A721D2232AD168FD179724539699C21163D5ADEB52290CB711C368572FF8BB95AA61DF2AD128307E768E73D3CF2BAFEAC8B6CD165BDD0316D2663D1ED61A15FB974082FC66A55E13ABA4FD084970EF6A59B0DFA1E934BF0E056C86E9B4C5B94CF863AB9F23BE2DB6A140A9CAA8DB31C83B21BDBDCD07304A52EB8501869D86BFDB68A376D94F847EED7E4CAB6A6EEC063945AE4DAF657D5509249E7FE430F5A13B188C4DD311F01746CE28F4F6540041EF6ADB299F712F591C83B0C12C1FB3E4A878C63217E25E08C004571FFC69E9C684E46F4D36C36409EBF3EB15F32A187176F4D177E0FE0E71ADFD4DA4AD2D57A0256B29AD5DAA6867AED20CC862AF5729D030514D41BB8D74551D8E925322C81A357A586227BBC885AB683BF835E9333A056AFEE96F2AD0FF6D6E235A9E2BC342ACBCF0B8EACC95E7B74215F6C65F12829433301F004EE1D9CFD16A4A1D092F48E99AEAE9E1FA4619ECE5E05F5C19F33C4C94A774EB8955409E3CFA73D8807CAA7C55FE45E980C7E7626AAA193F18A3AA7E525FFA6466D728FA25563DD383D855A0B6F8C011AC8C79C853CBED3A016DC26EF6E90B3E78119E465B9962A42B6AC168C1CDC9DB860D740B0C797303E2A62445FA618B5EB417BD4385C15BC548FEDF4D4842CA43F95188FFF63EB5D4AC85DAE618FDFB6CF5969EA0A3A52F73A4AC4957BC4EBCFEF593923EC79196021B25ED8D7558E4AF41ED74941585AC575CF1971D4F4C7C9E9516276734FF9FAFC7DE661F3090F71C98962789B31EA0FE406E2EF02F6F16B1708258C7559B8E05E27D647AD472805C865299FE30A5FE451DA7F2C493A37AA1655D492EC891B9AF559E12104CDD2EEB2E54138A1FB5A403AA32CEEB3946471A299604FA2DD3CA3E9567D01A3CEE5D09A1C2768B521C0C6142AF297CA5BFB3878B32D37D415542C15F655CB051240F3BA8FCE0E38449A0D7010A9B56BA2283E3A2047215813ED2090F7BDF16A40ADE32AB4E669684E6DEB6A94633E6643F29D10914F5A361C964CA9145514D4B80B45F3276EB0C649622034E71925FA038EB35E64C71CBDB11E91D779339516A351BD2A722CB60C2CBF145689B2E3F6FAEB74C3B58283929F70023503A96FED6A5D7D8A9E495FE1D85E0FCEC555F86747347D2FB5219FF65EFD144A5E1E88C63BE4259C42F6899C103536D75E0526508649E2836CACB94E88BD954B88EAC26F17B27BF62546C5C7573E2BC9EF4B65B8AE4951AF532F968FF050E504CC236DC48379E4390079DE451DCE710F9674D753C85B9FF7E7B09ED051EDD14C33AAFC8A188AE06234DFB61FE5A75C7A760B5286E1D6993BCEA0AB8A2C1D632145BD6A9F109ABB04E0B102D50DCB8C607AD6BA8C5FA5B21663E5A40194CA5DC2294BE10044E8D96AA0000000694ABC63BC5B27730C5223943C8341461474033BE3A221AFFDE66242AF14510CC656480CBDFC0B35205C89258A18BF6C29C4708CB2572DE15EE5DD481BC47060254954B5C5DD881AE6B358F7CDAB6F117235AAAC625B2750DB72BA4A96D7DFAA889BE780416E1CB264A413C6713710102D1D433BC6D0A47BF08AA74FD613D292A867261181BBD73557EE3AEB0F63579B71E58E97BAC1AACA3F34646350A13BB7ACE0AB3B062C41518768ABF3D32FB2F6A5E5C7F6B8B04C943D25A82F03F977755D74FD717A4B7E7674B03B577405210E23A2FE050E036DB0730359366A9436AD2CBCCE3E649F9E40023B2C12D9F5AA824319EAF571FD4842E573BB100BE9715D7B71F75521640D9B69B889349A283D62350D3A37264C89930F40603A5458B124EA850BA59024A46A8F325C9A9776817D739692FFAEA2758249888BF79D66FD496":"00000006000000043FC8322D04908C7C06C0D8B7A0CE24FA3AC253393CF9A56CF760294A06E75223E38C9E5329DDC493D8B51B1A4BBE41F8":0 + +LMS hash-sigs interop test #3 +lms_verify_test:"331D543362A163390508127AFB9894B8C18C6E0A":"0000000000000004F5378439E9C229550D40B725FD56BE48DB785093E62BD29B723C61FABEDCFD486EFA120445339DE2A21A8C7465073ACBFD6DE3E50F395AAC20E0BCB23B088C416199F80B540AA81B2C0B12B7785152263522E8F79AEBE3B28315CC834AEB68475CADBC724DB6B7B7F594A7F9DA2505F5F44DAA7EEF70B72665A250C1F61A19F3FA4CBF389BEB9B31DC327882D7983EEED46DA8E00AEBEF85AE179EBF6D8CC7F720E9F963C4D30DD4015DAA27993D0780AFD7A45688422B1444AD866FEFE12EBD94B4D313517708A6E652D6206A8B263E234685D8133C2258EF6CA9E9C6FFD6D153598B13B59576897DC4F77C71609427866A347AE62B5C3BACB0A2E44B60F2CCB4989B0C57F3E785CDCF22B1FC8C3460A163FF2BE7A578E82429BA823F392A13C11A5639A42453972D2185E81809EF0666F8F01F575FBD9A46135F45651AA814D9BA84F774A9E9303FD55038CA41A21484BA9C38E69BCE4E37052971690ED3EEC4ED9AD41B0AEAE4DCC913443B9FA5418FB75DC1725FA989BA8DB5D9E221804FC7F36F3135C8B93AFF66DF89408CFD50993D308E51DF00540F380C0AD06266B80F646B917BA58384B55658EAD2D453766C4843FCDD934E8352A6DF6A081A15BDE07BF67E977E72BFE1AC37F411111A0A4D101A2CCF95EBEC7FCFC82B45DBA88939B0831987AE4D15C05A2E08F713BB0B6BB0E2436B7F9C83D2D869432465DEB9185913DE215937EFB4A52DA50BEF88688F5AB4397A04B14CDBFA5BFD948CD6EA1122D9D3C2927DE9D066297AA2C6FE8E478EC0F41459287EF9B8A1A56164C72AE3DCE5E914E8BC3C3821E0ADD6D1C9048D71BD71F71F3A6E04E63687298DE5A3704ADA82AA369CCD7F342F79E988A7BE066CA55944E0E3712F472891761E5617DC048C69AA4C250AA1560D6591FC0E7492027BEED67310E3482B1487E41DEA5E070894A5FB93FF4462D1F60C4B1CA7C15275EEA2B3790ED12EA930FD7F7F07D60807E4AAB73D1F889DABF2E687A487F331AC17D8DE24E8448E672F87424F0D1A73721A1A987519D0E3BB91D15D012B1FCDB6E23EEA17E93869C5199984CE8A068CA96C3096273F8B23160A79EE0C208D9B70ED5E23CB3586DFD33E02D06F1C646250BD664C27D2BB9614FF5F043A6FEE1A235DA10DCAADB19205CB839BD616BB36B738AA28E1D4F767BD8BAB6C2F84887C7B2E16CF6E07AF90C1FCB6E6E5A4CC894072AF4393C63F7119FF694BF0A043AF5F0825557A99C40BABBDA97D5648687D493367812743335A8AD7696562538C8BA5DED182C4DC818E7E9F630B29A9534E2583E0F4B5862D4E4DB250A350BAF360EF133838FE55AA683E253746A704654EF692F4F818F5A172AB0B84673D0AF77CC1DF189AA5BB013E833D1B0943918768AC6A83E6BFB306D3C3786BD2C87129BFEA1C380A84C4983D262184427284BF3DEB9B4C58FB1899B07B9F60B4402618168B1445653E8E48CD92C048684302A6F5C217F110D6699707BA42316CB31FE8F4DA6B82243CF1264751225594AF1BB670339A9189163DB9E985A99BCF83A3039AF3E65BBCD8364745356B29D761853E00000006CDE5B63B9763DA3EABCFFDA517688BDEC2AE9213E6B0FD7003D95458798AE9449DE4F1135E093B39F597A34B14AAB7F596E25BA469533442F54C14921ABCC5D04A05486CD16C8564E6A19C11BEDA574A9800107DCEAD013A7E6A32966B5BBE9FDFDB0184FE0707209B6D9EC43066899717E487E5FDEE02061EA5069B2D6C9C87D6BEB1310F1B9E723AE372DB7BE9EF6657F51FD0DE62464D3B37755095829F625EA76F5FD7FCD5829863F963FCD7F9FFFF3729688D025DF7952B067C62198E4C6CE06E960B0BAC6ADBC9459D9AC0BE1BAD46F95A121BBBE6953BAA10252419E2AB6BCA1B0AA1FA64DF728160B4FB7A62499C24D269FF59977649064C5986D615E6952EA0DA5B1C04C443BC27A63D391D5BFAE824F0161791E65896DC100EAF80037FD800A5079337554BD990E0D0A1A4C4C45741E72FB3E840665F2881D2CCC5":"000000060000000461F2DF219685CF313043780A57C18071725490AB8D53B676D484238BA8C373572407938CC578045649964958C0A872FA":0 + +LMS hash-sigs interop negative test (altered random value) +lms_verify_test:"D5557C719EBB0DBECF563E5CDB16568BB11CD779":"0000000000000004B167A9AC495BD4EA34CD8EE5AAA2A656D518C33612FD87171421BFC3977CFA99765C6D496499C72A1DE21360DA57EB96BC83DB8AA92E560054C7805B04E336162FB4C411B509F76959F2458B0E53CF830E0145CCD439D494259EA4818CA68924A7E8B9DD36D6A9C7849B72F9338ED6C80A3E70B717E8E65B991B2FF9D8B49820E8ABC9E2ECC17DB38E855DA75D84DF9885C7F9DFB4ABC209CFF1D37D66595371D688A203CB89168945200C39169F784B19665CE1FB47D58BFA734C3E0E7E31D1206A033C6D8E25B7E45CA779A5FDE00C6B1CAC44884F2B52A380E1F6D8753549F7F4948A95AEA83703CF3AA108FA4F735AFC0DA1A03C378033D8B5959E7BE05D3C5070E709181AC09EFEC04128ABD7E8F37304FAD4B66373D4A83CFC1EF632DF6DB95577C2C6101CBDC807109ED8AE831FFB73DBC80942C58F334663B980F982C74B943BF7C57147250AADE595310387E3BB1A2705E9EC73DE7FABDA5EC0B1141A18798215B9A70F8D688357C833ED869059A2AA3360155EF84426288198D0FBB78223816B17093684C48942ED18FCD351C34E108E5B71D1CE39E318B5D991B650C46A91112E013E1180F2054C7A22429CAB31512BA34EA3AD9B68C5001EB70C993297CCF11914ECAF059922DAEE7D90ACE2567495ADA066E7DA1679CA45DAC1990B17184E7BE2E6A0F26AD77F19855D074F5B37372277484CE30B80A0540173C1B310C3E7B683A487B5D0676218EA1F65FEA444C493FC535E948EAB62252DCC90516BB45B60D4253DB6979FE342DC5CA1B86B01B2D8EBA79B0BC7B6984535616B792BB45F3C0E20B506E0694E1D5BA28FE96D34FE2BE354777D090404DD3508E9F7918FF5593ADB468478CA8A1F6AF752CC76F401E373B71471D9D70F455C8A73E4E7B6714394B1DD0E2A816AF3D5149835DAE477A70DEE0BDAC22F99A04BFB7C2D4AD53079C326F620DFD3F7CED4AB7F2E291507AA046331050F9E2205C52B36CBAEE817C5C3B1FBCDE61C54C8CB7B67E0570FA44728EC8FD091D5CEDC19C6B99840F7A0E49086F707E959D34B30E255B67BBAA24FADE532BF3D21825626E114BD8213170B0C2F01733D4ED420D01EE3ACD5F84DACE674AE7127DB0A80ACE252CAD9ADADDAFAB27281AFD6DDD72DB5AF878326C45D7DB1EFF8BC40895A3473A52461D076881310AD9937307217B5C0448B509EF9BA075936CC09E11B8838D3A6BC5EF9FAEA85A3EC87EEFDF2E38CD9732730085375A4FFC4E0A213B0E1FC3DE2D37F1EDACC3030F617F3459A03BFCF776A05FD3B7FD135782F6D6E7C5E92B56A1316525B26D3AE1CEA3C0C7CF3AA7B1E72B7599A31B50837D79A7AB61B9A9E2B7AABD2D605C97E302EB4B66C0588C24147955EA0892A54D42843568FE0863E7EFEAE336D302E672EA62689B4DAA02DD5BC99D93886EC7F411C53CE1CAEAB59FBC0B06E0E294F1900F8C626C6FF520AE2323DA797CDC120DBC19F7FEBA0E13429508C5B838A0F8B9B28A069C5DD40E2F6CC2C95FC6ACE7E1351516817BD2DC1AE08D498AD2B0BD1D8374942FF31FC6A4689C592244C919C3561E73DD4986FA500000006BBF34F6EE152B64FCDD1CB6848D2DA761798707060431761006E2EBD9312851F4F3DF3C46E10F643DDD58CB3D9F4D371F655EE26271F2DDE84A14CAA6A077DD96AF83849DE6CA8F2F3248902CBF49630C18C3EE3123D951CE9162D0E742B899AF9E5DA8D28A41C7CADF0194CDB09418BF48BF322F8C5E9563524196FA8AB785B43C4EA41A36148028D2F4C7356CDEEB09532CD7F2C80FC36589FF7A9954100C8697AEB014997C3088C242B4F70D26CE7F7E77384A9CF536EC5C5329E08BD6C1D65EFEFC1389A42D16FFB43A0E1D7661220E92A4A59703FB28410E73A677E803D4441929DFD7269E6F77AE8CA8C70B67B250A8728291EA5D4E3F03D505639408C88156DCBECC137142FA3585C09D99B84D8C380A5D29CE2ADA10A25F7CF939FE23288551F37FE2B7233BF97C0F5726B972E087BCBA095957CCD794794A4F50027":"00000006000000046B0927585C8547228D495361D73B970C287A2254BF8F1B170E55ACC9520A56CE5D2C711B6617718B49247D28CCC6D11D":MBEDTLS_ERR_LMS_VERIFY_FAILED + +LMS negative test (invalid lms type) #1 +lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000700000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS negative test (invalid lms type) #2 +lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000500000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS negative test (invalid lm_ots type) #1 +lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS negative test (invalid lm_ots type) #2 +lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS negative test (invalid leaf ID) +lms_verify_test:"0000000000000000000000000000000000000000":"000004000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_VERIFY_FAILED + +LMS import/export test +lms_import_export_test:"00000006000000046B0927585C8547228D495361D73B970C287A2254BF8F1B170E55ACC9520A56CE5D2C711B6617718B49247D28CCC6D11D" diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function new file mode 100644 index 0000000000..b19d074fa7 --- /dev/null +++ b/tests/suites/test_suite_lms.function @@ -0,0 +1,85 @@ +/* BEGIN_HEADER */ +#include "mbedtls/lms.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES + * depends_on:MBEDTLS_LMS_C:MBEDTLS_SHA256_C:MBEDTLS_CTR_DRBG_C + * END_DEPENDENCIES + */ + +/* BEGIN_CASE */ +void lms_sign_verify_test ( data_t * msg ) +{ + mbedtls_lms_context ctx; + unsigned char sig[MBEDTLS_LMS_SIG_LEN]; + mbedtls_entropy_context entropy_ctx; + mbedtls_ctr_drbg_context drbg_ctx; + uint8_t seed[16]; + int rc; + + mbedtls_entropy_init( &entropy_ctx ); + mbedtls_ctr_drbg_init( &drbg_ctx ); + mbedtls_lms_init( &ctx ); + + TEST_ASSERT( mbedtls_ctr_drbg_seed( &drbg_ctx, mbedtls_entropy_func, + &entropy_ctx, ( uint8_t* )"", 0 ) == 0 ); + TEST_ASSERT( mbedtls_ctr_drbg_random( &drbg_ctx, seed, sizeof( seed ) ) == 0 ); + + TEST_ASSERT( mbedtls_lms_set_algorithm_type( &ctx, MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8 ) == 0 ); + + /* Allocation failure isn't a test failure, since it likely just means there's not enough memory to run the test */ + rc = mbedtls_lms_gen_privkey( &ctx, mbedtls_ctr_drbg_random, &drbg_ctx, seed, sizeof( seed ) ); + TEST_ASSUME( rc != MBEDTLS_ERR_LMS_ALLOC_FAILED ); + TEST_ASSERT( rc == 0 ); + + TEST_ASSERT( mbedtls_lms_gen_pubkey( &ctx) == 0 ); + + TEST_ASSERT( mbedtls_lms_sign( &ctx, mbedtls_ctr_drbg_random, &drbg_ctx, msg->x, msg->len, sig ) == 0 ); + + TEST_ASSERT( mbedtls_lms_verify( &ctx, msg->x, msg->len, sig) == 0 ); + +exit: + mbedtls_entropy_free( &entropy_ctx ); + mbedtls_ctr_drbg_free( &drbg_ctx ); + mbedtls_lms_free( &ctx ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void lms_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, + int expected_rc ) +{ + mbedtls_lms_context ctx; + + mbedtls_lms_init( &ctx); + + mbedtls_lms_import_pubkey( &ctx, pub_key->x ); + + TEST_ASSERT( mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x ) == expected_rc ); + +exit: + mbedtls_lms_free( &ctx ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void lms_import_export_test ( data_t * pub_key ) +{ + mbedtls_lms_context ctx; + uint8_t exported_pub_key[MBEDTLS_LMS_PUBKEY_LEN]; + + mbedtls_lms_init(&ctx); + TEST_ASSERT( mbedtls_lms_import_pubkey( &ctx, pub_key->x ) == 0 ); + TEST_ASSERT( mbedtls_lms_export_pubkey( &ctx, exported_pub_key) == 0 ); + + ASSERT_COMPARE( pub_key->x, MBEDTLS_LMS_PUBKEY_LEN, + exported_pub_key, MBEDTLS_LMS_PUBKEY_LEN ); + +exit: + mbedtls_lms_free( &ctx ); +} +/* END_CASE */ + From c464746d456557135ec04b22c602865dc532ff8c Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 15 Jun 2022 12:17:51 +0100 Subject: [PATCH 002/104] Document LMS and LMOTS contexts And add some comments about the source of their type IDs Signed-off-by: Raef Coles --- include/mbedtls/lmots.h | 31 +++++++++++++++++++++---------- include/mbedtls/lms.h | 29 +++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/include/mbedtls/lmots.h b/include/mbedtls/lmots.h index a177ad4a57..c98f3bfd7e 100644 --- a/include/mbedtls/lmots.h +++ b/include/mbedtls/lmots.h @@ -59,8 +59,8 @@ extern "C" { #endif -/* We are only implementing a subset of the types, particularly n32_w8, for the - * sake of simplicty +/* https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml + * We are only implementing a subset of the types, particularly n32_w8, for the sake of simplicty. */ typedef enum { MBEDTLS_LMOTS_SHA256_N32_W8 = 4 @@ -68,14 +68,25 @@ typedef enum { typedef struct { - unsigned char MBEDTLS_PRIVATE(have_privkey); - unsigned char MBEDTLS_PRIVATE(have_pubkey); - unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); - unsigned int MBEDTLS_PRIVATE(q_leaf_identifier); - unsigned char MBEDTLS_PRIVATE(q_leaf_identifier_bytes)[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]; - mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); - unsigned char MBEDTLS_PRIVATE(priv_key[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32]); - unsigned char MBEDTLS_PRIVATE(pub_key[32]); + unsigned char MBEDTLS_PRIVATE(have_privkey); /*!< Whether the context contains a private key. + Boolean values only. */ + unsigned char MBEDTLS_PRIVATE(have_pubkey); /*!< Whether the context contains a public key. + Boolean values only. */ + unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key + identifier. */ + unsigned int MBEDTLS_PRIVATE(q_leaf_identifier); /*!< Which leaf of the LMS key this is. + 0 if the key is not part of an LMS key. */ + unsigned char MBEDTLS_PRIVATE(q_leaf_identifier_bytes)[MBEDTLS_LMOTS_Q_LEAF_ID_LEN];/*!< The + leaf identifier in network bytes form. */ + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as + per IANA. Only SHA256_N32_W8 is currently + supported. */ + unsigned char MBEDTLS_PRIVATE(priv_key[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32]); /*!< The private + key, one hash output per byte of the encoded + symbol string P (32 bytes of hash output + + 2 bytes of checksum). */ + unsigned char MBEDTLS_PRIVATE(pub_key[32]); /*!< The public key, in the form of a SHA256 + output. */ } mbedtls_lmots_context; diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 868a667e6a..2de03f7ef6 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -58,20 +58,33 @@ extern "C" { #endif +/* https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml + * We are only implementing a subset of the types, particularly H10, for the sake of simplicty. + */ typedef enum { MBEDTLS_LMS_SHA256_M32_H10 = 0x6, } mbedtls_lms_algorithm_type_t; typedef struct { - unsigned char MBEDTLS_PRIVATE(have_privkey); - unsigned char MBEDTLS_PRIVATE(have_pubkey); - unsigned char MBEDTLS_PRIVATE(I_key_identifier)[MBEDTLS_LMOTS_I_KEY_ID_LEN]; - mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); - mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); - unsigned int MBEDTLS_PRIVATE(q_next_usable_key); - mbedtls_lmots_context *MBEDTLS_PRIVATE(priv_keys); - unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES]; + unsigned char MBEDTLS_PRIVATE(have_privkey); /*!< Whether the context contains a private key. + Boolean values only. */ + unsigned char MBEDTLS_PRIVATE(have_pubkey); /*!< Whether the context contains a public key. + Boolean values only. */ + unsigned char MBEDTLS_PRIVATE(I_key_identifier)[MBEDTLS_LMOTS_I_KEY_ID_LEN]; /*!< The key + identifier. */ + mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per + IANA. Only SHA256_M32_H10 is currently + supported. */ + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as + per IANA. Only SHA256_N32_W8 is currently + supported. */ + unsigned int MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not + been used. */ + mbedtls_lmots_context *MBEDTLS_PRIVATE(priv_keys); /*!< The private key material. One OTS key + for each leaf node in the merkle tree. */ + unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES]; /*!< The public key, in + the form of the merkle tree root node. */ } mbedtls_lms_context; From 0aa18e041fe03a841a190e00f36395f0286dba8c Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 15 Jun 2022 13:05:56 +0100 Subject: [PATCH 003/104] Note that LMS sign function is for testing only Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 2de03f7ef6..77559e24b7 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -34,7 +34,7 @@ #define MBEDTLS_ERR_LMS_VERIFY_FAILED -0x0015 /**< LMS signature verification failed */ #define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ -#define MBEDTLS_LMS_TYPE_LEN (4) +#define MBEDTLS_LMS_TYPE_LEN (4) #define MBEDTLS_LMS_H_TREE_HEIGHT (10) #define MBEDTLS_LMS_M_NODE_BYTES (32) @@ -123,6 +123,10 @@ int mbedtls_lms_set_algorithm_type( mbedtls_lms_context *ctx, * \brief This function creates a LMS signature, using a * LMOTS context that contains a private key. * + * \note This function is intended for _testing purposes + * only_, due to complexities around updating stateful + * keys. + * * \note Before this function is called, the context must * have been initialized and must contain a private * key. From 2ad6e611f06a32a0721a1df2c625bc731d6e04f4 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 24 Aug 2022 13:33:35 +0100 Subject: [PATCH 004/104] Update LMS/LMOTS documentation Signed-off-by: Raef Coles --- ChangeLog.d/LMS.txt | 15 ++++++------- include/mbedtls/lmots.h | 49 +++++++++++++++++++++++++++++++++++------ include/mbedtls/lms.h | 41 +++++++++++++++++++++++++++++----- 3 files changed, 85 insertions(+), 20 deletions(-) diff --git a/ChangeLog.d/LMS.txt b/ChangeLog.d/LMS.txt index 0f09f01860..6de374f865 100644 --- a/ChangeLog.d/LMS.txt +++ b/ChangeLog.d/LMS.txt @@ -1,12 +1,11 @@ Features - * Add the LMS post-quantum-safe stateful-hash asymmetric signature scheme - as defined in RFC8554 and NIST.SP.200-208. This currently only supports - one parameter set (LMS_SHA256_M32_H10), meaning that each private key can - be used to sign 1024 messages. As such, it is not intended for use in TLS, - but instead for verification of assets transmitted over an insecure - channel, particularly firmware images. This is one of the signature - schemes recommended by the IETF draft SUIT standard for IOT firmware - upgrades (RFC9019). + * Add the LMS post-quantum-safe stateful-hash asymmetric signature scheme. + Signature verification is production-ready, but generation is for testing + purposes only. This currently only supports one parameter set + (LMS_SHA256_M32_H10), meaning that each private key can be used to sign + 1024 messages. As such, it is not intended for use in TLS, but instead for + verification of assets transmitted over an insecure channel, particularly + firmware images. * Add the LM-OTS post-quantum-safe one-time signature scheme, which is required for LMS. This can be used independently, but each key can only be used to sign one message so is impractical for most circumstances. diff --git a/include/mbedtls/lmots.h b/include/mbedtls/lmots.h index c98f3bfd7e..d89f5bb1c0 100644 --- a/include/mbedtls/lmots.h +++ b/include/mbedtls/lmots.h @@ -2,7 +2,9 @@ * \file lmots.h * * \brief This file provides an API for the LM-OTS post-quantum-safe one-time - * public-key signature scheme. + * public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. + * This implementation currently only supports a single parameter set + * MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity. */ /* * Copyright The Mbed TLS Contributors @@ -67,6 +69,33 @@ typedef enum { } mbedtls_lmots_algorithm_type_t; +/** LMOTS context structure. + * + * The context must be initialized before it is used. A public key must either + * be imported, or an algorithm type set, a private key generated and the public + * key calculated from it. A context that does not contain a public key cannot + * verify, and a context that does not contain a private key cannot sign. + * Signing a message will remove the private key from the context, as private + * keys can only be used a single time. + * + * \dot + * digraph lmots { + * UNINITIALIZED -> INIT [label="init"]; + * TYPE_SET -> INIT [label="free"]; + * PRIVATE -> INIT [label="free"]; + * PUBLIC -> INIT [label="free"]; + * "PRIVATE+PUBLIC" -> INIT [label="free"]; + * INIT -> TYPE_SET [label="set_algorithm_type"]; + * PRIVATE -> TYPE_SET [label="sign"]; + * "PRIVATE+PUBLIC" -> PUBLIC [label="sign"]; + * INIT -> PUBLIC [label="import_public"]; + * PUBLIC -> PUBLIC [label="export_pubkey"]; + * "PRIVATE+PUBLIC" -> "PRIVATE+PUBLIC" [label="export_pubkey"]; + * PRIVATE -> "PRIVATE+PUBLIC" [label="gen_pubkey"]; + * TYPE_SET -> PRIVATE [label="gen_privkey"]; + * } + * \enddot + */ typedef struct { unsigned char MBEDTLS_PRIVATE(have_privkey); /*!< Whether the context contains a private key. Boolean values only. */ @@ -129,15 +158,14 @@ int mbedtls_lmots_set_algorithm_type( mbedtls_lmots_context *ctx, * mbedtls_lmots_verify will be used for LMOTS * signature verification. * - * \param I_key_identifier The key identifier of the key, as a 16 byte - * bytestring. + * \param I_key_identifier The key identifier of the key, as a 16-byte string. * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is * not being used as part of an LMS key, this should * be set to 0. * \param msg The buffer from which the message will be read. * \param msg_len The size of the message that will be read. - * \param sig The buff from which the signature will be read. - * MBEDTLS_LMOTS_SIG_LEN bytes will be read from this. + * \param sig The buffer from which the signature will be read. + * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from this. * \param out The buffer where the candidate public key will be * stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN * bytes in size. @@ -189,6 +217,10 @@ int mbedtls_lmots_sign( mbedtls_lmots_context *ctx, * \brief This function verifies a LMOTS signature, using a * LMOTS context that contains a public key. * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. + * * \note Before this function is called, the context must * have been initialized and must contain a public key * (either by import or generation). @@ -270,6 +302,10 @@ int mbedtls_lmots_gen_pubkey( mbedtls_lmots_context *ctx ); * \brief This function generates an LMOTS private key, and * stores in into an LMOTS context. * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. + * * \note Before this function is called, the context must * have been initialized and the type of the LMOTS * context set using mbedtls_lmots_set_algorithm_type @@ -278,8 +314,7 @@ int mbedtls_lmots_gen_pubkey( mbedtls_lmots_context *ctx ); * * \param ctx The initialized LMOTS context to generate the key * into. - * \param I_key_identifier The key identifier of the key, as a 16 byte - * bytestring. + * \param I_key_identifier The key identifier of the key, as a 16-byte string. * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is * not being used as part of an LMS key, this should * be set to 0. diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 77559e24b7..72ed521fee 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -2,7 +2,11 @@ * \file lms.h * * \brief This file provides an API for the LMS post-quantum-safe stateful-hash - * public-key signature scheme. + public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. + * This implementation currently only supports a single parameter set + * MBEDTLS_LMS_SHA256_M32_H10 in order to reduce complexity. This is one + * of the signature schemes recommended by the IETF draft SUIT standard + * for IOT firmware upgrades (RFC9019). */ /* * Copyright The Mbed TLS Contributors @@ -36,7 +40,7 @@ #define MBEDTLS_LMS_TYPE_LEN (4) #define MBEDTLS_LMS_H_TREE_HEIGHT (10) -#define MBEDTLS_LMS_M_NODE_BYTES (32) +#define MBEDTLS_LMS_M_NODE_BYTES (32) /* The length of a hash output, 32 for SHA256 */ #define MBEDTLS_LMS_SIG_LEN (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + MBEDTLS_LMOTS_SIG_LEN + \ MBEDTLS_LMS_TYPE_LEN + MBEDTLS_LMS_H_TREE_HEIGHT * MBEDTLS_LMS_M_NODE_BYTES) @@ -66,6 +70,29 @@ typedef enum { } mbedtls_lms_algorithm_type_t; +/** LMS context structure. + * + * The context must be initialized before it is used. A public key must either + * be imported, or an algorithm type set, a private key generated and the public + * key calculated from it. A context that does not contain a public key cannot + * verify, and a context that does not contain a private key cannot sign. + * + * \dot + * digraph lmots { + * UNINITIALIZED -> INIT [label="init"]; + * TYPE_SET -> INIT [label="free"]; + * PRIVATE -> INIT [label="free"]; + * PUBLIC -> INIT [label="free"]; + * "PRIVATE+PUBLIC" -> INIT [label="free"]; + * INIT -> TYPE_SET [label="set_algorithm_type"]; + * INIT -> PUBLIC [label="import_public"]; + * PUBLIC -> PUBLIC [label="export_pubkey"]; + * "PRIVATE+PUBLIC" -> "PRIVATE+PUBLIC" [label="export_pubkey"]; + * PRIVATE -> "PRIVATE+PUBLIC" [label="gen_pubkey"]; + * TYPE_SET -> PRIVATE [label="gen_privkey"]; + * } + * \enddot + */ typedef struct { unsigned char MBEDTLS_PRIVATE(have_privkey); /*!< Whether the context contains a private key. Boolean values only. */ @@ -123,9 +150,9 @@ int mbedtls_lms_set_algorithm_type( mbedtls_lms_context *ctx, * \brief This function creates a LMS signature, using a * LMOTS context that contains a private key. * - * \note This function is intended for _testing purposes - * only_, due to complexities around updating stateful - * keys. + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. * * \note Before this function is called, the context must * have been initialized and must contain a private @@ -242,6 +269,10 @@ int mbedtls_lms_gen_pubkey( mbedtls_lms_context *ctx ); * \brief This function generates an LMS private key, and * stores in into an LMS context. * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. + * * \note Before this function is called, the context must * have been initialized and the type of the LMS * context set using mbedtls_lmots_set_algorithm_type From 7dce69a27aa606ac4b7be1199599a7ded3fc9397 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 24 Aug 2022 14:07:06 +0100 Subject: [PATCH 005/104] Make LMOTS a private api Signed-off-by: Raef Coles --- include/mbedtls/check_config.h | 9 ++---- include/mbedtls/error.h | 1 - include/mbedtls/lms.h | 3 +- include/mbedtls/mbedtls_config.h | 16 +--------- library/lmots.c | 41 +++++++++++++------------- {include/mbedtls => library}/lmots.h | 3 -- library/lms.c | 3 +- scripts/generate_errors.pl | 2 +- tests/suites/test_suite_lmots.data | 6 ++-- tests/suites/test_suite_lmots.function | 6 ++-- 10 files changed, 36 insertions(+), 54 deletions(-) rename {include/mbedtls => library}/lmots.h (98%) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 37253ab525..99e863cccf 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -353,14 +353,9 @@ #error "MBEDTLS_MD_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_LMOTS_C) && \ - ( !defined(MBEDTLS_MD_C) ) -#error "MBEDTLS_LMOTS_C requires MBEDTLS_MD_C" -#endif - #if defined(MBEDTLS_LMS_C) && \ - ( !defined(MBEDTLS_LMOTS_C) || !defined(MBEDTLS_MD_C) ) -#error "MBEDTLS_LMS_C requires MBEDTLS_LMOTS_C and MBEDTLS_MD_C" + ( !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_LMS_C requires MBEDTLS_MD_C" #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 73d61dbc63..fe5d497929 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -82,7 +82,6 @@ * POLY1305 3 0x0057-0x005B * CHACHAPOLY 2 0x0054-0x0056 * PLATFORM 2 0x0070-0x0072 - * LMOTS 2 0x0076-0x0078 * LMS 2 0x0011-0x0017 * * High-level module nr (3 bits - 0x0...-0x7...) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 72ed521fee..99fe678bf3 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -30,8 +30,9 @@ #include #include +#include "lmots.h" + #include "mbedtls/private_access.h" -#include "mbedtls/lmots.h" #define MBEDTLS_ERR_LMS_BAD_INPUT_DATA -0x0011 /**< Bad data has been input to an LMS function */ #define MBEDTLS_ERR_LMS_OUT_OF_PRIV_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */ diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 1da395b5c3..8c833b1cf9 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2461,20 +2461,6 @@ */ #define MBEDTLS_HMAC_DRBG_C -/** - * \def MBEDTLS_LMOTS_C - * - * Enable the LMOTS one-time asymmetric hash signature algorithm. - * - * Module: library/lm_ots.c - * Caller: - * - * Requires: MBEDTLS_SHA256_C - * - * Uncomment to enable the LMOTS signature algorithm. - */ -#define MBEDTLS_LMOTS_C - /** * \def MBEDTLS_LMS_C * @@ -2483,7 +2469,7 @@ * Module: library/lms.c * Caller: * - * Requires: MBEDTLS_LMS_C + * Requires: MBEDTLS_MD_C * * Uncomment to enable the LMS signature algorithm. */ diff --git a/library/lmots.c b/library/lmots.c index 7319d29be7..2c44772348 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -32,11 +32,12 @@ #include "common.h" -#ifdef MBEDTLS_LMOTS_C +#ifdef MBEDTLS_LMS_C #include -#include "mbedtls/lmots.h" +#include "lmots.h" + #include "mbedtls/md.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" @@ -329,7 +330,7 @@ int mbedtls_lmots_set_algorithm_type( mbedtls_lmots_context *ctx, { if( ctx == NULL ) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } ctx->MBEDTLS_PRIVATE(type) = type; @@ -350,7 +351,7 @@ int mbedtls_lmots_generate_pub_key_candidate( const unsigned char I_key_identifi if (I_key_identifier == NULL || msg == NULL || sig == NULL || out == NULL) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } ret = create_symbol_array( I_key_identifier, q_leaf_identifier, msg, msg_len, @@ -390,13 +391,13 @@ int mbedtls_lmots_sign( mbedtls_lmots_context *ctx, if( ctx == NULL || f_rng == NULL || p_rng == NULL || msg == NULL || sig == NULL) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } /* Check that a private key is loaded */ if ( !ctx->MBEDTLS_PRIVATE(have_privkey) ) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } ret = f_rng( p_rng, sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN ); @@ -447,23 +448,23 @@ int mbedtls_lmots_verify( mbedtls_lmots_context *ctx, const unsigned char *msg, if( ctx == NULL || msg == NULL || sig == NULL) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } if ( !ctx->MBEDTLS_PRIVATE(have_pubkey) ) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } if( ctx->MBEDTLS_PRIVATE(type ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } if ( network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { - return( MBEDTLS_ERR_LMOTS_VERIFY_FAILED ); + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } ret = mbedtls_lmots_generate_pub_key_candidate( ctx->MBEDTLS_PRIVATE(I_key_identifier), @@ -478,7 +479,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_context *ctx, const unsigned char *msg, if ( memcmp( &Kc_public_key_candidate, ctx->MBEDTLS_PRIVATE(pub_key), sizeof( ctx->MBEDTLS_PRIVATE(pub_key) ) ) ) { - return( MBEDTLS_ERR_LMOTS_VERIFY_FAILED ); + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } return( 0 ); @@ -489,7 +490,7 @@ int mbedtls_lmots_import_pubkey( mbedtls_lmots_context *ctx, { if ( ctx == NULL || key == NULL) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } ctx->MBEDTLS_PRIVATE(type) = network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, @@ -515,12 +516,12 @@ int mbedtls_lmots_export_pubkey( mbedtls_lmots_context *ctx, { if ( ctx == NULL || key == NULL) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } if ( ! ctx->MBEDTLS_PRIVATE(have_pubkey) ) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), MBEDTLS_LMOTS_TYPE_LEN, @@ -546,13 +547,13 @@ int mbedtls_lmots_gen_pubkey( mbedtls_lmots_context *ctx ) if( ctx == NULL ) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } /* Check that a private key is loaded */ if ( !ctx->MBEDTLS_PRIVATE(have_privkey) ) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } ret = hash_symbol_array( ctx->MBEDTLS_PRIVATE(I_key_identifier), @@ -592,16 +593,16 @@ int mbedtls_lmots_gen_privkey( mbedtls_lmots_context *ctx, if( ctx == NULL || I_key_identifier == NULL || seed == NULL) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } if ( ctx->MBEDTLS_PRIVATE(have_privkey) ) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } if ( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { - return( MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } memcpy( ctx->MBEDTLS_PRIVATE(I_key_identifier), I_key_identifier, @@ -681,4 +682,4 @@ out: return ret; } -#endif /* MBEDTLS_LMOTS_C */ +#endif /* MBEDTLS_LMS_C */ diff --git a/include/mbedtls/lmots.h b/library/lmots.h similarity index 98% rename from include/mbedtls/lmots.h rename to library/lmots.h index d89f5bb1c0..e425f9ec70 100644 --- a/include/mbedtls/lmots.h +++ b/library/lmots.h @@ -31,9 +31,6 @@ #include #include -#define MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA -0x0076 /**< Bad data has been input to an LMOTS function */ -#define MBEDTLS_ERR_LMOTS_VERIFY_FAILED -0x0078 /**< LMOTS signature verification failed */ - #define MBEDTLS_LMOTS_N_HASH_LEN (32) #define MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN (34) #define MBEDTLS_LMOTS_TYPE_LEN (4) diff --git a/library/lms.c b/library/lms.c index e1ac7b9353..d8969ba390 100644 --- a/library/lms.c +++ b/library/lms.c @@ -36,8 +36,9 @@ #include +#include "lmots.h" + #include "mbedtls/lms.h" -#include "mbedtls/lmots.h" #include "mbedtls/md.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index d333f6590f..41b03377d0 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -47,7 +47,7 @@ my $error_format_file = $data_dir.'/error.fmt'; my @low_level_modules = qw( AES ARIA ASN1 BASE64 BIGNUM CAMELLIA CCM CHACHA20 CHACHAPOLY CMAC CTR_DRBG DES - ENTROPY ERROR GCM HKDF HMAC_DRBG LMS LMOTS MD5 + ENTROPY ERROR GCM HKDF HMAC_DRBG LMS MD5 NET OID PADLOCK PBKDF2 PLATFORM POLY1305 RIPEMD160 SHA1 SHA256 SHA512 THREADING ); my @high_level_modules = qw( CIPHER DHM ECP MD diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index ed192bf7d7..d5088f9e57 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -14,13 +14,13 @@ LMOTS hash-sigs interop test #3 lmots_verify_test:"C32F83EFBFD87F386A6C0850CBB93A75F2506A35":"00000004BD2D174BEBEEF1CAF06E4BF1088DE2AAB17C0528579BD4E1C4A1ED583C36BDACA49798373961B605EAEFAEFC0B4BC39C7AD30572CD29BEBE9AEE503CA2D8BF8C31C8A1B71CF67A18EE01A8A878699F22A1AEE32731E51E3EAD3775EFD8339E263C5A4544559506BA5502B9AEF59217ABC24923EC5E28D18BA18B0D964DB277007A76B8075B39F48CDA92148C9BAE1C7E5421CA753FA2D6BEAE8F49977E4E5B6F38D35BA28A526A53061E57BB92DA0EBBD4AE01AE9FADBED74F503DC39FA2E10C20B47DFB3DFBE25EC35618D2307D21716B10F8FB5095B42C289D1847E5D6F9988C6763D288667D3B658A4F3613E084DAE8B78E0B295A6ED28E88C676995AA5EB1533CDF8EB6F95A5E5117F06B1759495A9CB6E40FBF1F97FF73FDCBFD315C48DA631AB0425CA0633817C46F25E84AEEA37DD77310EE56815E83F862EF14E15FC1246243AA02F40EA32567237D5ADC2944BD63CF55FA4F0DE251B3F5C067D9EC396D5E20F9CEF2C555D89DA721D91D6D607653B97636AB10B74F39FA984D23A3D276EFF5F49C336274A66AC491EDE34686C6CFC17F5312FD3E3E5749A2E472011FA391A5ACF09D918B01704B447FD5E3EA6BB726A3475775DFE6A98CE5473CDEDB630EA4D604BAF36A8B8A8E567F05929E8A74970AA742FBC945021017E464E753D5AC497925AA4AECA0CBF562B2E39F891E177FD8E4E61A698B099D21F13EFD0DE5357A1970314D8E3AA1D2A84D3BCF75A7876C16F585322CC4C613FE3AC8FEA5F258FC9C7200765E9209378C362AFC1A478A117D913CE2BEFEB51103E48D0802618C50918005F1AA4228B67BA1A1B001A91A032019A135B8AEEE3D0158A602C8DCCE5A6580DECC16204E410CBB15FCF36704BB2ECB826A229E45C454B4A5DFC12796E636B300C624DB4E6EAB424B17A18A5A5F52399F247A1507A5985D06F90889FE381129148AF8447B392D4EC0775D91502B48D9F212FCE3F81639901C462F752E27FBEEC9E2B7F8CCD16053FB839E8ADF8CD3E8FF8AF3B3E884F4F524C2026BD3B337B7058B53CFC7596F9C813FFD746B8AC0012C60E96140934B4EED1D8602E57A1A6EBC01FCFD66053AF9614FAF0D0F7320D50D440F2A3148A0DAEF5E2FA31F854D56045065AFAA52A60DC3321E2D7C104FF505057D55CD94C53C31C14DB0DAA4D55C4065CD9BCD78E1B8532A680F7DC3544021346CC59ADEC061DDA1B7606BAF28AD87C39AB8AF3D03E981EFFE50B4D5347175517EF212E61F02B594A96492091AC82625D334504EF19BEEE52E01B111D43313F35EC69C88EF38926071506AB3A5B372DD6F2B901AC1E12E61CCB3ACD3D0777A7A10F137126DAD0D1970D369A067C3A1F19D9CB8756D7130B7EB0C08CF725EB2ADFAD61204195CE14F3C99A88A9B8FA2FDCBD612DF9266614DEA073C9EDABE07B3793048167D4DA49B305AE27974D48A296871350DE036CAA348D2F9A9CB19DC094E5904E25DDCF5657227DCD2A4E620121FBDA032A58836EDC14F3A7C4E51319A60F91F941CC61757498B769799394574C9D198426AC3499F0D0BA1770AD6BAA0D3716333F785A9D7D":"00000004DA66203A7E7BCA2362DB3C8E897A84B10000000D1BD4EE08FAA341C2CE018BD12776E1B8E6B8B2C1EEDAE6BD0998E52F089936FE":0 LMOTS hash-sigs interop negative test (altered random value) -lmots_verify_test:"C80B24A82D52963AB241C84DCF0EEE55BB24F9F0":"00000004CB3B6B24FD191CE8894AE3C4E2CE2DE0C3F5D508691A9162F37704E07838488466CCD746E55BC8E3055C7A4D4DA2E10775DAFA2E8E5FEFB1CEB25973BC3323B61DE5E2EA7DCFF15DA482320F958023CA2E718C69B977019E8F2FCD47151388E2E5E11170AFE93BDEB508362B3A317835A9DDEB18F0CDCCC0731902DB3D37F441C93A490DE53962A915AB5060A1C157D61DDF061F272362AB7FD9EE95AE48D3448F204C81A3F260792784E1BFB49871A27C09CC549A406520F0B40BC74CAAD082EAAB12C994B8495B8C80E96384FF2222255BE6C4EE5AF439534E616F9C0B53E951F69D59BD0506C0C0366A679A8329ACF6E2D1D4E4EF49D35375A8EA46FCF3C9B2F8E033C242EC61B796E43B901407077A2AF3F0AABD2D0CB9004F10D91B57C2D5E8BA7BA9268FF94962CC102F55B5120D7D2F7A3BE281BA01D78895ADA2F05B77967EDA0E1EDEAFBB9BBC3D68DCBF682FBC70467FA2BEE5DE65F54247C4BE5BEF41F5108B6CD09E7698E3AAEA04B60746EDD0E2623B66B092DDA21EFA5A0D36805D101D805CC06F0E818B46059B3984C8B8A526C4239F66ED34B8CA57E178DC5E7B8D2BE029114B4CE466E2B5A081729B3F3A3F3845DDE177062F201C09125ED3CC381AF35EAD795440C421A136F941F09F3E4BA9E0203CBA875AF477AB0246342700F323E65DC327D27966377D871FD9C58BEC8797DEF35E1D0751A554719828B87332F601884EBFECB63A8D4F390785B3826BFA384BE502D2322C919ABD12A486C2AB124DCB7B74DE91241A30EF0388411E52145A88971C6C0A4E7C4F23EDD8D6008065A3D108C6B1EC5219BB0DFDBD37EE3A7A8DD37E3563A5777838FCA61E9E744813F39CF70B5A0F50E1BD4FF8733A3BDA76D2135969809D91A9786F22DC2ACBA4E0164C411019EC77A0BD253A42AC7528FC7C0DA1711FBD6C23825207060463080F9E04B7D819C8B150C22B8BA87C6277696EC409369C48AC0E3233DE52D31EF6D2207D2B57DFC2D0C43BE8212EAE6CB1BACBC2D3568E5527A14065D5F1F56AAE2AFB5FB1CEFFC228A30692BD030C71F4872DB54F2632CD919DA61576CF58D1EBE3D7988183A9C789EB74A3D7F6BBEBAC035A43397BF684C9E1130B252940DBA4454311A6A3D54D9386D48E1D5A3E70944EDF725AEDC5440CD610F79AB05A43C917FFC15213295EB8CB8432B6554A47C2AD419ADD52E0F5E0BD7A1E0F873257E69F8647F3A07093387B7A64C4812CDBEE536E45D531F89653AC5F14A4715CFF40692346FE6CBF2F9B92D9F1101C379AFD5E6154605059C1DA463B407E79C139396623DC7F15EEFCE424C8E214C6A645EF002F90A230D8F62177CBCF2A688D4F822B119835AD3D3A619F46230257A5AD59CB0924B2584DBA96AADE0A2487E7409EE5993A4F0E3DC46C10B96595CDD17D72C35EF4A52C5906655B0AE649B5DE03B7D46F3839E808761EE05E9300050647593C048669A952324B0188ED225AD11BED3FD94E44E134FB9D6DAD53CC34ECF62695E30637C4528C450D62174E2F8ABA2C09F134412EF889C24B36224BE4259B363A9D8EB89BAEE16BE1898D46":"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A":MBEDTLS_ERR_LMOTS_VERIFY_FAILED +lmots_verify_test:"C80B24A82D52963AB241C84DCF0EEE55BB24F9F0":"00000004CB3B6B24FD191CE8894AE3C4E2CE2DE0C3F5D508691A9162F37704E07838488466CCD746E55BC8E3055C7A4D4DA2E10775DAFA2E8E5FEFB1CEB25973BC3323B61DE5E2EA7DCFF15DA482320F958023CA2E718C69B977019E8F2FCD47151388E2E5E11170AFE93BDEB508362B3A317835A9DDEB18F0CDCCC0731902DB3D37F441C93A490DE53962A915AB5060A1C157D61DDF061F272362AB7FD9EE95AE48D3448F204C81A3F260792784E1BFB49871A27C09CC549A406520F0B40BC74CAAD082EAAB12C994B8495B8C80E96384FF2222255BE6C4EE5AF439534E616F9C0B53E951F69D59BD0506C0C0366A679A8329ACF6E2D1D4E4EF49D35375A8EA46FCF3C9B2F8E033C242EC61B796E43B901407077A2AF3F0AABD2D0CB9004F10D91B57C2D5E8BA7BA9268FF94962CC102F55B5120D7D2F7A3BE281BA01D78895ADA2F05B77967EDA0E1EDEAFBB9BBC3D68DCBF682FBC70467FA2BEE5DE65F54247C4BE5BEF41F5108B6CD09E7698E3AAEA04B60746EDD0E2623B66B092DDA21EFA5A0D36805D101D805CC06F0E818B46059B3984C8B8A526C4239F66ED34B8CA57E178DC5E7B8D2BE029114B4CE466E2B5A081729B3F3A3F3845DDE177062F201C09125ED3CC381AF35EAD795440C421A136F941F09F3E4BA9E0203CBA875AF477AB0246342700F323E65DC327D27966377D871FD9C58BEC8797DEF35E1D0751A554719828B87332F601884EBFECB63A8D4F390785B3826BFA384BE502D2322C919ABD12A486C2AB124DCB7B74DE91241A30EF0388411E52145A88971C6C0A4E7C4F23EDD8D6008065A3D108C6B1EC5219BB0DFDBD37EE3A7A8DD37E3563A5777838FCA61E9E744813F39CF70B5A0F50E1BD4FF8733A3BDA76D2135969809D91A9786F22DC2ACBA4E0164C411019EC77A0BD253A42AC7528FC7C0DA1711FBD6C23825207060463080F9E04B7D819C8B150C22B8BA87C6277696EC409369C48AC0E3233DE52D31EF6D2207D2B57DFC2D0C43BE8212EAE6CB1BACBC2D3568E5527A14065D5F1F56AAE2AFB5FB1CEFFC228A30692BD030C71F4872DB54F2632CD919DA61576CF58D1EBE3D7988183A9C789EB74A3D7F6BBEBAC035A43397BF684C9E1130B252940DBA4454311A6A3D54D9386D48E1D5A3E70944EDF725AEDC5440CD610F79AB05A43C917FFC15213295EB8CB8432B6554A47C2AD419ADD52E0F5E0BD7A1E0F873257E69F8647F3A07093387B7A64C4812CDBEE536E45D531F89653AC5F14A4715CFF40692346FE6CBF2F9B92D9F1101C379AFD5E6154605059C1DA463B407E79C139396623DC7F15EEFCE424C8E214C6A645EF002F90A230D8F62177CBCF2A688D4F822B119835AD3D3A619F46230257A5AD59CB0924B2584DBA96AADE0A2487E7409EE5993A4F0E3DC46C10B96595CDD17D72C35EF4A52C5906655B0AE649B5DE03B7D46F3839E808761EE05E9300050647593C048669A952324B0188ED225AD11BED3FD94E44E134FB9D6DAD53CC34ECF62695E30637C4528C450D62174E2F8ABA2C09F134412EF889C24B36224BE4259B363A9D8EB89BAEE16BE1898D46":"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A":MBEDTLS_ERR_LMS_VERIFY_FAILED LMOTS negative test (invalid type) #1 -lmots_verify_test:"0000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA +lmots_verify_test:"0000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMOTS negative test (invalid type) #2 -lmots_verify_test:"0000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMOTS_BAD_INPUT_DATA +lmots_verify_test:"0000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMOTS key import / export test lmots_import_export_test:"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A" diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 6de94d1247..0f76aa6dfc 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -1,12 +1,14 @@ /* BEGIN_HEADER */ -#include "mbedtls/lmots.h" +#include "lmots.h" +#include "mbedtls/lms.h" + #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMOTS_C:MBEDTLS_SHA256_C:MBEDTLS_CTR_DRBG_C + * depends_on:MBEDTLS_LMS_C:MBEDTLS_SHA256_C:MBEDTLS_CTR_DRBG_C * END_DEPENDENCIES */ From c8f9604d7b5eb75fe45759f936438f3f008405a9 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 25 Aug 2022 13:49:54 +0100 Subject: [PATCH 006/104] Use PSA hashing for LMS and LMOTS Signed-off-by: Raef Coles --- include/mbedtls/check_config.h | 4 +- include/mbedtls/error.h | 2 +- include/mbedtls/lms.h | 1 + library/lmots.c | 209 +++++++++++++++---------- library/lmots.h | 15 ++ library/lms.c | 77 ++++----- tests/suites/test_suite_lmots.function | 2 +- tests/suites/test_suite_lms.function | 2 +- 8 files changed, 185 insertions(+), 127 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 99e863cccf..2921278b32 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -354,8 +354,8 @@ #endif #if defined(MBEDTLS_LMS_C) && \ - ( !defined(MBEDTLS_MD_C) ) -#error "MBEDTLS_LMS_C requires MBEDTLS_MD_C" + ( !defined(MBEDTLS_PSA_CRYPTO_C) ) +#error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C" #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index fe5d497929..eb8391311f 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -82,7 +82,7 @@ * POLY1305 3 0x0057-0x005B * CHACHAPOLY 2 0x0054-0x0056 * PLATFORM 2 0x0070-0x0072 - * LMS 2 0x0011-0x0017 + * LMS 5 0x0011-0x0019 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 99fe678bf3..8430309d46 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -38,6 +38,7 @@ #define MBEDTLS_ERR_LMS_OUT_OF_PRIV_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */ #define MBEDTLS_ERR_LMS_VERIFY_FAILED -0x0015 /**< LMS signature verification failed */ #define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ +#define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */ #define MBEDTLS_LMS_TYPE_LEN (4) #define MBEDTLS_LMS_H_TREE_HEIGHT (10) diff --git a/library/lmots.c b/library/lmots.c index 2c44772348..915291c272 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -38,10 +38,12 @@ #include "lmots.h" -#include "mbedtls/md.h" +#include "mbedtls/lms.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" +#include "psa/crypto.h" + #define W_SYMBOL_BIT_LEN (8) #define CHECKSUM_LEN (2) #define I_SYMBOL_IDX_LEN (2) @@ -94,56 +96,61 @@ static int create_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMO const unsigned char C_random_value[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN], unsigned char out[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN] ) { - mbedtls_md_context_t hash_ctx; + psa_hash_operation_t op; + psa_status_t status; + size_t output_hash_len; unsigned char D_MESG_BYTES[D_CONST_LEN]; unsigned short checksum; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_md_init( &hash_ctx ); - ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); - if( ret ) - { - goto out; - } - ret = mbedtls_md_starts( &hash_ctx ); - if ( ret ) + op = psa_hash_operation_init(); + status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - if ( ret ) + status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - if ( ret ) + status = psa_hash_update( &op, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } val_to_network_bytes( D_MESG_CONSTANT, D_CONST_LEN, D_MESG_BYTES ); - ret = mbedtls_md_update( &hash_ctx, D_MESG_BYTES, sizeof( D_MESG_BYTES ) ); - if ( ret ) + status = psa_hash_update( &op, D_MESG_BYTES, sizeof( D_MESG_BYTES ) ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, C_random_value, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN ); - if ( ret ) + status = psa_hash_update( &op, C_random_value, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, msg, msg_len ); - if ( ret ) + status = psa_hash_update( &op, msg, msg_len ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_finish( &hash_ctx, out ); - if ( ret ) + status = psa_hash_finish( &op, out, MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN, + &output_hash_len ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } @@ -152,7 +159,7 @@ static int create_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMO val_to_network_bytes( checksum, CHECKSUM_LEN, out + MBEDTLS_LMOTS_N_HASH_LEN ); out: - mbedtls_md_free( &hash_ctx ); + psa_hash_abort( &op ); return( ret ); } @@ -170,7 +177,9 @@ static int hash_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMOTS unsigned char j_hash_idx_bytes[1]; unsigned short j_hash_idx_min; unsigned short j_hash_idx_max; - mbedtls_md_context_t hash_ctx; + psa_hash_operation_t op; + psa_status_t status; + size_t output_hash_len; unsigned char tmp_hash[32]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -184,57 +193,59 @@ static int hash_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMOTS for ( j_hash_idx = (unsigned char)j_hash_idx_min; j_hash_idx < j_hash_idx_max; j_hash_idx++ ) { - mbedtls_md_init( &hash_ctx ); - ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); - if( ret ) - { - goto out; - } - ret = mbedtls_md_starts( &hash_ctx ); - if ( ret ) + op = psa_hash_operation_init(); + status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - if ( ret ) + status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - if ( ret ) + status = psa_hash_update( &op, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } val_to_network_bytes( i_symbol_idx, I_SYMBOL_IDX_LEN, i_symbol_idx_bytes ); - ret = mbedtls_md_update( &hash_ctx, i_symbol_idx_bytes, I_SYMBOL_IDX_LEN ); - if ( ret ) + status = psa_hash_update( &op, i_symbol_idx_bytes, I_SYMBOL_IDX_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } val_to_network_bytes( j_hash_idx, J_HASH_IDX_LEN, j_hash_idx_bytes ); - ret = mbedtls_md_update( &hash_ctx, j_hash_idx_bytes, J_HASH_IDX_LEN ); - if ( ret ) + status = psa_hash_update( &op, j_hash_idx_bytes, J_HASH_IDX_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); - if ( ret ) + status = psa_hash_update( &op, tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_finish( &hash_ctx, tmp_hash ); - if ( ret ) + status = psa_hash_finish( &op, tmp_hash, sizeof( tmp_hash ), &output_hash_len ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - mbedtls_md_free( &hash_ctx ); + psa_hash_abort( &op ); } memcpy( &output[i_symbol_idx], tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); @@ -243,7 +254,7 @@ static int hash_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMOTS out: if( ret ) { - mbedtls_md_free( &hash_ctx ); + psa_hash_abort( &op ); return( ret ); } @@ -256,56 +267,75 @@ static int public_key_from_hashed_symbol_array( const unsigned char I_key_identi unsigned char *pub_key ) { unsigned char D_PBLC_bytes[D_CONST_LEN]; - mbedtls_md_context_t hash_ctx; + psa_hash_operation_t op; + psa_status_t status; + size_t output_hash_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_md_init( &hash_ctx ); - ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); - if( ret ) - { - goto out; - } - ret = mbedtls_md_starts( &hash_ctx ); - if ( ret ) + op = psa_hash_operation_init( ); + status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN ); - if ( ret ) + status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - if ( ret ) + status = psa_hash_update( &op, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } val_to_network_bytes( D_PBLC_CONSTANT, D_CONST_LEN, D_PBLC_bytes ); - ret = mbedtls_md_update( &hash_ctx, D_PBLC_bytes, D_CONST_LEN ); - if ( ret ) + status = psa_hash_update( &op, D_PBLC_bytes, D_CONST_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, ( unsigned char * )y_hashed_symbols, - MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN * MBEDTLS_LMOTS_N_HASH_LEN ); - if ( ret ) + status = psa_hash_update( &op, ( unsigned char * )y_hashed_symbols, + MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN * MBEDTLS_LMOTS_N_HASH_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_finish( &hash_ctx, pub_key ); + status = psa_hash_finish( &op, pub_key, 32, &output_hash_len ); + ret = mbedtls_lms_error_from_psa( status ); out: - mbedtls_md_free( &hash_ctx ); + psa_hash_abort( &op ); return( ret ); } +int mbedtls_lms_error_from_psa(psa_status_t status) +{ + switch( status ) { + case PSA_SUCCESS: + return( 0 ); + case PSA_ERROR_HARDWARE_FAILURE: + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ); + case PSA_ERROR_BUFFER_TOO_SMALL: + return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + case PSA_ERROR_INVALID_ARGUMENT: + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + default: + return( MBEDTLS_ERR_ERROR_GENERIC_ERROR ); + } +} + void mbedtls_lmots_init( mbedtls_lmots_context *ctx ) { if( ctx == NULL ) { @@ -585,7 +615,9 @@ int mbedtls_lmots_gen_privkey( mbedtls_lmots_context *ctx, const unsigned char *seed, size_t seed_len ) { - mbedtls_md_context_t hash_ctx; + psa_hash_operation_t op; + psa_status_t status; + size_t output_hash_len; unsigned int i_symbol_idx; unsigned char i_symbol_idx_bytes[2]; unsigned char const_bytes[1]; @@ -617,57 +649,60 @@ int mbedtls_lmots_gen_privkey( mbedtls_lmots_context *ctx, for ( i_symbol_idx = 0; i_symbol_idx < MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN; i_symbol_idx++ ) { - mbedtls_md_init( &hash_ctx ); - ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); - if( ret ) - { - goto out; - } - ret = mbedtls_md_starts( &hash_ctx ); - if ( ret ) + op = psa_hash_operation_init( ); + status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, ctx->MBEDTLS_PRIVATE(I_key_identifier), - sizeof( ctx->MBEDTLS_PRIVATE(I_key_identifier) ) ); + ret = psa_hash_update( &op, ctx->MBEDTLS_PRIVATE(I_key_identifier), + sizeof( ctx->MBEDTLS_PRIVATE(I_key_identifier) ) ); + ret = mbedtls_lms_error_from_psa( status ); if ( ret ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), - sizeof( ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes) ) ); + status = psa_hash_update( &op, ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), + sizeof( ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes) ) ); + ret = mbedtls_lms_error_from_psa( status ); if ( ret ) { goto out; } val_to_network_bytes( i_symbol_idx, I_SYMBOL_IDX_LEN, i_symbol_idx_bytes ); - ret = mbedtls_md_update( &hash_ctx, i_symbol_idx_bytes, I_SYMBOL_IDX_LEN ); + status = psa_hash_update( &op, i_symbol_idx_bytes, I_SYMBOL_IDX_LEN ); + ret = mbedtls_lms_error_from_psa( status ); if ( ret ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, const_bytes, sizeof( const_bytes) ); + status = psa_hash_update( &op, const_bytes, sizeof( const_bytes) ); + ret = mbedtls_lms_error_from_psa( status ); if ( ret ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, seed, seed_len ); + status = psa_hash_update( &op, seed, seed_len ); + ret = mbedtls_lms_error_from_psa( status ); if ( ret ) { goto out; } - ret = mbedtls_md_finish( &hash_ctx, ctx->MBEDTLS_PRIVATE(priv_key)[i_symbol_idx] ); + status = psa_hash_finish( &op, ctx->MBEDTLS_PRIVATE(priv_key)[i_symbol_idx], + 32, &output_hash_len ); + ret = mbedtls_lms_error_from_psa( status ); if ( ret ) { goto out; } - mbedtls_md_free( &hash_ctx); + psa_hash_abort( &op ); } ctx->MBEDTLS_PRIVATE(have_privkey) = 1; @@ -675,7 +710,7 @@ int mbedtls_lmots_gen_privkey( mbedtls_lmots_context *ctx, out: if( ret ) { - mbedtls_md_free( &hash_ctx ); + psa_hash_abort( &op ); return( ret ); } diff --git a/library/lmots.h b/library/lmots.h index e425f9ec70..ec68967bea 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -28,6 +28,8 @@ #include "mbedtls/private_access.h" +#include "psa/crypto.h" + #include #include @@ -115,6 +117,16 @@ typedef struct { output. */ } mbedtls_lmots_context; +/** + * \brief This function converts a \ref psa_status_t to a + * low-level LMS error code. + * + * \param status The psa_status_t to convert + * + * \return The corresponding LMS error code. + */ +int mbedtls_lms_error_from_psa(psa_status_t status); + /** * \brief This function initializes an LMOTS context @@ -140,6 +152,9 @@ void mbedtls_lmots_free( mbedtls_lmots_context *ctx ); * * \param ctx The initialized LMOTS context. * \param type The type that will be set in the context. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. */ int mbedtls_lmots_set_algorithm_type( mbedtls_lmots_context *ctx, mbedtls_lmots_algorithm_type_t type ); diff --git a/library/lms.c b/library/lms.c index d8969ba390..4b4f151283 100644 --- a/library/lms.c +++ b/library/lms.c @@ -38,8 +38,9 @@ #include "lmots.h" +#include "psa/crypto.h" + #include "mbedtls/lms.h" -#include "mbedtls/md.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" @@ -88,59 +89,61 @@ static int create_merkle_leaf_node( const mbedtls_lms_context *ctx, unsigned int r_node_idx, unsigned char out[32] ) { - mbedtls_md_context_t hash_ctx; + psa_hash_operation_t op; + psa_status_t status; + size_t output_hash_len; unsigned char D_LEAF_bytes[D_CONST_LEN]; unsigned char r_node_idx_bytes[4]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_md_init( &hash_ctx ); - ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); - if( ret ) - { - goto out; - } - ret = mbedtls_md_starts( &hash_ctx ); - if( ret ) + op = psa_hash_operation_init( ); + status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, - ctx->MBEDTLS_PRIVATE(I_key_identifier), - MBEDTLS_LMOTS_I_KEY_ID_LEN ); + status = psa_hash_update( &op, ctx->MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } val_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); - ret = mbedtls_md_update( &hash_ctx, r_node_idx_bytes, 4 ); + status = psa_hash_update( &op, r_node_idx_bytes, 4 ); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } val_to_network_bytes( D_LEAF_CONSTANT, D_CONST_LEN, D_LEAF_bytes ); - ret = mbedtls_md_update( &hash_ctx, D_LEAF_bytes, D_CONST_LEN ); + status = psa_hash_update( &op, D_LEAF_bytes, D_CONST_LEN ); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, pub_key, MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN ); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } - ret = mbedtls_md_finish( &hash_ctx, out ); + status = psa_hash_finish( &op, out, 32, &output_hash_len); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } out: - mbedtls_md_free( &hash_ctx ); + psa_hash_abort( &op ); return( ret ); } @@ -151,64 +154,68 @@ static int create_merkle_intr_node( const mbedtls_lms_context *ctx, unsigned int r_node_idx, unsigned char out[32] ) { - mbedtls_md_context_t hash_ctx; + psa_hash_operation_t op; + psa_status_t status; + size_t output_hash_len; unsigned char D_INTR_bytes[D_CONST_LEN]; unsigned char r_node_idx_bytes[4]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_md_init( &hash_ctx ); - ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); - if( ret ) - { - goto out; - } - ret = mbedtls_md_starts( &hash_ctx ); - if( ret ) + op = psa_hash_operation_init( ); + status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, ctx->MBEDTLS_PRIVATE(I_key_identifier), - MBEDTLS_LMOTS_I_KEY_ID_LEN ); + status = psa_hash_update( &op, ctx->MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } val_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); - ret = mbedtls_md_update( &hash_ctx, r_node_idx_bytes, 4 ); + status = psa_hash_update( &op, r_node_idx_bytes, 4 ); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } val_to_network_bytes( D_INTR_CONSTANT, D_CONST_LEN, D_INTR_bytes ); - ret = mbedtls_md_update( &hash_ctx, D_INTR_bytes, D_CONST_LEN ); + status = psa_hash_update( &op, D_INTR_bytes, D_CONST_LEN ); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, left_node, MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, left_node, MBEDTLS_LMOTS_N_HASH_LEN ); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } - ret = mbedtls_md_update( &hash_ctx, rght_node, MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, rght_node, MBEDTLS_LMOTS_N_HASH_LEN ); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } - ret = mbedtls_md_finish( &hash_ctx, out ); + ret = psa_hash_finish( &op, out, 32, &output_hash_len); + ret = mbedtls_lms_error_from_psa( status ); if( ret ) { goto out; } out: - mbedtls_md_free( &hash_ctx ); + psa_hash_abort( &op ); return ret; } diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 0f76aa6dfc..82dbcbab27 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -8,7 +8,7 @@ /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:MBEDTLS_SHA256_C:MBEDTLS_CTR_DRBG_C + * depends_on:MBEDTLS_LMS_C:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_CTR_DRBG_C * END_DEPENDENCIES */ diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index b19d074fa7..c6c706139c 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -6,7 +6,7 @@ /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:MBEDTLS_SHA256_C:MBEDTLS_CTR_DRBG_C + * depends_on:MBEDTLS_LMS_C:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_CTR_DRBG_C * END_DEPENDENCIES */ From 01c71a17b33bac6c11759df71f0cc56d02ade733 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 31 Aug 2022 15:55:00 +0100 Subject: [PATCH 007/104] Update LMS and LMOTS api Fix function names and parameters. Move macros to be more private. Update implementation. Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 390 ++++++------ library/lmots.c | 835 ++++++++++++------------- library/lmots.h | 419 +++++++------ library/lms.c | 701 ++++++++++----------- tests/suites/test_suite_lmots.function | 60 +- tests/suites/test_suite_lms.function | 52 +- 6 files changed, 1238 insertions(+), 1219 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 8430309d46..c463b2abb7 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -32,33 +32,24 @@ #include "lmots.h" -#include "mbedtls/private_access.h" +#include "mbedtls/build_info.h" #define MBEDTLS_ERR_LMS_BAD_INPUT_DATA -0x0011 /**< Bad data has been input to an LMS function */ -#define MBEDTLS_ERR_LMS_OUT_OF_PRIV_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */ +#define MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */ #define MBEDTLS_ERR_LMS_VERIFY_FAILED -0x0015 /**< LMS signature verification failed */ #define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ #define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */ -#define MBEDTLS_LMS_TYPE_LEN (4) -#define MBEDTLS_LMS_H_TREE_HEIGHT (10) #define MBEDTLS_LMS_M_NODE_BYTES (32) /* The length of a hash output, 32 for SHA256 */ +#define MBEDTLS_LMS_TYPE_LEN (4) +#define MBEDTLS_LMS_H_TREE_HEIGHT (10u) #define MBEDTLS_LMS_SIG_LEN (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + MBEDTLS_LMOTS_SIG_LEN + \ MBEDTLS_LMS_TYPE_LEN + MBEDTLS_LMS_H_TREE_HEIGHT * MBEDTLS_LMS_M_NODE_BYTES) -#define MBEDTLS_LMS_PUBKEY_LEN (MBEDTLS_LMS_TYPE_LEN + MBEDTLS_LMOTS_TYPE_LEN + \ +#define MBEDTLS_LMS_PUBLIC_KEY_LEN (MBEDTLS_LMS_TYPE_LEN + MBEDTLS_LMOTS_TYPE_LEN + \ MBEDTLS_LMOTS_I_KEY_ID_LEN + MBEDTLS_LMS_M_NODE_BYTES) -#define MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET (0) -#define MBEDTLS_LMS_SIG_OTS_SIG_OFFSET (MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) -#define MBEDTLS_LMS_SIG_TYPE_OFFSET (MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_LEN) -#define MBEDTLS_LMS_SIG_PATH_OFFSET (MBEDTLS_LMS_SIG_TYPE_OFFSET + MBEDTLS_LMS_TYPE_LEN) - -#define MBEDTLS_LMS_PUBKEY_TYPE_OFFSET (0) -#define MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET (MBEDTLS_LMS_PUBKEY_TYPE_OFFSET + MBEDTLS_LMS_TYPE_LEN) -#define MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET (MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMS_PUBKEY_ROOT_NODE_OFFSET (MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET + MBEDTLS_LMOTS_I_KEY_ID_LEN) #ifdef __cplusplus extern "C" { @@ -72,85 +63,234 @@ typedef enum { } mbedtls_lms_algorithm_type_t; -/** LMS context structure. +/** LMS parameters structure. + * + * This contains the metadata associated with an LMS key, detailing the + * algorithm type, the type of the underlying OTS algorithm, and the key ID. + */ +typedef struct { + unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key + identifier. */ + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as + per IANA. Only SHA256_N32_W8 is + currently supported. */ + mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per + IANA. Only SHA256_M32_H10 is currently + supported. */ +} mbedtls_lms_parameters_t; + +/** LMS public context structure. + * + *A LMS public key is the hash output that is the root of the merkle tree, and + * the applicable parameter set * * The context must be initialized before it is used. A public key must either - * be imported, or an algorithm type set, a private key generated and the public - * key calculated from it. A context that does not contain a public key cannot - * verify, and a context that does not contain a private key cannot sign. + * be imported or generated from a private context. * * \dot - * digraph lmots { + * digraph lms_public_t { * UNINITIALIZED -> INIT [label="init"]; - * TYPE_SET -> INIT [label="free"]; - * PRIVATE -> INIT [label="free"]; - * PUBLIC -> INIT [label="free"]; - * "PRIVATE+PUBLIC" -> INIT [label="free"]; - * INIT -> TYPE_SET [label="set_algorithm_type"]; - * INIT -> PUBLIC [label="import_public"]; - * PUBLIC -> PUBLIC [label="export_pubkey"]; - * "PRIVATE+PUBLIC" -> "PRIVATE+PUBLIC" [label="export_pubkey"]; - * PRIVATE -> "PRIVATE+PUBLIC" [label="gen_pubkey"]; - * TYPE_SET -> PRIVATE [label="gen_privkey"]; + * HAVE_PUBLIC_KEY -> INIT [label="free"]; + * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; + * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; + * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; * } * \enddot */ typedef struct { - unsigned char MBEDTLS_PRIVATE(have_privkey); /*!< Whether the context contains a private key. - Boolean values only. */ - unsigned char MBEDTLS_PRIVATE(have_pubkey); /*!< Whether the context contains a public key. - Boolean values only. */ - unsigned char MBEDTLS_PRIVATE(I_key_identifier)[MBEDTLS_LMOTS_I_KEY_ID_LEN]; /*!< The key - identifier. */ - mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per - IANA. Only SHA256_M32_H10 is currently - supported. */ - mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as - per IANA. Only SHA256_N32_W8 is currently - supported. */ - unsigned int MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not - been used. */ - mbedtls_lmots_context *MBEDTLS_PRIVATE(priv_keys); /*!< The private key material. One OTS key - for each leaf node in the merkle tree. */ + mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES]; /*!< The public key, in the form of the merkle tree root node. */ -} mbedtls_lms_context; + unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. + Boolean values only. */ +} mbedtls_lms_public_t; +/** LMS private context structure. + * + * A LMS private key is a set of LMOTS private keys, an index to the next usable + * key, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lms_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PRIVATE_KEY -> INIT [label="free"]; + * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); + uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not + been used. */ + mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key + for each leaf node in the merkle tree. */ + mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to + build the merkle tree. */ + unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. + Boolean values only. */ +} mbedtls_lms_private_t; + /** - * \brief This function initializes an LMS context + * \brief This function initializes an LMS public context * * \param ctx The uninitialized LMS context that will then be * initialized. */ -void mbedtls_lms_init( mbedtls_lms_context *ctx ); +void mbedtls_lms_init_public( mbedtls_lms_public_t *ctx ); /** - * \brief This function uninitializes an LMS context + * \brief This function uninitializes an LMS public context * * \param ctx The initialized LMS context that will then be * uninitialized. */ -void mbedtls_lms_free( mbedtls_lms_context *ctx ); +void mbedtls_lms_free_public( mbedtls_lms_public_t *ctx ); /** - * \brief This function sets the type of an LMS context + * \brief This function imports an LMS public key into a + * public LMS context. * - * \note The parameter set in the context will then be used - * for keygen operations etc. + * \note Before this function is called, the context must + * have been initialized. * - * \param ctx The initialized LMS context. - * \param type The type that will be set in the context. - * \param otstype The type of the LMOTS implementation used by this - * context. + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMS context store the key in. + * \param key The buffer from which the key will be read. + * #MBEDTLS_LMS_PUBLIC_KEY_LEN bytes will be read from + * this. + * \param key_size The size of the key being imported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. */ -int mbedtls_lms_set_algorithm_type( mbedtls_lms_context *ctx, - mbedtls_lms_algorithm_type_t type, - mbedtls_lmots_algorithm_type_t otstype); +int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, + const unsigned char *key, size_t key_size ); + +/** + * \brief This function verifies a LMS signature, using a + * LMS context that contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and must contain a public key + * (either by import or generation). + * + * \param ctx The initialized LMS public context from which the + * public key will be read. + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf from which the signature will be read. + * #MBEDTLS_LMS_SIG_LEN bytes will be read from + * this. + * \param sig_size The size of the signature to be verified. + * + * \return \c 0 on successful verification. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, + const unsigned char *msg, size_t msg_size, + const unsigned char *sig, size_t sig_size ); + +/** + * \brief This function initializes an LMS private context + * + * \param ctx The uninitialized LMS private context that will + * then be initialized. */ +void mbedtls_lms_init_private( mbedtls_lms_private_t *ctx ); + +/** + * \brief This function uninitializes an LMS private context + * + * \param ctx The initialized LMS private context that will then + * be uninitialized. + */ +void mbedtls_lms_free_private( mbedtls_lms_private_t *ctx ); + +/** + * \brief This function generates an LMS private key, and + * stores in into an LMS private context. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. + * + * \note The seed must have at least 256 bits of entropy. + * + * \param ctx The initialized LMOTS context to generate the key + * into. + * \param type The LMS parameter set identifier. + * \param otstype The LMOTS parameter set identifier. + * \param f_rng The RNG function to be used to generate the key ID. + * \param p_rng The RNG context to be passed to f_rng + * \param seed The seed used to deterministically generate the + * key. + * \param seed_size The length of the seed. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, + mbedtls_lms_algorithm_type_t type, + mbedtls_lmots_algorithm_type_t otstype, + int (*f_rng)(void *, unsigned char *, size_t), + void* p_rng, unsigned char *seed, + size_t seed_size ); + +/** + * \brief This function generates an LMS public key from a + * LMS context that already contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a private key. + * + * \param ctx The initialized LMS public context to generate the key + * from and store it into. + * + * \param ctx The LMS private context to read the private key + * from. This must have been initialized and contain a + * private key. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, + mbedtls_lms_private_t *priv_ctx ); + +/** + * \brief This function exports an LMS public key from a + * LMS public context that already contains a public + * key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMS public context that contains + * the public key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size. + * \param key_size The size of the key buffer. + * \param key_len If not NULL, will be written with the size of the + * key. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key, + size_t key_size, size_t *key_len ); /** * \brief This function creates a LMS signature, using a - * LMOTS context that contains a private key. + * LMS context that contains unused private keys. * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with @@ -167,135 +307,27 @@ int mbedtls_lms_set_algorithm_type( mbedtls_lms_context *ctx, * important to not perform copy operations on LMS * contexts that contain private key material. * - * \param ctx The initialized LMS context from which the + * \param ctx The initialized LMS private context from which the * private key will be read. * \param f_rng The RNG function to be used for signature * generation. * \param p_rng The RNG context to be passed to f_rng * \param msg The buffer from which the message will be read. - * \param msg_len The size of the message that will be read. + * \param msg_size The size of the message that will be read. * \param sig The buf into which the signature will be stored. - * Must be at least #MBEDTLS_LMOTS_SIG_LEN in size. + * Must be at least #MBEDTLS_LMS_SIG_LEN in size. + * \param sig_size The size of the buffer the signature will be + * written into. + * \param sig_len If not NULL, will be written with the size of the + * signature. * * \return \c 0 on success. * \return A non-zero error code on failure. */ -int mbedtls_lms_sign( mbedtls_lms_context *ctx, +int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), - void* p_rng, unsigned char *msg, unsigned int msg_len, - unsigned char *sig); - -/** - * \brief This function verifies a LMS signature, using a - * LMS context that contains a public key. - * - * \note Before this function is called, the context must - * have been initialized and must contain a public key - * (either by import or generation). - * - * \param ctx The initialized LMS context from which the public - * key will be read. - * \param msg The buffer from which the message will be read. - * \param msg_len The size of the message that will be read. - * \param sig The buf from which the signature will be read. - * #MBEDTLS_LMS_SIG_LEN bytes will be read from - * this. - * - * \return \c 0 on successful verification. - * \return A non-zero error code on failure. - */ -int mbedtls_lms_verify( const mbedtls_lms_context *ctx, - const unsigned char *msg, unsigned int msg_len, - const unsigned char *sig ); - -/** - * \brief This function imports an LMOTS public key into a - * LMS context. - * - * \note Before this function is called, the context must - * have been initialized. - * - * \note See IETF RFC8554 for details of the encoding of - * this public key. - * - * \param ctx The initialized LMS context store the key in. - * \param key The buffer from which the key will be read. - * #MBEDTLS_LMS_PUBKEY_LEN bytes will be read from - * this. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lms_import_pubkey( mbedtls_lms_context *ctx, - const unsigned char *key ); - -/** - * \brief This function exports an LMOTS public key from a - * LMS context that already contains a public key. - * - * \note Before this function is called, the context must - * have been initialized and the context must contain - * a public key. - * - * \note See IETF RFC8554 for details of the encoding of - * this public key. - * - * \param ctx The initialized LMS context that contains the - * publc key. - * \param key The buffer into which the key will be output. Must - * be at least #MBEDTLS_LMS_PUBKEY_LEN in size. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lms_export_pubkey( mbedtls_lms_context *ctx, - unsigned char *key ); - -/** - * \brief This function generates an LMS public key from a - * LMS context that already contains a private key. - * - * \note Before this function is called, the context must - * have been initialized and the context must contain - * a private key. - * - * \param ctx The initialized LMS context to generate the key - * from and store it into. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lms_gen_pubkey( mbedtls_lms_context *ctx ); - -/** - * \brief This function generates an LMS private key, and - * stores in into an LMS context. - * - * \warning This function is **not intended for use in - * production**, due to as-yet unsolved problems with - * handling stateful keys. - * - * \note Before this function is called, the context must - * have been initialized and the type of the LMS - * context set using mbedtls_lmots_set_algorithm_type - * - * \note The seed must have at least 256 bits of entropy. - * - * \param ctx The initialized LMOTS context to generate the key - * into. - * \param f_rng The RNG function to be used to generate the key ID. - * \param p_rng The RNG context to be passed to f_rng - * \param seed The seed used to deterministically generate the - * key. - * \param seed_len The length of the seed. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lms_gen_privkey( mbedtls_lms_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void* p_rng, unsigned char *seed, - size_t seed_len ); + void* p_rng, unsigned char *msg, unsigned int msg_size, + unsigned char *sig, size_t sig_size, size_t *sig_len); #ifdef __cplusplus } diff --git a/library/lmots.c b/library/lmots.c index 915291c272..e2f86e62d2 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -44,18 +44,29 @@ #include "psa/crypto.h" -#define W_SYMBOL_BIT_LEN (8) -#define CHECKSUM_LEN (2) -#define I_SYMBOL_IDX_LEN (2) -#define J_HASH_IDX_LEN (1) +#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN) + +#define MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET (0) +#define MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET + MBEDTLS_LMOTS_I_KEY_ID_LEN) +#define MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) + +/* We only support parameter sets that use 8-bit digits, as it does not require + * translation logic between digits and bytes */ +#define W_WINTERNITZ_PARAMETER (8u) +#define CHECKSUM_LEN (2) +#define I_DIGIT_IDX_LEN (2) +#define J_HASH_IDX_LEN (1) +#define D_CONST_LEN (2) + +#define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) + #define D_CONST_LEN (2) +static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = {0x80, 0x80}; +static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = {0x81, 0x81}; -#define SYMBOL_MAX_VAL ((1 << W_SYMBOL_BIT_LEN) - 1) - -#define D_PBLC_CONSTANT (0x8080) -#define D_MESG_CONSTANT (0x8181) - -static void val_to_network_bytes(unsigned int val, size_t len, unsigned char *bytes) +void unsigned_int_to_network_bytes(unsigned int val, size_t len, unsigned char *bytes) { size_t idx; @@ -64,7 +75,7 @@ static void val_to_network_bytes(unsigned int val, size_t len, unsigned char *by } } -static unsigned int network_bytes_to_val(size_t len, const unsigned char *bytes) +unsigned int network_bytes_to_unsigned_int(size_t len, const unsigned char *bytes) { size_t idx; unsigned int val = 0; @@ -76,30 +87,28 @@ static unsigned int network_bytes_to_val(size_t len, const unsigned char *bytes) return val; } -static unsigned short lmots_checksum_generate( const unsigned char* digest ) +static unsigned short lmots_checksum_calculate( const unsigned char* digest ) { size_t idx; - unsigned short sum = 0; + unsigned sum = 0; for ( idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN; idx++ ) { - sum += ( 1 << W_SYMBOL_BIT_LEN ) - 1 - digest[idx]; + sum += DIGIT_MAX_VALUE - digest[idx]; } return sum; } -static int create_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], - const unsigned char *msg, - size_t msg_len, - const unsigned char C_random_value[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN], - unsigned char out[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN] ) +static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *params, + const unsigned char *msg, + size_t msg_len, + const unsigned char C_random_value[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN], + unsigned char out[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT] ) { psa_hash_operation_t op; psa_status_t status; size_t output_hash_len; - unsigned char D_MESG_BYTES[D_CONST_LEN]; unsigned short checksum; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -107,166 +116,146 @@ static int create_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMO status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + status = psa_hash_update( &op, params->MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + status = psa_hash_update( &op, params->MBEDTLS_PRIVATE(q_leaf_identifier), + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - val_to_network_bytes( D_MESG_CONSTANT, D_CONST_LEN, D_MESG_BYTES ); - status = psa_hash_update( &op, D_MESG_BYTES, sizeof( D_MESG_BYTES ) ); + status = psa_hash_update( &op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; status = psa_hash_update( &op, C_random_value, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; status = psa_hash_update( &op, msg, msg_len ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_finish( &op, out, MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN, + status = psa_hash_finish( &op, out, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT, &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - checksum = lmots_checksum_generate( out ); - val_to_network_bytes( checksum, CHECKSUM_LEN, out + MBEDTLS_LMOTS_N_HASH_LEN ); + checksum = lmots_checksum_calculate( out ); + unsigned_int_to_network_bytes( checksum, CHECKSUM_LEN, out + MBEDTLS_LMOTS_N_HASH_LEN ); -out: +exit: psa_hash_abort( &op ); return( ret ); } -static int hash_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], - const unsigned char x_symbol_array[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32], - const unsigned char hash_idx_min_values[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN], - const unsigned char hash_idx_max_values[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN], - unsigned char output[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32] ) +static int hash_digit_array( const mbedtls_lmots_parameters_t *params, + const unsigned char x_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN], + const unsigned char *hash_idx_min_values, + const unsigned char *hash_idx_max_values, + unsigned char output[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN] ) { - unsigned char i_symbol_idx; + unsigned char i_digit_idx; unsigned char j_hash_idx; - unsigned char i_symbol_idx_bytes[I_SYMBOL_IDX_LEN]; + unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN]; unsigned char j_hash_idx_bytes[1]; - unsigned short j_hash_idx_min; - unsigned short j_hash_idx_max; + /* These can't be unsigned chars, because they are sometimes set to + * #DIGIT_MAX_VALUE, which has a value of 256 + */ + unsigned int j_hash_idx_min; + unsigned int j_hash_idx_max; psa_hash_operation_t op; psa_status_t status; size_t output_hash_len; - unsigned char tmp_hash[32]; + unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - for ( i_symbol_idx = 0; i_symbol_idx < MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN; i_symbol_idx++ ) + op = psa_hash_operation_init(); + + for ( i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT; i_digit_idx++ ) { - memcpy( tmp_hash, &x_symbol_array[i_symbol_idx], MBEDTLS_LMOTS_N_HASH_LEN ); + memcpy( tmp_hash, &x_digit_array[i_digit_idx], MBEDTLS_LMOTS_N_HASH_LEN ); - j_hash_idx_min = hash_idx_min_values != NULL ? hash_idx_min_values[i_symbol_idx] : 0; - j_hash_idx_max = hash_idx_max_values != NULL ? hash_idx_max_values[i_symbol_idx] : SYMBOL_MAX_VAL; + j_hash_idx_min = hash_idx_min_values != NULL ? hash_idx_min_values[i_digit_idx] : 0; + j_hash_idx_max = hash_idx_max_values != NULL ? hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; for ( j_hash_idx = (unsigned char)j_hash_idx_min; j_hash_idx < j_hash_idx_max; j_hash_idx++ ) { - op = psa_hash_operation_init(); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + status = psa_hash_update( &op, + params->MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + status = psa_hash_update( &op, + params->MBEDTLS_PRIVATE(q_leaf_identifier), + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - val_to_network_bytes( i_symbol_idx, I_SYMBOL_IDX_LEN, i_symbol_idx_bytes ); - status = psa_hash_update( &op, i_symbol_idx_bytes, I_SYMBOL_IDX_LEN ); + unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, i_digit_idx_bytes ); + status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - val_to_network_bytes( j_hash_idx, J_HASH_IDX_LEN, j_hash_idx_bytes ); + unsigned_int_to_network_bytes( j_hash_idx, J_HASH_IDX_LEN, j_hash_idx_bytes ); status = psa_hash_update( &op, j_hash_idx_bytes, J_HASH_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; status = psa_hash_update( &op, tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; status = psa_hash_finish( &op, tmp_hash, sizeof( tmp_hash ), &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; psa_hash_abort( &op ); } - memcpy( &output[i_symbol_idx], tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); + memcpy( &output[i_digit_idx], tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); } -out: +exit: if( ret ) { psa_hash_abort( &op ); return( ret ); } + mbedtls_platform_zeroize( tmp_hash, sizeof( tmp_hash ) ); + return ret; } -static int public_key_from_hashed_symbol_array( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], - const unsigned char y_hashed_symbols[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32], - unsigned char *pub_key ) +static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t *params, + const unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN], + unsigned char *pub_key ) { - unsigned char D_PBLC_bytes[D_CONST_LEN]; psa_hash_operation_t op; psa_status_t status; size_t output_hash_len; @@ -276,44 +265,36 @@ static int public_key_from_hashed_symbol_array( const unsigned char I_key_identi status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + status = psa_hash_update( &op, + params->MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + status = psa_hash_update( &op, params->MBEDTLS_PRIVATE(q_leaf_identifier), + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - val_to_network_bytes( D_PBLC_CONSTANT, D_CONST_LEN, D_PBLC_bytes ); - status = psa_hash_update( &op, D_PBLC_bytes, D_CONST_LEN ); + status = psa_hash_update( &op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, ( unsigned char * )y_hashed_symbols, - MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN * MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, ( unsigned char * )y_hashed_digits, + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT * MBEDTLS_LMOTS_N_HASH_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; status = psa_hash_finish( &op, pub_key, 32, &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); -out: +exit: psa_hash_abort( &op ); return( ret ); } @@ -336,96 +317,352 @@ int mbedtls_lms_error_from_psa(psa_status_t status) } } -void mbedtls_lmots_init( mbedtls_lmots_context *ctx ) +void mbedtls_lmots_init_public( mbedtls_lmots_public_t *ctx ) { - if( ctx == NULL ) { - return; - } - - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_context ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_public_t ) ) ; } -void mbedtls_lmots_free( mbedtls_lmots_context *ctx ) +void mbedtls_lmots_free_public( mbedtls_lmots_public_t *ctx ) { - if( ctx == NULL ) - { - return; - } - - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_context ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_public_t ) ) ; } -int mbedtls_lmots_set_algorithm_type( mbedtls_lmots_context *ctx, - mbedtls_lmots_algorithm_type_t type ) +int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, + const unsigned char *key, size_t key_len ) { - if( ctx == NULL ) + if ( key_len < MBEDTLS_LMOTS_PUBLIC_KEY_LEN ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ctx->MBEDTLS_PRIVATE(type) = type; + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) = + network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + + memcpy( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + + memcpy( ctx->MBEDTLS_PRIVATE(MBEDTLS_PRIVATE(params).q_leaf_identifier), + key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + + memcpy( ctx->MBEDTLS_PRIVATE(public_key), + key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, + MBEDTLS_LMOTS_N_HASH_LEN ); + + ctx->MBEDTLS_PRIVATE(have_public_key) = 1; return( 0 ); } -int mbedtls_lmots_generate_pub_key_candidate( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], - const unsigned char *msg, - size_t msg_len, - const unsigned char *sig, - unsigned char *out ) +int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters_t *params, + const unsigned char *msg, + size_t msg_size, + const unsigned char *sig, + size_t sig_size, + unsigned char *out, + size_t out_size, + size_t *out_len) { - unsigned char tmp_symbol_array[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN]; - unsigned char y_hashed_symbols[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32]; + unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT]; + unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if (I_key_identifier == NULL || msg == NULL || sig == NULL || out == NULL) + if ( msg == NULL && msg_size != 0 ) + { + return ( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if ( sig_size != MBEDTLS_LMOTS_SIG_LEN || out_size < MBEDTLS_LMOTS_N_HASH_LEN ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ret = create_symbol_array( I_key_identifier, q_leaf_identifier, msg, msg_len, - sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_symbol_array ); + ret = create_digit_array_with_checksum( params, msg, msg_size, + sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, + tmp_digit_array ); if ( ret ) { return ( ret ); } - ret = hash_symbol_array( I_key_identifier, q_leaf_identifier, - ( const unsigned char( *)[32] )(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET), - tmp_symbol_array, NULL, y_hashed_symbols ); + ret = hash_digit_array( params, + ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET), + tmp_digit_array, NULL, y_hashed_digits ); if ( ret ) { return ( ret ); } - ret = public_key_from_hashed_symbol_array( I_key_identifier, q_leaf_identifier, - ( const unsigned char( *)[32] )y_hashed_symbols, + ret = public_key_from_hashed_digit_array( params, + ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )y_hashed_digits, out ); if ( ret ) { return ( ret ); } + if ( out_len != NULL ) + { + *out_len = MBEDTLS_LMOTS_N_HASH_LEN; + } + return( 0 ); } -int mbedtls_lmots_sign( mbedtls_lmots_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, const unsigned char *msg, size_t msg_len, - unsigned char *sig ) +int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, + size_t msg_size, const unsigned char *sig, + size_t sig_size ) { - unsigned char tmp_symbol_array[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN]; - unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][MBEDTLS_LMOTS_N_HASH_LEN]; + unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( ctx == NULL || f_rng == NULL || p_rng == NULL || msg == NULL || sig == NULL) + if ( msg == NULL && msg_size != 0 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if ( !ctx->MBEDTLS_PRIVATE(have_public_key) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE( type ) + != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if ( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, + sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + + ret = mbedtls_lmots_calculate_public_key_candidate( &ctx->MBEDTLS_PRIVATE(params), + msg, msg_size, sig, sig_size, + Kc_public_key_candidate, + MBEDTLS_LMOTS_N_HASH_LEN, + NULL); + if ( ret ) + { + return( ret ); + } + + if ( memcmp( &Kc_public_key_candidate, ctx->MBEDTLS_PRIVATE(public_key), + sizeof( ctx->MBEDTLS_PRIVATE(public_key) ) ) ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + + return( 0 ); +} + +void mbedtls_lmots_init_private( mbedtls_lmots_private_t *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_private_t ) ) ; +} + +void mbedtls_lmots_free_private( mbedtls_lmots_private_t *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_private_t ) ) ; +} + +int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, + mbedtls_lmots_algorithm_type_t type, + const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + uint32_t q_leaf_identifier, + const unsigned char *seed, + size_t seed_size ) +{ + psa_hash_operation_t op; + psa_status_t status; + size_t output_hash_len; + unsigned int i_digit_idx; + unsigned char i_digit_idx_bytes[2]; + unsigned char const_bytes[1]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ( ctx->MBEDTLS_PRIVATE(have_private_key) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if ( type != MBEDTLS_LMOTS_SHA256_N32_W8 ) { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) = type; + + memcpy( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + I_key_identifier, + sizeof( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier) ) ); + + unsigned_int_to_network_bytes(q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(q_leaf_identifier) ); + + unsigned_int_to_network_bytes( 0xFF, sizeof( const_bytes ), const_bytes ); + + for ( i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT; i_digit_idx++ ) + { + op = psa_hash_operation_init( ); + status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret != 0 ) + goto exit; + + ret = psa_hash_update( &op, + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + sizeof( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier) ) ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret ) + goto exit; + + status = psa_hash_update( &op, + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(q_leaf_identifier), + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret ) + goto exit; + + unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, i_digit_idx_bytes ); + status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret ) + goto exit; + + status = psa_hash_update( &op, const_bytes, sizeof( const_bytes) ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret ) + goto exit; + + status = psa_hash_update( &op, seed, seed_size ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret ) + goto exit; + + status = psa_hash_finish( &op, + ctx->MBEDTLS_PRIVATE(private_key)[i_digit_idx], + 32, &output_hash_len ); + ret = mbedtls_lms_error_from_psa( status ); + if ( ret ) + goto exit; + + psa_hash_abort( &op ); + } + + ctx->MBEDTLS_PRIVATE(have_private_key) = 1; + +exit: + if( ret ) + { + psa_hash_abort( &op ); + return( ret ); + } + + return ret; +} + +int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, + mbedtls_lmots_private_t *priv_ctx) +{ + unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx == NULL ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } /* Check that a private key is loaded */ - if ( !ctx->MBEDTLS_PRIVATE(have_privkey) ) + if ( !priv_ctx->MBEDTLS_PRIVATE(have_private_key) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + ret = hash_digit_array( &priv_ctx->MBEDTLS_PRIVATE(params), + ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(priv_ctx->MBEDTLS_PRIVATE(private_key)), + NULL, NULL, y_hashed_digits ); + if ( ret ) + { + return( ret ); + } + + ret = public_key_from_hashed_digit_array( &priv_ctx->MBEDTLS_PRIVATE(params), + ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )y_hashed_digits, + ctx->MBEDTLS_PRIVATE(public_key) ); + if ( ret ) + { + return( ret ); + } + + memcpy( &ctx->MBEDTLS_PRIVATE(params), &priv_ctx->MBEDTLS_PRIVATE(params), + sizeof( ctx->MBEDTLS_PRIVATE(params) ) ); + + ctx->MBEDTLS_PRIVATE(have_public_key = 1); + + return( ret ); +} + + +int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len ) +{ + if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN ) + { + return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + } + + if( ! ctx->MBEDTLS_PRIVATE(have_public_key) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + unsigned_int_to_network_bytes( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type), + MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + + memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + + memcpy(key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(q_leaf_identifier), + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + + memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, ctx->MBEDTLS_PRIVATE(public_key), + MBEDTLS_LMOTS_N_HASH_LEN ); + + if( key_len != NULL ) + { + *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN; + } + + return( 0 ); +} + +int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, size_t msg_size, + unsigned char *sig, size_t sig_size, size_t* sig_len ) +{ + unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT]; + unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ( msg == NULL && msg_size != 0 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + if( sig_size < MBEDTLS_LMOTS_SIG_LEN ) + { + return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + } + + /* Check that a private key is loaded */ + if ( !ctx->MBEDTLS_PRIVATE(have_private_key) ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -436,285 +673,43 @@ int mbedtls_lmots_sign( mbedtls_lmots_context *ctx, return( ret ); } - ret = create_symbol_array( ctx->MBEDTLS_PRIVATE(I_key_identifier), - ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), - msg, msg_len, sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, - tmp_symbol_array ); + ret = create_digit_array_with_checksum( &ctx->MBEDTLS_PRIVATE(params), + msg, msg_size, + sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, + tmp_digit_array ); if ( ret ) { return( ret ); } - ret = hash_symbol_array( ctx->MBEDTLS_PRIVATE(I_key_identifier), - ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), - ( const unsigned char( *)[32] )(ctx->MBEDTLS_PRIVATE(priv_key)), - NULL, tmp_symbol_array, tmp_sig ); + ret = hash_digit_array( &ctx->MBEDTLS_PRIVATE(params), + ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(ctx->MBEDTLS_PRIVATE(private_key)), + NULL, tmp_digit_array, tmp_sig ); if ( ret ) { return( ret ); } - val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), MBEDTLS_LMOTS_TYPE_LEN, - sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + unsigned_int_to_network_bytes( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type), + MBEDTLS_LMOTS_TYPE_LEN, + sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); /* We've got a valid signature now, so it's time to make sure the private * key can't be reused. */ - ctx->MBEDTLS_PRIVATE(have_privkey) = 0; - mbedtls_platform_zeroize(ctx->MBEDTLS_PRIVATE(priv_key), - sizeof(ctx->MBEDTLS_PRIVATE(priv_key))); + ctx->MBEDTLS_PRIVATE(have_private_key) = 0; + mbedtls_platform_zeroize(ctx->MBEDTLS_PRIVATE(private_key), + sizeof(ctx->MBEDTLS_PRIVATE(private_key))); memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET, tmp_sig, - MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN * MBEDTLS_LMOTS_N_HASH_LEN); + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT * MBEDTLS_LMOTS_N_HASH_LEN); - return( 0 ); -} - -int mbedtls_lmots_verify( mbedtls_lmots_context *ctx, const unsigned char *msg, - size_t msg_len, const unsigned char *sig ) -{ - unsigned char Kc_public_key_candidate[32]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if( ctx == NULL || msg == NULL || sig == NULL) + if( sig_len != NULL ) { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if ( !ctx->MBEDTLS_PRIVATE(have_pubkey) ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if( ctx->MBEDTLS_PRIVATE(type ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if ( network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, - sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) - { - return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); - } - - ret = mbedtls_lmots_generate_pub_key_candidate( ctx->MBEDTLS_PRIVATE(I_key_identifier), - ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), - msg, msg_len, sig, - Kc_public_key_candidate ); - if ( ret ) - { - return( ret ); - } - - if ( memcmp( &Kc_public_key_candidate, ctx->MBEDTLS_PRIVATE(pub_key), - sizeof( ctx->MBEDTLS_PRIVATE(pub_key) ) ) ) - { - return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + *sig_len = MBEDTLS_LMS_SIG_LEN; } return( 0 ); } -int mbedtls_lmots_import_pubkey( mbedtls_lmots_context *ctx, - const unsigned char *key ) -{ - if ( ctx == NULL || key == NULL) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - ctx->MBEDTLS_PRIVATE(type) = network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, - key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); - - memcpy( ctx->MBEDTLS_PRIVATE(I_key_identifier), key + MBEDTLS_LMOTS_PUBKEY_I_KEY_ID_OFFSET, - MBEDTLS_LMOTS_I_KEY_ID_LEN ); - - memcpy( ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), key + MBEDTLS_LMOTS_PUBKEY_Q_LEAF_ID_OFFSET, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - ctx->MBEDTLS_PRIVATE(q_leaf_identifier) = network_bytes_to_val( MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes) ); - - memcpy( ctx->MBEDTLS_PRIVATE(pub_key), key + MBEDTLS_LMOTS_PUBKEY_KEY_HASH_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN ); - - ctx->MBEDTLS_PRIVATE(have_pubkey) = 1; - - return( 0 ); -} - -int mbedtls_lmots_export_pubkey( mbedtls_lmots_context *ctx, - unsigned char *key ) -{ - if ( ctx == NULL || key == NULL) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if ( ! ctx->MBEDTLS_PRIVATE(have_pubkey) ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), MBEDTLS_LMOTS_TYPE_LEN, - key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); - - memcpy( key + MBEDTLS_LMOTS_PUBKEY_I_KEY_ID_OFFSET, ctx->MBEDTLS_PRIVATE(I_key_identifier), - MBEDTLS_LMOTS_I_KEY_ID_LEN ); - - memcpy( key + MBEDTLS_LMOTS_PUBKEY_Q_LEAF_ID_OFFSET, ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), - MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - - memcpy( key + MBEDTLS_LMOTS_PUBKEY_KEY_HASH_OFFSET, ctx->MBEDTLS_PRIVATE(pub_key), - MBEDTLS_LMOTS_N_HASH_LEN ); - - return( 0 ); -} - - -int mbedtls_lmots_gen_pubkey( mbedtls_lmots_context *ctx ) -{ - unsigned char y_hashed_symbols[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if( ctx == NULL ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - /* Check that a private key is loaded */ - if ( !ctx->MBEDTLS_PRIVATE(have_privkey) ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - ret = hash_symbol_array( ctx->MBEDTLS_PRIVATE(I_key_identifier), - ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), - ( const unsigned char( *)[32] )(ctx->MBEDTLS_PRIVATE(priv_key)), - NULL, NULL, y_hashed_symbols ); - if ( ret ) - { - return( ret ); - } - - ret = public_key_from_hashed_symbol_array( ctx->MBEDTLS_PRIVATE(I_key_identifier), - ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), - ( const unsigned char( *)[32] )y_hashed_symbols, - ctx->MBEDTLS_PRIVATE(pub_key) ); - if ( ret ) - { - return( ret ); - } - - ctx->MBEDTLS_PRIVATE(have_pubkey = 1); - - return( ret ); -} - -int mbedtls_lmots_gen_privkey( mbedtls_lmots_context *ctx, - const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - unsigned int q_leaf_identifier, - const unsigned char *seed, - size_t seed_len ) -{ - psa_hash_operation_t op; - psa_status_t status; - size_t output_hash_len; - unsigned int i_symbol_idx; - unsigned char i_symbol_idx_bytes[2]; - unsigned char const_bytes[1]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if( ctx == NULL || I_key_identifier == NULL || seed == NULL) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if ( ctx->MBEDTLS_PRIVATE(have_privkey) ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if ( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - memcpy( ctx->MBEDTLS_PRIVATE(I_key_identifier), I_key_identifier, - sizeof( ctx->MBEDTLS_PRIVATE(I_key_identifier) ) ); - - ctx->MBEDTLS_PRIVATE(q_leaf_identifier) = q_leaf_identifier; - - val_to_network_bytes( ctx->MBEDTLS_PRIVATE(q_leaf_identifier), MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes) ); - - val_to_network_bytes( 0xFF, sizeof( const_bytes ), const_bytes ); - - for ( i_symbol_idx = 0; i_symbol_idx < MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN; i_symbol_idx++ ) - { - op = psa_hash_operation_init( ); - status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); - ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) - { - goto out; - } - - ret = psa_hash_update( &op, ctx->MBEDTLS_PRIVATE(I_key_identifier), - sizeof( ctx->MBEDTLS_PRIVATE(I_key_identifier) ) ); - ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) { - goto out; - } - - status = psa_hash_update( &op, ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes), - sizeof( ctx->MBEDTLS_PRIVATE(q_leaf_identifier_bytes) ) ); - ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) - { - goto out; - } - - val_to_network_bytes( i_symbol_idx, I_SYMBOL_IDX_LEN, i_symbol_idx_bytes ); - status = psa_hash_update( &op, i_symbol_idx_bytes, I_SYMBOL_IDX_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) - { - goto out; - } - - status = psa_hash_update( &op, const_bytes, sizeof( const_bytes) ); - ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) - { - goto out; - } - - status = psa_hash_update( &op, seed, seed_len ); - ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) - { - goto out; - } - - status = psa_hash_finish( &op, ctx->MBEDTLS_PRIVATE(priv_key)[i_symbol_idx], - 32, &output_hash_len ); - ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) - { - goto out; - } - - psa_hash_abort( &op ); - } - - ctx->MBEDTLS_PRIVATE(have_privkey) = 1; - -out: - if( ret ) - { - psa_hash_abort( &op ); - return( ret ); - } - - return ret; -} - #endif /* MBEDTLS_LMS_C */ diff --git a/library/lmots.h b/library/lmots.h index ec68967bea..ca7d4bf344 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -26,7 +26,7 @@ #ifndef MBEDTLS_LMOTS_H #define MBEDTLS_LMOTS_H -#include "mbedtls/private_access.h" +#include "mbedtls/build_info.h" #include "psa/crypto.h" @@ -34,27 +34,19 @@ #include #define MBEDTLS_LMOTS_N_HASH_LEN (32) -#define MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN (34) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT (34) #define MBEDTLS_LMOTS_TYPE_LEN (4) #define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN (MBEDTLS_LMOTS_N_HASH_LEN) #define MBEDTLS_LMOTS_I_KEY_ID_LEN (16) #define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4) #define MBEDTLS_LMOTS_SIG_LEN (MBEDTLS_LMOTS_TYPE_LEN + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN + \ - (MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN * MBEDTLS_LMOTS_N_HASH_LEN)) + (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT * MBEDTLS_LMOTS_N_HASH_LEN)) -#define MBEDTLS_LMOTS_PUBKEY_LEN (MBEDTLS_LMOTS_TYPE_LEN + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ +#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN (MBEDTLS_LMOTS_TYPE_LEN + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ MBEDTLS_LMOTS_Q_LEAF_ID_LEN + MBEDTLS_LMOTS_N_HASH_LEN) -#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0) -#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN) - -#define MBEDTLS_LMOTS_PUBKEY_TYPE_OFFSET (0) -#define MBEDTLS_LMOTS_PUBKEY_I_KEY_ID_OFFSET (MBEDTLS_LMOTS_PUBKEY_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMOTS_PUBKEY_Q_LEAF_ID_OFFSET (MBEDTLS_LMOTS_PUBKEY_I_KEY_ID_OFFSET + MBEDTLS_LMOTS_I_KEY_ID_LEN) -#define MBEDTLS_LMOTS_PUBKEY_KEY_HASH_OFFSET (MBEDTLS_LMOTS_PUBKEY_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) - +#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0) #ifdef __cplusplus extern "C" { @@ -68,54 +60,93 @@ typedef enum { } mbedtls_lmots_algorithm_type_t; -/** LMOTS context structure. +/** LMOTS parameters structure. + * + * This contains the metadata associated with an LMOTS key, detailing the + * algorithm type, the key ID, and the leaf identifier should be key be part of + * a LMS key. + */ +typedef struct { + unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key + identifier. */ + unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which + leaf of the LMS key this is. + 0 if the key is not part of an LMS key. */ + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as + per IANA. Only SHA256_N32_W8 is + currently supported. */ +} mbedtls_lmots_parameters_t; + +/** LMOTS public context structure. + * + * A LMOTS public key is a hash output, and the applicable parameter set. * * The context must be initialized before it is used. A public key must either - * be imported, or an algorithm type set, a private key generated and the public - * key calculated from it. A context that does not contain a public key cannot - * verify, and a context that does not contain a private key cannot sign. - * Signing a message will remove the private key from the context, as private - * keys can only be used a single time. + * be imported or generated from a private context. * * \dot - * digraph lmots { + * digraph lmots_public_t { * UNINITIALIZED -> INIT [label="init"]; - * TYPE_SET -> INIT [label="free"]; - * PRIVATE -> INIT [label="free"]; - * PUBLIC -> INIT [label="free"]; - * "PRIVATE+PUBLIC" -> INIT [label="free"]; - * INIT -> TYPE_SET [label="set_algorithm_type"]; - * PRIVATE -> TYPE_SET [label="sign"]; - * "PRIVATE+PUBLIC" -> PUBLIC [label="sign"]; - * INIT -> PUBLIC [label="import_public"]; - * PUBLIC -> PUBLIC [label="export_pubkey"]; - * "PRIVATE+PUBLIC" -> "PRIVATE+PUBLIC" [label="export_pubkey"]; - * PRIVATE -> "PRIVATE+PUBLIC" [label="gen_pubkey"]; - * TYPE_SET -> PRIVATE [label="gen_privkey"]; + * HAVE_PUBLIC_KEY -> INIT [label="free"]; + * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; + * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; + * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; * } * \enddot */ typedef struct { - unsigned char MBEDTLS_PRIVATE(have_privkey); /*!< Whether the context contains a private key. + mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(public_key)[32]; + unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. Boolean values only. */ - unsigned char MBEDTLS_PRIVATE(have_pubkey); /*!< Whether the context contains a public key. +} mbedtls_lmots_public_t; + +/** LMOTS private context structure. + * + * A LMOTS private key is one hash output for each of digit of the digest + + * checksum, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lmots_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PRIVATE_KEY -> INIT [label="free"]; + * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; + * HAVE_PRIVATE_KEY -> INIT [label="sign"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][32]; + unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ - unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key - identifier. */ - unsigned int MBEDTLS_PRIVATE(q_leaf_identifier); /*!< Which leaf of the LMS key this is. - 0 if the key is not part of an LMS key. */ - unsigned char MBEDTLS_PRIVATE(q_leaf_identifier_bytes)[MBEDTLS_LMOTS_Q_LEAF_ID_LEN];/*!< The - leaf identifier in network bytes form. */ - mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as - per IANA. Only SHA256_N32_W8 is currently - supported. */ - unsigned char MBEDTLS_PRIVATE(priv_key[MBEDTLS_LMOTS_P_SIG_SYMBOL_LEN][32]); /*!< The private - key, one hash output per byte of the encoded - symbol string P (32 bytes of hash output + - 2 bytes of checksum). */ - unsigned char MBEDTLS_PRIVATE(pub_key[32]); /*!< The public key, in the form of a SHA256 - output. */ -} mbedtls_lmots_context; +} mbedtls_lmots_private_t; + +/** + * \brief This function converts an unsigned int into a + * network-byte-order (big endian) string. + * + * \param val The unsigned integer value + * \param len The length of the string. + * \param bytes The string to output into. + * + * \return The corresponding LMS error code. + */ +void unsigned_int_to_network_bytes(unsigned int val, size_t len, unsigned char *bytes); + +/** + * \brief This function converts a network-byte-order + * (big endian) string into an unsigned integer. + * + * \param len The length of the string. + * \param bytes The string. + * + * \return The corresponding LMS error code. + */ +unsigned int network_bytes_to_unsigned_int(size_t len, const unsigned char *bytes); /** * \brief This function converts a \ref psa_status_t to a @@ -129,35 +160,41 @@ int mbedtls_lms_error_from_psa(psa_status_t status); /** - * \brief This function initializes an LMOTS context + * \brief This function initializes a public LMOTS context * * \param ctx The uninitialized LMOTS context that will then be * initialized. */ -void mbedtls_lmots_init( mbedtls_lmots_context *ctx ); +void mbedtls_lmots_init_public( mbedtls_lmots_public_t *ctx ); /** - * \brief This function uninitializes an LMOTS context + * \brief This function uninitializes a public LMOTS context * * \param ctx The initialized LMOTS context that will then be * uninitialized. */ -void mbedtls_lmots_free( mbedtls_lmots_context *ctx ); +void mbedtls_lmots_free_public( mbedtls_lmots_public_t *ctx ); /** - * \brief This function sets the type of an LMOTS context + * \brief This function imports an LMOTS public key into a + * LMOTS context. * - * \note The parameter set in the context will then be used - * for keygen operations etc. + * \note Before this function is called, the context must + * have been initialized. * - * \param ctx The initialized LMOTS context. - * \param type The type that will be set in the context. + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMOTS context store the key in. + * \param key The buffer from which the key will be read. + * #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read from + * this. * * \return \c 0 on success. * \return A non-zero error code on failure. */ -int mbedtls_lmots_set_algorithm_type( mbedtls_lmots_context *ctx, - mbedtls_lmots_algorithm_type_t type ); +int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, + const unsigned char *key, size_t key_size ); /** * \brief This function creates a candidate public key from @@ -170,12 +207,10 @@ int mbedtls_lmots_set_algorithm_type( mbedtls_lmots_context *ctx, * mbedtls_lmots_verify will be used for LMOTS * signature verification. * - * \param I_key_identifier The key identifier of the key, as a 16-byte string. - * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is - * not being used as part of an LMS key, this should - * be set to 0. + * \param params The LMOTS parameter set, q and I values as an + * mbedtls_lmots_parameters_t struct. * \param msg The buffer from which the message will be read. - * \param msg_len The size of the message that will be read. + * \param msg_size The size of the message that will be read. * \param sig The buffer from which the signature will be read. * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from this. * \param out The buffer where the candidate public key will be @@ -185,13 +220,128 @@ int mbedtls_lmots_set_algorithm_type( mbedtls_lmots_context *ctx, * \return \c 0 on success. * \return A non-zero error code on failure. */ -int mbedtls_lmots_generate_pub_key_candidate( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - const unsigned char q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN], - const unsigned char *msg, - size_t msg_len, - const unsigned char *sig, - unsigned char *out ); +int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters_t *params, + const unsigned char *msg, + size_t msg_size, + const unsigned char *sig, + size_t sig_size, + unsigned char *out, + size_t out_size, + size_t *out_len); +/** + * \brief This function verifies a LMOTS signature, using a + * LMOTS context that contains a public key. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. + * + * \note Before this function is called, the context must + * have been initialized and must contain a public key + * (either by import or calculation from a private key). + * + * \param ctx The initialized LMOTS context from which the public + * key will be read. + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf from which the signature will be read. + * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from + * this. + * + * \return \c 0 on successful verification. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, + size_t msg_size, const unsigned char *sig, + size_t sig_size ); + +/** + * \brief This function initializes a private LMOTS context + * + * \param ctx The uninitialized LMOTS context that will then be + * initialized. + */ +void mbedtls_lmots_init_private( mbedtls_lmots_private_t *ctx ); + +/** + * \brief This function uninitializes a private LMOTS context + * + * \param ctx The initialized LMOTS context that will then be + * uninitialized. + */ +void mbedtls_lmots_free_private( mbedtls_lmots_private_t *ctx ); + +/** + * \brief This function generates an LMOTS private key, and + * stores in into an LMOTS context. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. + * + * \note The seed must have at least 256 bits of entropy. + * + * \param ctx The initialized LMOTS context to generate the key + * into. + * \param I_key_identifier The key identifier of the key, as a 16-byte string. + * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is + * not being used as part of an LMS key, this should + * be set to 0. + * \param seed The seed used to deterministically generate the + * key. + * \param seed_size The length of the seed. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, + mbedtls_lmots_algorithm_type_t type, + const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + uint32_t q_leaf_identifier, + const unsigned char *seed, + size_t seed_size ); + +/** + * \brief This function generates an LMOTS public key from a + * LMOTS context that already contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a private key. + * + * \param ctx The initialized LMOTS context to generate the key + * from and store it into. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, + mbedtls_lmots_private_t *priv_ctx); + + +/** + * \brief This function exports an LMOTS public key from a + * LMOTS context that already contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMOTS context that contains the + * publc key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len ); /** * \brief This function creates a LMOTS signature, using a * LMOTS context that contains a private key. @@ -213,135 +363,18 @@ int mbedtls_lmots_generate_pub_key_candidate( const unsigned char I_key_identifi * generation. * \param p_rng The RNG context to be passed to f_rng * \param msg The buffer from which the message will be read. - * \param msg_len The size of the message that will be read. + * \param msg_size The size of the message that will be read. * \param sig The buf into which the signature will be stored. * Must be at least #MBEDTLS_LMOTS_SIG_LEN in size. * * \return \c 0 on success. * \return A non-zero error code on failure. */ -int mbedtls_lmots_sign( mbedtls_lmots_context *ctx, +int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, const unsigned char *msg, size_t msg_len, - unsigned char *sig ); + void *p_rng, const unsigned char *msg, size_t msg_size, + unsigned char *sig, size_t sig_size, size_t* sig_len ); -/** - * \brief This function verifies a LMOTS signature, using a - * LMOTS context that contains a public key. - * - * \warning This function is **not intended for use in - * production**, due to as-yet unsolved problems with - * handling stateful keys. - * - * \note Before this function is called, the context must - * have been initialized and must contain a public key - * (either by import or generation). - * - * \param ctx The initialized LMOTS context from which the public - * key will be read. - * \param msg The buffer from which the message will be read. - * \param msg_len The size of the message that will be read. - * \param sig The buf from which the signature will be read. - * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from - * this. - * - * \return \c 0 on successful verification. - * \return A non-zero error code on failure. - */ -int mbedtls_lmots_verify( mbedtls_lmots_context *ctx, const unsigned char *msg, - size_t msg_len, const unsigned char *sig ); - -/** - * \brief This function imports an LMOTS public key into a - * LMOTS context. - * - * \note Before this function is called, the context must - * have been initialized. - * - * \note See IETF RFC8554 for details of the encoding of - * this public key. - * - * \param ctx The initialized LMOTS context store the key in. - * \param key The buffer from which the key will be read. - * #MBEDTLS_LMOTS_PUBKEY_LEN bytes will be read from - * this. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lmots_import_pubkey( mbedtls_lmots_context *ctx, - const unsigned char *key ); - -/** - * \brief This function exports an LMOTS public key from a - * LMOTS context that already contains a public key. - * - * \note Before this function is called, the context must - * have been initialized and the context must contain - * a public key. - * - * \note See IETF RFC8554 for details of the encoding of - * this public key. - * - * \param ctx The initialized LMOTS context that contains the - * publc key. - * \param key The buffer into which the key will be output. Must - * be at least #MBEDTLS_LMOTS_PUBKEY_LEN in size. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lmots_export_pubkey( mbedtls_lmots_context *ctx, - unsigned char *key ); - -/** - * \brief This function generates an LMOTS public key from a - * LMOTS context that already contains a private key. - * - * \note Before this function is called, the context must - * have been initialized and the context must contain - * a private key. - * - * \param ctx The initialized LMOTS context to generate the key - * from and store it into. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lmots_gen_pubkey( mbedtls_lmots_context *ctx ); - -/** - * \brief This function generates an LMOTS private key, and - * stores in into an LMOTS context. - * - * \warning This function is **not intended for use in - * production**, due to as-yet unsolved problems with - * handling stateful keys. - * - * \note Before this function is called, the context must - * have been initialized and the type of the LMOTS - * context set using mbedtls_lmots_set_algorithm_type - * - * \note The seed must have at least 256 bits of entropy. - * - * \param ctx The initialized LMOTS context to generate the key - * into. - * \param I_key_identifier The key identifier of the key, as a 16-byte string. - * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is - * not being used as part of an LMS key, this should - * be set to 0. - * \param seed The seed used to deterministically generate the - * key. - * \param seed_len The length of the seed. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lmots_gen_privkey( mbedtls_lmots_context *ctx, - const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - unsigned int q_leaf_identifier, - const unsigned char *seed, - size_t seed_len ); #ifdef __cplusplus } diff --git a/library/lms.c b/library/lms.c index 4b4f151283..b58aeea7f7 100644 --- a/library/lms.c +++ b/library/lms.c @@ -54,45 +54,33 @@ #define mbedtls_free free #endif -#define MERKLE_TREE_NODE_AM (1 << (MBEDTLS_LMS_H_TREE_HEIGHT + 1)) -#define MERKLE_TREE_LEAF_AM (1 << MBEDTLS_LMS_H_TREE_HEIGHT) -#define MERKLE_TREE_INTR_AM (1 << MBEDTLS_LMS_H_TREE_HEIGHT) +#define MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET (0) +#define MBEDTLS_LMS_SIG_OTS_SIG_OFFSET (MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) +#define MBEDTLS_LMS_SIG_TYPE_OFFSET (MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_LEN) +#define MBEDTLS_LMS_SIG_PATH_OFFSET (MBEDTLS_LMS_SIG_TYPE_OFFSET + MBEDTLS_LMS_TYPE_LEN) + +#define MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET (0) +#define MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET + MBEDTLS_LMS_TYPE_LEN) +#define MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET + MBEDTLS_LMOTS_I_KEY_ID_LEN) + + +#define MERKLE_TREE_NODE_AM (1u << (MBEDTLS_LMS_H_TREE_HEIGHT + 1u)) +#define MERKLE_TREE_LEAF_NODE_AM (1u << MBEDTLS_LMS_H_TREE_HEIGHT) +#define MERKLE_TREE_INTERNAL_NODE_AM (1u << MBEDTLS_LMS_H_TREE_HEIGHT) #define D_CONST_LEN (2) +static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = {0x82, 0x82}; +static const unsigned char D_INTERNAL_CONSTANT_BYTES[D_CONST_LEN] = {0x83, 0x83}; -#define D_LEAF_CONSTANT (0x8282) -#define D_INTR_CONSTANT (0x8383) - -static void val_to_network_bytes(unsigned int val, size_t len, unsigned char *bytes) -{ - size_t idx; - - for (idx = 0; idx < len; idx++) { - bytes[idx] = (val >> ((len - 1 - idx) * 8)) & 0xFF; - } -} - -static unsigned int network_bytes_to_val(size_t len, const unsigned char *bytes) -{ - size_t idx; - unsigned int val = 0; - - for (idx = 0; idx < len; idx++) { - val |= ((unsigned int)bytes[idx]) << (8 * (len - 1 - idx)); - } - - return val; -} - -static int create_merkle_leaf_node( const mbedtls_lms_context *ctx, +static int create_merkle_leaf_node( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], unsigned char pub_key[MBEDTLS_LMOTS_N_HASH_LEN], unsigned int r_node_idx, - unsigned char out[32] ) + unsigned char out[MBEDTLS_LMS_M_NODE_BYTES] ) { psa_hash_operation_t op; psa_status_t status; size_t output_hash_len; - unsigned char D_LEAF_bytes[D_CONST_LEN]; unsigned char r_node_idx_bytes[4]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -100,64 +88,49 @@ static int create_merkle_leaf_node( const mbedtls_lms_context *ctx, status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, ctx->MBEDTLS_PRIVATE(I_key_identifier), - MBEDTLS_LMOTS_I_KEY_ID_LEN ); + status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; - val_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); + unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); status = psa_hash_update( &op, r_node_idx_bytes, 4 ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; - val_to_network_bytes( D_LEAF_CONSTANT, D_CONST_LEN, D_LEAF_bytes ); - status = psa_hash_update( &op, D_LEAF_bytes, D_CONST_LEN ); + status = psa_hash_update( &op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; status = psa_hash_update( &op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; - status = psa_hash_finish( &op, out, 32, &output_hash_len); + status = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES, &output_hash_len); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; -out: +exit: psa_hash_abort( &op ); return( ret ); } -static int create_merkle_intr_node( const mbedtls_lms_context *ctx, - const unsigned char left_node[32], - const unsigned char rght_node[32], - unsigned int r_node_idx, - unsigned char out[32] ) +static int create_merkle_internal_node( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + const unsigned char left_node[MBEDTLS_LMS_M_NODE_BYTES], + const unsigned char right_node[MBEDTLS_LMS_M_NODE_BYTES], + unsigned int r_node_idx, + unsigned char out[MBEDTLS_LMS_M_NODE_BYTES] ) { psa_hash_operation_t op; psa_status_t status; size_t output_hash_len; - unsigned char D_INTR_bytes[D_CONST_LEN]; unsigned char r_node_idx_bytes[4]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -165,75 +138,62 @@ static int create_merkle_intr_node( const mbedtls_lms_context *ctx, status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, ctx->MBEDTLS_PRIVATE(I_key_identifier), - MBEDTLS_LMOTS_I_KEY_ID_LEN ); + status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; - val_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); + unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); status = psa_hash_update( &op, r_node_idx_bytes, 4 ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; - val_to_network_bytes( D_INTR_CONSTANT, D_CONST_LEN, D_INTR_bytes ); - status = psa_hash_update( &op, D_INTR_bytes, D_CONST_LEN ); + status = psa_hash_update( &op, D_INTERNAL_CONSTANT_BYTES, D_CONST_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; status = psa_hash_update( &op, left_node, MBEDTLS_LMOTS_N_HASH_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; - status = psa_hash_update( &op, rght_node, MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, right_node, MBEDTLS_LMOTS_N_HASH_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; - ret = psa_hash_finish( &op, out, 32, &output_hash_len); + ret = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES, &output_hash_len); ret = mbedtls_lms_error_from_psa( status ); if( ret ) - { - goto out; - } + goto exit; -out: +exit: psa_hash_abort( &op ); return ret; } -static int generate_merkle_tree( mbedtls_lms_context *ctx, - unsigned char tree[MERKLE_TREE_NODE_AM][32] ) +static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, + unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES] ) { unsigned int priv_key_idx; unsigned int r_node_idx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* First create the leaf nodes, in ascending order */ - for( priv_key_idx = 0; priv_key_idx < MERKLE_TREE_INTR_AM; priv_key_idx++ ) + for( priv_key_idx = 0; priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM; + priv_key_idx++ ) { - r_node_idx = MERKLE_TREE_INTR_AM + priv_key_idx; + r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM + priv_key_idx; - ret = create_merkle_leaf_node( ctx, ctx->MBEDTLS_PRIVATE(priv_keys)[priv_key_idx].pub_key, - r_node_idx, tree[r_node_idx] ); + ret = create_merkle_leaf_node( + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + ctx->MBEDTLS_PRIVATE(ots_public_keys)[priv_key_idx].MBEDTLS_PRIVATE(public_key), + r_node_idx, tree[r_node_idx] ); if( ret ) { return( ret ); @@ -242,11 +202,12 @@ static int generate_merkle_tree( mbedtls_lms_context *ctx, /* Then the internal nodes, in reverse order so that we can guarantee the * parent has been created */ - for( r_node_idx = MERKLE_TREE_INTR_AM - 1; r_node_idx > 0; r_node_idx-- ) + for( r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM - 1; r_node_idx > 0; + r_node_idx-- ) { - ret = create_merkle_intr_node( ctx, tree[(r_node_idx * 2)], - tree[(r_node_idx * 2 + 1)], - r_node_idx, tree[r_node_idx] ); + ret = create_merkle_internal_node( + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + tree[(r_node_idx * 2)], tree[(r_node_idx * 2 + 1)], r_node_idx, tree[r_node_idx] ); if( ret ) { return( ret ); @@ -256,18 +217,17 @@ static int generate_merkle_tree( mbedtls_lms_context *ctx, return( 0 ); } -static int get_merkle_path( mbedtls_lms_context *ctx, - unsigned int leaf_node_id, unsigned char path[MBEDTLS_LMS_H_TREE_HEIGHT][32] ) +static int get_merkle_path( mbedtls_lms_private_t *ctx, + unsigned int leaf_node_id, + unsigned char path[MBEDTLS_LMS_H_TREE_HEIGHT][MBEDTLS_LMS_M_NODE_BYTES] ) { - unsigned char tree[MERKLE_TREE_NODE_AM][32]; + unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES]; unsigned int curr_node_id = leaf_node_id; - unsigned int parent_node_id; - unsigned char sibling_relative_id; unsigned int adjacent_node_id; unsigned int height; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ret = generate_merkle_tree( ctx, tree); + ret = calculate_merkle_tree( ctx, tree); if( ret ) { return( ret ); @@ -275,195 +235,107 @@ static int get_merkle_path( mbedtls_lms_context *ctx, for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ ) { - parent_node_id = ( curr_node_id / 2 ); - - /* 0 if the node is a left child, 1 if the node is a right child */ - sibling_relative_id = curr_node_id & 1; - - adjacent_node_id = ( parent_node_id * 2 ) + ( 1 - sibling_relative_id ); + adjacent_node_id = curr_node_id ^ 1; memcpy( &path[height], &tree[adjacent_node_id], MBEDTLS_LMOTS_N_HASH_LEN ); - curr_node_id = parent_node_id; + curr_node_id >>=1; } return( 0 ); } -void mbedtls_lms_init( mbedtls_lms_context *ctx ) +void mbedtls_lms_init_public( mbedtls_lms_public_t *ctx ) { - if( ctx == NULL ) - { - return; - } - - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_context ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ) ; } -void mbedtls_lms_free( mbedtls_lms_context *ctx ) +void mbedtls_lms_free_public( mbedtls_lms_public_t *ctx ) { - unsigned int idx; - - if( ctx == NULL ) - { - return; - } - - if( ctx->MBEDTLS_PRIVATE(have_privkey) ) - { - for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ ) - { - mbedtls_lmots_free( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx] ); - } - - mbedtls_free( ctx->MBEDTLS_PRIVATE(priv_keys) ); - } - - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ); } -int mbedtls_lms_set_algorithm_type( mbedtls_lms_context *ctx, - mbedtls_lms_algorithm_type_t type, - mbedtls_lmots_algorithm_type_t otstype ) +int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, + const unsigned char *key, size_t key_size ) { - if( ctx == NULL ) + mbedtls_lms_algorithm_type_t type; + mbedtls_lmots_algorithm_type_t otstype; + + if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN ) + { + return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + } + + type = network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); + if( type != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) = type; - ctx->MBEDTLS_PRIVATE(type) = type; - ctx->MBEDTLS_PRIVATE(otstype) = otstype; + otstype = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); + if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) = otstype; + + memcpy( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + key + MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + memcpy( ctx->MBEDTLS_PRIVATE(T_1_pub_key), key + MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET, + MBEDTLS_LMOTS_N_HASH_LEN ); + + ctx->MBEDTLS_PRIVATE(have_public_key) = 1; return( 0 ); } -int mbedtls_lms_sign( mbedtls_lms_context *ctx, - int ( *f_rng)(void *, unsigned char *, size_t), - void* p_rng, unsigned char *msg, unsigned int msg_len, - unsigned char *sig ) -{ - unsigned int q_leaf_identifier; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if( ctx == NULL ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if( ! ctx->MBEDTLS_PRIVATE(have_privkey) ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if( msg == NULL ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if( sig == NULL ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - - if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - - if( ctx->MBEDTLS_PRIVATE(q_next_usable_key) >= MERKLE_TREE_LEAF_AM ) - { - return( MBEDTLS_ERR_LMS_OUT_OF_PRIV_KEYS ); - } - - - q_leaf_identifier = ctx->MBEDTLS_PRIVATE(q_next_usable_key); - /* This new value must _always_ be written back to the disk before the - * signature is returned. - */ - ctx->MBEDTLS_PRIVATE(q_next_usable_key) += 1; - - ret = mbedtls_lmots_sign( &ctx->MBEDTLS_PRIVATE(priv_keys)[q_leaf_identifier], - f_rng, p_rng, msg, msg_len, - sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET ); - if( ret ) - { - return( ret ); - } - - val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), MBEDTLS_LMS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_TYPE_OFFSET ); - val_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET); - - ret = get_merkle_path( ctx, MERKLE_TREE_INTR_AM + q_leaf_identifier, - ( unsigned char( * )[32] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) ); - if( ret ) - { - return( ret ); - } - - return( 0 ); -} - -int mbedtls_lms_verify( const mbedtls_lms_context *ctx, - const unsigned char *msg, unsigned int msg_len, - const unsigned char *sig ) +int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, + const unsigned char *msg, size_t msg_size, + const unsigned char *sig, size_t sig_size ) { unsigned int q_leaf_identifier; unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN]; - unsigned char Tc_candidate_root_node[32]; + unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES]; unsigned int height; unsigned int curr_node_id; unsigned int parent_node_id; const unsigned char* left_node; - const unsigned char* rght_node; + const unsigned char* right_node; + mbedtls_lmots_parameters_t ots_params; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( ctx == NULL ) + if( ! ctx->MBEDTLS_PRIVATE(have_public_key) ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ! ctx->MBEDTLS_PRIVATE(have_pubkey) ) + if( sig_size != MBEDTLS_LMS_SIG_LEN ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( msg == NULL) + if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) + != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( sig == NULL) + if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) + != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - - if( network_bytes_to_val( MBEDTLS_LMS_TYPE_LEN, + if( network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, sig + MBEDTLS_LMS_SIG_TYPE_OFFSET) != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } - if( network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, + if( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { @@ -471,29 +343,39 @@ int mbedtls_lms_verify( const mbedtls_lms_context *ctx, } - q_leaf_identifier = network_bytes_to_val( MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + q_leaf_identifier = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); - if( q_leaf_identifier >= MERKLE_TREE_LEAF_AM ) + if( q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } - ret = mbedtls_lmots_generate_pub_key_candidate( ctx->MBEDTLS_PRIVATE(I_key_identifier), - sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET, - msg, msg_len, - sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, - Kc_candidate_ots_pub_key ); + memcpy(ots_params.MBEDTLS_PRIVATE(I_key_identifier), + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN); + unsigned_int_to_network_bytes( q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + ots_params.MBEDTLS_PRIVATE(q_leaf_identifier) ); + ots_params.type = ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype); + + ret = mbedtls_lmots_calculate_public_key_candidate( &ots_params, msg, msg_size, + sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, + MBEDTLS_LMOTS_SIG_LEN, + Kc_candidate_ots_pub_key, + sizeof(Kc_candidate_ots_pub_key), + NULL ); if( ret ) { return( ret ); } - create_merkle_leaf_node( ctx, Kc_candidate_ots_pub_key, - MERKLE_TREE_INTR_AM + q_leaf_identifier, - Tc_candidate_root_node ); + create_merkle_leaf_node( + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + Kc_candidate_ots_pub_key, MERKLE_TREE_INTERNAL_NODE_AM + q_leaf_identifier, + Tc_candidate_root_node ); - curr_node_id = MERKLE_TREE_INTR_AM + q_leaf_identifier; + curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM + q_leaf_identifier; for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ ) { @@ -502,17 +384,18 @@ int mbedtls_lms_verify( const mbedtls_lms_context *ctx, /* Left/right node ordering matters for the hash */ if( curr_node_id & 1 ) { - left_node = ( ( const unsigned char( * )[32] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height]; - rght_node = Tc_candidate_root_node; + left_node = ( ( const unsigned char( * )[MBEDTLS_LMS_M_NODE_BYTES] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height]; + right_node = Tc_candidate_root_node; } else { left_node = Tc_candidate_root_node; - rght_node = ( ( const unsigned char( * )[32] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height]; + right_node = ( ( const unsigned char( * )[MBEDTLS_LMS_M_NODE_BYTES] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height]; } - create_merkle_intr_node( ctx, left_node, rght_node, parent_node_id, - Tc_candidate_root_node); + create_merkle_internal_node( + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + left_node, right_node, parent_node_id, Tc_candidate_root_node); curr_node_id /= 2; } @@ -526,115 +409,148 @@ int mbedtls_lms_verify( const mbedtls_lms_context *ctx, return( 0 ); } -int mbedtls_lms_import_pubkey( mbedtls_lms_context *ctx, - const unsigned char *key ) +void mbedtls_lms_init_private( mbedtls_lms_private_t *ctx ) { - mbedtls_lms_algorithm_type_t type; - mbedtls_lmots_algorithm_type_t otstype; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ) ; +} - if( ctx == NULL ) +void mbedtls_lms_free_private( mbedtls_lms_private_t *ctx ) +{ + unsigned int idx; + + if( ctx->MBEDTLS_PRIVATE(have_private_key) ) { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM; idx++ ) + { + mbedtls_lmots_free_private( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[idx] ); + mbedtls_lmots_free_public( &ctx->MBEDTLS_PRIVATE(ots_public_keys)[idx] ); + } + + mbedtls_free( ctx->MBEDTLS_PRIVATE(ots_private_keys) ); + mbedtls_free( ctx->MBEDTLS_PRIVATE(ots_public_keys) ); } - if( key == NULL ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ); +} + + +int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, + mbedtls_lms_algorithm_type_t type, + mbedtls_lmots_algorithm_type_t otstype, + int (*f_rng)(void *, unsigned char *, size_t), + void* p_rng, unsigned char *seed, + size_t seed_size ) +{ + unsigned int idx = 0; + unsigned int free_idx = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - type = network_bytes_to_val( MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBKEY_TYPE_OFFSET ); if( type != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ctx->MBEDTLS_PRIVATE(type) = type; - otstype = network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN, - key + MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET ); if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ctx->MBEDTLS_PRIVATE(otstype) = otstype; - memcpy( ctx->MBEDTLS_PRIVATE(I_key_identifier), key + MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET, - MBEDTLS_LMOTS_I_KEY_ID_LEN ); - memcpy( ctx->MBEDTLS_PRIVATE(T_1_pub_key), key + MBEDTLS_LMS_PUBKEY_ROOT_NODE_OFFSET, - MBEDTLS_LMOTS_N_HASH_LEN ); + if( ctx->MBEDTLS_PRIVATE(have_private_key) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } - ctx->MBEDTLS_PRIVATE(have_pubkey) = 1; + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) = type; + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) = otstype; + + f_rng( p_rng, + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + + ctx->MBEDTLS_PRIVATE(ots_private_keys) = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM, + sizeof( mbedtls_lmots_private_t)); + if( ctx->MBEDTLS_PRIVATE(ots_private_keys) == NULL ) + { + ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; + goto exit; + } + + ctx->MBEDTLS_PRIVATE(ots_public_keys) = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM, + sizeof( mbedtls_lmots_public_t)); + if( ctx->MBEDTLS_PRIVATE(ots_public_keys) == NULL ) + { + ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; + goto exit; + } + + for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM; idx++ ) + { + mbedtls_lmots_init_private( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[idx] ); + mbedtls_lmots_init_public( &ctx->MBEDTLS_PRIVATE(ots_public_keys)[idx] ); + } + + + for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM; idx++ ) + { + ret = mbedtls_lmots_generate_private_key( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[idx], + otstype, + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + idx, seed, seed_size ); + if( ret) + goto exit; + + ret = mbedtls_lmots_calculate_public_key( &ctx->MBEDTLS_PRIVATE(ots_public_keys)[idx], + &ctx->MBEDTLS_PRIVATE(ots_private_keys)[idx] ); + if( ret) + goto exit; + } + + ctx->MBEDTLS_PRIVATE(q_next_usable_key) = 0; + ctx->MBEDTLS_PRIVATE(have_private_key) = 1; + +exit: + if( ret ) + { + for ( free_idx = 0; free_idx < idx; free_idx++ ) { + mbedtls_lmots_free_private( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[free_idx] ); + mbedtls_lmots_free_public( &ctx->MBEDTLS_PRIVATE(ots_public_keys)[free_idx] ); + } + + mbedtls_free( ctx->MBEDTLS_PRIVATE(ots_private_keys) ); + mbedtls_free( ctx->MBEDTLS_PRIVATE(ots_public_keys) ); + return( ret ); + } return( 0 ); } -int mbedtls_lms_export_pubkey( mbedtls_lms_context *ctx, - unsigned char *key ) +int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, + mbedtls_lms_private_t *priv_ctx ) { - if( ctx == NULL ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if( key == NULL ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - if( ! ctx->MBEDTLS_PRIVATE(have_pubkey) ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), - MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBKEY_TYPE_OFFSET ); - val_to_network_bytes( ctx->MBEDTLS_PRIVATE(otstype), - MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET ); - memcpy( key + MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET, - ctx->MBEDTLS_PRIVATE(I_key_identifier), - MBEDTLS_LMOTS_I_KEY_ID_LEN ); - memcpy( key + MBEDTLS_LMS_PUBKEY_ROOT_NODE_OFFSET, - ctx->MBEDTLS_PRIVATE(T_1_pub_key), - MBEDTLS_LMOTS_N_HASH_LEN ); - - return( 0 ); -} - -int mbedtls_lms_gen_pubkey( mbedtls_lms_context *ctx ) -{ - unsigned char tree[MERKLE_TREE_NODE_AM][32]; - unsigned int idx; + unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( ctx == NULL ) + if( ! priv_ctx->MBEDTLS_PRIVATE( have_private_key ) ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ! ctx->MBEDTLS_PRIVATE( have_privkey ) ) + if( priv_ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) + != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) + if( priv_ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) + != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } + memcpy( &ctx->MBEDTLS_PRIVATE(params), &priv_ctx->MBEDTLS_PRIVATE(params), + sizeof(mbedtls_lmots_parameters_t) ); - for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ ) - { - ret = mbedtls_lmots_gen_pubkey( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx] ); - if( ret ) - { - return( ret ); - } - } - - ret = generate_merkle_tree( ctx, tree); + ret = calculate_merkle_tree( priv_ctx, tree); if( ret ) { return( ret ); @@ -643,83 +559,112 @@ int mbedtls_lms_gen_pubkey( mbedtls_lms_context *ctx ) /* Root node is always at position 1, due to 1-based indexing */ memcpy( ctx->MBEDTLS_PRIVATE(T_1_pub_key), &tree[1], MBEDTLS_LMOTS_N_HASH_LEN ); - ctx->MBEDTLS_PRIVATE(have_pubkey) = 1; + ctx->MBEDTLS_PRIVATE(have_public_key) = 1; return( 0 ); } -int mbedtls_lms_gen_privkey( mbedtls_lms_context *ctx, - int ( *f_rng)(void *, unsigned char *, size_t), - void* p_rng, unsigned char *seed, - size_t seed_len ) + +int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key, + size_t key_size, size_t *key_len ) { - unsigned int idx; + if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN ) { + return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + } + + if( ! ctx->MBEDTLS_PRIVATE(have_public_key) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + unsigned_int_to_network_bytes( + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type), + MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); + unsigned_int_to_network_bytes( + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype), + MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); + memcpy( key + MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET, + ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + memcpy( key + MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET, + ctx->MBEDTLS_PRIVATE(T_1_pub_key), + MBEDTLS_LMOTS_N_HASH_LEN ); + + if( key_len != NULL ) { + *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN; + } + + return( 0 ); +} + + +int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void* p_rng, unsigned char *msg, unsigned int msg_size, + unsigned char *sig, size_t sig_size, size_t *sig_len) +{ + uint32_t q_leaf_identifier; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( ctx == NULL ) + if( ! ctx->MBEDTLS_PRIVATE(have_private_key) ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) + if( sig_size < MBEDTLS_LMS_SIG_LEN ) + { + return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + } + + if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 ) + if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) + != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(have_privkey) ) + if( ctx->MBEDTLS_PRIVATE(q_next_usable_key) >= MERKLE_TREE_LEAF_NODE_AM ) { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - f_rng( p_rng, ctx->MBEDTLS_PRIVATE(I_key_identifier), - sizeof( ctx->MBEDTLS_PRIVATE(I_key_identifier) ) ); - - ctx->MBEDTLS_PRIVATE(priv_keys) = mbedtls_calloc( MERKLE_TREE_LEAF_AM, - sizeof( mbedtls_lmots_context)); - if( ctx->MBEDTLS_PRIVATE(priv_keys) == NULL ) - { - ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; - goto out; - } - - for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ ) - { - mbedtls_lmots_init( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx] ); - ret = mbedtls_lmots_set_algorithm_type( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx], - ctx->MBEDTLS_PRIVATE(otstype) ); - if( ret) - { - goto out; - } + return( MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS ); } - for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ ) - { - ret = mbedtls_lmots_gen_privkey( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx], - ctx->MBEDTLS_PRIVATE(I_key_identifier), - idx, seed, seed_len ); - if( ret) - { - goto out; - } - } + q_leaf_identifier = ctx->MBEDTLS_PRIVATE(q_next_usable_key); + /* This new value must _always_ be written back to the disk before the + * signature is returned. + */ + ctx->MBEDTLS_PRIVATE(q_next_usable_key) += 1; - ctx->MBEDTLS_PRIVATE(q_next_usable_key) = 0; - ctx->MBEDTLS_PRIVATE(have_privkey) = 1; - -out: + ret = mbedtls_lmots_sign( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[q_leaf_identifier], + f_rng, p_rng, msg, msg_size, + sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, + MBEDTLS_LMS_SIG_LEN, NULL ); if( ret ) { - mbedtls_free( ctx->MBEDTLS_PRIVATE(priv_keys) ); return( ret ); } + unsigned_int_to_network_bytes( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type), + MBEDTLS_LMS_TYPE_LEN, sig + MBEDTLS_LMS_SIG_TYPE_OFFSET ); + unsigned_int_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET); + + ret = get_merkle_path( ctx, MERKLE_TREE_INTERNAL_NODE_AM + q_leaf_identifier, + ( unsigned char( * )[MBEDTLS_LMS_M_NODE_BYTES] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) ); + if( ret ) + { + return( ret ); + } + + if( sig_len != NULL ) { + *sig_len = MBEDTLS_LMS_SIG_LEN; + } + + return( 0 ); } diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 82dbcbab27..4492daaae1 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -15,7 +15,8 @@ /* BEGIN_CASE */ void lmots_sign_verify_test ( data_t * msg ) { - mbedtls_lmots_context ctx; + mbedtls_lmots_public_t pub_ctx; + mbedtls_lmots_private_t priv_ctx; unsigned char sig[MBEDTLS_LMOTS_SIG_LEN]; mbedtls_entropy_context entropy_ctx; mbedtls_ctr_drbg_context drbg_ctx; @@ -23,22 +24,25 @@ void lmots_sign_verify_test ( data_t * msg ) mbedtls_entropy_init( &entropy_ctx ); mbedtls_ctr_drbg_init( &drbg_ctx ); - mbedtls_lmots_init( &ctx ); + mbedtls_lmots_init_public( &pub_ctx ); + mbedtls_lmots_init_private( &priv_ctx ); TEST_ASSERT( mbedtls_ctr_drbg_seed( &drbg_ctx, mbedtls_entropy_func, &entropy_ctx, (uint8_t*)"", 0 ) == 0 ); TEST_ASSERT( mbedtls_ctr_drbg_random( &drbg_ctx, seed, sizeof( seed ) ) == 0 ); - TEST_ASSERT( mbedtls_lmots_set_algorithm_type(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8) == 0 ); - TEST_ASSERT( mbedtls_lmots_gen_privkey(&ctx, (uint8_t[16]){0}, 0x12, seed, sizeof( seed ) ) == 0 ); - TEST_ASSERT( mbedtls_lmots_gen_pubkey(&ctx) == 0 ); - TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, msg->x, msg->len, sig ) == 0 ); - TEST_ASSERT( mbedtls_lmots_verify(&ctx, msg->x, msg->len, sig) == 0 ); + TEST_ASSERT( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, + (uint8_t[16]){0}, 0x12, seed, sizeof( seed ) ) == 0 ); + TEST_ASSERT( mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx) == 0 ); + TEST_ASSERT( mbedtls_lmots_sign(&priv_ctx, mbedtls_ctr_drbg_random, &drbg_ctx, + msg->x, msg->len, sig, sizeof(sig), NULL ) == 0 ); + TEST_ASSERT( mbedtls_lmots_verify(&pub_ctx, msg->x, msg->len, sig, sizeof(sig)) == 0 ); exit: mbedtls_entropy_free( &entropy_ctx ); mbedtls_ctr_drbg_free( &drbg_ctx ); - mbedtls_lmots_free( &ctx ); + mbedtls_lmots_free_public( &pub_ctx ); + mbedtls_lmots_free_private( &priv_ctx ); } /* END_CASE */ @@ -46,40 +50,40 @@ exit: void lmots_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, int expected_rc ) { - mbedtls_lmots_context ctx; + mbedtls_lmots_public_t ctx; - mbedtls_lmots_init( &ctx ); + mbedtls_lmots_init_public( &ctx ); - mbedtls_lmots_import_pubkey( &ctx, pub_key->x ); + mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ); - TEST_ASSERT(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x ) == expected_rc ); + TEST_ASSERT(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ) == expected_rc ); exit: - mbedtls_lmots_free( &ctx ); + mbedtls_lmots_free_public( &ctx ); } /* END_CASE */ /* BEGIN_CASE */ void lmots_import_export_test ( data_t * pub_key ) { - mbedtls_lmots_context ctx; - uint8_t exported_pub_key[MBEDTLS_LMOTS_PUBKEY_LEN]; + mbedtls_lmots_public_t ctx; + uint8_t exported_pub_key[MBEDTLS_LMOTS_PUBLIC_KEY_LEN]; - mbedtls_lmots_init( &ctx ); - TEST_ASSERT( mbedtls_lmots_import_pubkey( &ctx, pub_key->x ) == 0 ); - TEST_ASSERT( mbedtls_lmots_export_pubkey( &ctx, exported_pub_key ) == 0 ); + mbedtls_lmots_init_public( &ctx ); + TEST_ASSERT( mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ) == 0 ); + TEST_ASSERT( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, sizeof( exported_pub_key ), NULL ) == 0 ); - TEST_ASSERT( memcmp( pub_key->x, exported_pub_key, MBEDTLS_LMOTS_PUBKEY_LEN ) == 0 ); + TEST_ASSERT( memcmp( pub_key->x, exported_pub_key, MBEDTLS_LMOTS_PUBLIC_KEY_LEN ) == 0 ); exit: - mbedtls_lmots_free( &ctx ); + mbedtls_lmots_free_public( &ctx ); } /* END_CASE */ /* BEGIN_CASE */ void lmots_reuse_test ( data_t * msg ) { - mbedtls_lmots_context ctx; + mbedtls_lmots_private_t ctx; unsigned char sig[MBEDTLS_LMOTS_SIG_LEN]; mbedtls_entropy_context entropy_ctx; mbedtls_ctr_drbg_context drbg_ctx; @@ -92,19 +96,21 @@ void lmots_reuse_test ( data_t * msg ) mbedtls_ctr_drbg_random( &drbg_ctx, seed, sizeof( seed ) ); - mbedtls_lmots_init( &ctx ); - TEST_ASSERT( mbedtls_lmots_set_algorithm_type( &ctx, MBEDTLS_LMOTS_SHA256_N32_W8 ) == 0 ); - TEST_ASSERT( mbedtls_lmots_gen_privkey(&ctx, (uint8_t[16]){0}, 0x12, seed, sizeof( seed ) ) == 0 ); - TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, msg->x, msg->len, sig ) == 0 ); + mbedtls_lmots_init_private( &ctx ); + TEST_ASSERT( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, + (uint8_t[16]){0}, 0x12, seed, sizeof( seed ) ) == 0 ); + TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, + msg->x, msg->len, sig, sizeof( sig ), NULL ) == 0 ); /* Running another sign operation should fail, since the key should now have * been erased. */ - TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, msg->x, msg->len, sig ) != 0 ); + TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, + msg->x, msg->len, sig, sizeof( sig ), NULL ) != 0 ); exit: mbedtls_entropy_free( &entropy_ctx ); mbedtls_ctr_drbg_free( &drbg_ctx ); - mbedtls_lmots_free( &ctx ); + mbedtls_lmots_free_private( &ctx ); } /* END_CASE */ diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index c6c706139c..64ea900f1e 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -13,7 +13,8 @@ /* BEGIN_CASE */ void lms_sign_verify_test ( data_t * msg ) { - mbedtls_lms_context ctx; + mbedtls_lms_public_t pub_ctx; + mbedtls_lms_private_t priv_ctx; unsigned char sig[MBEDTLS_LMS_SIG_LEN]; mbedtls_entropy_context entropy_ctx; mbedtls_ctr_drbg_context drbg_ctx; @@ -22,29 +23,35 @@ void lms_sign_verify_test ( data_t * msg ) mbedtls_entropy_init( &entropy_ctx ); mbedtls_ctr_drbg_init( &drbg_ctx ); - mbedtls_lms_init( &ctx ); + mbedtls_lms_init_public( &pub_ctx ); + mbedtls_lms_init_private( &priv_ctx ); TEST_ASSERT( mbedtls_ctr_drbg_seed( &drbg_ctx, mbedtls_entropy_func, &entropy_ctx, ( uint8_t* )"", 0 ) == 0 ); TEST_ASSERT( mbedtls_ctr_drbg_random( &drbg_ctx, seed, sizeof( seed ) ) == 0 ); - TEST_ASSERT( mbedtls_lms_set_algorithm_type( &ctx, MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8 ) == 0 ); - /* Allocation failure isn't a test failure, since it likely just means there's not enough memory to run the test */ - rc = mbedtls_lms_gen_privkey( &ctx, mbedtls_ctr_drbg_random, &drbg_ctx, seed, sizeof( seed ) ); + rc = mbedtls_lms_generate_private_key( &priv_ctx, MBEDTLS_LMS_SHA256_M32_H10, + MBEDTLS_LMOTS_SHA256_N32_W8, + mbedtls_ctr_drbg_random, &drbg_ctx, seed, + sizeof( seed ) ); TEST_ASSUME( rc != MBEDTLS_ERR_LMS_ALLOC_FAILED ); TEST_ASSERT( rc == 0 ); - TEST_ASSERT( mbedtls_lms_gen_pubkey( &ctx) == 0 ); + TEST_ASSERT( mbedtls_lms_calculate_public_key( &pub_ctx, &priv_ctx ) == 0 ); - TEST_ASSERT( mbedtls_lms_sign( &ctx, mbedtls_ctr_drbg_random, &drbg_ctx, msg->x, msg->len, sig ) == 0 ); + TEST_ASSERT( mbedtls_lms_sign( &priv_ctx, mbedtls_ctr_drbg_random, + &drbg_ctx, msg->x, msg->len, sig, + sizeof( sig ), NULL ) == 0 ); - TEST_ASSERT( mbedtls_lms_verify( &ctx, msg->x, msg->len, sig) == 0 ); + TEST_ASSERT( mbedtls_lms_verify( &pub_ctx, msg->x, msg->len, sig, + sizeof( sig ) ) == 0 ); exit: mbedtls_entropy_free( &entropy_ctx ); mbedtls_ctr_drbg_free( &drbg_ctx ); - mbedtls_lms_free( &ctx ); + mbedtls_lms_free_public( &pub_ctx ); + mbedtls_lms_free_private( &priv_ctx ); } /* END_CASE */ @@ -52,34 +59,35 @@ exit: void lms_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, int expected_rc ) { - mbedtls_lms_context ctx; + mbedtls_lms_public_t ctx; - mbedtls_lms_init( &ctx); + mbedtls_lms_init_public( &ctx); - mbedtls_lms_import_pubkey( &ctx, pub_key->x ); + mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ); - TEST_ASSERT( mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x ) == expected_rc ); + TEST_ASSERT( mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ) == expected_rc ); exit: - mbedtls_lms_free( &ctx ); + mbedtls_lms_free_public( &ctx ); } /* END_CASE */ /* BEGIN_CASE */ void lms_import_export_test ( data_t * pub_key ) { - mbedtls_lms_context ctx; - uint8_t exported_pub_key[MBEDTLS_LMS_PUBKEY_LEN]; + mbedtls_lms_public_t ctx; + uint8_t exported_pub_key[MBEDTLS_LMS_PUBLIC_KEY_LEN]; - mbedtls_lms_init(&ctx); - TEST_ASSERT( mbedtls_lms_import_pubkey( &ctx, pub_key->x ) == 0 ); - TEST_ASSERT( mbedtls_lms_export_pubkey( &ctx, exported_pub_key) == 0 ); + mbedtls_lms_init_public(&ctx); + TEST_ASSERT( mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ) == 0 ); + TEST_ASSERT( mbedtls_lms_export_public_key( &ctx, exported_pub_key, + sizeof(exported_pub_key), NULL ) == 0 ); - ASSERT_COMPARE( pub_key->x, MBEDTLS_LMS_PUBKEY_LEN, - exported_pub_key, MBEDTLS_LMS_PUBKEY_LEN ); + ASSERT_COMPARE( pub_key->x, MBEDTLS_LMS_PUBLIC_KEY_LEN, + exported_pub_key, MBEDTLS_LMS_PUBLIC_KEY_LEN ); exit: - mbedtls_lms_free( &ctx ); + mbedtls_lms_free_public( &ctx ); } /* END_CASE */ From f5632d3efca722296ec59a7c7d99773b36b8708e Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 1 Sep 2022 09:56:52 +0100 Subject: [PATCH 008/104] Remove MBEDTLS_PRIVATE usage from LMS and LMOTS Signed-off-by: Raef Coles --- library/lmots.c | 92 ++++++++++++++++++------------------ library/lms.c | 122 ++++++++++++++++++++++++------------------------ 2 files changed, 107 insertions(+), 107 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index e2f86e62d2..74191ebbca 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -118,13 +118,13 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p if ( ret != 0 ) goto exit; - status = psa_hash_update( &op, params->MBEDTLS_PRIVATE(I_key_identifier), + status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) goto exit; - status = psa_hash_update( &op, params->MBEDTLS_PRIVATE(q_leaf_identifier), + status = psa_hash_update( &op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) @@ -199,14 +199,14 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, goto exit; status = psa_hash_update( &op, - params->MBEDTLS_PRIVATE(I_key_identifier), + params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) goto exit; status = psa_hash_update( &op, - params->MBEDTLS_PRIVATE(q_leaf_identifier), + params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) @@ -268,13 +268,13 @@ static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t goto exit; status = psa_hash_update( &op, - params->MBEDTLS_PRIVATE(I_key_identifier), + params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) goto exit; - status = psa_hash_update( &op, params->MBEDTLS_PRIVATE(q_leaf_identifier), + status = psa_hash_update( &op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) @@ -335,21 +335,21 @@ int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) = + ctx->params.type = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); - memcpy( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + memcpy( ctx->params.I_key_identifier, key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - memcpy( ctx->MBEDTLS_PRIVATE(MBEDTLS_PRIVATE(params).q_leaf_identifier), + memcpy( ctx->params.q_leaf_identifier, key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - memcpy( ctx->MBEDTLS_PRIVATE(public_key), + memcpy( ctx->public_key, key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN ); - ctx->MBEDTLS_PRIVATE(have_public_key) = 1; + ctx->have_public_key = 1; return( 0 ); } @@ -421,12 +421,12 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if ( !ctx->MBEDTLS_PRIVATE(have_public_key) ) + if ( !ctx->have_public_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE( type ) + if( ctx->params.MBEDTLS_PRIVATE( type ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); @@ -438,7 +438,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } - ret = mbedtls_lmots_calculate_public_key_candidate( &ctx->MBEDTLS_PRIVATE(params), + ret = mbedtls_lmots_calculate_public_key_candidate( &ctx->params, msg, msg_size, sig, sig_size, Kc_public_key_candidate, MBEDTLS_LMOTS_N_HASH_LEN, @@ -448,8 +448,8 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, return( ret ); } - if ( memcmp( &Kc_public_key_candidate, ctx->MBEDTLS_PRIVATE(public_key), - sizeof( ctx->MBEDTLS_PRIVATE(public_key) ) ) ) + if ( memcmp( &Kc_public_key_candidate, ctx->public_key, + sizeof( ctx->public_key ) ) ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } @@ -482,7 +482,7 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, unsigned char const_bytes[1]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if ( ctx->MBEDTLS_PRIVATE(have_private_key) ) + if ( ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -491,15 +491,15 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) = type; + ctx->params.type = type; - memcpy( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + memcpy( ctx->params.I_key_identifier, I_key_identifier, - sizeof( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier) ) ); + sizeof( ctx->params.I_key_identifier ) ); unsigned_int_to_network_bytes(q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(q_leaf_identifier) ); + ctx->params.q_leaf_identifier ); unsigned_int_to_network_bytes( 0xFF, sizeof( const_bytes ), const_bytes ); @@ -512,14 +512,14 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, goto exit; ret = psa_hash_update( &op, - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), - sizeof( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier) ) ); + ctx->params.I_key_identifier, + sizeof( ctx->params.I_key_identifier ) ); ret = mbedtls_lms_error_from_psa( status ); if ( ret ) goto exit; status = psa_hash_update( &op, - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(q_leaf_identifier), + ctx->params.q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret ) @@ -542,7 +542,7 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, goto exit; status = psa_hash_finish( &op, - ctx->MBEDTLS_PRIVATE(private_key)[i_digit_idx], + ctx->private_key[i_digit_idx], 32, &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); if ( ret ) @@ -551,7 +551,7 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, psa_hash_abort( &op ); } - ctx->MBEDTLS_PRIVATE(have_private_key) = 1; + ctx->have_private_key = 1; exit: if( ret ) @@ -575,29 +575,29 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, } /* Check that a private key is loaded */ - if ( !priv_ctx->MBEDTLS_PRIVATE(have_private_key) ) + if ( !priv_ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ret = hash_digit_array( &priv_ctx->MBEDTLS_PRIVATE(params), - ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(priv_ctx->MBEDTLS_PRIVATE(private_key)), + ret = hash_digit_array( &priv_ctx->params, + ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(priv_ctx->private_key), NULL, NULL, y_hashed_digits ); if ( ret ) { return( ret ); } - ret = public_key_from_hashed_digit_array( &priv_ctx->MBEDTLS_PRIVATE(params), + ret = public_key_from_hashed_digit_array( &priv_ctx->params, ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )y_hashed_digits, - ctx->MBEDTLS_PRIVATE(public_key) ); + ctx->public_key ); if ( ret ) { return( ret ); } - memcpy( &ctx->MBEDTLS_PRIVATE(params), &priv_ctx->MBEDTLS_PRIVATE(params), - sizeof( ctx->MBEDTLS_PRIVATE(params) ) ); + memcpy( &ctx->params, &priv_ctx->params, + sizeof( ctx->params ) ); ctx->MBEDTLS_PRIVATE(have_public_key = 1); @@ -614,24 +614,24 @@ int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } - if( ! ctx->MBEDTLS_PRIVATE(have_public_key) ) + if( ! ctx->have_public_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - unsigned_int_to_network_bytes( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type), + unsigned_int_to_network_bytes( ctx->params.type, MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); memcpy(key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(q_leaf_identifier), + ctx->params.q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); - memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, ctx->MBEDTLS_PRIVATE(public_key), + memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, MBEDTLS_LMOTS_N_HASH_LEN ); if( key_len != NULL ) @@ -662,7 +662,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, } /* Check that a private key is loaded */ - if ( !ctx->MBEDTLS_PRIVATE(have_private_key) ) + if ( !ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -673,7 +673,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( ret ); } - ret = create_digit_array_with_checksum( &ctx->MBEDTLS_PRIVATE(params), + ret = create_digit_array_with_checksum( &ctx->params, msg, msg_size, sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_digit_array ); @@ -682,24 +682,24 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( ret ); } - ret = hash_digit_array( &ctx->MBEDTLS_PRIVATE(params), - ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(ctx->MBEDTLS_PRIVATE(private_key)), + ret = hash_digit_array( &ctx->params, + ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(ctx->private_key), NULL, tmp_digit_array, tmp_sig ); if ( ret ) { return( ret ); } - unsigned_int_to_network_bytes( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type), + unsigned_int_to_network_bytes( ctx->params.type, MBEDTLS_LMOTS_TYPE_LEN, sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); /* We've got a valid signature now, so it's time to make sure the private * key can't be reused. */ - ctx->MBEDTLS_PRIVATE(have_private_key) = 0; - mbedtls_platform_zeroize(ctx->MBEDTLS_PRIVATE(private_key), - sizeof(ctx->MBEDTLS_PRIVATE(private_key))); + ctx->have_private_key = 0; + mbedtls_platform_zeroize(ctx->private_key, + sizeof(ctx->private_key)); memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET, tmp_sig, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT * MBEDTLS_LMOTS_N_HASH_LEN); diff --git a/library/lms.c b/library/lms.c index b58aeea7f7..94f5abe5cc 100644 --- a/library/lms.c +++ b/library/lms.c @@ -191,8 +191,8 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM + priv_key_idx; ret = create_merkle_leaf_node( - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), - ctx->MBEDTLS_PRIVATE(ots_public_keys)[priv_key_idx].MBEDTLS_PRIVATE(public_key), + ctx->params.I_key_identifier, + ctx->ots_public_keys[priv_key_idx].public_key, r_node_idx, tree[r_node_idx] ); if( ret ) { @@ -206,7 +206,7 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, r_node_idx-- ) { ret = create_merkle_internal_node( - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + ctx->params.I_key_identifier, tree[(r_node_idx * 2)], tree[(r_node_idx * 2 + 1)], r_node_idx, tree[r_node_idx] ); if( ret ) { @@ -271,7 +271,7 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) = type; + ctx->params.type = type; otstype = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); @@ -279,15 +279,15 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) = otstype; + ctx->params.otstype = otstype; - memcpy( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + memcpy( ctx->params.I_key_identifier, key + MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - memcpy( ctx->MBEDTLS_PRIVATE(T_1_pub_key), key + MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET, + memcpy( ctx->T_1_pub_key, key + MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN ); - ctx->MBEDTLS_PRIVATE(have_public_key) = 1; + ctx->have_public_key = 1; return( 0 ); } @@ -307,7 +307,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, mbedtls_lmots_parameters_t ots_params; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( ! ctx->MBEDTLS_PRIVATE(have_public_key) ) + if( ! ctx->have_public_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -317,13 +317,13 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) + if( ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) + if( ctx->params.otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); @@ -351,13 +351,13 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } - memcpy(ots_params.MBEDTLS_PRIVATE(I_key_identifier), - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + memcpy(ots_params.I_key_identifier, + ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); unsigned_int_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - ots_params.MBEDTLS_PRIVATE(q_leaf_identifier) ); - ots_params.type = ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype); + ots_params.q_leaf_identifier ); + ots_params.type = ctx->params.otstype; ret = mbedtls_lmots_calculate_public_key_candidate( &ots_params, msg, msg_size, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, @@ -371,7 +371,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, } create_merkle_leaf_node( - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + ctx->params.I_key_identifier, Kc_candidate_ots_pub_key, MERKLE_TREE_INTERNAL_NODE_AM + q_leaf_identifier, Tc_candidate_root_node ); @@ -394,13 +394,13 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, } create_merkle_internal_node( - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + ctx->params.I_key_identifier, left_node, right_node, parent_node_id, Tc_candidate_root_node); curr_node_id /= 2; } - if( memcmp( Tc_candidate_root_node, ctx->MBEDTLS_PRIVATE(T_1_pub_key), + if( memcmp( Tc_candidate_root_node, ctx->T_1_pub_key, MBEDTLS_LMOTS_N_HASH_LEN) ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); @@ -418,16 +418,16 @@ void mbedtls_lms_free_private( mbedtls_lms_private_t *ctx ) { unsigned int idx; - if( ctx->MBEDTLS_PRIVATE(have_private_key) ) + if( ctx->have_private_key ) { for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM; idx++ ) { - mbedtls_lmots_free_private( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[idx] ); - mbedtls_lmots_free_public( &ctx->MBEDTLS_PRIVATE(ots_public_keys)[idx] ); + mbedtls_lmots_free_private( &ctx->ots_private_keys[idx] ); + mbedtls_lmots_free_public( &ctx->ots_public_keys[idx] ); } - mbedtls_free( ctx->MBEDTLS_PRIVATE(ots_private_keys) ); - mbedtls_free( ctx->MBEDTLS_PRIVATE(ots_public_keys) ); + mbedtls_free( ctx->ots_private_keys ); + mbedtls_free( ctx->ots_public_keys ); } mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ); @@ -455,29 +455,29 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(have_private_key) ) + if( ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) = type; - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) = otstype; + ctx->params.type = type; + ctx->params.otstype = otstype; f_rng( p_rng, - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - ctx->MBEDTLS_PRIVATE(ots_private_keys) = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM, + ctx->ots_private_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM, sizeof( mbedtls_lmots_private_t)); - if( ctx->MBEDTLS_PRIVATE(ots_private_keys) == NULL ) + if( ctx->ots_private_keys == NULL ) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; } - ctx->MBEDTLS_PRIVATE(ots_public_keys) = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM, + ctx->ots_public_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM, sizeof( mbedtls_lmots_public_t)); - if( ctx->MBEDTLS_PRIVATE(ots_public_keys) == NULL ) + if( ctx->ots_public_keys == NULL ) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; @@ -485,39 +485,39 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM; idx++ ) { - mbedtls_lmots_init_private( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[idx] ); - mbedtls_lmots_init_public( &ctx->MBEDTLS_PRIVATE(ots_public_keys)[idx] ); + mbedtls_lmots_init_private( &ctx->ots_private_keys[idx] ); + mbedtls_lmots_init_public( &ctx->ots_public_keys[idx] ); } for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM; idx++ ) { - ret = mbedtls_lmots_generate_private_key( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[idx], + ret = mbedtls_lmots_generate_private_key( &ctx->ots_private_keys[idx], otstype, - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + ctx->params.I_key_identifier, idx, seed, seed_size ); if( ret) goto exit; - ret = mbedtls_lmots_calculate_public_key( &ctx->MBEDTLS_PRIVATE(ots_public_keys)[idx], - &ctx->MBEDTLS_PRIVATE(ots_private_keys)[idx] ); + ret = mbedtls_lmots_calculate_public_key( &ctx->ots_public_keys[idx], + &ctx->ots_private_keys[idx] ); if( ret) goto exit; } - ctx->MBEDTLS_PRIVATE(q_next_usable_key) = 0; - ctx->MBEDTLS_PRIVATE(have_private_key) = 1; + ctx->q_next_usable_key = 0; + ctx->have_private_key = 1; exit: if( ret ) { for ( free_idx = 0; free_idx < idx; free_idx++ ) { - mbedtls_lmots_free_private( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[free_idx] ); - mbedtls_lmots_free_public( &ctx->MBEDTLS_PRIVATE(ots_public_keys)[free_idx] ); + mbedtls_lmots_free_private( &ctx->ots_private_keys[free_idx] ); + mbedtls_lmots_free_public( &ctx->ots_public_keys[free_idx] ); } - mbedtls_free( ctx->MBEDTLS_PRIVATE(ots_private_keys) ); - mbedtls_free( ctx->MBEDTLS_PRIVATE(ots_public_keys) ); + mbedtls_free( ctx->ots_private_keys ); + mbedtls_free( ctx->ots_public_keys ); return( ret ); } @@ -535,19 +535,19 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( priv_ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) + if( priv_ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( priv_ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) + if( priv_ctx->params.otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - memcpy( &ctx->MBEDTLS_PRIVATE(params), &priv_ctx->MBEDTLS_PRIVATE(params), + memcpy( &ctx->params, &priv_ctx->params, sizeof(mbedtls_lmots_parameters_t) ); ret = calculate_merkle_tree( priv_ctx, tree); @@ -557,9 +557,9 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, } /* Root node is always at position 1, due to 1-based indexing */ - memcpy( ctx->MBEDTLS_PRIVATE(T_1_pub_key), &tree[1], MBEDTLS_LMOTS_N_HASH_LEN ); + memcpy( ctx->T_1_pub_key, &tree[1], MBEDTLS_LMOTS_N_HASH_LEN ); - ctx->MBEDTLS_PRIVATE(have_public_key) = 1; + ctx->have_public_key = 1; return( 0 ); } @@ -572,22 +572,22 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } - if( ! ctx->MBEDTLS_PRIVATE(have_public_key) ) + if( ! ctx->have_public_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } unsigned_int_to_network_bytes( - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type), + ctx->params.type, MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); unsigned_int_to_network_bytes( - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype), + ctx->params.otstype, MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); memcpy( key + MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET, - ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(I_key_identifier), + ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); memcpy( key + MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET, - ctx->MBEDTLS_PRIVATE(T_1_pub_key), + ctx->T_1_pub_key, MBEDTLS_LMOTS_N_HASH_LEN ); if( key_len != NULL ) { @@ -606,7 +606,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, uint32_t q_leaf_identifier; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( ! ctx->MBEDTLS_PRIVATE(have_private_key) ) + if( ! ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -616,30 +616,30 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } - if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 ) + if( ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(otstype) + if( ctx->params.otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->MBEDTLS_PRIVATE(q_next_usable_key) >= MERKLE_TREE_LEAF_NODE_AM ) + if( ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM ) { return( MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS ); } - q_leaf_identifier = ctx->MBEDTLS_PRIVATE(q_next_usable_key); + q_leaf_identifier = ctx->q_next_usable_key; /* This new value must _always_ be written back to the disk before the * signature is returned. */ - ctx->MBEDTLS_PRIVATE(q_next_usable_key) += 1; + ctx->q_next_usable_key += 1; - ret = mbedtls_lmots_sign( &ctx->MBEDTLS_PRIVATE(ots_private_keys)[q_leaf_identifier], + ret = mbedtls_lmots_sign( &ctx->ots_private_keys[q_leaf_identifier], f_rng, p_rng, msg, msg_size, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, MBEDTLS_LMS_SIG_LEN, NULL ); @@ -648,7 +648,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, return( ret ); } - unsigned_int_to_network_bytes( ctx->MBEDTLS_PRIVATE(params).MBEDTLS_PRIVATE(type), + unsigned_int_to_network_bytes( ctx->params.type, MBEDTLS_LMS_TYPE_LEN, sig + MBEDTLS_LMS_SIG_TYPE_OFFSET ); unsigned_int_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET); From 0c88d4e447943d41a661c194863cfa63275d0b57 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 1 Sep 2022 10:48:32 +0100 Subject: [PATCH 009/104] Remove superfluous casts in LMS and LMOTS Signed-off-by: Raef Coles --- library/lmots.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 74191ebbca..50559e5948 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -393,9 +393,7 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters return ( ret ); } - ret = public_key_from_hashed_digit_array( params, - ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )y_hashed_digits, - out ); + ret = public_key_from_hashed_digit_array( params, y_hashed_digits, out ); if ( ret ) { return ( ret ); @@ -569,28 +567,22 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( ctx == NULL ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - /* Check that a private key is loaded */ if ( !priv_ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ret = hash_digit_array( &priv_ctx->params, - ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(priv_ctx->private_key), - NULL, NULL, y_hashed_digits ); + ret = hash_digit_array( &priv_ctx->params, priv_ctx->private_key, NULL, + NULL, y_hashed_digits ); if ( ret ) { return( ret ); } ret = public_key_from_hashed_digit_array( &priv_ctx->params, - ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )y_hashed_digits, - ctx->public_key ); + y_hashed_digits, + ctx->public_key ); if ( ret ) { return( ret ); @@ -683,7 +675,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, } ret = hash_digit_array( &ctx->params, - ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(ctx->private_key), + ctx->private_key, NULL, tmp_digit_array, tmp_sig ); if ( ret ) { From 891c613f315b5c4b749851860e394ca4cc7b9ca1 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 1 Sep 2022 11:05:48 +0100 Subject: [PATCH 010/104] Update LMOTS signature use of temporary variables Document them properly, and move random value to a temporary variable Signed-off-by: Raef Coles --- library/lmots.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 50559e5948..f5a2343a6c 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -640,7 +640,15 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, unsigned char *sig, size_t sig_size, size_t* sig_len ) { unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT]; + /* Create a temporary buffer to prepare the signature in. This allows us to + * finish creating a signature (ensuring the process doesn't fail), and then + * erase the private key **before** writing any data into the sig parameter + * buffer. If data were directly written into the sig buffer, it might leak + * a partial signature on failure, which effectively compromises the private + * key. + */ unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN]; + unsigned char tmp_c_random[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ( msg == NULL && msg_size != 0 ) @@ -659,7 +667,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ret = f_rng( p_rng, sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN ); + ret = f_rng( p_rng, tmp_c_random, MBEDTLS_LMOTS_N_HASH_LEN ); if ( ret ) { return( ret ); @@ -667,7 +675,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, ret = create_digit_array_with_checksum( &ctx->params, msg, msg_size, - sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, + tmp_c_random, tmp_digit_array ); if ( ret ) { @@ -693,8 +701,11 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, mbedtls_platform_zeroize(ctx->private_key, sizeof(ctx->private_key)); - memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET, tmp_sig, - MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT * MBEDTLS_LMOTS_N_HASH_LEN); + memcpy( sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random, + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN ); + + memcpy( sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET, tmp_sig, + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT * MBEDTLS_LMOTS_N_HASH_LEN ); if( sig_len != NULL ) { From ebd35b5b80993221757a9c90a22336ecc6f59c4d Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 1 Sep 2022 11:52:17 +0100 Subject: [PATCH 011/104] Rename LMS internal tree-manipulation functions Signed-off-by: Raef Coles --- library/lmots.c | 3 ++- library/lms.c | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index f5a2343a6c..d92d385255 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -489,6 +489,8 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } + op = psa_hash_operation_init( ); + ctx->params.type = type; memcpy( ctx->params.I_key_identifier, @@ -503,7 +505,6 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, for ( i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT; i_digit_idx++ ) { - op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) diff --git a/library/lms.c b/library/lms.c index 94f5abe5cc..44d4c79027 100644 --- a/library/lms.c +++ b/library/lms.c @@ -73,10 +73,10 @@ static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = {0x82, 0x82}; static const unsigned char D_INTERNAL_CONSTANT_BYTES[D_CONST_LEN] = {0x83, 0x83}; -static int create_merkle_leaf_node( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - unsigned char pub_key[MBEDTLS_LMOTS_N_HASH_LEN], - unsigned int r_node_idx, - unsigned char out[MBEDTLS_LMS_M_NODE_BYTES] ) +static int create_merkle_leaf_value( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + unsigned char pub_key[MBEDTLS_LMOTS_N_HASH_LEN], + unsigned int r_node_idx, + unsigned char out[MBEDTLS_LMS_M_NODE_BYTES] ) { psa_hash_operation_t op; psa_status_t status; @@ -122,11 +122,11 @@ exit: return( ret ); } -static int create_merkle_internal_node( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - const unsigned char left_node[MBEDTLS_LMS_M_NODE_BYTES], - const unsigned char right_node[MBEDTLS_LMS_M_NODE_BYTES], - unsigned int r_node_idx, - unsigned char out[MBEDTLS_LMS_M_NODE_BYTES] ) +static int create_merkle_internal_value( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + const unsigned char left_node[MBEDTLS_LMS_M_NODE_BYTES], + const unsigned char right_node[MBEDTLS_LMS_M_NODE_BYTES], + unsigned int r_node_idx, + unsigned char out[MBEDTLS_LMS_M_NODE_BYTES] ) { psa_hash_operation_t op; psa_status_t status; @@ -190,7 +190,7 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, { r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM + priv_key_idx; - ret = create_merkle_leaf_node( + ret = create_merkle_leaf_value( ctx->params.I_key_identifier, ctx->ots_public_keys[priv_key_idx].public_key, r_node_idx, tree[r_node_idx] ); @@ -205,7 +205,7 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, for( r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM - 1; r_node_idx > 0; r_node_idx-- ) { - ret = create_merkle_internal_node( + ret = create_merkle_internal_value( ctx->params.I_key_identifier, tree[(r_node_idx * 2)], tree[(r_node_idx * 2 + 1)], r_node_idx, tree[r_node_idx] ); if( ret ) @@ -370,7 +370,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( ret ); } - create_merkle_leaf_node( + create_merkle_leaf_value( ctx->params.I_key_identifier, Kc_candidate_ots_pub_key, MERKLE_TREE_INTERNAL_NODE_AM + q_leaf_identifier, Tc_candidate_root_node ); @@ -393,7 +393,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, right_node = ( ( const unsigned char( * )[MBEDTLS_LMS_M_NODE_BYTES] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height]; } - create_merkle_internal_node( + create_merkle_internal_value( ctx->params.I_key_identifier, left_node, right_node, parent_node_id, Tc_candidate_root_node); From ab4f87413a79b5fb9158530fa7e7b0f8324c0328 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 1 Sep 2022 12:24:31 +0100 Subject: [PATCH 012/104] Add MBEDTLS_LMS_PRIVATE define To enable private key operations Signed-off-by: Raef Coles --- include/mbedtls/check_config.h | 5 + include/mbedtls/lms.h | 4 + include/mbedtls/mbedtls_config.h | 16 ++- library/lmots.c | 3 + library/lmots.h | 5 + library/lms.c | 139 +++++++++++++------------ tests/suites/test_suite_lmots.function | 2 +- tests/suites/test_suite_lms.function | 2 +- 8 files changed, 104 insertions(+), 72 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 2921278b32..570d9dba27 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -358,6 +358,11 @@ #error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C" #endif +#if defined(MBEDTLS_LMS_PRIVATE) && \ + ( !defined(MBEDTLS_LMS_C) ) +#error "MBEDTLS_LMS_PRIVATE requires MBEDTLS_LMS_C" +#endif + #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) #error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index c463b2abb7..65b1b7e0ec 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -106,6 +106,7 @@ typedef struct { } mbedtls_lms_public_t; +#ifdef MBEDTLS_LMS_PRIVATE /** LMS private context structure. * * A LMS private key is a set of LMOTS private keys, an index to the next usable @@ -133,6 +134,7 @@ typedef struct { unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lms_private_t; +#endif /* MBEDTLS_LMS_PRIVATE */ /** * \brief This function initializes an LMS public context @@ -196,6 +198,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size ); +#ifdef MBEDTLS_LMS_PRIVATE /** * \brief This function initializes an LMS private context * @@ -328,6 +331,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void* p_rng, unsigned char *msg, unsigned int msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len); +#endif /* MBEDTLS_LMS_PRIVATE */ #ifdef __cplusplus } diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 8c833b1cf9..c0caf75623 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2469,12 +2469,24 @@ * Module: library/lms.c * Caller: * - * Requires: MBEDTLS_MD_C + * Requires: MBEDTLS_PSA_CRYPTO_C * - * Uncomment to enable the LMS signature algorithm. + * Uncomment to enable the LMS verification algorithm and public key operations. */ #define MBEDTLS_LMS_C +/** + * \def MBEDTLS_LMS_PRIVATE + * + * Enable LMS private-key operations and signing code. Functions enabled by this + * option are experimental, and should not be used in production. + * + * Requires: MBEDTLS_LMS_C + * + * Uncomment to enable the LMS signature algorithm and private key operations. + */ +// #define MBEDTLS_LMS_PRIVATE + /** * \def MBEDTLS_NIST_KW_C * diff --git a/library/lmots.c b/library/lmots.c index d92d385255..bf6644935b 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -455,6 +455,8 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, return( 0 ); } +#ifdef MBEDTLS_LMS_PRIVATE + void mbedtls_lmots_init_private( mbedtls_lmots_private_t *ctx ) { mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_private_t ) ) ; @@ -716,4 +718,5 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( 0 ); } +#endif /* MBEDTLS_LMS_PRIVATE */ #endif /* MBEDTLS_LMS_C */ diff --git a/library/lmots.h b/library/lmots.h index ca7d4bf344..e784bf586e 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -101,6 +101,7 @@ typedef struct { Boolean values only. */ } mbedtls_lmots_public_t; +#ifdef MBEDTLS_LMS_PRIVATE /** LMOTS private context structure. * * A LMOTS private key is one hash output for each of digit of the digest + @@ -124,6 +125,7 @@ typedef struct { unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lmots_private_t; +#endif /* MBEDTLS_LMS_PRIVATE */ /** * \brief This function converts an unsigned int into a @@ -256,6 +258,8 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size ); +#ifdef MBEDTLS_LMS_PRIVATE + /** * \brief This function initializes a private LMOTS context * @@ -375,6 +379,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, void *p_rng, const unsigned char *msg, size_t msg_size, unsigned char *sig, size_t sig_size, size_t* sig_len ); +#endif /* MBEDTLS_LMS_PRIVATE */ #ifdef __cplusplus } diff --git a/library/lms.c b/library/lms.c index 44d4c79027..cb56cb31c6 100644 --- a/library/lms.c +++ b/library/lms.c @@ -177,74 +177,6 @@ exit: return ret; } -static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, - unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES] ) -{ - unsigned int priv_key_idx; - unsigned int r_node_idx; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* First create the leaf nodes, in ascending order */ - for( priv_key_idx = 0; priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM; - priv_key_idx++ ) - { - r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM + priv_key_idx; - - ret = create_merkle_leaf_value( - ctx->params.I_key_identifier, - ctx->ots_public_keys[priv_key_idx].public_key, - r_node_idx, tree[r_node_idx] ); - if( ret ) - { - return( ret ); - } - } - - /* Then the internal nodes, in reverse order so that we can guarantee the - * parent has been created */ - for( r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM - 1; r_node_idx > 0; - r_node_idx-- ) - { - ret = create_merkle_internal_value( - ctx->params.I_key_identifier, - tree[(r_node_idx * 2)], tree[(r_node_idx * 2 + 1)], r_node_idx, tree[r_node_idx] ); - if( ret ) - { - return( ret ); - } - } - - return( 0 ); -} - -static int get_merkle_path( mbedtls_lms_private_t *ctx, - unsigned int leaf_node_id, - unsigned char path[MBEDTLS_LMS_H_TREE_HEIGHT][MBEDTLS_LMS_M_NODE_BYTES] ) -{ - unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES]; - unsigned int curr_node_id = leaf_node_id; - unsigned int adjacent_node_id; - unsigned int height; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - ret = calculate_merkle_tree( ctx, tree); - if( ret ) - { - return( ret ); - } - - for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ ) - { - adjacent_node_id = curr_node_id ^ 1; - - memcpy( &path[height], &tree[adjacent_node_id], MBEDTLS_LMOTS_N_HASH_LEN ); - - curr_node_id >>=1; - } - - return( 0 ); -} - void mbedtls_lms_init_public( mbedtls_lms_public_t *ctx ) { mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ) ; @@ -409,6 +341,76 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( 0 ); } +#ifdef MBEDTLS_LMS_PRIVATE + +static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, + unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES] ) +{ + unsigned int priv_key_idx; + unsigned int r_node_idx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* First create the leaf nodes, in ascending order */ + for( priv_key_idx = 0; priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM; + priv_key_idx++ ) + { + r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM + priv_key_idx; + + ret = create_merkle_leaf_value( + ctx->params.I_key_identifier, + ctx->ots_public_keys[priv_key_idx].public_key, + r_node_idx, tree[r_node_idx] ); + if( ret ) + { + return( ret ); + } + } + + /* Then the internal nodes, in reverse order so that we can guarantee the + * parent has been created */ + for( r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM - 1; r_node_idx > 0; + r_node_idx-- ) + { + ret = create_merkle_internal_value( + ctx->params.I_key_identifier, + tree[(r_node_idx * 2)], tree[(r_node_idx * 2 + 1)], r_node_idx, tree[r_node_idx] ); + if( ret ) + { + return( ret ); + } + } + + return( 0 ); +} + +static int get_merkle_path( mbedtls_lms_private_t *ctx, + unsigned int leaf_node_id, + unsigned char path[MBEDTLS_LMS_H_TREE_HEIGHT][MBEDTLS_LMS_M_NODE_BYTES] ) +{ + unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES]; + unsigned int curr_node_id = leaf_node_id; + unsigned int adjacent_node_id; + unsigned int height; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = calculate_merkle_tree( ctx, tree); + if( ret ) + { + return( ret ); + } + + for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ ) + { + adjacent_node_id = curr_node_id ^ 1; + + memcpy( &path[height], &tree[adjacent_node_id], MBEDTLS_LMOTS_N_HASH_LEN ); + + curr_node_id >>=1; + } + + return( 0 ); +} + void mbedtls_lms_init_private( mbedtls_lms_private_t *ctx ) { mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ) ; @@ -668,4 +670,5 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, return( 0 ); } +#endif /* MBEDTLS_LMS_PRIVATE */ #endif /* MBEDTLS_LMS_C */ diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 4492daaae1..73c9aff096 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -8,7 +8,7 @@ /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_CTR_DRBG_C + * depends_on:MBEDTLS_LMS_C:MBEDTLS_LMS_PRIVATE:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_CTR_DRBG_C * END_DEPENDENCIES */ diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 64ea900f1e..22c8eb5a12 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -6,7 +6,7 @@ /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_CTR_DRBG_C + * depends_on:MBEDTLS_LMS_C:MBEDTLS_LMS_PRIVATE:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_CTR_DRBG_C * END_DEPENDENCIES */ From e9479a02647cab34520390900e62ea931c8f5cec Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 1 Sep 2022 16:06:35 +0100 Subject: [PATCH 013/104] Update LMS API to support multiple parameter sets Parameterise macros to allow variation of sizes Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 27 +++- library/lmots.c | 133 ++++++++++-------- library/lmots.h | 29 ++-- library/lms.c | 181 ++++++++++++++----------- tests/suites/test_suite_lmots.function | 9 +- tests/suites/test_suite_lms.function | 8 +- 6 files changed, 226 insertions(+), 161 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 65b1b7e0ec..becfb89e31 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -40,15 +40,28 @@ #define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ #define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */ -#define MBEDTLS_LMS_M_NODE_BYTES (32) /* The length of a hash output, 32 for SHA256 */ #define MBEDTLS_LMS_TYPE_LEN (4) -#define MBEDTLS_LMS_H_TREE_HEIGHT (10u) +#define MBEDTLS_LMS_H_TREE_HEIGHT(type) (type == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0) -#define MBEDTLS_LMS_SIG_LEN (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + MBEDTLS_LMOTS_SIG_LEN + \ - MBEDTLS_LMS_TYPE_LEN + MBEDTLS_LMS_H_TREE_HEIGHT * MBEDTLS_LMS_M_NODE_BYTES) +/* The length of a hash output, Currently only imlemented for SHA256. + * Max is 32 bytes. + */ +/* The length of a hash output, Currently only imlemented for SHA256. + * Max is 32 bytes. + */ +#define MBEDTLS_LMS_M_NODE_BYTES(type) (type == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0) +#define MBEDTLS_LMS_M_NODE_BYTES_MAX 32 -#define MBEDTLS_LMS_PUBLIC_KEY_LEN (MBEDTLS_LMS_TYPE_LEN + MBEDTLS_LMOTS_TYPE_LEN + \ - MBEDTLS_LMOTS_I_KEY_ID_LEN + MBEDTLS_LMS_M_NODE_BYTES) +#define MBEDTLS_LMS_SIG_LEN(type, otstype) (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ + MBEDTLS_LMOTS_SIG_LEN(otstype) + \ + MBEDTLS_LMS_TYPE_LEN + \ + (MBEDTLS_LMS_H_TREE_HEIGHT(type) * \ + MBEDTLS_LMS_M_NODE_BYTES(type))) + +#define MBEDTLS_LMS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMS_TYPE_LEN + \ + MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ + MBEDTLS_LMS_M_NODE_BYTES(type)) #ifdef __cplusplus @@ -99,7 +112,7 @@ typedef struct { */ typedef struct { mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); - unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES]; /*!< The public key, in + unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES_MAX]; /*!< The public key, in the form of the merkle tree root node. */ unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. Boolean values only. */ diff --git a/library/lmots.c b/library/lmots.c index bf6644935b..41ca0422bf 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -45,7 +45,7 @@ #include "psa/crypto.h" #define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN) +#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type)) #define MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET (0) #define MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) @@ -60,6 +60,9 @@ #define J_HASH_IDX_LEN (1) #define D_CONST_LEN (2) +/* Currently only defined for SHA256, 32 is the max hash output size */ +#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN_MAX (MBEDTLS_LMOTS_N_HASH_LEN_MAX) + #define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) #define D_CONST_LEN (2) @@ -87,12 +90,13 @@ unsigned int network_bytes_to_unsigned_int(size_t len, const unsigned char *byte return val; } -static unsigned short lmots_checksum_calculate( const unsigned char* digest ) +static unsigned short lmots_checksum_calculate( const mbedtls_lmots_parameters_t *params, + const unsigned char* digest ) { size_t idx; unsigned sum = 0; - for ( idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN; idx++ ) + for ( idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++ ) { sum += DIGIT_MAX_VALUE - digest[idx]; } @@ -103,8 +107,8 @@ static unsigned short lmots_checksum_calculate( const unsigned char* digest ) static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *params, const unsigned char *msg, size_t msg_len, - const unsigned char C_random_value[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN], - unsigned char out[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT] ) + const unsigned char *C_random_value, + unsigned char *out ) { psa_hash_operation_t op; psa_status_t status; @@ -135,7 +139,8 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p if ( ret != 0 ) goto exit; - status = psa_hash_update( &op, C_random_value, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN ); + status = psa_hash_update( &op, C_random_value, + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type) ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) goto exit; @@ -145,14 +150,16 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p if ( ret != 0 ) goto exit; - status = psa_hash_finish( &op, out, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT, + status = psa_hash_finish( &op, out, + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type), &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) goto exit; - checksum = lmots_checksum_calculate( out ); - unsigned_int_to_network_bytes( checksum, CHECKSUM_LEN, out + MBEDTLS_LMOTS_N_HASH_LEN ); + checksum = lmots_checksum_calculate( params, out ); + unsigned_int_to_network_bytes( checksum, CHECKSUM_LEN, + out + MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); exit: psa_hash_abort( &op ); @@ -161,10 +168,10 @@ exit: } static int hash_digit_array( const mbedtls_lmots_parameters_t *params, - const unsigned char x_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN], + const unsigned char *x_digit_array, const unsigned char *hash_idx_min_values, const unsigned char *hash_idx_max_values, - unsigned char output[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN] ) + unsigned char *output ) { unsigned char i_digit_idx; unsigned char j_hash_idx; @@ -178,15 +185,18 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, psa_hash_operation_t op; psa_status_t status; size_t output_hash_len; - unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN]; + unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; op = psa_hash_operation_init(); - for ( i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT; i_digit_idx++ ) + for ( i_digit_idx = 0; + i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); + i_digit_idx++ ) { - memcpy( tmp_hash, &x_digit_array[i_digit_idx], MBEDTLS_LMOTS_N_HASH_LEN ); + memcpy( tmp_hash, &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], + MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); j_hash_idx_min = hash_idx_min_values != NULL ? hash_idx_min_values[i_digit_idx] : 0; j_hash_idx_max = hash_idx_max_values != NULL ? hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; @@ -224,7 +234,8 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, if ( ret != 0 ) goto exit; - status = psa_hash_update( &op, tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, tmp_hash, + MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) goto exit; @@ -237,7 +248,8 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, psa_hash_abort( &op ); } - memcpy( &output[i_digit_idx], tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN ); + memcpy( &output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], tmp_hash, + MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); } exit: @@ -253,7 +265,7 @@ exit: } static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t *params, - const unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN], + const unsigned char *y_hashed_digits, unsigned char *pub_key ) { psa_hash_operation_t op; @@ -285,13 +297,15 @@ static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t if ( ret != 0 ) goto exit; - status = psa_hash_update( &op, ( unsigned char * )y_hashed_digits, - MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT * MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, y_hashed_digits, + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) * + MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) goto exit; - status = psa_hash_finish( &op, pub_key, 32, &output_hash_len ); + status = psa_hash_finish( &op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN(params->type), + &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); exit: @@ -330,15 +344,15 @@ void mbedtls_lmots_free_public( mbedtls_lmots_public_t *ctx ) int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, const unsigned char *key, size_t key_len ) { - if ( key_len < MBEDTLS_LMOTS_PUBLIC_KEY_LEN ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - ctx->params.type = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + if ( key_len < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + memcpy( ctx->params.I_key_identifier, key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN ); @@ -347,7 +361,7 @@ int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, memcpy( ctx->public_key, key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, - MBEDTLS_LMOTS_N_HASH_LEN ); + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); ctx->have_public_key = 1; @@ -363,8 +377,8 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters size_t out_size, size_t *out_len) { - unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT]; - unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN]; + unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; + unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ( msg == NULL && msg_size != 0 ) @@ -372,7 +386,8 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters return ( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if ( sig_size != MBEDTLS_LMOTS_SIG_LEN || out_size < MBEDTLS_LMOTS_N_HASH_LEN ) + if ( sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) || + out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type) ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -386,14 +401,16 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters } ret = hash_digit_array( params, - ( const unsigned char( *)[MBEDTLS_LMOTS_N_HASH_LEN] )(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET), - tmp_digit_array, NULL, y_hashed_digits ); + sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type), + tmp_digit_array, NULL, (unsigned char *)y_hashed_digits ); if ( ret ) { return ( ret ); } - ret = public_key_from_hashed_digit_array( params, y_hashed_digits, out ); + ret = public_key_from_hashed_digit_array( params, + (unsigned char *)y_hashed_digits, + out ); if ( ret ) { return ( ret ); @@ -401,7 +418,7 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters if ( out_len != NULL ) { - *out_len = MBEDTLS_LMOTS_N_HASH_LEN; + *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type); } return( 0 ); @@ -411,7 +428,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size ) { - unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN]; + unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ( msg == NULL && msg_size != 0 ) @@ -439,7 +456,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, ret = mbedtls_lmots_calculate_public_key_candidate( &ctx->params, msg, msg_size, sig, sig_size, Kc_public_key_candidate, - MBEDTLS_LMOTS_N_HASH_LEN, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), NULL); if ( ret ) { @@ -505,7 +522,9 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, unsigned_int_to_network_bytes( 0xFF, sizeof( const_bytes ), const_bytes ); - for ( i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT; i_digit_idx++ ) + for ( i_digit_idx = 0; + i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type); + i_digit_idx++ ) { status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); @@ -544,7 +563,8 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, status = psa_hash_finish( &op, ctx->private_key[i_digit_idx], - 32, &output_hash_len ); + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), + &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); if ( ret ) goto exit; @@ -567,7 +587,7 @@ exit: int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, mbedtls_lmots_private_t *priv_ctx) { - unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN]; + unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Check that a private key is loaded */ @@ -576,15 +596,16 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ret = hash_digit_array( &priv_ctx->params, priv_ctx->private_key, NULL, - NULL, y_hashed_digits ); + ret = hash_digit_array( &priv_ctx->params, + (unsigned char *)priv_ctx->private_key, NULL, + NULL, (unsigned char *)y_hashed_digits ); if ( ret ) { return( ret ); } ret = public_key_from_hashed_digit_array( &priv_ctx->params, - y_hashed_digits, + (unsigned char *)y_hashed_digits, ctx->public_key ); if ( ret ) { @@ -604,7 +625,7 @@ int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len ) { - if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN ) + if( key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) ) { return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } @@ -627,11 +648,11 @@ int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, - MBEDTLS_LMOTS_N_HASH_LEN ); + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); if( key_len != NULL ) { - *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN; + *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type); } return( 0 ); @@ -642,7 +663,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, void *p_rng, const unsigned char *msg, size_t msg_size, unsigned char *sig, size_t sig_size, size_t* sig_len ) { - unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT]; + unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; /* Create a temporary buffer to prepare the signature in. This allows us to * finish creating a signature (ensuring the process doesn't fail), and then * erase the private key **before** writing any data into the sig parameter @@ -650,8 +671,8 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, * a partial signature on failure, which effectively compromises the private * key. */ - unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][MBEDTLS_LMOTS_N_HASH_LEN]; - unsigned char tmp_c_random[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN]; + unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char tmp_c_random[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ( msg == NULL && msg_size != 0 ) @@ -659,7 +680,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( sig_size < MBEDTLS_LMOTS_SIG_LEN ) + if( sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type) ) { return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } @@ -670,7 +691,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ret = f_rng( p_rng, tmp_c_random, MBEDTLS_LMOTS_N_HASH_LEN ); + ret = f_rng( p_rng, tmp_c_random, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); if ( ret ) { return( ret ); @@ -685,9 +706,8 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( ret ); } - ret = hash_digit_array( &ctx->params, - ctx->private_key, - NULL, tmp_digit_array, tmp_sig ); + ret = hash_digit_array( &ctx->params, (unsigned char *)ctx->private_key, + NULL, tmp_digit_array, (unsigned char *)tmp_sig ); if ( ret ) { return( ret ); @@ -705,14 +725,15 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, sizeof(ctx->private_key)); memcpy( sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random, - MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN ); + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type) ); - memcpy( sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET, tmp_sig, - MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT * MBEDTLS_LMOTS_N_HASH_LEN ); + memcpy( sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig, + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type) + * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); if( sig_len != NULL ) { - *sig_len = MBEDTLS_LMS_SIG_LEN; + *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type); } return( 0 ); diff --git a/library/lmots.h b/library/lmots.h index e784bf586e..6ada0bad64 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -33,18 +33,25 @@ #include #include -#define MBEDTLS_LMOTS_N_HASH_LEN (32) -#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT (34) -#define MBEDTLS_LMOTS_TYPE_LEN (4) -#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN (MBEDTLS_LMOTS_N_HASH_LEN) -#define MBEDTLS_LMOTS_I_KEY_ID_LEN (16) -#define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4) +/* Currently only defined for SHA256, 32 is the max hash output size */ +#define MBEDTLS_LMOTS_N_HASH_LEN_MAX (32u) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX (34u) +#define MBEDTLS_LMOTS_N_HASH_LEN(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) +#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type)) +#define MBEDTLS_LMOTS_TYPE_LEN (4u) +#define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u) +#define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u) -#define MBEDTLS_LMOTS_SIG_LEN (MBEDTLS_LMOTS_TYPE_LEN + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN + \ - (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT * MBEDTLS_LMOTS_N_HASH_LEN)) +#define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \ + (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \ + MBEDTLS_LMOTS_N_HASH_LEN(type))) -#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN (MBEDTLS_LMOTS_TYPE_LEN + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ - MBEDTLS_LMOTS_Q_LEAF_ID_LEN + MBEDTLS_LMOTS_N_HASH_LEN) +#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ + MBEDTLS_LMOTS_N_HASH_LEN(type)) #define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0) @@ -121,7 +128,7 @@ typedef struct { */ typedef struct { mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); - unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT][32]; + unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][32]; unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lmots_private_t; diff --git a/library/lms.c b/library/lms.c index cb56cb31c6..71921f7cb5 100644 --- a/library/lms.c +++ b/library/lms.c @@ -54,10 +54,10 @@ #define mbedtls_free free #endif -#define MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET (0) -#define MBEDTLS_LMS_SIG_OTS_SIG_OFFSET (MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) -#define MBEDTLS_LMS_SIG_TYPE_OFFSET (MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_LEN) -#define MBEDTLS_LMS_SIG_PATH_OFFSET (MBEDTLS_LMS_SIG_TYPE_OFFSET + MBEDTLS_LMS_TYPE_LEN) +#define MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET (0) +#define MBEDTLS_LMS_SIG_OTS_SIG_OFFSET (MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) +#define MBEDTLS_LMS_SIG_TYPE_OFFSET(otstype) (MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_LEN(otstype)) +#define MBEDTLS_LMS_SIG_PATH_OFFSET(otstype) (MBEDTLS_LMS_SIG_TYPE_OFFSET(otstype) + MBEDTLS_LMS_TYPE_LEN) #define MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET (0) #define MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET + MBEDTLS_LMS_TYPE_LEN) @@ -65,18 +65,21 @@ #define MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET + MBEDTLS_LMOTS_I_KEY_ID_LEN) -#define MERKLE_TREE_NODE_AM (1u << (MBEDTLS_LMS_H_TREE_HEIGHT + 1u)) -#define MERKLE_TREE_LEAF_NODE_AM (1u << MBEDTLS_LMS_H_TREE_HEIGHT) -#define MERKLE_TREE_INTERNAL_NODE_AM (1u << MBEDTLS_LMS_H_TREE_HEIGHT) +/* Currently only support H=10 */ +#define MBEDTLS_LMS_H_TREE_HEIGHT_MAX 10 +#define MERKLE_TREE_NODE_AM_MAX (1u << (MBEDTLS_LMS_H_TREE_HEIGHT_MAX + 1u)) +#define MERKLE_TREE_NODE_AM(type) (1u << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u)) +#define MERKLE_TREE_LEAF_NODE_AM(type) (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)) +#define MERKLE_TREE_INTERNAL_NODE_AM(type) (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)) #define D_CONST_LEN (2) static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = {0x82, 0x82}; static const unsigned char D_INTERNAL_CONSTANT_BYTES[D_CONST_LEN] = {0x83, 0x83}; -static int create_merkle_leaf_value( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - unsigned char pub_key[MBEDTLS_LMOTS_N_HASH_LEN], +static int create_merkle_leaf_value( const mbedtls_lms_parameters_t *params, + unsigned char *pub_key, unsigned int r_node_idx, - unsigned char out[MBEDTLS_LMS_M_NODE_BYTES] ) + unsigned char *out ) { psa_hash_operation_t op; psa_status_t status; @@ -90,7 +93,8 @@ static int create_merkle_leaf_value( const unsigned char I_key_identifier[MBEDTL if ( ret != 0 ) goto exit; - status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + status = psa_hash_update( &op, params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) goto exit; @@ -106,12 +110,14 @@ static int create_merkle_leaf_value( const unsigned char I_key_identifier[MBEDTL if( ret ) goto exit; - status = psa_hash_update( &op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, pub_key, + MBEDTLS_LMOTS_N_HASH_LEN(params->otstype) ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) goto exit; - status = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES, &output_hash_len); + status = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), + &output_hash_len); ret = mbedtls_lms_error_from_psa( status ); if( ret ) goto exit; @@ -122,11 +128,11 @@ exit: return( ret ); } -static int create_merkle_internal_value( const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - const unsigned char left_node[MBEDTLS_LMS_M_NODE_BYTES], - const unsigned char right_node[MBEDTLS_LMS_M_NODE_BYTES], +static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params, + const unsigned char *left_node, + const unsigned char *right_node, unsigned int r_node_idx, - unsigned char out[MBEDTLS_LMS_M_NODE_BYTES] ) + unsigned char *out ) { psa_hash_operation_t op; psa_status_t status; @@ -140,7 +146,8 @@ static int create_merkle_internal_value( const unsigned char I_key_identifier[MB if ( ret != 0 ) goto exit; - status = psa_hash_update( &op, I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + status = psa_hash_update( &op, params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) goto exit; @@ -156,17 +163,20 @@ static int create_merkle_internal_value( const unsigned char I_key_identifier[MB if( ret ) goto exit; - status = psa_hash_update( &op, left_node, MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, left_node, + MBEDTLS_LMS_M_NODE_BYTES(params->type) ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) goto exit; - status = psa_hash_update( &op, right_node, MBEDTLS_LMOTS_N_HASH_LEN ); + status = psa_hash_update( &op, right_node, + MBEDTLS_LMS_M_NODE_BYTES(params->type) ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) goto exit; - ret = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES, &output_hash_len); + ret = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), + &output_hash_len); ret = mbedtls_lms_error_from_psa( status ); if( ret ) goto exit; @@ -193,7 +203,7 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, mbedtls_lms_algorithm_type_t type; mbedtls_lmots_algorithm_type_t otstype; - if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN ) + if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) { return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } @@ -217,7 +227,7 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, key + MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN ); memcpy( ctx->T_1_pub_key, key + MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET, - MBEDTLS_LMOTS_N_HASH_LEN ); + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) ); ctx->have_public_key = 1; @@ -229,8 +239,8 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, const unsigned char *sig, size_t sig_size ) { unsigned int q_leaf_identifier; - unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN]; - unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES]; + unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX]; unsigned int height; unsigned int curr_node_id; unsigned int parent_node_id; @@ -244,7 +254,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( sig_size != MBEDTLS_LMS_SIG_LEN ) + if( sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -261,15 +271,16 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_TYPE_OFFSET) != MBEDTLS_LMS_SHA256_M32_H10 ) + if( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, + sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) + != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } - if( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) - != MBEDTLS_LMOTS_SHA256_N32_W8 ) + if( network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, + sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype)) + != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } @@ -278,7 +289,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, q_leaf_identifier = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); - if( q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM ) + if( q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type) ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } @@ -293,7 +304,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, ret = mbedtls_lmots_calculate_public_key_candidate( &ots_params, msg, msg_size, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, - MBEDTLS_LMOTS_SIG_LEN, + MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), Kc_candidate_ots_pub_key, sizeof(Kc_candidate_ots_pub_key), NULL ); @@ -303,37 +314,40 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, } create_merkle_leaf_value( - ctx->params.I_key_identifier, - Kc_candidate_ots_pub_key, MERKLE_TREE_INTERNAL_NODE_AM + q_leaf_identifier, + &ctx->params, + Kc_candidate_ots_pub_key, + MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, Tc_candidate_root_node ); - curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM + q_leaf_identifier; + curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier; - for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ ) + for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); + height++ ) { parent_node_id = curr_node_id / 2; /* Left/right node ordering matters for the hash */ if( curr_node_id & 1 ) { - left_node = ( ( const unsigned char( * )[MBEDTLS_LMS_M_NODE_BYTES] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height]; + left_node = sig + MBEDTLS_LMS_SIG_PATH_OFFSET(ctx->params.otstype) + + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); right_node = Tc_candidate_root_node; } else { left_node = Tc_candidate_root_node; - right_node = ( ( const unsigned char( * )[MBEDTLS_LMS_M_NODE_BYTES] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height]; + right_node = sig + MBEDTLS_LMS_SIG_PATH_OFFSET(ctx->params.otstype) + + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); } - create_merkle_internal_value( - ctx->params.I_key_identifier, - left_node, right_node, parent_node_id, Tc_candidate_root_node); + create_merkle_internal_value( &ctx->params, left_node, right_node, + parent_node_id, Tc_candidate_root_node); curr_node_id /= 2; } if( memcmp( Tc_candidate_root_node, ctx->T_1_pub_key, - MBEDTLS_LMOTS_N_HASH_LEN) ) + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)) ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } @@ -344,22 +358,22 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, #ifdef MBEDTLS_LMS_PRIVATE static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, - unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES] ) + unsigned char *tree ) { unsigned int priv_key_idx; unsigned int r_node_idx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* First create the leaf nodes, in ascending order */ - for( priv_key_idx = 0; priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM; + for( priv_key_idx = 0; + priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type); priv_key_idx++ ) { - r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM + priv_key_idx; + r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx; - ret = create_merkle_leaf_value( - ctx->params.I_key_identifier, - ctx->ots_public_keys[priv_key_idx].public_key, - r_node_idx, tree[r_node_idx] ); + ret = create_merkle_leaf_value( &ctx->params, + ctx->ots_public_keys[priv_key_idx].public_key, r_node_idx, + &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)] ); if( ret ) { return( ret ); @@ -368,12 +382,14 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, /* Then the internal nodes, in reverse order so that we can guarantee the * parent has been created */ - for( r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM - 1; r_node_idx > 0; + for( r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1; + r_node_idx > 0; r_node_idx-- ) { - ret = create_merkle_internal_value( - ctx->params.I_key_identifier, - tree[(r_node_idx * 2)], tree[(r_node_idx * 2 + 1)], r_node_idx, tree[r_node_idx] ); + ret = create_merkle_internal_value( &ctx->params, + &tree[(r_node_idx * 2) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], + &tree[(r_node_idx * 2 + 1) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], + r_node_idx, &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)] ); if( ret ) { return( ret ); @@ -385,25 +401,28 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, static int get_merkle_path( mbedtls_lms_private_t *ctx, unsigned int leaf_node_id, - unsigned char path[MBEDTLS_LMS_H_TREE_HEIGHT][MBEDTLS_LMS_M_NODE_BYTES] ) + unsigned char *path ) { - unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES]; + unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX]; unsigned int curr_node_id = leaf_node_id; unsigned int adjacent_node_id; unsigned int height; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ret = calculate_merkle_tree( ctx, tree); + ret = calculate_merkle_tree( ctx, (unsigned char *)tree); if( ret ) { return( ret ); } - for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ ) + for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); + height++ ) { adjacent_node_id = curr_node_id ^ 1; - memcpy( &path[height], &tree[adjacent_node_id], MBEDTLS_LMOTS_N_HASH_LEN ); + memcpy( &path[height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], + &tree[adjacent_node_id], + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) ); curr_node_id >>=1; } @@ -422,7 +441,7 @@ void mbedtls_lms_free_private( mbedtls_lms_private_t *ctx ) if( ctx->have_private_key ) { - for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM; idx++ ) + for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) { mbedtls_lmots_free_private( &ctx->ots_private_keys[idx] ); mbedtls_lmots_free_public( &ctx->ots_public_keys[idx] ); @@ -469,30 +488,30 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - ctx->ots_private_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM, - sizeof( mbedtls_lmots_private_t)); + ctx->ots_private_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + sizeof( mbedtls_lmots_private_t)); if( ctx->ots_private_keys == NULL ) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; } - ctx->ots_public_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM, - sizeof( mbedtls_lmots_public_t)); + ctx->ots_public_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + sizeof( mbedtls_lmots_public_t)); if( ctx->ots_public_keys == NULL ) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; } - for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM; idx++ ) + for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) { mbedtls_lmots_init_private( &ctx->ots_private_keys[idx] ); mbedtls_lmots_init_public( &ctx->ots_public_keys[idx] ); } - for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM; idx++ ) + for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) { ret = mbedtls_lmots_generate_private_key( &ctx->ots_private_keys[idx], otstype, @@ -529,7 +548,7 @@ exit: int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, mbedtls_lms_private_t *priv_ctx ) { - unsigned char tree[MERKLE_TREE_NODE_AM][MBEDTLS_LMS_M_NODE_BYTES]; + unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if( ! priv_ctx->MBEDTLS_PRIVATE( have_private_key ) ) @@ -552,14 +571,15 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, memcpy( &ctx->params, &priv_ctx->params, sizeof(mbedtls_lmots_parameters_t) ); - ret = calculate_merkle_tree( priv_ctx, tree); + ret = calculate_merkle_tree( priv_ctx, (unsigned char *)tree); if( ret ) { return( ret ); } /* Root node is always at position 1, due to 1-based indexing */ - memcpy( ctx->T_1_pub_key, &tree[1], MBEDTLS_LMOTS_N_HASH_LEN ); + memcpy( ctx->T_1_pub_key, &tree[1], + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); ctx->have_public_key = 1; @@ -570,7 +590,7 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len ) { - if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN ) { + if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) { return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } @@ -590,10 +610,10 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key MBEDTLS_LMOTS_I_KEY_ID_LEN ); memcpy( key + MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET, ctx->T_1_pub_key, - MBEDTLS_LMOTS_N_HASH_LEN ); + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) ); if( key_len != NULL ) { - *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN; + *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type); } return( 0 ); @@ -613,7 +633,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( sig_size < MBEDTLS_LMS_SIG_LEN ) + if( sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) ) { return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } @@ -629,7 +649,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM ) + if( ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type) ) { return( MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS ); } @@ -644,26 +664,29 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, ret = mbedtls_lmots_sign( &ctx->ots_private_keys[q_leaf_identifier], f_rng, p_rng, msg, msg_size, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, - MBEDTLS_LMS_SIG_LEN, NULL ); + MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype), + NULL ); if( ret ) { return( ret ); } unsigned_int_to_network_bytes( ctx->params.type, - MBEDTLS_LMS_TYPE_LEN, sig + MBEDTLS_LMS_SIG_TYPE_OFFSET ); + MBEDTLS_LMS_TYPE_LEN, + sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype) ); unsigned_int_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET); - ret = get_merkle_path( ctx, MERKLE_TREE_INTERNAL_NODE_AM + q_leaf_identifier, - ( unsigned char( * )[MBEDTLS_LMS_M_NODE_BYTES] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) ); + ret = get_merkle_path( ctx, + MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, + sig + MBEDTLS_LMS_SIG_PATH_OFFSET(ctx->params.otstype) ); if( ret ) { return( ret ); } if( sig_len != NULL ) { - *sig_len = MBEDTLS_LMS_SIG_LEN; + *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype); } diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 73c9aff096..ce69803f4e 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -17,7 +17,7 @@ void lmots_sign_verify_test ( data_t * msg ) { mbedtls_lmots_public_t pub_ctx; mbedtls_lmots_private_t priv_ctx; - unsigned char sig[MBEDTLS_LMOTS_SIG_LEN]; + unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; mbedtls_entropy_context entropy_ctx; mbedtls_ctr_drbg_context drbg_ctx; uint8_t seed[16]; @@ -67,13 +67,14 @@ exit: void lmots_import_export_test ( data_t * pub_key ) { mbedtls_lmots_public_t ctx; - uint8_t exported_pub_key[MBEDTLS_LMOTS_PUBLIC_KEY_LEN]; + uint8_t exported_pub_key[MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; mbedtls_lmots_init_public( &ctx ); TEST_ASSERT( mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ) == 0 ); TEST_ASSERT( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, sizeof( exported_pub_key ), NULL ) == 0 ); - TEST_ASSERT( memcmp( pub_key->x, exported_pub_key, MBEDTLS_LMOTS_PUBLIC_KEY_LEN ) == 0 ); + TEST_ASSERT( memcmp( pub_key->x, exported_pub_key, + MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ) == 0 ); exit: mbedtls_lmots_free_public( &ctx ); @@ -84,7 +85,7 @@ exit: void lmots_reuse_test ( data_t * msg ) { mbedtls_lmots_private_t ctx; - unsigned char sig[MBEDTLS_LMOTS_SIG_LEN]; + unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; mbedtls_entropy_context entropy_ctx; mbedtls_ctr_drbg_context drbg_ctx; uint8_t seed[16]; diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 22c8eb5a12..92a5a07ab1 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -15,7 +15,7 @@ void lms_sign_verify_test ( data_t * msg ) { mbedtls_lms_public_t pub_ctx; mbedtls_lms_private_t priv_ctx; - unsigned char sig[MBEDTLS_LMS_SIG_LEN]; + unsigned char sig[MBEDTLS_LMS_SIG_LEN(MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8)]; mbedtls_entropy_context entropy_ctx; mbedtls_ctr_drbg_context drbg_ctx; uint8_t seed[16]; @@ -76,15 +76,15 @@ exit: void lms_import_export_test ( data_t * pub_key ) { mbedtls_lms_public_t ctx; - uint8_t exported_pub_key[MBEDTLS_LMS_PUBLIC_KEY_LEN]; + uint8_t exported_pub_key[MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10)]; mbedtls_lms_init_public(&ctx); TEST_ASSERT( mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ) == 0 ); TEST_ASSERT( mbedtls_lms_export_public_key( &ctx, exported_pub_key, sizeof(exported_pub_key), NULL ) == 0 ); - ASSERT_COMPARE( pub_key->x, MBEDTLS_LMS_PUBLIC_KEY_LEN, - exported_pub_key, MBEDTLS_LMS_PUBLIC_KEY_LEN ); + ASSERT_COMPARE( pub_key->x, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10), + exported_pub_key, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10) ); exit: mbedtls_lms_free_public( &ctx ); From 366d67d9af1165bf313f58b6f7e93af507957f90 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 1 Sep 2022 17:23:12 +0100 Subject: [PATCH 014/104] Shorted LMS and LMOTS line-lengths To attempt to comply with the 80-char suggestion Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 3 +- library/lmots.c | 66 ++++++++++++++++++++++++++++--------------- library/lmots.h | 21 ++++++++------ library/lms.c | 62 ++++++++++++++++++++++------------------ 4 files changed, 92 insertions(+), 60 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index becfb89e31..23c5ebdf46 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -68,7 +68,8 @@ extern "C" { #endif -/* https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml +/** The Identifier of the LMS parameter set, as per + * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml * We are only implementing a subset of the types, particularly H10, for the sake of simplicty. */ typedef enum { diff --git a/library/lmots.c b/library/lmots.c index 41ca0422bf..82da4c1391 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -44,13 +44,18 @@ #include "psa/crypto.h" -#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type)) +#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \ + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type)) -#define MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET (0) -#define MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET + MBEDTLS_LMOTS_I_KEY_ID_LEN) -#define MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) +#define MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET (0) +#define MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN) +#define MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) /* We only support parameter sets that use 8-bit digits, as it does not require * translation logic between digits and bytes */ @@ -69,7 +74,8 @@ static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = {0x80, 0x80}; static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = {0x81, 0x81}; -void unsigned_int_to_network_bytes(unsigned int val, size_t len, unsigned char *bytes) +void unsigned_int_to_network_bytes(unsigned int val, size_t len, + unsigned char *bytes) { size_t idx; @@ -78,7 +84,8 @@ void unsigned_int_to_network_bytes(unsigned int val, size_t len, unsigned char * } } -unsigned int network_bytes_to_unsigned_int(size_t len, const unsigned char *bytes) +unsigned int network_bytes_to_unsigned_int(size_t len, + const unsigned char *bytes) { size_t idx; unsigned int val = 0; @@ -195,13 +202,18 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, i_digit_idx++ ) { - memcpy( tmp_hash, &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], + memcpy( tmp_hash, + &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); - j_hash_idx_min = hash_idx_min_values != NULL ? hash_idx_min_values[i_digit_idx] : 0; - j_hash_idx_max = hash_idx_max_values != NULL ? hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; + j_hash_idx_min = hash_idx_min_values != NULL ? + hash_idx_min_values[i_digit_idx] : 0; + j_hash_idx_max = hash_idx_max_values != NULL ? + hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; - for ( j_hash_idx = (unsigned char)j_hash_idx_min; j_hash_idx < j_hash_idx_max; j_hash_idx++ ) + for ( j_hash_idx = (unsigned char)j_hash_idx_min; + j_hash_idx < j_hash_idx_max; + j_hash_idx++ ) { status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); @@ -222,13 +234,15 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, if ( ret != 0 ) goto exit; - unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, i_digit_idx_bytes ); + unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, + i_digit_idx_bytes ); status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) goto exit; - unsigned_int_to_network_bytes( j_hash_idx, J_HASH_IDX_LEN, j_hash_idx_bytes ); + unsigned_int_to_network_bytes( j_hash_idx, J_HASH_IDX_LEN, + j_hash_idx_bytes ); status = psa_hash_update( &op, j_hash_idx_bytes, J_HASH_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) @@ -240,7 +254,8 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, if ( ret != 0 ) goto exit; - status = psa_hash_finish( &op, tmp_hash, sizeof( tmp_hash ), &output_hash_len ); + status = psa_hash_finish( &op, tmp_hash, sizeof( tmp_hash ), + &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) goto exit; @@ -248,8 +263,8 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, psa_hash_abort( &op ); } - memcpy( &output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], tmp_hash, - MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); + memcpy( &output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], + tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); } exit: @@ -304,7 +319,8 @@ static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t if ( ret != 0 ) goto exit; - status = psa_hash_finish( &op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN(params->type), + status = psa_hash_finish( &op, pub_key, + MBEDTLS_LMOTS_N_HASH_LEN(params->type), &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); @@ -354,10 +370,12 @@ int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, } memcpy( ctx->params.I_key_identifier, - key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN ); + key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); memcpy( ctx->params.q_leaf_identifier, - key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); memcpy( ctx->public_key, key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, @@ -448,7 +466,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, } if ( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, - sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) + sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } @@ -545,7 +563,8 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, if ( ret ) goto exit; - unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, i_digit_idx_bytes ); + unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, + i_digit_idx_bytes ); status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); if ( ret ) @@ -691,7 +710,8 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - ret = f_rng( p_rng, tmp_c_random, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); + ret = f_rng( p_rng, tmp_c_random, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); if ( ret ) { return( ret ); diff --git a/library/lmots.h b/library/lmots.h index 6ada0bad64..46e03d6f52 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -59,8 +59,9 @@ extern "C" { #endif -/* https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml - * We are only implementing a subset of the types, particularly n32_w8, for the sake of simplicty. +/** The Identifier of the LMS parameter set, as per + * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml. + * We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicty. */ typedef enum { MBEDTLS_LMOTS_SHA256_N32_W8 = 4 @@ -144,7 +145,8 @@ typedef struct { * * \return The corresponding LMS error code. */ -void unsigned_int_to_network_bytes(unsigned int val, size_t len, unsigned char *bytes); +void unsigned_int_to_network_bytes(unsigned int val, size_t len, + unsigned char *bytes); /** * \brief This function converts a network-byte-order @@ -155,7 +157,8 @@ void unsigned_int_to_network_bytes(unsigned int val, size_t len, unsigned char * * * \return The corresponding LMS error code. */ -unsigned int network_bytes_to_unsigned_int(size_t len, const unsigned char *bytes); +unsigned int network_bytes_to_unsigned_int(size_t len, + const unsigned char *bytes); /** * \brief This function converts a \ref psa_status_t to a @@ -196,8 +199,8 @@ void mbedtls_lmots_free_public( mbedtls_lmots_public_t *ctx ); * * \param ctx The initialized LMOTS context store the key in. * \param key The buffer from which the key will be read. - * #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read from - * this. + * #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read + * from this. * * \return \c 0 on success. * \return A non-zero error code on failure. @@ -221,7 +224,8 @@ int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buffer from which the signature will be read. - * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from this. + * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from + * this. * \param out The buffer where the candidate public key will be * stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN * bytes in size. @@ -248,7 +252,8 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters * * \note Before this function is called, the context must * have been initialized and must contain a public key - * (either by import or calculation from a private key). + * (either by import or calculation from a private + * key). * * \param ctx The initialized LMOTS context from which the public * key will be read. diff --git a/library/lms.c b/library/lms.c index 71921f7cb5..a1e4c243a8 100644 --- a/library/lms.c +++ b/library/lms.c @@ -55,14 +55,20 @@ #endif #define MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET (0) -#define MBEDTLS_LMS_SIG_OTS_SIG_OFFSET (MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) -#define MBEDTLS_LMS_SIG_TYPE_OFFSET(otstype) (MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_LEN(otstype)) -#define MBEDTLS_LMS_SIG_PATH_OFFSET(otstype) (MBEDTLS_LMS_SIG_TYPE_OFFSET(otstype) + MBEDTLS_LMS_TYPE_LEN) +#define MBEDTLS_LMS_SIG_OTS_SIG_OFFSET (MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) +#define MBEDTLS_LMS_SIG_TYPE_OFFSET(otstype) (MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + \ + MBEDTLS_LMOTS_SIG_LEN(otstype)) +#define MBEDTLS_LMS_SIG_PATH_OFFSET(otstype) (MBEDTLS_LMS_SIG_TYPE_OFFSET(otstype) + \ + MBEDTLS_LMS_TYPE_LEN) #define MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET (0) -#define MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET + MBEDTLS_LMS_TYPE_LEN) -#define MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET + MBEDTLS_LMOTS_I_KEY_ID_LEN) +#define MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET + \ + MBEDTLS_LMS_TYPE_LEN) +#define MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN) /* Currently only support H=10 */ @@ -208,7 +214,8 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } - type = network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); + type = network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, + key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); if( type != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); @@ -216,7 +223,7 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, ctx->params.type = type; otstype = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, - key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); + key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); @@ -272,14 +279,14 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, } if( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) + sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } if( network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype)) + sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype)) != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); @@ -287,7 +294,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, q_leaf_identifier = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); + sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); if( q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type) ) { @@ -302,12 +309,10 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, ots_params.q_leaf_identifier ); ots_params.type = ctx->params.otstype; - ret = mbedtls_lmots_calculate_public_key_candidate( &ots_params, msg, msg_size, - sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, - MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), - Kc_candidate_ots_pub_key, - sizeof(Kc_candidate_ots_pub_key), - NULL ); + ret = mbedtls_lmots_calculate_public_key_candidate( &ots_params, msg, + msg_size, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, + MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), Kc_candidate_ots_pub_key, + sizeof(Kc_candidate_ots_pub_key), NULL ); if( ret ) { return( ret ); @@ -319,7 +324,8 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, Tc_candidate_root_node ); - curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier; + curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + + q_leaf_identifier; for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); height++ ) @@ -389,7 +395,8 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, ret = create_merkle_internal_value( &ctx->params, &tree[(r_node_idx * 2) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], &tree[(r_node_idx * 2 + 1) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], - r_node_idx, &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)] ); + r_node_idx, + &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)] ); if( ret ) { return( ret ); @@ -587,7 +594,8 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, } -int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key, +int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, + unsigned char *key, size_t key_size, size_t *key_len ) { if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) { @@ -602,9 +610,8 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key unsigned_int_to_network_bytes( ctx->params.type, MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); - unsigned_int_to_network_bytes( - ctx->params.otstype, - MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); + unsigned_int_to_network_bytes( ctx->params.otstype, MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); memcpy( key + MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); @@ -671,15 +678,14 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, return( ret ); } - unsigned_int_to_network_bytes( ctx->params.type, - MBEDTLS_LMS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype) ); + unsigned_int_to_network_bytes( ctx->params.type, MBEDTLS_LMS_TYPE_LEN, + sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype) ); unsigned_int_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET); ret = get_merkle_path( ctx, - MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, - sig + MBEDTLS_LMS_SIG_PATH_OFFSET(ctx->params.otstype) ); + MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, + sig + MBEDTLS_LMS_SIG_PATH_OFFSET(ctx->params.otstype) ); if( ret ) { return( ret ); From 9b88ee5d5dcdcf2498f7388c326c88dced0b5f08 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 2 Sep 2022 12:04:21 +0100 Subject: [PATCH 015/104] Fix LMS and LMOTS coding style violations Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 2 +- library/lmots.c | 79 ++++++++++++++++++++++--------------------- library/lmots.h | 14 ++++---- library/lms.c | 52 +++++++++++++++------------- 4 files changed, 77 insertions(+), 70 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 23c5ebdf46..3e84ce0575 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -344,7 +344,7 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void* p_rng, unsigned char *msg, unsigned int msg_size, - unsigned char *sig, size_t sig_size, size_t *sig_len); + unsigned char *sig, size_t sig_size, size_t *sig_len ); #endif /* MBEDTLS_LMS_PRIVATE */ #ifdef __cplusplus diff --git a/library/lmots.c b/library/lmots.c index 82da4c1391..fe78894f4c 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -68,30 +68,32 @@ /* Currently only defined for SHA256, 32 is the max hash output size */ #define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN_MAX (MBEDTLS_LMOTS_N_HASH_LEN_MAX) -#define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) +#define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) -#define D_CONST_LEN (2) +#define D_CONST_LEN (2) static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = {0x80, 0x80}; static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = {0x81, 0x81}; -void unsigned_int_to_network_bytes(unsigned int val, size_t len, - unsigned char *bytes) +void unsigned_int_to_network_bytes( unsigned int val, size_t len, + unsigned char *bytes ) { size_t idx; - for (idx = 0; idx < len; idx++) { - bytes[idx] = (val >> ((len - 1 - idx) * 8)) & 0xFF; + for ( idx = 0; idx < len; idx++ ) + { + bytes[idx] = ( val >> ( ( len - 1 - idx ) * 8 ) ) & 0xFF; } } -unsigned int network_bytes_to_unsigned_int(size_t len, - const unsigned char *bytes) +unsigned int network_bytes_to_unsigned_int( size_t len, + const unsigned char *bytes ) { size_t idx; unsigned int val = 0; - for (idx = 0; idx < len; idx++) { - val |= ((unsigned int)bytes[idx]) << (8 * (len - 1 - idx)); + for ( idx = 0; idx < len; idx++ ) + { + val |= ( ( unsigned int )bytes[idx] ) << (8 * ( len - 1 - idx ) ); } return val; @@ -123,7 +125,7 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p unsigned short checksum; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - op = psa_hash_operation_init(); + op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); if ( ret != 0 ) @@ -195,7 +197,7 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - op = psa_hash_operation_init(); + op = psa_hash_operation_init( ); for ( i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); @@ -211,7 +213,7 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, j_hash_idx_max = hash_idx_max_values != NULL ? hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; - for ( j_hash_idx = (unsigned char)j_hash_idx_min; + for ( j_hash_idx = ( unsigned char )j_hash_idx_min; j_hash_idx < j_hash_idx_max; j_hash_idx++ ) { @@ -329,9 +331,10 @@ exit: return( ret ); } -int mbedtls_lms_error_from_psa(psa_status_t status) +int mbedtls_lms_error_from_psa( psa_status_t status ) { - switch( status ) { + switch( status ) + { case PSA_SUCCESS: return( 0 ); case PSA_ERROR_HARDWARE_FAILURE: @@ -393,7 +396,7 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters size_t sig_size, unsigned char *out, size_t out_size, - size_t *out_len) + size_t *out_len ) { unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; @@ -420,14 +423,14 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters ret = hash_digit_array( params, sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type), - tmp_digit_array, NULL, (unsigned char *)y_hashed_digits ); + tmp_digit_array, NULL, ( unsigned char * )y_hashed_digits ); if ( ret ) { return ( ret ); } ret = public_key_from_hashed_digit_array( params, - (unsigned char *)y_hashed_digits, + ( unsigned char * )y_hashed_digits, out ); if ( ret ) { @@ -459,8 +462,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( ctx->params.MBEDTLS_PRIVATE( type ) - != MBEDTLS_LMOTS_SHA256_N32_W8 ) + if( ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -475,7 +477,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, msg, msg_size, sig, sig_size, Kc_public_key_candidate, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), - NULL); + NULL ); if ( ret ) { return( ret ); @@ -522,7 +524,8 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if ( type != MBEDTLS_LMOTS_SHA256_N32_W8 ) { + if ( type != MBEDTLS_LMOTS_SHA256_N32_W8 ) + { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -534,9 +537,9 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, I_key_identifier, sizeof( ctx->params.I_key_identifier ) ); - unsigned_int_to_network_bytes(q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - ctx->params.q_leaf_identifier ); + unsigned_int_to_network_bytes( q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + ctx->params.q_leaf_identifier ); unsigned_int_to_network_bytes( 0xFF, sizeof( const_bytes ), const_bytes ); @@ -570,7 +573,7 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, if ( ret ) goto exit; - status = psa_hash_update( &op, const_bytes, sizeof( const_bytes) ); + status = psa_hash_update( &op, const_bytes, sizeof( const_bytes ) ); ret = mbedtls_lms_error_from_psa( status ); if ( ret ) goto exit; @@ -604,7 +607,7 @@ exit: } int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, - mbedtls_lmots_private_t *priv_ctx) + mbedtls_lmots_private_t *priv_ctx ) { unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -616,15 +619,15 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, } ret = hash_digit_array( &priv_ctx->params, - (unsigned char *)priv_ctx->private_key, NULL, - NULL, (unsigned char *)y_hashed_digits ); + ( unsigned char * )priv_ctx->private_key, NULL, + NULL, ( unsigned char * )y_hashed_digits ); if ( ret ) { return( ret ); } ret = public_key_from_hashed_digit_array( &priv_ctx->params, - (unsigned char *)y_hashed_digits, + ( unsigned char * )y_hashed_digits, ctx->public_key ); if ( ret ) { @@ -634,7 +637,7 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, memcpy( &ctx->params, &priv_ctx->params, sizeof( ctx->params ) ); - ctx->MBEDTLS_PRIVATE(have_public_key = 1); + ctx->have_public_key = 1; return( ret ); } @@ -662,9 +665,9 @@ int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - memcpy(key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, - ctx->params.q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, + ctx->params.q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); @@ -726,8 +729,8 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( ret ); } - ret = hash_digit_array( &ctx->params, (unsigned char *)ctx->private_key, - NULL, tmp_digit_array, (unsigned char *)tmp_sig ); + ret = hash_digit_array( &ctx->params, ( unsigned char * )ctx->private_key, + NULL, tmp_digit_array, ( unsigned char * )tmp_sig ); if ( ret ) { return( ret ); @@ -741,8 +744,8 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, * key can't be reused. */ ctx->have_private_key = 0; - mbedtls_platform_zeroize(ctx->private_key, - sizeof(ctx->private_key)); + mbedtls_platform_zeroize( ctx->private_key, + sizeof( ctx->private_key ) ); memcpy( sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type) ); diff --git a/library/lmots.h b/library/lmots.h index 46e03d6f52..03e44af00a 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -145,8 +145,8 @@ typedef struct { * * \return The corresponding LMS error code. */ -void unsigned_int_to_network_bytes(unsigned int val, size_t len, - unsigned char *bytes); +void unsigned_int_to_network_bytes( unsigned int val, size_t len, + unsigned char *bytes ); /** * \brief This function converts a network-byte-order @@ -157,8 +157,8 @@ void unsigned_int_to_network_bytes(unsigned int val, size_t len, * * \return The corresponding LMS error code. */ -unsigned int network_bytes_to_unsigned_int(size_t len, - const unsigned char *bytes); +unsigned int network_bytes_to_unsigned_int( size_t len, + const unsigned char *bytes ); /** * \brief This function converts a \ref psa_status_t to a @@ -168,7 +168,7 @@ unsigned int network_bytes_to_unsigned_int(size_t len, * * \return The corresponding LMS error code. */ -int mbedtls_lms_error_from_psa(psa_status_t status); +int mbedtls_lms_error_from_psa( psa_status_t status ); /** @@ -240,7 +240,7 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters size_t sig_size, unsigned char *out, size_t out_size, - size_t *out_len); + size_t *out_len ); /** * \brief This function verifies a LMOTS signature, using a @@ -333,7 +333,7 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, * \return A non-zero error code on failure. */ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, - mbedtls_lmots_private_t *priv_ctx); + mbedtls_lmots_private_t *priv_ctx ); /** diff --git a/library/lms.c b/library/lms.c index a1e4c243a8..2ff8946c90 100644 --- a/library/lms.c +++ b/library/lms.c @@ -123,7 +123,7 @@ static int create_merkle_leaf_value( const mbedtls_lms_parameters_t *params, goto exit; status = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), - &output_hash_len); + &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) goto exit; @@ -182,7 +182,7 @@ static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params, goto exit; ret = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), - &output_hash_len); + &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) goto exit; @@ -279,7 +279,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, } if( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) + sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); @@ -301,9 +301,9 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } - memcpy(ots_params.I_key_identifier, - ctx->params.I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); + memcpy( ots_params.I_key_identifier, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); unsigned_int_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, ots_params.q_leaf_identifier ); @@ -312,7 +312,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, ret = mbedtls_lmots_calculate_public_key_candidate( &ots_params, msg, msg_size, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), Kc_candidate_ots_pub_key, - sizeof(Kc_candidate_ots_pub_key), NULL ); + sizeof( Kc_candidate_ots_pub_key ), NULL ); if( ret ) { return( ret ); @@ -393,8 +393,8 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, r_node_idx-- ) { ret = create_merkle_internal_value( &ctx->params, - &tree[(r_node_idx * 2) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], - &tree[(r_node_idx * 2 + 1) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], + &tree[( r_node_idx * 2 ) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], + &tree[( r_node_idx * 2 + 1 ) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], r_node_idx, &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)] ); if( ret ) @@ -416,7 +416,7 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx, unsigned int height; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ret = calculate_merkle_tree( ctx, (unsigned char *)tree); + ret = calculate_merkle_tree( ctx, ( unsigned char * )tree ); if( ret ) { return( ret ); @@ -496,7 +496,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ctx->ots_private_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), - sizeof( mbedtls_lmots_private_t)); + sizeof( mbedtls_lmots_private_t ) ); if( ctx->ots_private_keys == NULL ) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; @@ -504,7 +504,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, } ctx->ots_public_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), - sizeof( mbedtls_lmots_public_t)); + sizeof( mbedtls_lmots_public_t ) ); if( ctx->ots_public_keys == NULL ) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; @@ -524,12 +524,12 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, otstype, ctx->params.I_key_identifier, idx, seed, seed_size ); - if( ret) + if( ret ) goto exit; ret = mbedtls_lmots_calculate_public_key( &ctx->ots_public_keys[idx], &ctx->ots_private_keys[idx] ); - if( ret) + if( ret ) goto exit; } @@ -539,7 +539,8 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, exit: if( ret ) { - for ( free_idx = 0; free_idx < idx; free_idx++ ) { + for ( free_idx = 0; free_idx < idx; free_idx++ ) + { mbedtls_lmots_free_private( &ctx->ots_private_keys[free_idx] ); mbedtls_lmots_free_public( &ctx->ots_public_keys[free_idx] ); } @@ -558,7 +559,7 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( ! priv_ctx->MBEDTLS_PRIVATE( have_private_key ) ) + if( ! priv_ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -576,9 +577,9 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, } memcpy( &ctx->params, &priv_ctx->params, - sizeof(mbedtls_lmots_parameters_t) ); + sizeof( mbedtls_lmots_parameters_t ) ); - ret = calculate_merkle_tree( priv_ctx, (unsigned char *)tree); + ret = calculate_merkle_tree( priv_ctx, ( unsigned char * )tree ); if( ret ) { return( ret ); @@ -586,7 +587,7 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, /* Root node is always at position 1, due to 1-based indexing */ memcpy( ctx->T_1_pub_key, &tree[1], - MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) ); ctx->have_public_key = 1; @@ -598,7 +599,8 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len ) { - if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) { + if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) + { return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } @@ -619,7 +621,8 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, ctx->T_1_pub_key, MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) ); - if( key_len != NULL ) { + if( key_len != NULL ) + { *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type); } @@ -630,7 +633,7 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void* p_rng, unsigned char *msg, unsigned int msg_size, - unsigned char *sig, size_t sig_size, size_t *sig_len) + unsigned char *sig, size_t sig_size, size_t *sig_len ) { uint32_t q_leaf_identifier; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -681,7 +684,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, unsigned_int_to_network_bytes( ctx->params.type, MBEDTLS_LMS_TYPE_LEN, sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype) ); unsigned_int_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET); + sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); ret = get_merkle_path( ctx, MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, @@ -691,7 +694,8 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, return( ret ); } - if( sig_len != NULL ) { + if( sig_len != NULL ) + { *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype); } From e0a17610d1e67483842392cc9cbc84c738e79239 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 2 Sep 2022 16:04:47 +0100 Subject: [PATCH 016/104] Fix LMS/LMOTS if-statement style Signed-off-by: Raef Coles --- library/lmots.c | 100 ++++++++++++++++++++++++------------------------ library/lms.c | 46 +++++++++++----------- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index fe78894f4c..878d671cb0 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -128,42 +128,42 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, C_random_value, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type) ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, msg, msg_len ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_finish( &op, out, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type), &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; checksum = lmots_checksum_calculate( params, out ); @@ -219,47 +219,47 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, { status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, i_digit_idx_bytes ); status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; unsigned_int_to_network_bytes( j_hash_idx, J_HASH_IDX_LEN, j_hash_idx_bytes ); status = psa_hash_update( &op, j_hash_idx_bytes, J_HASH_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_finish( &op, tmp_hash, sizeof( tmp_hash ), &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; psa_hash_abort( &op ); @@ -270,7 +270,7 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, } exit: - if( ret ) + if( ret != 0 ) { psa_hash_abort( &op ); return( ret ); @@ -293,32 +293,32 @@ static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, y_hashed_digits, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) * MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_finish( &op, pub_key, @@ -367,7 +367,7 @@ int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); - if ( key_len < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) ) + if( key_len < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -402,12 +402,12 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if ( msg == NULL && msg_size != 0 ) + if( msg == NULL && msg_size != 0 ) { return ( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if ( sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) || + if( sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) || out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type) ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); @@ -416,7 +416,7 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters ret = create_digit_array_with_checksum( params, msg, msg_size, sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_digit_array ); - if ( ret ) + if( ret ) { return ( ret ); } @@ -424,7 +424,7 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters ret = hash_digit_array( params, sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type), tmp_digit_array, NULL, ( unsigned char * )y_hashed_digits ); - if ( ret ) + if( ret ) { return ( ret ); } @@ -432,12 +432,12 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters ret = public_key_from_hashed_digit_array( params, ( unsigned char * )y_hashed_digits, out ); - if ( ret ) + if( ret ) { return ( ret ); } - if ( out_len != NULL ) + if( out_len != NULL ) { *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type); } @@ -452,12 +452,12 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if ( msg == NULL && msg_size != 0 ) + if( msg == NULL && msg_size != 0 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if ( !ctx->have_public_key ) + if( !ctx->have_public_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -467,7 +467,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if ( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, + if( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); @@ -478,12 +478,12 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, Kc_public_key_candidate, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), NULL ); - if ( ret ) + if( ret ) { return( ret ); } - if ( memcmp( &Kc_public_key_candidate, ctx->public_key, + if( memcmp( &Kc_public_key_candidate, ctx->public_key, sizeof( ctx->public_key ) ) ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); @@ -519,12 +519,12 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, unsigned char const_bytes[1]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if ( ctx->have_private_key ) + if( ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if ( type != MBEDTLS_LMOTS_SHA256_N32_W8 ) + if( type != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -549,38 +549,38 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, { status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; ret = psa_hash_update( &op, ctx->params.I_key_identifier, sizeof( ctx->params.I_key_identifier ) ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) + if( ret ) goto exit; status = psa_hash_update( &op, ctx->params.q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) + if( ret ) goto exit; unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, i_digit_idx_bytes ); status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) + if( ret ) goto exit; status = psa_hash_update( &op, const_bytes, sizeof( const_bytes ) ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) + if( ret ) goto exit; status = psa_hash_update( &op, seed, seed_size ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) + if( ret ) goto exit; status = psa_hash_finish( &op, @@ -588,7 +588,7 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret ) + if( ret ) goto exit; psa_hash_abort( &op ); @@ -597,7 +597,7 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, ctx->have_private_key = 1; exit: - if( ret ) + if( ret != 0 ) { psa_hash_abort( &op ); return( ret ); @@ -613,7 +613,7 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Check that a private key is loaded */ - if ( !priv_ctx->have_private_key ) + if( !priv_ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -621,7 +621,7 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, ret = hash_digit_array( &priv_ctx->params, ( unsigned char * )priv_ctx->private_key, NULL, NULL, ( unsigned char * )y_hashed_digits ); - if ( ret ) + if( ret ) { return( ret ); } @@ -629,7 +629,7 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, ret = public_key_from_hashed_digit_array( &priv_ctx->params, ( unsigned char * )y_hashed_digits, ctx->public_key ); - if ( ret ) + if( ret ) { return( ret ); } @@ -697,7 +697,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, unsigned char tmp_c_random[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if ( msg == NULL && msg_size != 0 ) + if( msg == NULL && msg_size != 0 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } @@ -708,14 +708,14 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, } /* Check that a private key is loaded */ - if ( !ctx->have_private_key ) + if( !ctx->have_private_key ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } ret = f_rng( p_rng, tmp_c_random, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); - if ( ret ) + if( ret ) { return( ret ); } @@ -724,14 +724,14 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, msg, msg_size, tmp_c_random, tmp_digit_array ); - if ( ret ) + if( ret ) { return( ret ); } ret = hash_digit_array( &ctx->params, ( unsigned char * )ctx->private_key, NULL, tmp_digit_array, ( unsigned char * )tmp_sig ); - if ( ret ) + if( ret ) { return( ret ); } diff --git a/library/lms.c b/library/lms.c index 2ff8946c90..72f93192bf 100644 --- a/library/lms.c +++ b/library/lms.c @@ -96,36 +96,36 @@ static int create_merkle_leaf_value( const mbedtls_lms_parameters_t *params, op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); status = psa_hash_update( &op, r_node_idx_bytes, 4 ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN(params->otstype) ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; status = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; exit: @@ -149,42 +149,42 @@ static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params, op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); - if ( ret != 0 ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); status = psa_hash_update( &op, r_node_idx_bytes, 4 ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, D_INTERNAL_CONSTANT_BYTES, D_CONST_LEN ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, left_node, MBEDTLS_LMS_M_NODE_BYTES(params->type) ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; status = psa_hash_update( &op, right_node, MBEDTLS_LMS_M_NODE_BYTES(params->type) ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; ret = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( ret != 0 ) goto exit; exit: @@ -313,7 +313,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, msg_size, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), Kc_candidate_ots_pub_key, sizeof( Kc_candidate_ots_pub_key ), NULL ); - if( ret ) + if( ret != 0 ) { return( ret ); } @@ -380,7 +380,7 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, ret = create_merkle_leaf_value( &ctx->params, ctx->ots_public_keys[priv_key_idx].public_key, r_node_idx, &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)] ); - if( ret ) + if( ret != 0 ) { return( ret ); } @@ -397,7 +397,7 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, &tree[( r_node_idx * 2 + 1 ) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], r_node_idx, &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)] ); - if( ret ) + if( ret != 0 ) { return( ret ); } @@ -417,7 +417,7 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = calculate_merkle_tree( ctx, ( unsigned char * )tree ); - if( ret ) + if( ret != 0 ) { return( ret ); } @@ -524,12 +524,12 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, otstype, ctx->params.I_key_identifier, idx, seed, seed_size ); - if( ret ) + if( ret != 0 ) goto exit; ret = mbedtls_lmots_calculate_public_key( &ctx->ots_public_keys[idx], &ctx->ots_private_keys[idx] ); - if( ret ) + if( ret != 0 ) goto exit; } @@ -537,7 +537,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, ctx->have_private_key = 1; exit: - if( ret ) + if( ret != 0 ) { for ( free_idx = 0; free_idx < idx; free_idx++ ) { @@ -580,7 +580,7 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, sizeof( mbedtls_lmots_parameters_t ) ); ret = calculate_merkle_tree( priv_ctx, ( unsigned char * )tree ); - if( ret ) + if( ret != 0 ) { return( ret ); } @@ -676,7 +676,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype), NULL ); - if( ret ) + if( ret != 0 ) { return( ret ); } @@ -689,7 +689,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, ret = get_merkle_path( ctx, MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, sig + MBEDTLS_LMS_SIG_PATH_OFFSET(ctx->params.otstype) ); - if( ret ) + if( ret != 0 ) { return( ret ); } From f5919e299781f9a4541b5d7c5f07a43c9203c20b Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 2 Sep 2022 16:05:10 +0100 Subject: [PATCH 017/104] Update LMS/LMOTS tests Document tests and source of data, use test RNG, pass more parameters into each test Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.data | 39 ++++++++++++++++-- tests/suites/test_suite_lmots.function | 55 ++++++++------------------ tests/suites/test_suite_lms.data | 42 +++++++++++++++++++- tests/suites/test_suite_lms.function | 31 +++++---------- 4 files changed, 103 insertions(+), 64 deletions(-) diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index d5088f9e57..6b4cc35d98 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -1,29 +1,62 @@ LMOTS sign-verify test #1 -lmots_sign_verify_test:"c41ba177a0ca1ec31dfb2e145237e65b" +# This test uses a fixed message, and then generates a private key, signs the +# message, and verifies the signature. +lmots_sign_verify_test:"c41ba177a0ca1ec31dfb2e145237e65b":"00000000000000000000000000000000":12:"403cbcc9808bb4b5ad72476ea297b2854c928ff5336f0b98ac2237ec83225ae7" LMOTS sign-verify test #2 -lmots_sign_verify_test:"55a6647a581004306792b653a561d9f3" +# This test uses a fixed message, and then generates a private key, signs the +# message, and verifies the signature. +lmots_sign_verify_test:"55a6647a581004306792b653a561d9f3":"00000000000000000000000000000000":12:"c3dbc3fea047dca8fb7a3cdf609a5b7f48599c193c90e958ce9388c84df0a906" LMOTS hash-sigs interop test #1 +# This test uses data from https://github.com/cisco/hash-sigs due to the limited +# amount of available test vectors for LMOTS. A public/private key was generated +# and used to sign a randomly generated message. We expect this +# message/signature/public key trio to verify correctly. lmots_verify_test:"C80B24A82D52963AB241C84DCF0EEE55BB24F9F0":"00000004DB3B6B24FD191CE8894AE3C4E2CE2DE0C3F5D508691A9162F37704E07838488466CCD746E55BC8E3055C7A4D4DA2E10775DAFA2E8E5FEFB1CEB25973BC3323B61DE5E2EA7DCFF15DA482320F958023CA2E718C69B977019E8F2FCD47151388E2E5E11170AFE93BDEB508362B3A317835A9DDEB18F0CDCCC0731902DB3D37F441C93A490DE53962A915AB5060A1C157D61DDF061F272362AB7FD9EE95AE48D3448F204C81A3F260792784E1BFB49871A27C09CC549A406520F0B40BC74CAAD082EAAB12C994B8495B8C80E96384FF2222255BE6C4EE5AF439534E616F9C0B53E951F69D59BD0506C0C0366A679A8329ACF6E2D1D4E4EF49D35375A8EA46FCF3C9B2F8E033C242EC61B796E43B901407077A2AF3F0AABD2D0CB9004F10D91B57C2D5E8BA7BA9268FF94962CC102F55B5120D7D2F7A3BE281BA01D78895ADA2F05B77967EDA0E1EDEAFBB9BBC3D68DCBF682FBC70467FA2BEE5DE65F54247C4BE5BEF41F5108B6CD09E7698E3AAEA04B60746EDD0E2623B66B092DDA21EFA5A0D36805D101D805CC06F0E818B46059B3984C8B8A526C4239F66ED34B8CA57E178DC5E7B8D2BE029114B4CE466E2B5A081729B3F3A3F3845DDE177062F201C09125ED3CC381AF35EAD795440C421A136F941F09F3E4BA9E0203CBA875AF477AB0246342700F323E65DC327D27966377D871FD9C58BEC8797DEF35E1D0751A554719828B87332F601884EBFECB63A8D4F390785B3826BFA384BE502D2322C919ABD12A486C2AB124DCB7B74DE91241A30EF0388411E52145A88971C6C0A4E7C4F23EDD8D6008065A3D108C6B1EC5219BB0DFDBD37EE3A7A8DD37E3563A5777838FCA61E9E744813F39CF70B5A0F50E1BD4FF8733A3BDA76D2135969809D91A9786F22DC2ACBA4E0164C411019EC77A0BD253A42AC7528FC7C0DA1711FBD6C23825207060463080F9E04B7D819C8B150C22B8BA87C6277696EC409369C48AC0E3233DE52D31EF6D2207D2B57DFC2D0C43BE8212EAE6CB1BACBC2D3568E5527A14065D5F1F56AAE2AFB5FB1CEFFC228A30692BD030C71F4872DB54F2632CD919DA61576CF58D1EBE3D7988183A9C789EB74A3D7F6BBEBAC035A43397BF684C9E1130B252940DBA4454311A6A3D54D9386D48E1D5A3E70944EDF725AEDC5440CD610F79AB05A43C917FFC15213295EB8CB8432B6554A47C2AD419ADD52E0F5E0BD7A1E0F873257E69F8647F3A07093387B7A64C4812CDBEE536E45D531F89653AC5F14A4715CFF40692346FE6CBF2F9B92D9F1101C379AFD5E6154605059C1DA463B407E79C139396623DC7F15EEFCE424C8E214C6A645EF002F90A230D8F62177CBCF2A688D4F822B119835AD3D3A619F46230257A5AD59CB0924B2584DBA96AADE0A2487E7409EE5993A4F0E3DC46C10B96595CDD17D72C35EF4A52C5906655B0AE649B5DE03B7D46F3839E808761EE05E9300050647593C048669A952324B0188ED225AD11BED3FD94E44E134FB9D6DAD53CC34ECF62695E30637C4528C450D62174E2F8ABA2C09F134412EF889C24B36224BE4259B363A9D8EB89BAEE16BE1898D46":"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A":0 LMOTS hash-sigs interop test #2 +# This test uses data from https://github.com/cisco/hash-sigs due to the limited +# amount of available test vectors for LMOTS. A public/private key was generated +# and used to sign a randomly generated message. We expect this +# message/signature/public key trio to verify correctly. lmots_verify_test:"85A77D026E8C704B14EF665DEB0A648350FA8859":"00000004BEEF900CA9A14982E011A5A94503D566288932AD4B9CB85D1551C766A56F788B0D223FBA0E1AD722BE48365B4CE5DA21051B3A79EAD8C1046944192EE51E162DE1E9AE9B13DD8FA90867A17666CB8967F7CD7F4F5383703CCFF555EEBDC8123AF3C4E39D0A5D61725B6A7F23CE587D256C08D31510BCD895106CD524B432A9211CDCBDF5ADDAD5F1D76D428A76DF2556FFA8AB546CFAAA7F2FE86164B976FDA2940498DB0D1A2DE29972FFD55D83E7CA3318DBAC31670565A1E5F59E36342F887E0EF7855AD93CA5F1951307D79EEA375168BC35A3A0B053AEBDB4D7157AD929B0D7DE9FC1E8C32C9A2D679843CBC77560EEDA5959D0AC8407648344C6952649A303E7B6FCC2EE979E1B2786B898A01E2918894DB4E37A0ED79A30260A45959B4BB3016F081181190CB740376389827B2D56DF7EC00871DC9A198B74C7C6086C940A845D54198F2D5DD7A47F97A192F33A85AAA1304A3251B82AC33C5E7B3BA20D2A9BD49BBEE0B2DA2338E578E6F139BB7596DC3BD89E86CB393C42765B9FE85457116906C3F9A8499CF5E539A5CCB3F6D1F36CA209DE6942F807E579AF0EBF072EA110A812C9E420647CE7C8B2BDBB5F56C5B3B7EA80A53C3574F4ED32E4708DFEED60280ABBE2021B3791B0CB09C1F0731353234A6A327CDDFD4E3E2D9DD5A16FCDE3EEF09C67065BD702C07B53A005D3FE7D23FFD77D40E49C82165EB104343A166E808A3CAEDE1A43AE3A82E1788B49C565CF88A2AB8E2FD37657D53E3679D7A818D864F55144011AB498A4A985C46342F3562FD80ECB86497C3DBB759006E5FFFDC01CAA15C69B716174EDCB6E9870CF391003D3826451D1BEFDCC84C093428EE01DAF883190F5D2542B36A7DE44A453AECD5E93B768ACEE75076BE3D73A66F17CFD8E4A49B1F61CE9446815A86FF5FB0EA070A751893C85360C038A161D3DD4D2C66F440E7265153AB346EF620156605C028DD9636FAE0C9A20DF09303ECC5E57A6424505530F70D25F1C95FE51CBD82C2AD0015EB9AD5379CEC463FA0331A14DD971B7C2311FC45979C531653E7252884BAB7C49F8CD652BDF6FDFA76984445C63B54ED22B4A8A267D091381BE7B9B7608133968BA46106BF42B9091F78C085E674D1F70FB91C68D07733F6412B1583DD2F37C6ECAD6BCCE1A1C7D0A7CA80677F679A5AFE08D15427E5C78CE6EB9AA90F51F40343DC9FD1316DCEB2C1EF8EA217B714B0DE1AEECE04D19D0D7757481EDA6E8C51BE85B7B24720E8D62B8AEC56C1A1B9D278B874AACC0B492CF44ED4E7B1200C82323C1AFA0FC776E92B227E8979E3A92EAB05FCF18A43AE648397088F4991F73ECE22C03B3F42F51C0C0FE0DF37919D048FB473F7AB0E33310B9782DE56384BD888CE5E2A644E20A52DD47F710DB0D3169991E29E716ABFD84CA4850080B6C252CB96CD8979189819E532DF56ECB172F773919733BF4D442901EBFB656EBFED4C6D83FAFF288279779499091C94432ECDF83188048AB596D65BC48FA708D485F9CDC50C8B470DFE22157E8F5EE366722A04E8CE7B861573E5FC97D34055BB50B562738F803B202F7F8":"00000004DE9CE10EA7125AC6399B6B3C7EE24224000000161D61E675F3EA19C5B95DA4EE2E35BA061B39E7639F3989F8AE4B0696B3F87E4E":0 LMOTS hash-sigs interop test #3 +# This test uses data from https://github.com/cisco/hash-sigs due to the limited +# amount of available test vectors for LMOTS. A public/private key was generated +# and used to sign a randomly generated message. We expect this +# message/signature/public key trio to verify correctly. lmots_verify_test:"C32F83EFBFD87F386A6C0850CBB93A75F2506A35":"00000004BD2D174BEBEEF1CAF06E4BF1088DE2AAB17C0528579BD4E1C4A1ED583C36BDACA49798373961B605EAEFAEFC0B4BC39C7AD30572CD29BEBE9AEE503CA2D8BF8C31C8A1B71CF67A18EE01A8A878699F22A1AEE32731E51E3EAD3775EFD8339E263C5A4544559506BA5502B9AEF59217ABC24923EC5E28D18BA18B0D964DB277007A76B8075B39F48CDA92148C9BAE1C7E5421CA753FA2D6BEAE8F49977E4E5B6F38D35BA28A526A53061E57BB92DA0EBBD4AE01AE9FADBED74F503DC39FA2E10C20B47DFB3DFBE25EC35618D2307D21716B10F8FB5095B42C289D1847E5D6F9988C6763D288667D3B658A4F3613E084DAE8B78E0B295A6ED28E88C676995AA5EB1533CDF8EB6F95A5E5117F06B1759495A9CB6E40FBF1F97FF73FDCBFD315C48DA631AB0425CA0633817C46F25E84AEEA37DD77310EE56815E83F862EF14E15FC1246243AA02F40EA32567237D5ADC2944BD63CF55FA4F0DE251B3F5C067D9EC396D5E20F9CEF2C555D89DA721D91D6D607653B97636AB10B74F39FA984D23A3D276EFF5F49C336274A66AC491EDE34686C6CFC17F5312FD3E3E5749A2E472011FA391A5ACF09D918B01704B447FD5E3EA6BB726A3475775DFE6A98CE5473CDEDB630EA4D604BAF36A8B8A8E567F05929E8A74970AA742FBC945021017E464E753D5AC497925AA4AECA0CBF562B2E39F891E177FD8E4E61A698B099D21F13EFD0DE5357A1970314D8E3AA1D2A84D3BCF75A7876C16F585322CC4C613FE3AC8FEA5F258FC9C7200765E9209378C362AFC1A478A117D913CE2BEFEB51103E48D0802618C50918005F1AA4228B67BA1A1B001A91A032019A135B8AEEE3D0158A602C8DCCE5A6580DECC16204E410CBB15FCF36704BB2ECB826A229E45C454B4A5DFC12796E636B300C624DB4E6EAB424B17A18A5A5F52399F247A1507A5985D06F90889FE381129148AF8447B392D4EC0775D91502B48D9F212FCE3F81639901C462F752E27FBEEC9E2B7F8CCD16053FB839E8ADF8CD3E8FF8AF3B3E884F4F524C2026BD3B337B7058B53CFC7596F9C813FFD746B8AC0012C60E96140934B4EED1D8602E57A1A6EBC01FCFD66053AF9614FAF0D0F7320D50D440F2A3148A0DAEF5E2FA31F854D56045065AFAA52A60DC3321E2D7C104FF505057D55CD94C53C31C14DB0DAA4D55C4065CD9BCD78E1B8532A680F7DC3544021346CC59ADEC061DDA1B7606BAF28AD87C39AB8AF3D03E981EFFE50B4D5347175517EF212E61F02B594A96492091AC82625D334504EF19BEEE52E01B111D43313F35EC69C88EF38926071506AB3A5B372DD6F2B901AC1E12E61CCB3ACD3D0777A7A10F137126DAD0D1970D369A067C3A1F19D9CB8756D7130B7EB0C08CF725EB2ADFAD61204195CE14F3C99A88A9B8FA2FDCBD612DF9266614DEA073C9EDABE07B3793048167D4DA49B305AE27974D48A296871350DE036CAA348D2F9A9CB19DC094E5904E25DDCF5657227DCD2A4E620121FBDA032A58836EDC14F3A7C4E51319A60F91F941CC61757498B769799394574C9D198426AC3499F0D0BA1770AD6BAA0D3716333F785A9D7D":"00000004DA66203A7E7BCA2362DB3C8E897A84B10000000D1BD4EE08FAA341C2CE018BD12776E1B8E6B8B2C1EEDAE6BD0998E52F089936FE":0 LMOTS hash-sigs interop negative test (altered random value) +# This test uses data from https://github.com/cisco/hash-sigs due to the limited +# amount of available test vectors for LMOTS. A public/private key was generated +# and used to sign a randomly generated message. This test is a negative test +# where the signature from the hash-sigs interop test #1 data has been altered, +# and is expected to fail to verify. lmots_verify_test:"C80B24A82D52963AB241C84DCF0EEE55BB24F9F0":"00000004CB3B6B24FD191CE8894AE3C4E2CE2DE0C3F5D508691A9162F37704E07838488466CCD746E55BC8E3055C7A4D4DA2E10775DAFA2E8E5FEFB1CEB25973BC3323B61DE5E2EA7DCFF15DA482320F958023CA2E718C69B977019E8F2FCD47151388E2E5E11170AFE93BDEB508362B3A317835A9DDEB18F0CDCCC0731902DB3D37F441C93A490DE53962A915AB5060A1C157D61DDF061F272362AB7FD9EE95AE48D3448F204C81A3F260792784E1BFB49871A27C09CC549A406520F0B40BC74CAAD082EAAB12C994B8495B8C80E96384FF2222255BE6C4EE5AF439534E616F9C0B53E951F69D59BD0506C0C0366A679A8329ACF6E2D1D4E4EF49D35375A8EA46FCF3C9B2F8E033C242EC61B796E43B901407077A2AF3F0AABD2D0CB9004F10D91B57C2D5E8BA7BA9268FF94962CC102F55B5120D7D2F7A3BE281BA01D78895ADA2F05B77967EDA0E1EDEAFBB9BBC3D68DCBF682FBC70467FA2BEE5DE65F54247C4BE5BEF41F5108B6CD09E7698E3AAEA04B60746EDD0E2623B66B092DDA21EFA5A0D36805D101D805CC06F0E818B46059B3984C8B8A526C4239F66ED34B8CA57E178DC5E7B8D2BE029114B4CE466E2B5A081729B3F3A3F3845DDE177062F201C09125ED3CC381AF35EAD795440C421A136F941F09F3E4BA9E0203CBA875AF477AB0246342700F323E65DC327D27966377D871FD9C58BEC8797DEF35E1D0751A554719828B87332F601884EBFECB63A8D4F390785B3826BFA384BE502D2322C919ABD12A486C2AB124DCB7B74DE91241A30EF0388411E52145A88971C6C0A4E7C4F23EDD8D6008065A3D108C6B1EC5219BB0DFDBD37EE3A7A8DD37E3563A5777838FCA61E9E744813F39CF70B5A0F50E1BD4FF8733A3BDA76D2135969809D91A9786F22DC2ACBA4E0164C411019EC77A0BD253A42AC7528FC7C0DA1711FBD6C23825207060463080F9E04B7D819C8B150C22B8BA87C6277696EC409369C48AC0E3233DE52D31EF6D2207D2B57DFC2D0C43BE8212EAE6CB1BACBC2D3568E5527A14065D5F1F56AAE2AFB5FB1CEFFC228A30692BD030C71F4872DB54F2632CD919DA61576CF58D1EBE3D7988183A9C789EB74A3D7F6BBEBAC035A43397BF684C9E1130B252940DBA4454311A6A3D54D9386D48E1D5A3E70944EDF725AEDC5440CD610F79AB05A43C917FFC15213295EB8CB8432B6554A47C2AD419ADD52E0F5E0BD7A1E0F873257E69F8647F3A07093387B7A64C4812CDBEE536E45D531F89653AC5F14A4715CFF40692346FE6CBF2F9B92D9F1101C379AFD5E6154605059C1DA463B407E79C139396623DC7F15EEFCE424C8E214C6A645EF002F90A230D8F62177CBCF2A688D4F822B119835AD3D3A619F46230257A5AD59CB0924B2584DBA96AADE0A2487E7409EE5993A4F0E3DC46C10B96595CDD17D72C35EF4A52C5906655B0AE649B5DE03B7D46F3839E808761EE05E9300050647593C048669A952324B0188ED225AD11BED3FD94E44E134FB9D6DAD53CC34ECF62695E30637C4528C450D62174E2F8ABA2C09F134412EF889C24B36224BE4259B363A9D8EB89BAEE16BE1898D46":"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A":MBEDTLS_ERR_LMS_VERIFY_FAILED LMOTS negative test (invalid type) #1 +# This test uses a null (zeroed) message/signature/public key trio, with the +# only parts set being the LMOTS type. This test has an invalid LMOTS type, and +# should fail with a bad input data error. lmots_verify_test:"0000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMOTS negative test (invalid type) #2 +# This test uses a null (zeroed) message/signature/public key trio, with the +# only parts set being the LMOTS type. This test has an invalid LMOTS type, and +# should fail with a bad input data error. lmots_verify_test:"0000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMOTS key import / export test +# This test uses a randomly generated LMOTS public key. It imports the key, and +# then exports it, and verifies that the exported key is identical to the +# original key. lmots_import_export_test:"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A" LMOTS key reuse test -lmots_reuse_test:"cfcd1e81193e310c9d931d1b00818d14" +# This test uses a fixed message, and then generates a private key, signs the +# message, and then attempts to sign the message again. The second signature +# must fail as private key material must be deleted after a key is used to sign. +lmots_reuse_test:"cfcd1e81193e310c9d931d1b00818d14":"00000000000000000000000000000000":12:"a7f53cc5a228ce63811ba4d7c1f74f7fce62afbf6813f3ca3ae43c11b138086f" diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index ce69803f4e..2a9ea541a4 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -2,52 +2,39 @@ #include "lmots.h" #include "mbedtls/lms.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" - /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:MBEDTLS_LMS_PRIVATE:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_CTR_DRBG_C + * depends_on:MBEDTLS_LMS_C:MBEDTLS_LMS_PRIVATE:MBEDTLS_PSA_CRYPTO_C * END_DEPENDENCIES */ /* BEGIN_CASE */ -void lmots_sign_verify_test ( data_t * msg ) +void lmots_sign_verify_test ( data_t *msg, data_t *key_id, int leaf_id, + data_t *seed ) { mbedtls_lmots_public_t pub_ctx; mbedtls_lmots_private_t priv_ctx; unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; - mbedtls_entropy_context entropy_ctx; - mbedtls_ctr_drbg_context drbg_ctx; - uint8_t seed[16]; - mbedtls_entropy_init( &entropy_ctx ); - mbedtls_ctr_drbg_init( &drbg_ctx ); mbedtls_lmots_init_public( &pub_ctx ); mbedtls_lmots_init_private( &priv_ctx ); - TEST_ASSERT( mbedtls_ctr_drbg_seed( &drbg_ctx, mbedtls_entropy_func, - &entropy_ctx, (uint8_t*)"", 0 ) == 0 ); - TEST_ASSERT( mbedtls_ctr_drbg_random( &drbg_ctx, seed, sizeof( seed ) ) == 0 ); - TEST_ASSERT( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, - (uint8_t[16]){0}, 0x12, seed, sizeof( seed ) ) == 0 ); + key_id->x, leaf_id, seed->x, seed->len ) == 0 ); TEST_ASSERT( mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx) == 0 ); - TEST_ASSERT( mbedtls_lmots_sign(&priv_ctx, mbedtls_ctr_drbg_random, &drbg_ctx, + TEST_ASSERT( mbedtls_lmots_sign(&priv_ctx, &mbedtls_test_rnd_std_rand, NULL, msg->x, msg->len, sig, sizeof(sig), NULL ) == 0 ); TEST_ASSERT( mbedtls_lmots_verify(&pub_ctx, msg->x, msg->len, sig, sizeof(sig)) == 0 ); exit: - mbedtls_entropy_free( &entropy_ctx ); - mbedtls_ctr_drbg_free( &drbg_ctx ); mbedtls_lmots_free_public( &pub_ctx ); mbedtls_lmots_free_private( &priv_ctx ); } /* END_CASE */ /* BEGIN_CASE */ -void lmots_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, +void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, int expected_rc ) { mbedtls_lmots_public_t ctx; @@ -68,13 +55,16 @@ void lmots_import_export_test ( data_t * pub_key ) { mbedtls_lmots_public_t ctx; uint8_t exported_pub_key[MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; + size_t exported_pub_key_len; mbedtls_lmots_init_public( &ctx ); TEST_ASSERT( mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ) == 0 ); - TEST_ASSERT( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, sizeof( exported_pub_key ), NULL ) == 0 ); + TEST_ASSERT( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, + sizeof( exported_pub_key ), + &exported_pub_key_len ) == 0 ); - TEST_ASSERT( memcmp( pub_key->x, exported_pub_key, - MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ) == 0 ); + ASSERT_COMPARE( pub_key->x, pub_key->len, + exported_pub_key, exported_pub_key_len ); exit: mbedtls_lmots_free_public( &ctx ); @@ -82,36 +72,25 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void lmots_reuse_test ( data_t * msg ) +void lmots_reuse_test ( data_t *msg, data_t *key_id, int leaf_id, data_t *seed ) { mbedtls_lmots_private_t ctx; unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; - mbedtls_entropy_context entropy_ctx; - mbedtls_ctr_drbg_context drbg_ctx; - uint8_t seed[16]; - - mbedtls_entropy_init( &entropy_ctx ); - mbedtls_ctr_drbg_init( &drbg_ctx ); - TEST_ASSERT( mbedtls_ctr_drbg_seed(&drbg_ctx, mbedtls_entropy_func, - &entropy_ctx, (uint8_t*)"", 0 ) == 0 ); - - mbedtls_ctr_drbg_random( &drbg_ctx, seed, sizeof( seed ) ); mbedtls_lmots_init_private( &ctx ); TEST_ASSERT( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, - (uint8_t[16]){0}, 0x12, seed, sizeof( seed ) ) == 0 ); - TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, + key_id->x, leaf_id, seed->x, + seed->len ) == 0 ); + TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, msg->x, msg->len, sig, sizeof( sig ), NULL ) == 0 ); /* Running another sign operation should fail, since the key should now have * been erased. */ - TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_ctr_drbg_random, &drbg_ctx, + TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, msg->x, msg->len, sig, sizeof( sig ), NULL ) != 0 ); exit: - mbedtls_entropy_free( &entropy_ctx ); - mbedtls_ctr_drbg_free( &drbg_ctx ); mbedtls_lmots_free_private( &ctx ); } /* END_CASE */ diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index b17fddc153..c17d05ac57 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -1,32 +1,70 @@ LMS sign-verify test -lms_sign_verify_test:"c41ba177a0ca1ec31dfb2e145237e65b" +# This test uses a fixed message, and then generates a private key, signs the +# message, and verifies the signature. +lms_sign_verify_test:"c41ba177a0ca1ec31dfb2e145237e65b":"626201f41afd7c9af793cf158da58e33" LMS hash-sigs interop test #1 +# This test uses data from https://github.com/cisco/hash-sigs due to the limited +# amount of available test vectors for LMS. A public/private key was generated +# and used to sign a randomly generated message. We expect this +# message/signature/public key trio to verify correctly. lms_verify_test:"D5557C719EBB0DBECF563E5CDB16568BB11CD779":"0000000000000004C167A9AC495BD4EA34CD8EE5AAA2A656D518C33612FD87171421BFC3977CFA99765C6D496499C72A1DE21360DA57EB96BC83DB8AA92E560054C7805B04E336162FB4C411B509F76959F2458B0E53CF830E0145CCD439D494259EA4818CA68924A7E8B9DD36D6A9C7849B72F9338ED6C80A3E70B717E8E65B991B2FF9D8B49820E8ABC9E2ECC17DB38E855DA75D84DF9885C7F9DFB4ABC209CFF1D37D66595371D688A203CB89168945200C39169F784B19665CE1FB47D58BFA734C3E0E7E31D1206A033C6D8E25B7E45CA779A5FDE00C6B1CAC44884F2B52A380E1F6D8753549F7F4948A95AEA83703CF3AA108FA4F735AFC0DA1A03C378033D8B5959E7BE05D3C5070E709181AC09EFEC04128ABD7E8F37304FAD4B66373D4A83CFC1EF632DF6DB95577C2C6101CBDC807109ED8AE831FFB73DBC80942C58F334663B980F982C74B943BF7C57147250AADE595310387E3BB1A2705E9EC73DE7FABDA5EC0B1141A18798215B9A70F8D688357C833ED869059A2AA3360155EF84426288198D0FBB78223816B17093684C48942ED18FCD351C34E108E5B71D1CE39E318B5D991B650C46A91112E013E1180F2054C7A22429CAB31512BA34EA3AD9B68C5001EB70C993297CCF11914ECAF059922DAEE7D90ACE2567495ADA066E7DA1679CA45DAC1990B17184E7BE2E6A0F26AD77F19855D074F5B37372277484CE30B80A0540173C1B310C3E7B683A487B5D0676218EA1F65FEA444C493FC535E948EAB62252DCC90516BB45B60D4253DB6979FE342DC5CA1B86B01B2D8EBA79B0BC7B6984535616B792BB45F3C0E20B506E0694E1D5BA28FE96D34FE2BE354777D090404DD3508E9F7918FF5593ADB468478CA8A1F6AF752CC76F401E373B71471D9D70F455C8A73E4E7B6714394B1DD0E2A816AF3D5149835DAE477A70DEE0BDAC22F99A04BFB7C2D4AD53079C326F620DFD3F7CED4AB7F2E291507AA046331050F9E2205C52B36CBAEE817C5C3B1FBCDE61C54C8CB7B67E0570FA44728EC8FD091D5CEDC19C6B99840F7A0E49086F707E959D34B30E255B67BBAA24FADE532BF3D21825626E114BD8213170B0C2F01733D4ED420D01EE3ACD5F84DACE674AE7127DB0A80ACE252CAD9ADADDAFAB27281AFD6DDD72DB5AF878326C45D7DB1EFF8BC40895A3473A52461D076881310AD9937307217B5C0448B509EF9BA075936CC09E11B8838D3A6BC5EF9FAEA85A3EC87EEFDF2E38CD9732730085375A4FFC4E0A213B0E1FC3DE2D37F1EDACC3030F617F3459A03BFCF776A05FD3B7FD135782F6D6E7C5E92B56A1316525B26D3AE1CEA3C0C7CF3AA7B1E72B7599A31B50837D79A7AB61B9A9E2B7AABD2D605C97E302EB4B66C0588C24147955EA0892A54D42843568FE0863E7EFEAE336D302E672EA62689B4DAA02DD5BC99D93886EC7F411C53CE1CAEAB59FBC0B06E0E294F1900F8C626C6FF520AE2323DA797CDC120DBC19F7FEBA0E13429508C5B838A0F8B9B28A069C5DD40E2F6CC2C95FC6ACE7E1351516817BD2DC1AE08D498AD2B0BD1D8374942FF31FC6A4689C592244C919C3561E73DD4986FA500000006BBF34F6EE152B64FCDD1CB6848D2DA761798707060431761006E2EBD9312851F4F3DF3C46E10F643DDD58CB3D9F4D371F655EE26271F2DDE84A14CAA6A077DD96AF83849DE6CA8F2F3248902CBF49630C18C3EE3123D951CE9162D0E742B899AF9E5DA8D28A41C7CADF0194CDB09418BF48BF322F8C5E9563524196FA8AB785B43C4EA41A36148028D2F4C7356CDEEB09532CD7F2C80FC36589FF7A9954100C8697AEB014997C3088C242B4F70D26CE7F7E77384A9CF536EC5C5329E08BD6C1D65EFEFC1389A42D16FFB43A0E1D7661220E92A4A59703FB28410E73A677E803D4441929DFD7269E6F77AE8CA8C70B67B250A8728291EA5D4E3F03D505639408C88156DCBECC137142FA3585C09D99B84D8C380A5D29CE2ADA10A25F7CF939FE23288551F37FE2B7233BF97C0F5726B972E087BCBA095957CCD794794A4F50027":"00000006000000046B0927585C8547228D495361D73B970C287A2254BF8F1B170E55ACC9520A56CE5D2C711B6617718B49247D28CCC6D11D":0 LMS hash-sigs interop test #2 +# This test uses data from https://github.com/cisco/hash-sigs due to the limited +# amount of available test vectors for LMS. A public/private key was generated +# and used to sign a randomly generated message. We expect this +# message/signature/public key trio to verify correctly. lms_verify_test:"DA16BE0B8FB691248486ACAFD531BE6EE4C362E0":"000000000000000484FCD0D791D175A0F86D64B2E8949F793CA9FFDC0347DE125DDB2F895BB9D2B43740B9B326B24F934D67586812BE6F3FB57E76FB12FBAD60A685F22A82C95C84AFAE63F47BB3CD951D483F61F5626B2B5FB6FDCA0CF02293EFDE1EB0AF6712D635678E825099E95435B43EF83C49C6589054D0905D82D597FB11A721D2232AD168FD179724539699C21163D5ADEB52290CB711C368572FF8BB95AA61DF2AD128307E768E73D3CF2BAFEAC8B6CD165BDD0316D2663D1ED61A15FB974082FC66A55E13ABA4FD084970EF6A59B0DFA1E934BF0E056C86E9B4C5B94CF863AB9F23BE2DB6A140A9CAA8DB31C83B21BDBDCD07304A52EB8501869D86BFDB68A376D94F847EED7E4CAB6A6EEC063945AE4DAF657D5509249E7FE430F5A13B188C4DD311F01746CE28F4F6540041EF6ADB299F712F591C83B0C12C1FB3E4A878C63217E25E08C004571FFC69E9C684E46F4D36C36409EBF3EB15F32A187176F4D177E0FE0E71ADFD4DA4AD2D57A0256B29AD5DAA6867AED20CC862AF5729D030514D41BB8D74551D8E925322C81A357A586227BBC885AB683BF835E9333A056AFEE96F2AD0FF6D6E235A9E2BC342ACBCF0B8EACC95E7B74215F6C65F12829433301F004EE1D9CFD16A4A1D092F48E99AEAE9E1FA4619ECE5E05F5C19F33C4C94A774EB8955409E3CFA73D8807CAA7C55FE45E980C7E7626AAA193F18A3AA7E525FFA6466D728FA25563DD383D855A0B6F8C011AC8C79C853CBED3A016DC26EF6E90B3E78119E465B9962A42B6AC168C1CDC9DB860D740B0C797303E2A62445FA618B5EB417BD4385C15BC548FEDF4D4842CA43F95188FFF63EB5D4AC85DAE618FDFB6CF5969EA0A3A52F73A4AC4957BC4EBCFEF593923EC79196021B25ED8D7558E4AF41ED74941585AC575CF1971D4F4C7C9E9516276734FF9FAFC7DE661F3090F71C98962789B31EA0FE406E2EF02F6F16B1708258C7559B8E05E27D647AD472805C865299FE30A5FE451DA7F2C493A37AA1655D492EC891B9AF559E12104CDD2EEB2E54138A1FB5A403AA32CEEB3946471A299604FA2DD3CA3E9567D01A3CEE5D09A1C2768B521C0C6142AF297CA5BFB3878B32D37D415542C15F655CB051240F3BA8FCE0E38449A0D7010A9B56BA2283E3A2047215813ED2090F7BDF16A40ADE32AB4E669684E6DEB6A94633E6643F29D10914F5A361C964CA9145514D4B80B45F3276EB0C649622034E71925FA038EB35E64C71CBDB11E91D779339516A351BD2A722CB60C2CBF145689B2E3F6FAEB74C3B58283929F70023503A96FED6A5D7D8A9E495FE1D85E0FCEC555F86747347D2FB5219FF65EFD144A5E1E88C63BE4259C42F6899C103536D75E0526508649E2836CACB94E88BD954B88EAC26F17B27BF62546C5C7573E2BC9EF4B65B8AE4951AF532F968FF050E504CC236DC48379E4390079DE451DCE710F9674D753C85B9FF7E7B09ED051EDD14C33AAFC8A188AE06234DFB61FE5A75C7A760B5286E1D6993BCEA0AB8A2C1D632145BD6A9F109ABB04E0B102D50DCB8C607AD6BA8C5FA5B21663E5A40194CA5DC2294BE10044E8D96AA0000000694ABC63BC5B27730C5223943C8341461474033BE3A221AFFDE66242AF14510CC656480CBDFC0B35205C89258A18BF6C29C4708CB2572DE15EE5DD481BC47060254954B5C5DD881AE6B358F7CDAB6F117235AAAC625B2750DB72BA4A96D7DFAA889BE780416E1CB264A413C6713710102D1D433BC6D0A47BF08AA74FD613D292A867261181BBD73557EE3AEB0F63579B71E58E97BAC1AACA3F34646350A13BB7ACE0AB3B062C41518768ABF3D32FB2F6A5E5C7F6B8B04C943D25A82F03F977755D74FD717A4B7E7674B03B577405210E23A2FE050E036DB0730359366A9436AD2CBCCE3E649F9E40023B2C12D9F5AA824319EAF571FD4842E573BB100BE9715D7B71F75521640D9B69B889349A283D62350D3A37264C89930F40603A5458B124EA850BA59024A46A8F325C9A9776817D739692FFAEA2758249888BF79D66FD496":"00000006000000043FC8322D04908C7C06C0D8B7A0CE24FA3AC253393CF9A56CF760294A06E75223E38C9E5329DDC493D8B51B1A4BBE41F8":0 LMS hash-sigs interop test #3 +# This test uses data from https://github.com/cisco/hash-sigs due to the limited +# amount of available test vectors for LMS. A public/private key was generated +# and used to sign a randomly generated message. We expect this +# message/signature/public key trio to verify correctly. lms_verify_test:"331D543362A163390508127AFB9894B8C18C6E0A":"0000000000000004F5378439E9C229550D40B725FD56BE48DB785093E62BD29B723C61FABEDCFD486EFA120445339DE2A21A8C7465073ACBFD6DE3E50F395AAC20E0BCB23B088C416199F80B540AA81B2C0B12B7785152263522E8F79AEBE3B28315CC834AEB68475CADBC724DB6B7B7F594A7F9DA2505F5F44DAA7EEF70B72665A250C1F61A19F3FA4CBF389BEB9B31DC327882D7983EEED46DA8E00AEBEF85AE179EBF6D8CC7F720E9F963C4D30DD4015DAA27993D0780AFD7A45688422B1444AD866FEFE12EBD94B4D313517708A6E652D6206A8B263E234685D8133C2258EF6CA9E9C6FFD6D153598B13B59576897DC4F77C71609427866A347AE62B5C3BACB0A2E44B60F2CCB4989B0C57F3E785CDCF22B1FC8C3460A163FF2BE7A578E82429BA823F392A13C11A5639A42453972D2185E81809EF0666F8F01F575FBD9A46135F45651AA814D9BA84F774A9E9303FD55038CA41A21484BA9C38E69BCE4E37052971690ED3EEC4ED9AD41B0AEAE4DCC913443B9FA5418FB75DC1725FA989BA8DB5D9E221804FC7F36F3135C8B93AFF66DF89408CFD50993D308E51DF00540F380C0AD06266B80F646B917BA58384B55658EAD2D453766C4843FCDD934E8352A6DF6A081A15BDE07BF67E977E72BFE1AC37F411111A0A4D101A2CCF95EBEC7FCFC82B45DBA88939B0831987AE4D15C05A2E08F713BB0B6BB0E2436B7F9C83D2D869432465DEB9185913DE215937EFB4A52DA50BEF88688F5AB4397A04B14CDBFA5BFD948CD6EA1122D9D3C2927DE9D066297AA2C6FE8E478EC0F41459287EF9B8A1A56164C72AE3DCE5E914E8BC3C3821E0ADD6D1C9048D71BD71F71F3A6E04E63687298DE5A3704ADA82AA369CCD7F342F79E988A7BE066CA55944E0E3712F472891761E5617DC048C69AA4C250AA1560D6591FC0E7492027BEED67310E3482B1487E41DEA5E070894A5FB93FF4462D1F60C4B1CA7C15275EEA2B3790ED12EA930FD7F7F07D60807E4AAB73D1F889DABF2E687A487F331AC17D8DE24E8448E672F87424F0D1A73721A1A987519D0E3BB91D15D012B1FCDB6E23EEA17E93869C5199984CE8A068CA96C3096273F8B23160A79EE0C208D9B70ED5E23CB3586DFD33E02D06F1C646250BD664C27D2BB9614FF5F043A6FEE1A235DA10DCAADB19205CB839BD616BB36B738AA28E1D4F767BD8BAB6C2F84887C7B2E16CF6E07AF90C1FCB6E6E5A4CC894072AF4393C63F7119FF694BF0A043AF5F0825557A99C40BABBDA97D5648687D493367812743335A8AD7696562538C8BA5DED182C4DC818E7E9F630B29A9534E2583E0F4B5862D4E4DB250A350BAF360EF133838FE55AA683E253746A704654EF692F4F818F5A172AB0B84673D0AF77CC1DF189AA5BB013E833D1B0943918768AC6A83E6BFB306D3C3786BD2C87129BFEA1C380A84C4983D262184427284BF3DEB9B4C58FB1899B07B9F60B4402618168B1445653E8E48CD92C048684302A6F5C217F110D6699707BA42316CB31FE8F4DA6B82243CF1264751225594AF1BB670339A9189163DB9E985A99BCF83A3039AF3E65BBCD8364745356B29D761853E00000006CDE5B63B9763DA3EABCFFDA517688BDEC2AE9213E6B0FD7003D95458798AE9449DE4F1135E093B39F597A34B14AAB7F596E25BA469533442F54C14921ABCC5D04A05486CD16C8564E6A19C11BEDA574A9800107DCEAD013A7E6A32966B5BBE9FDFDB0184FE0707209B6D9EC43066899717E487E5FDEE02061EA5069B2D6C9C87D6BEB1310F1B9E723AE372DB7BE9EF6657F51FD0DE62464D3B37755095829F625EA76F5FD7FCD5829863F963FCD7F9FFFF3729688D025DF7952B067C62198E4C6CE06E960B0BAC6ADBC9459D9AC0BE1BAD46F95A121BBBE6953BAA10252419E2AB6BCA1B0AA1FA64DF728160B4FB7A62499C24D269FF59977649064C5986D615E6952EA0DA5B1C04C443BC27A63D391D5BFAE824F0161791E65896DC100EAF80037FD800A5079337554BD990E0D0A1A4C4C45741E72FB3E840665F2881D2CCC5":"000000060000000461F2DF219685CF313043780A57C18071725490AB8D53B676D484238BA8C373572407938CC578045649964958C0A872FA":0 LMS hash-sigs interop negative test (altered random value) +# This test uses data from https://github.com/cisco/hash-sigs due to the limited +# amount of available test vectors for LMS. A public/private key was generated +# and used to sign a randomly generated message. This test is a negative test +# where the signature from the hash-sigs interop test #1 data has been altered, +# and is expected to fail to verify. lms_verify_test:"D5557C719EBB0DBECF563E5CDB16568BB11CD779":"0000000000000004B167A9AC495BD4EA34CD8EE5AAA2A656D518C33612FD87171421BFC3977CFA99765C6D496499C72A1DE21360DA57EB96BC83DB8AA92E560054C7805B04E336162FB4C411B509F76959F2458B0E53CF830E0145CCD439D494259EA4818CA68924A7E8B9DD36D6A9C7849B72F9338ED6C80A3E70B717E8E65B991B2FF9D8B49820E8ABC9E2ECC17DB38E855DA75D84DF9885C7F9DFB4ABC209CFF1D37D66595371D688A203CB89168945200C39169F784B19665CE1FB47D58BFA734C3E0E7E31D1206A033C6D8E25B7E45CA779A5FDE00C6B1CAC44884F2B52A380E1F6D8753549F7F4948A95AEA83703CF3AA108FA4F735AFC0DA1A03C378033D8B5959E7BE05D3C5070E709181AC09EFEC04128ABD7E8F37304FAD4B66373D4A83CFC1EF632DF6DB95577C2C6101CBDC807109ED8AE831FFB73DBC80942C58F334663B980F982C74B943BF7C57147250AADE595310387E3BB1A2705E9EC73DE7FABDA5EC0B1141A18798215B9A70F8D688357C833ED869059A2AA3360155EF84426288198D0FBB78223816B17093684C48942ED18FCD351C34E108E5B71D1CE39E318B5D991B650C46A91112E013E1180F2054C7A22429CAB31512BA34EA3AD9B68C5001EB70C993297CCF11914ECAF059922DAEE7D90ACE2567495ADA066E7DA1679CA45DAC1990B17184E7BE2E6A0F26AD77F19855D074F5B37372277484CE30B80A0540173C1B310C3E7B683A487B5D0676218EA1F65FEA444C493FC535E948EAB62252DCC90516BB45B60D4253DB6979FE342DC5CA1B86B01B2D8EBA79B0BC7B6984535616B792BB45F3C0E20B506E0694E1D5BA28FE96D34FE2BE354777D090404DD3508E9F7918FF5593ADB468478CA8A1F6AF752CC76F401E373B71471D9D70F455C8A73E4E7B6714394B1DD0E2A816AF3D5149835DAE477A70DEE0BDAC22F99A04BFB7C2D4AD53079C326F620DFD3F7CED4AB7F2E291507AA046331050F9E2205C52B36CBAEE817C5C3B1FBCDE61C54C8CB7B67E0570FA44728EC8FD091D5CEDC19C6B99840F7A0E49086F707E959D34B30E255B67BBAA24FADE532BF3D21825626E114BD8213170B0C2F01733D4ED420D01EE3ACD5F84DACE674AE7127DB0A80ACE252CAD9ADADDAFAB27281AFD6DDD72DB5AF878326C45D7DB1EFF8BC40895A3473A52461D076881310AD9937307217B5C0448B509EF9BA075936CC09E11B8838D3A6BC5EF9FAEA85A3EC87EEFDF2E38CD9732730085375A4FFC4E0A213B0E1FC3DE2D37F1EDACC3030F617F3459A03BFCF776A05FD3B7FD135782F6D6E7C5E92B56A1316525B26D3AE1CEA3C0C7CF3AA7B1E72B7599A31B50837D79A7AB61B9A9E2B7AABD2D605C97E302EB4B66C0588C24147955EA0892A54D42843568FE0863E7EFEAE336D302E672EA62689B4DAA02DD5BC99D93886EC7F411C53CE1CAEAB59FBC0B06E0E294F1900F8C626C6FF520AE2323DA797CDC120DBC19F7FEBA0E13429508C5B838A0F8B9B28A069C5DD40E2F6CC2C95FC6ACE7E1351516817BD2DC1AE08D498AD2B0BD1D8374942FF31FC6A4689C592244C919C3561E73DD4986FA500000006BBF34F6EE152B64FCDD1CB6848D2DA761798707060431761006E2EBD9312851F4F3DF3C46E10F643DDD58CB3D9F4D371F655EE26271F2DDE84A14CAA6A077DD96AF83849DE6CA8F2F3248902CBF49630C18C3EE3123D951CE9162D0E742B899AF9E5DA8D28A41C7CADF0194CDB09418BF48BF322F8C5E9563524196FA8AB785B43C4EA41A36148028D2F4C7356CDEEB09532CD7F2C80FC36589FF7A9954100C8697AEB014997C3088C242B4F70D26CE7F7E77384A9CF536EC5C5329E08BD6C1D65EFEFC1389A42D16FFB43A0E1D7661220E92A4A59703FB28410E73A677E803D4441929DFD7269E6F77AE8CA8C70B67B250A8728291EA5D4E3F03D505639408C88156DCBECC137142FA3585C09D99B84D8C380A5D29CE2ADA10A25F7CF939FE23288551F37FE2B7233BF97C0F5726B972E087BCBA095957CCD794794A4F50027":"00000006000000046B0927585C8547228D495361D73B970C287A2254BF8F1B170E55ACC9520A56CE5D2C711B6617718B49247D28CCC6D11D":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lms type) #1 +# This test uses a null (zeroed) message/signature/public key trio, with the +# only parts set being the LMS and LMOTS types. This test has a valid LMOTS type +# (0x4) but an invalid LMS type, and should fail with a bad input data error. lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000700000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMS negative test (invalid lms type) #2 +# This test uses a null (zeroed) message/signature/public key trio, with the +# only parts set being the LMS and LMOTS types. This test has a valid LMOTS type +# (0x4) but an invalid LMS type, and should fail with a bad input data error. lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000500000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMS negative test (invalid lm_ots type) #1 +# This test uses a null (zeroed) message/signature/public key trio, with the +# only parts set being the LMS and LMOTS types. This test has a valid LMS type +# (0x6) but an invalid LMOTS type, and should fail with a bad input data error. lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMS negative test (invalid lm_ots type) #2 +# This test uses a null (zeroed) message/signature/public key trio, with the +# only parts set being the LMS and LMOTS types. This test has a valid LMS type +# (0x6) but an invalid LMOTS type, and should fail with a bad input data error. lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA -LMS negative test (invalid leaf ID) +LMS negative test (invalid lm_ots type) #2 +# This test uses a null (zeroed) message/signature/public key trio, with the +# only parts set being the LMS and LMOTS types and the leaf ID. In this case, +# the leaf ID is 1024, which is invalid for MBEDTLS_LMS_SHA256_M32_H10. This +# test should fail to verify the signature. lms_verify_test:"0000000000000000000000000000000000000000":"000004000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS import/export test +# This test uses a randomly generated LMS public key. It imports the key, and +# then exports it, and verifies that the exported key is identical to the +# original key. lms_import_export_test:"00000006000000046B0927585C8547228D495361D73B970C287A2254BF8F1B170E55ACC9520A56CE5D2C711B6617718B49247D28CCC6D11D" diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 92a5a07ab1..148075d1b8 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -1,55 +1,44 @@ /* BEGIN_HEADER */ #include "mbedtls/lms.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:MBEDTLS_LMS_PRIVATE:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_CTR_DRBG_C + * depends_on:MBEDTLS_LMS_C:MBEDTLS_LMS_PRIVATE:MBEDTLS_PSA_CRYPTO_C * END_DEPENDENCIES */ /* BEGIN_CASE */ -void lms_sign_verify_test ( data_t * msg ) +void lms_sign_verify_test ( data_t *msg, data_t *seed ) { mbedtls_lms_public_t pub_ctx; mbedtls_lms_private_t priv_ctx; unsigned char sig[MBEDTLS_LMS_SIG_LEN(MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8)]; - mbedtls_entropy_context entropy_ctx; - mbedtls_ctr_drbg_context drbg_ctx; - uint8_t seed[16]; int rc; - mbedtls_entropy_init( &entropy_ctx ); - mbedtls_ctr_drbg_init( &drbg_ctx ); mbedtls_lms_init_public( &pub_ctx ); mbedtls_lms_init_private( &priv_ctx ); - TEST_ASSERT( mbedtls_ctr_drbg_seed( &drbg_ctx, mbedtls_entropy_func, - &entropy_ctx, ( uint8_t* )"", 0 ) == 0 ); - TEST_ASSERT( mbedtls_ctr_drbg_random( &drbg_ctx, seed, sizeof( seed ) ) == 0 ); - - /* Allocation failure isn't a test failure, since it likely just means there's not enough memory to run the test */ + /* Allocation failure isn't a test failure, since it likely just means + * there's not enough memory to run the test. + */ rc = mbedtls_lms_generate_private_key( &priv_ctx, MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8, - mbedtls_ctr_drbg_random, &drbg_ctx, seed, - sizeof( seed ) ); + mbedtls_test_rnd_std_rand, NULL, + seed->x, seed->len ); TEST_ASSUME( rc != MBEDTLS_ERR_LMS_ALLOC_FAILED ); TEST_ASSERT( rc == 0 ); TEST_ASSERT( mbedtls_lms_calculate_public_key( &pub_ctx, &priv_ctx ) == 0 ); - TEST_ASSERT( mbedtls_lms_sign( &priv_ctx, mbedtls_ctr_drbg_random, - &drbg_ctx, msg->x, msg->len, sig, - sizeof( sig ), NULL ) == 0 ); + TEST_ASSERT( mbedtls_lms_sign( &priv_ctx, mbedtls_test_rnd_std_rand, NULL, + msg->x, msg->len, sig, sizeof( sig ), + NULL ) == 0 ); TEST_ASSERT( mbedtls_lms_verify( &pub_ctx, msg->x, msg->len, sig, sizeof( sig ) ) == 0 ); exit: - mbedtls_entropy_free( &entropy_ctx ); - mbedtls_ctr_drbg_free( &drbg_ctx ); mbedtls_lms_free_public( &pub_ctx ); mbedtls_lms_free_private( &priv_ctx ); } From 8738a49d0c46617523edf98f436e7e8641fd195e Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 2 Sep 2022 17:13:01 +0100 Subject: [PATCH 018/104] Fix iterator types in LMOTS Signed-off-by: Raef Coles --- library/lmots.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 878d671cb0..7dbf8a206b 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -182,13 +182,10 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, const unsigned char *hash_idx_max_values, unsigned char *output ) { - unsigned char i_digit_idx; - unsigned char j_hash_idx; + unsigned int i_digit_idx; unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN]; - unsigned char j_hash_idx_bytes[1]; - /* These can't be unsigned chars, because they are sometimes set to - * #DIGIT_MAX_VALUE, which has a value of 256 - */ + unsigned int j_hash_idx; + unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN]; unsigned int j_hash_idx_min; unsigned int j_hash_idx_max; psa_hash_operation_t op; @@ -213,7 +210,7 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, j_hash_idx_max = hash_idx_max_values != NULL ? hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; - for ( j_hash_idx = ( unsigned char )j_hash_idx_min; + for ( j_hash_idx = j_hash_idx_min; j_hash_idx < j_hash_idx_max; j_hash_idx++ ) { From 0a967ccf9ac868ddaf5f8da3cd4ab3a0119d81af Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 2 Sep 2022 17:46:15 +0100 Subject: [PATCH 019/104] Document LMS and LMOTS internal functions Signed-off-by: Raef Coles --- library/lmots.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ library/lms.c | 69 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 146 insertions(+), 1 deletion(-) diff --git a/library/lmots.c b/library/lmots.c index 7dbf8a206b..fe01bf6721 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -99,6 +99,17 @@ unsigned int network_bytes_to_unsigned_int( size_t len, return val; } +/* Calculate the checksum digits that are appended to the end of the LMOTS digit + * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of + * the checksum algorithm. + * + * \param params The LMOTS parameter set, I and q values which + * describe the key being used. + * + * \param digest The digit string to create the digest from. As + * this does not contain a checksum, it is the same + * size as a hash output. + */ static unsigned short lmots_checksum_calculate( const mbedtls_lmots_parameters_t *params, const unsigned char* digest ) { @@ -113,6 +124,29 @@ static unsigned short lmots_checksum_calculate( const mbedtls_lmots_parameters_t return sum; } +/* Create the string of digest digits (in the base determined by the Winternitz + * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST + * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm + * 4b step 3) for details. + * + * \param params The LMOTS parameter set, I and q values which + * describe the key being used. + * + * \param msg The message that will be hashed to create the + * digest. + * + * \param msg_size The size of the message. + * + * \param C_random_value The random value that will be combined with the + * message digest. This is always the same size as a + * hash output for whichever hash algorithm is + * determined by the parameter set. + * + * \param output An output containing the digit string (+ + * checksum) of length P digits (in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of + * size P bytes). + */ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *params, const unsigned char *msg, size_t msg_len, @@ -176,6 +210,35 @@ exit: return( ret ); } +/* Hash each element of the string of digits (+ checksum), producing a hash + * output for each element. This is used in several places (by varying the + * hash_idx_min/max_values) in order to calculate a public key from a private + * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554 + * Algorithm 3 step 5), and to calculate a public key candidate from a + * signature and message (RFC8554 Algorithm 4b step 3). + * + * \param params The LMOTS parameter set, I and q values which + * describe the key being used. + * + * \param x_digit_array The array of digits (of size P, 34 in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8). + * + * \param hash_idx_min_values An array of the starting values of the j iterator + * for each of the members of the digit array. If + * this value in NULL, then all iterators will start + * at 0. + * + * \param hash_idx_max_values An array of the upper bound values of the j + * iterator for each of the members of the digit + * array. If this value in NULL, then iterator is + * bounded to be less than 2^w - 1 (255 in the case + * of MBEDTLS_LMOTS_SHA256_N32_W8) + * + * \param output An array containing a hash output for each member + * of the digit string P. In the case of + * MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 * + * 34. + */ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, const unsigned char *x_digit_array, const unsigned char *hash_idx_min_values, @@ -278,6 +341,21 @@ exit: return ret; } +/* Combine the hashes of the digit array into a public key. This is used in + * in order to calculate a public key from a private key (RFC8554 Algorithm 1 + * step 4), and to calculate a public key candidate from a signature and message + * (RFC8554 Algorithm 4b step 3). + * + * \param params The LMOTS parameter set, I and q values which describe + * the key being used. + * \param y_hashed_digits The array of hashes, one hash for each digit of the + * symbol array (which is of size P, 34 in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8) + * + * \param pub_key The output public key (or candidate public key in + * case this is being run as part of signature + * verification), in the form of a hash output. + */ static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t *params, const unsigned char *y_hashed_digits, unsigned char *pub_key ) diff --git a/library/lms.c b/library/lms.c index 72f93192bf..e0f5946efb 100644 --- a/library/lms.c +++ b/library/lms.c @@ -80,8 +80,27 @@ #define D_CONST_LEN (2) static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = {0x82, 0x82}; -static const unsigned char D_INTERNAL_CONSTANT_BYTES[D_CONST_LEN] = {0x83, 0x83}; +static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = {0x83, 0x83}; + +/* Calculate the value of a leaf node of the merkle tree (which is a hash of a + * public key and some other parameters like the leaf index). This function + * implements RFC8554 section 5.3, in the case where r >= 2^h. + * + * \param params The LMS parameter set, the underlying LMOTS + * parameter set, and I value which describe the key + * being used. + * + * \param pub_key The public key of the private whose index + * corresponds to the index of this leaf node. This + * is a hash output. + * + * \param r_node_idx The index of this node in the merkle tree. Note + * that the root node of the merkle tree is + * 1-indexed. + * + * \param out The output node value, which is a hash output. + */ static int create_merkle_leaf_value( const mbedtls_lms_parameters_t *params, unsigned char *pub_key, unsigned int r_node_idx, @@ -134,6 +153,28 @@ exit: return( ret ); } +/* Calculate the value of an internal node of the merkle tree (which is a hash + * of a public key and some other parameters like the node index). This function + * implements RFC8554 section 5.3, in the case where r < 2^h. + * + * \param params The LMS parameter set, the underlying LMOTS + * parameter set, and I value which describe the key + * being used. + * + * \param left_node The value of the child of this node which is on + * the left-hand side. As with all nodes on the + * merkle tree, this is a hash output. + * + * \param right_node The value of the child of this node which is on + * the right-hand side. As with all nodes on the + * merkle tree, this is a hash output. + * + * \param r_node_idx The index of this node in the merkle tree. Note + * that the root node of the merkle tree is + * 1-indexed. + * + * \param out The output node value, which is a hash output. + */ static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params, const unsigned char *left_node, const unsigned char *right_node, @@ -363,6 +404,20 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, #ifdef MBEDTLS_LMS_PRIVATE +/* Calculate a full merkle tree based on a private key. This function + * implements RFC8554 section 5.3, and is used to generate a public key (as the + * public key is the root node of the merkle tree). + * + * \param ctx The LMS private context, containing a parameter + * set and private key material consisting of both + * public and private OTS. + * + * \param tree The output tree, which is 2^(H + 1) hash outputs. + * In the case of H=10 we have 2048 tree nodes (of + * which 1024 of them are leaf nodes). Note that + * because the merkle tree root is 1-indexed, the 0 + * index tree node is never used. + */ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, unsigned char *tree ) { @@ -406,6 +461,18 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, return( 0 ); } +/* Calculate a path from a leaf node of the merkle tree to the root of the tree, + * and return the full path. This function implements RFC8554 section 5.4.1, as + * the merkle path is the main component of an LMS signature. + * + * \param ctx The LMS private context, containing a parameter + * set and private key material consisting of both + * public and private OTS. + * + * \param leaf_node_id Which leaf node to calculate the path from. + * + * \param tree The output path, which is H hash outputs. + */ static int get_merkle_path( mbedtls_lms_private_t *ctx, unsigned int leaf_node_id, unsigned char *path ) From fa24f9d6ea4be3aa5f91a0e9c5a13753022a6fd0 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 2 Sep 2022 17:46:52 +0100 Subject: [PATCH 020/104] Minor fixes to LMS and LMOTS macros Update some names, use the correct macro in certain places. Signed-off-by: Raef Coles --- library/lmots.c | 2 +- library/lmots.h | 4 ++-- library/lms.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index fe01bf6721..8e56696e57 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -194,7 +194,7 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p goto exit; status = psa_hash_finish( &op, out, - MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type), + MBEDTLS_LMOTS_N_HASH_LEN(params->type), &output_hash_len ); ret = mbedtls_lms_error_from_psa( status ); if( ret != 0 ) diff --git a/library/lmots.h b/library/lmots.h index 03e44af00a..56d23f855a 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -104,7 +104,7 @@ typedef struct { */ typedef struct { mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); - unsigned char MBEDTLS_PRIVATE(public_key)[32]; + unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. Boolean values only. */ } mbedtls_lmots_public_t; @@ -129,7 +129,7 @@ typedef struct { */ typedef struct { mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); - unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][32]; + unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lmots_private_t; diff --git a/library/lms.c b/library/lms.c index e0f5946efb..26c48efa3b 100644 --- a/library/lms.c +++ b/library/lms.c @@ -205,7 +205,7 @@ static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params, if( ret != 0 ) goto exit; - status = psa_hash_update( &op, D_INTERNAL_CONSTANT_BYTES, D_CONST_LEN ); + status = psa_hash_update( &op, D_INTR_CONSTANT_BYTES, D_CONST_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret != 0 ) goto exit; From 9c9027b1a47f64ac16ceeaf61bc261bdc9f5c90b Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 2 Sep 2022 18:26:31 +0100 Subject: [PATCH 021/104] Add extra LMS and LMOTS tests NULL-message and LMOTS signature leak tests Signed-off-by: Raef Coles --- library/lmots.c | 21 ++++++-- library/lmots.h | 4 ++ tests/suites/test_suite_lmots.data | 12 +++++ tests/suites/test_suite_lmots.function | 69 ++++++++++++++++++++++++++ tests/suites/test_suite_lms.data | 5 ++ tests/suites/test_suite_lms.function | 36 ++++++++++++++ 6 files changed, 142 insertions(+), 5 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 8e56696e57..d733dc02e6 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -44,11 +44,6 @@ #include "psa/crypto.h" -#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \ - MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \ - MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type)) - #define MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET (0) #define MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET + \ MBEDTLS_LMOTS_TYPE_LEN) @@ -74,6 +69,10 @@ static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = {0x80, 0x80}; static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = {0x81, 0x81}; +#if defined(MBEDTLS_TEST_HOOKS) +int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * ) = NULL; +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + void unsigned_int_to_network_bytes( unsigned int val, size_t len, unsigned char *bytes ) { @@ -815,6 +814,18 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, MBEDTLS_LMOTS_TYPE_LEN, sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + /* Test hook to check if sig is being written to before we invalidate the + * private key. + */ +#if defined(MBEDTLS_TEST_HOOKS) + if( mbedtls_lmots_sign_private_key_invalidated_hook != NULL ) + { + ret = ( *mbedtls_lmots_sign_private_key_invalidated_hook )( sig ); + if( ret != 0 ) + return( ret ); + } +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + /* We've got a valid signature now, so it's time to make sure the private * key can't be reused. */ diff --git a/library/lmots.h b/library/lmots.h index 56d23f855a..993c01c10e 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -54,6 +54,10 @@ MBEDTLS_LMOTS_N_HASH_LEN(type)) #define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0) +#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \ + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type)) #ifdef __cplusplus extern "C" { diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index 6b4cc35d98..0845a17d09 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -8,6 +8,11 @@ LMOTS sign-verify test #2 # message, and verifies the signature. lmots_sign_verify_test:"55a6647a581004306792b653a561d9f3":"00000000000000000000000000000000":12:"c3dbc3fea047dca8fb7a3cdf609a5b7f48599c193c90e958ce9388c84df0a906" +LMOTS NULL-message sign-verify test +# This test uses a NULL zero-length message, and then generates a private key, +# signs the message, and verifies the signature. +lmots_sign_verify_null_msg_test::"00000000000000000000000000000000":12:"be5fa89144f2d665c66ead8216bc02006e0eccd8b3697a0aea44f6c93afe7955" + LMOTS hash-sigs interop test #1 # This test uses data from https://github.com/cisco/hash-sigs due to the limited # amount of available test vectors for LMOTS. A public/private key was generated @@ -60,3 +65,10 @@ LMOTS key reuse test # message, and then attempts to sign the message again. The second signature # must fail as private key material must be deleted after a key is used to sign. lmots_reuse_test:"cfcd1e81193e310c9d931d1b00818d14":"00000000000000000000000000000000":12:"a7f53cc5a228ce63811ba4d7c1f74f7fce62afbf6813f3ca3ae43c11b138086f" + +LMOTS signature leak test +# This test uses a fixed message, and then generates a private key, signs the +# message, and then uses a test hook to check that the signature has not been +# modifier before the private key has been deleted (which could cause signature +# leakage during errors). +lmots_signature_leak_test:"cfcd1e81193e310c9d931d1b00818d14":"00000000000000000000000000000000":12:"a7f53cc5a228ce63811ba4d7c1f74f7fce62afbf6813f3ca3ae43c11b138086f" diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 2a9ea541a4..d7067dfe00 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -2,6 +2,27 @@ #include "lmots.h" #include "mbedtls/lms.h" +#if defined(MBEDTLS_TEST_HOOKS) +extern int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * ); + +int check_lmots_private_key_for_leak(unsigned char * sig) +{ + size_t idx; + + for( idx = MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(MBEDTLS_LMOTS_SHA256_N32_W8); + idx < MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8); + idx++ ) + { + if( sig[idx] != 0x7E ) { + while(1){} + return 1; + } + } + + return 0; +} +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -33,6 +54,29 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void lmots_sign_verify_null_msg_test ( data_t *key_id, int leaf_id, data_t *seed ) +{ + mbedtls_lmots_public_t pub_ctx; + mbedtls_lmots_private_t priv_ctx; + unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; + + mbedtls_lmots_init_public( &pub_ctx ); + mbedtls_lmots_init_private( &priv_ctx ); + + TEST_ASSERT( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, + key_id->x, leaf_id, seed->x, seed->len ) == 0 ); + TEST_ASSERT( mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx) == 0 ); + TEST_ASSERT( mbedtls_lmots_sign(&priv_ctx, &mbedtls_test_rnd_std_rand, NULL, + NULL, 0, sig, sizeof(sig), NULL ) == 0 ); + TEST_ASSERT( mbedtls_lmots_verify(&pub_ctx, NULL, 0, sig, sizeof(sig)) == 0 ); + +exit: + mbedtls_lmots_free_public( &pub_ctx ); + mbedtls_lmots_free_private( &priv_ctx ); +} +/* END_CASE */ + /* BEGIN_CASE */ void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, int expected_rc ) @@ -94,3 +138,28 @@ exit: mbedtls_lmots_free_private( &ctx ); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */ +void lmots_signature_leak_test ( data_t *msg, data_t *key_id, int leaf_id, + data_t *seed ) +{ + mbedtls_lmots_private_t ctx; + unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; + + mbedtls_lmots_sign_private_key_invalidated_hook = &check_lmots_private_key_for_leak; + + /* Fill with recognisable pattern */ + memset( sig, 0x7E, sizeof( sig ) ); + + mbedtls_lmots_init_private( &ctx ); + TEST_ASSERT( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, + key_id->x, leaf_id, seed->x, + seed->len ) == 0 ); + TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, + msg->x, msg->len, sig, sizeof( sig ), NULL ) == 0 ); + +exit: + mbedtls_lmots_free_private( &ctx ); + mbedtls_lmots_sign_private_key_invalidated_hook = NULL; +} +/* END_CASE */ diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index c17d05ac57..d890dd4ddc 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -3,6 +3,11 @@ LMS sign-verify test # message, and verifies the signature. lms_sign_verify_test:"c41ba177a0ca1ec31dfb2e145237e65b":"626201f41afd7c9af793cf158da58e33" +LMS NULL-message sign-verify test +# This test uses a NULL zero-length message, and then generates a private key, +# signs the message, and verifies the signature. +lms_sign_verify_null_msg_test:"923a3c8e38c9b72e067996bfdaa36856" + LMS hash-sigs interop test #1 # This test uses data from https://github.com/cisco/hash-sigs due to the limited # amount of available test vectors for LMS. A public/private key was generated diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 148075d1b8..900392334d 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -44,6 +44,42 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void lms_sign_verify_null_msg_test( data_t *seed ) +{ + mbedtls_lms_public_t pub_ctx; + mbedtls_lms_private_t priv_ctx; + unsigned char sig[MBEDTLS_LMS_SIG_LEN(MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8)]; + int rc; + + mbedtls_lms_init_public( &pub_ctx ); + mbedtls_lms_init_private( &priv_ctx ); + + /* Allocation failure isn't a test failure, since it likely just means + * there's not enough memory to run the test. + */ + rc = mbedtls_lms_generate_private_key( &priv_ctx, MBEDTLS_LMS_SHA256_M32_H10, + MBEDTLS_LMOTS_SHA256_N32_W8, + mbedtls_test_rnd_std_rand, NULL, + seed->x, seed->len ); + TEST_ASSUME( rc != MBEDTLS_ERR_LMS_ALLOC_FAILED ); + TEST_ASSERT( rc == 0 ); + + TEST_ASSERT( mbedtls_lms_calculate_public_key( &pub_ctx, &priv_ctx ) == 0 ); + + TEST_ASSERT( mbedtls_lms_sign( &priv_ctx, mbedtls_test_rnd_std_rand, NULL, + NULL, 0, sig, sizeof( sig ), + NULL ) == 0 ); + + TEST_ASSERT( mbedtls_lms_verify( &pub_ctx, NULL, 0, sig, + sizeof( sig ) ) == 0 ); + +exit: + mbedtls_lms_free_public( &pub_ctx ); + mbedtls_lms_free_private( &priv_ctx ); +} +/* END_CASE */ + /* BEGIN_CASE */ void lms_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, int expected_rc ) From 1310ecb38906f0902b4a1c861cbf5f541220458e Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 22 Sep 2022 15:41:49 +0100 Subject: [PATCH 022/104] Update LMOTS function documentation To avoid CI failure Signed-off-by: Raef Coles --- library/lmots.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/lmots.h b/library/lmots.h index 993c01c10e..f6daa0bcca 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -146,8 +146,6 @@ typedef struct { * \param val The unsigned integer value * \param len The length of the string. * \param bytes The string to output into. - * - * \return The corresponding LMS error code. */ void unsigned_int_to_network_bytes( unsigned int val, size_t len, unsigned char *bytes ); From 40f184c83ee9ab0a96284365c8c4a1c3d0445631 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 22 Sep 2022 18:30:33 +0100 Subject: [PATCH 023/104] Cast LMS allocation sizes to size_t To prevent implict casting errors on 64-bit platforms Signed-off-by: Raef Coles --- library/lms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/lms.c b/library/lms.c index 26c48efa3b..f1230c7e70 100644 --- a/library/lms.c +++ b/library/lms.c @@ -562,7 +562,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - ctx->ots_private_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + ctx->ots_private_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof( mbedtls_lmots_private_t ) ); if( ctx->ots_private_keys == NULL ) { @@ -570,7 +570,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, goto exit; } - ctx->ots_public_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + ctx->ots_public_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof( mbedtls_lmots_public_t ) ); if( ctx->ots_public_keys == NULL ) { From 98d6e2205090e26f20f56f7839edb153c54cdc81 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 23 Sep 2022 09:04:04 +0100 Subject: [PATCH 024/104] Remove doxygen markup from internal LMS functions Signed-off-by: Raef Coles --- library/lmots.c | 86 ++++++++++++++++++++++++------------------------- library/lms.c | 72 ++++++++++++++++++++--------------------- 2 files changed, 79 insertions(+), 79 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index d733dc02e6..bdcd44570e 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -102,12 +102,12 @@ unsigned int network_bytes_to_unsigned_int( size_t len, * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of * the checksum algorithm. * - * \param params The LMOTS parameter set, I and q values which - * describe the key being used. + * params The LMOTS parameter set, I and q values which + * describe the key being used. * - * \param digest The digit string to create the digest from. As - * this does not contain a checksum, it is the same - * size as a hash output. + * digest The digit string to create the digest from. As + * this does not contain a checksum, it is the same + * size as a hash output. */ static unsigned short lmots_checksum_calculate( const mbedtls_lmots_parameters_t *params, const unsigned char* digest ) @@ -128,23 +128,23 @@ static unsigned short lmots_checksum_calculate( const mbedtls_lmots_parameters_t * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm * 4b step 3) for details. * - * \param params The LMOTS parameter set, I and q values which - * describe the key being used. + * params The LMOTS parameter set, I and q values which + * describe the key being used. * - * \param msg The message that will be hashed to create the - * digest. + * msg The message that will be hashed to create the + * digest. * - * \param msg_size The size of the message. + * msg_size The size of the message. * - * \param C_random_value The random value that will be combined with the - * message digest. This is always the same size as a - * hash output for whichever hash algorithm is - * determined by the parameter set. + * C_random_value The random value that will be combined with the + * message digest. This is always the same size as a + * hash output for whichever hash algorithm is + * determined by the parameter set. * - * \param output An output containing the digit string (+ - * checksum) of length P digits (in the case of - * MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of - * size P bytes). + * output An output containing the digit string (+ + * checksum) of length P digits (in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of + * size P bytes). */ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *params, const unsigned char *msg, @@ -216,27 +216,27 @@ exit: * Algorithm 3 step 5), and to calculate a public key candidate from a * signature and message (RFC8554 Algorithm 4b step 3). * - * \param params The LMOTS parameter set, I and q values which - * describe the key being used. + * params The LMOTS parameter set, I and q values which + * describe the key being used. * - * \param x_digit_array The array of digits (of size P, 34 in the case of - * MBEDTLS_LMOTS_SHA256_N32_W8). + * x_digit_array The array of digits (of size P, 34 in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8). * - * \param hash_idx_min_values An array of the starting values of the j iterator - * for each of the members of the digit array. If - * this value in NULL, then all iterators will start - * at 0. + * hash_idx_min_values An array of the starting values of the j iterator + * for each of the members of the digit array. If + * this value in NULL, then all iterators will start + * at 0. * - * \param hash_idx_max_values An array of the upper bound values of the j - * iterator for each of the members of the digit - * array. If this value in NULL, then iterator is - * bounded to be less than 2^w - 1 (255 in the case - * of MBEDTLS_LMOTS_SHA256_N32_W8) + * hash_idx_max_values An array of the upper bound values of the j + * iterator for each of the members of the digit + * array. If this value in NULL, then iterator is + * bounded to be less than 2^w - 1 (255 in the case + * of MBEDTLS_LMOTS_SHA256_N32_W8) * - * \param output An array containing a hash output for each member - * of the digit string P. In the case of - * MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 * - * 34. + * output An array containing a hash output for each member + * of the digit string P. In the case of + * MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 * + * 34. */ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, const unsigned char *x_digit_array, @@ -345,15 +345,15 @@ exit: * step 4), and to calculate a public key candidate from a signature and message * (RFC8554 Algorithm 4b step 3). * - * \param params The LMOTS parameter set, I and q values which describe - * the key being used. - * \param y_hashed_digits The array of hashes, one hash for each digit of the - * symbol array (which is of size P, 34 in the case of - * MBEDTLS_LMOTS_SHA256_N32_W8) + * params The LMOTS parameter set, I and q values which describe + * the key being used. + * y_hashed_digits The array of hashes, one hash for each digit of the + * symbol array (which is of size P, 34 in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8) * - * \param pub_key The output public key (or candidate public key in - * case this is being run as part of signature - * verification), in the form of a hash output. + * pub_key The output public key (or candidate public key in + * case this is being run as part of signature + * verification), in the form of a hash output. */ static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t *params, const unsigned char *y_hashed_digits, diff --git a/library/lms.c b/library/lms.c index f1230c7e70..7ec2b103fa 100644 --- a/library/lms.c +++ b/library/lms.c @@ -87,19 +87,19 @@ static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = {0x83, 0x83}; * public key and some other parameters like the leaf index). This function * implements RFC8554 section 5.3, in the case where r >= 2^h. * - * \param params The LMS parameter set, the underlying LMOTS - * parameter set, and I value which describe the key - * being used. + * params The LMS parameter set, the underlying LMOTS + * parameter set, and I value which describe the key + * being used. * - * \param pub_key The public key of the private whose index - * corresponds to the index of this leaf node. This - * is a hash output. + * pub_key The public key of the private whose index + * corresponds to the index of this leaf node. This + * is a hash output. * - * \param r_node_idx The index of this node in the merkle tree. Note - * that the root node of the merkle tree is - * 1-indexed. + * r_node_idx The index of this node in the merkle tree. Note + * that the root node of the merkle tree is + * 1-indexed. * - * \param out The output node value, which is a hash output. + * out The output node value, which is a hash output. */ static int create_merkle_leaf_value( const mbedtls_lms_parameters_t *params, unsigned char *pub_key, @@ -157,23 +157,23 @@ exit: * of a public key and some other parameters like the node index). This function * implements RFC8554 section 5.3, in the case where r < 2^h. * - * \param params The LMS parameter set, the underlying LMOTS - * parameter set, and I value which describe the key - * being used. + * params The LMS parameter set, the underlying LMOTS + * parameter set, and I value which describe the key + * being used. * - * \param left_node The value of the child of this node which is on - * the left-hand side. As with all nodes on the - * merkle tree, this is a hash output. + * left_node The value of the child of this node which is on + * the left-hand side. As with all nodes on the + * merkle tree, this is a hash output. * - * \param right_node The value of the child of this node which is on - * the right-hand side. As with all nodes on the - * merkle tree, this is a hash output. + * right_node The value of the child of this node which is on + * the right-hand side. As with all nodes on the + * merkle tree, this is a hash output. * - * \param r_node_idx The index of this node in the merkle tree. Note - * that the root node of the merkle tree is - * 1-indexed. + * r_node_idx The index of this node in the merkle tree. Note + * that the root node of the merkle tree is + * 1-indexed. * - * \param out The output node value, which is a hash output. + * out The output node value, which is a hash output. */ static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params, const unsigned char *left_node, @@ -408,15 +408,15 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, * implements RFC8554 section 5.3, and is used to generate a public key (as the * public key is the root node of the merkle tree). * - * \param ctx The LMS private context, containing a parameter - * set and private key material consisting of both - * public and private OTS. + * ctx The LMS private context, containing a parameter + * set and private key material consisting of both + * public and private OTS. * - * \param tree The output tree, which is 2^(H + 1) hash outputs. - * In the case of H=10 we have 2048 tree nodes (of - * which 1024 of them are leaf nodes). Note that - * because the merkle tree root is 1-indexed, the 0 - * index tree node is never used. + * tree The output tree, which is 2^(H + 1) hash outputs. + * In the case of H=10 we have 2048 tree nodes (of + * which 1024 of them are leaf nodes). Note that + * because the merkle tree root is 1-indexed, the 0 + * index tree node is never used. */ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, unsigned char *tree ) @@ -465,13 +465,13 @@ static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, * and return the full path. This function implements RFC8554 section 5.4.1, as * the merkle path is the main component of an LMS signature. * - * \param ctx The LMS private context, containing a parameter - * set and private key material consisting of both - * public and private OTS. + * ctx The LMS private context, containing a parameter + * set and private key material consisting of both + * public and private OTS. * - * \param leaf_node_id Which leaf node to calculate the path from. + * leaf_node_id Which leaf node to calculate the path from. * - * \param tree The output path, which is H hash outputs. + * tree The output path, which is H hash outputs. */ static int get_merkle_path( mbedtls_lms_private_t *ctx, unsigned int leaf_node_id, From 3982040232bfa983439d28edb831291a8121f4d0 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 23 Sep 2022 09:12:54 +0100 Subject: [PATCH 025/104] Fix LMS zeroization using wrong sizeof type Causing a buffer write out of bounds Signed-off-by: Raef Coles --- library/lms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lms.c b/library/lms.c index 7ec2b103fa..653530c75d 100644 --- a/library/lms.c +++ b/library/lms.c @@ -525,7 +525,7 @@ void mbedtls_lms_free_private( mbedtls_lms_private_t *ctx ) mbedtls_free( ctx->ots_public_keys ); } - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_private_t ) ); } From 403558c1c96256737cffb20822e3869d1f4721fa Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 23 Sep 2022 17:03:53 +0100 Subject: [PATCH 026/104] Fix LMS function documentation Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 3e84ce0575..9a8afa1c40 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -269,7 +269,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, * \param ctx The initialized LMS public context to generate the key * from and store it into. * - * \param ctx The LMS private context to read the private key + * \param priv_ctx The LMS private context to read the private key * from. This must have been initialized and contain a * private key. * From 40158e11fc6bd46ebbf759eab3958fb562c595ac Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Tue, 27 Sep 2022 10:23:53 +0100 Subject: [PATCH 027/104] Add LMOTS test hook to header Signed-off-by: Raef Coles --- library/lmots.h | 4 ++++ tests/suites/test_suite_lmots.function | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/lmots.h b/library/lmots.h index f6daa0bcca..d0379e3a2d 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -139,6 +139,10 @@ typedef struct { } mbedtls_lmots_private_t; #endif /* MBEDTLS_LMS_PRIVATE */ +#if defined(MBEDTLS_TEST_HOOKS) +extern int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * ); +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + /** * \brief This function converts an unsigned int into a * network-byte-order (big endian) string. diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index d7067dfe00..dd8a665d58 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -3,8 +3,6 @@ #include "mbedtls/lms.h" #if defined(MBEDTLS_TEST_HOOKS) -extern int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * ); - int check_lmots_private_key_for_leak(unsigned char * sig) { size_t idx; From ad05425ab75951763490d64df931759e0087a318 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Tue, 27 Sep 2022 10:59:16 +0100 Subject: [PATCH 028/104] Update naming of internal LMS functions To comply with the mbedtls_ requirement Signed-off-by: Raef Coles --- library/lmots.c | 53 ++++++++++++++++++++++++++----------------------- library/lmots.h | 8 ++++---- library/lms.c | 35 +++++++++++++++++--------------- 3 files changed, 51 insertions(+), 45 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index bdcd44570e..6846d4cde4 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -73,8 +73,8 @@ static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = {0x81, 0x81}; int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * ) = NULL; #endif /* defined(MBEDTLS_TEST_HOOKS) */ -void unsigned_int_to_network_bytes( unsigned int val, size_t len, - unsigned char *bytes ) +void mbedtls_lms_unsigned_int_to_network_bytes( unsigned int val, size_t len, + unsigned char *bytes ) { size_t idx; @@ -84,8 +84,8 @@ void unsigned_int_to_network_bytes( unsigned int val, size_t len, } } -unsigned int network_bytes_to_unsigned_int( size_t len, - const unsigned char *bytes ) +unsigned int mbedtls_lms_network_bytes_to_unsigned_int( size_t len, + const unsigned char *bytes ) { size_t idx; unsigned int val = 0; @@ -200,8 +200,8 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p goto exit; checksum = lmots_checksum_calculate( params, out ); - unsigned_int_to_network_bytes( checksum, CHECKSUM_LEN, - out + MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); + mbedtls_lms_unsigned_int_to_network_bytes( checksum, CHECKSUM_LEN, + out + MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); exit: psa_hash_abort( &op ); @@ -295,15 +295,17 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, if( ret != 0 ) goto exit; - unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, - i_digit_idx_bytes ); + mbedtls_lms_unsigned_int_to_network_bytes( i_digit_idx, + I_DIGIT_IDX_LEN, + i_digit_idx_bytes ); status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret != 0 ) goto exit; - unsigned_int_to_network_bytes( j_hash_idx, J_HASH_IDX_LEN, - j_hash_idx_bytes ); + mbedtls_lms_unsigned_int_to_network_bytes( j_hash_idx, + J_HASH_IDX_LEN, + j_hash_idx_bytes ); status = psa_hash_update( &op, j_hash_idx_bytes, J_HASH_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret != 0 ) @@ -438,8 +440,8 @@ int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, const unsigned char *key, size_t key_len ) { ctx->params.type = - network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, - key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); if( key_len < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) ) { @@ -541,7 +543,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, + if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); @@ -611,11 +613,12 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, I_key_identifier, sizeof( ctx->params.I_key_identifier ) ); - unsigned_int_to_network_bytes( q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - ctx->params.q_leaf_identifier ); + mbedtls_lms_unsigned_int_to_network_bytes( q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + ctx->params.q_leaf_identifier ); - unsigned_int_to_network_bytes( 0xFF, sizeof( const_bytes ), const_bytes ); + mbedtls_lms_unsigned_int_to_network_bytes( 0xFF, sizeof( const_bytes ), + const_bytes ); for ( i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type); @@ -640,8 +643,8 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, if( ret ) goto exit; - unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, - i_digit_idx_bytes ); + mbedtls_lms_unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, + i_digit_idx_bytes ); status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); ret = mbedtls_lms_error_from_psa( status ); if( ret ) @@ -731,9 +734,9 @@ int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - unsigned_int_to_network_bytes( ctx->params.type, - MBEDTLS_LMOTS_TYPE_LEN, - key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type, + MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, ctx->params.I_key_identifier, @@ -810,9 +813,9 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( ret ); } - unsigned_int_to_network_bytes( ctx->params.type, - MBEDTLS_LMOTS_TYPE_LEN, - sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type, + MBEDTLS_LMOTS_TYPE_LEN, + sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); /* Test hook to check if sig is being written to before we invalidate the * private key. diff --git a/library/lmots.h b/library/lmots.h index d0379e3a2d..05bd55a70b 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -151,8 +151,8 @@ extern int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * * \param len The length of the string. * \param bytes The string to output into. */ -void unsigned_int_to_network_bytes( unsigned int val, size_t len, - unsigned char *bytes ); +void mbedtls_lms_unsigned_int_to_network_bytes( unsigned int val, size_t len, + unsigned char *bytes ); /** * \brief This function converts a network-byte-order @@ -163,8 +163,8 @@ void unsigned_int_to_network_bytes( unsigned int val, size_t len, * * \return The corresponding LMS error code. */ -unsigned int network_bytes_to_unsigned_int( size_t len, - const unsigned char *bytes ); +unsigned int mbedtls_lms_network_bytes_to_unsigned_int( size_t len, + const unsigned char *bytes ); /** * \brief This function converts a \ref psa_status_t to a diff --git a/library/lms.c b/library/lms.c index 653530c75d..cd39502a62 100644 --- a/library/lms.c +++ b/library/lms.c @@ -124,7 +124,7 @@ static int create_merkle_leaf_value( const mbedtls_lms_parameters_t *params, if( ret != 0 ) goto exit; - unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); + mbedtls_lms_unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); status = psa_hash_update( &op, r_node_idx_bytes, 4 ); ret = mbedtls_lms_error_from_psa( status ); if( ret != 0 ) @@ -199,7 +199,7 @@ static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params, if( ret != 0 ) goto exit; - unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); + mbedtls_lms_unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); status = psa_hash_update( &op, r_node_idx_bytes, 4 ); ret = mbedtls_lms_error_from_psa( status ); if( ret != 0 ) @@ -255,7 +255,7 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); } - type = network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, + type = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); if( type != MBEDTLS_LMS_SHA256_M32_H10 ) { @@ -263,7 +263,7 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, } ctx->params.type = type; - otstype = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, + otstype = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) { @@ -319,14 +319,14 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, + if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } - if( network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, + if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype)) != MBEDTLS_LMS_SHA256_M32_H10 ) { @@ -334,8 +334,8 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, } - q_leaf_identifier = network_bytes_to_unsigned_int( MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); + q_leaf_identifier = mbedtls_lms_network_bytes_to_unsigned_int( + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); if( q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type) ) { @@ -345,9 +345,9 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, memcpy( ots_params.I_key_identifier, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - unsigned_int_to_network_bytes( q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - ots_params.q_leaf_identifier ); + mbedtls_lms_unsigned_int_to_network_bytes( q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + ots_params.q_leaf_identifier ); ots_params.type = ctx->params.otstype; ret = mbedtls_lmots_calculate_public_key_candidate( &ots_params, msg, @@ -676,10 +676,11 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - unsigned_int_to_network_bytes( + mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type, MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); - unsigned_int_to_network_bytes( ctx->params.otstype, MBEDTLS_LMOTS_TYPE_LEN, + mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.otstype, + MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); memcpy( key + MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET, ctx->params.I_key_identifier, @@ -748,10 +749,12 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, return( ret ); } - unsigned_int_to_network_bytes( ctx->params.type, MBEDTLS_LMS_TYPE_LEN, + mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type, + MBEDTLS_LMS_TYPE_LEN, sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype) ); - unsigned_int_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); + mbedtls_lms_unsigned_int_to_network_bytes( q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); ret = get_merkle_path( ctx, MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, From 57d5328ad5197092d3c47c71244326267e02d4a3 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Tue, 27 Sep 2022 11:30:51 +0100 Subject: [PATCH 029/104] Remove MBEDTLS_LM(OT)S prefix from internal macros Signed-off-by: Raef Coles --- library/lmots.c | 30 +++++++++++----------- library/lms.c | 68 ++++++++++++++++++++++++------------------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 6846d4cde4..e196635c36 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -44,13 +44,13 @@ #include "psa/crypto.h" -#define MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET (0) -#define MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_TYPE_OFFSET + \ - MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET + \ - MBEDTLS_LMOTS_I_KEY_ID_LEN) -#define MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET (MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET + \ - MBEDTLS_LMOTS_Q_LEAF_ID_LEN) +#define PUBLIC_KEY_TYPE_OFFSET (0) +#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN) +#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) /* We only support parameter sets that use 8-bit digits, as it does not require * translation logic between digits and bytes */ @@ -61,7 +61,7 @@ #define D_CONST_LEN (2) /* Currently only defined for SHA256, 32 is the max hash output size */ -#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN_MAX (MBEDTLS_LMOTS_N_HASH_LEN_MAX) +#define C_RANDOM_VALUE_LEN_MAX (MBEDTLS_LMOTS_N_HASH_LEN_MAX) #define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) @@ -449,15 +449,15 @@ int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, } memcpy( ctx->params.I_key_identifier, - key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, + key + PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN ); memcpy( ctx->params.q_leaf_identifier, - key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, + key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); memcpy( ctx->public_key, - key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, + key + PUBLIC_KEY_KEY_HASH_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); ctx->have_public_key = 1; @@ -738,15 +738,15 @@ int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); - memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_I_KEY_ID_OFFSET, + memcpy( key + PUBLIC_KEY_I_KEY_ID_OFFSET, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_Q_LEAF_ID_OFFSET, + memcpy( key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, ctx->params.q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - memcpy( key + MBEDTLS_LMOTS_PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, + memcpy( key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); if( key_len != NULL ) @@ -771,7 +771,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, * key. */ unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - unsigned char tmp_c_random[MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN_MAX]; + unsigned char tmp_c_random[C_RANDOM_VALUE_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if( msg == NULL && msg_size != 0 ) diff --git a/library/lms.c b/library/lms.c index cd39502a62..d3801c73f3 100644 --- a/library/lms.c +++ b/library/lms.c @@ -54,26 +54,26 @@ #define mbedtls_free free #endif -#define MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET (0) -#define MBEDTLS_LMS_SIG_OTS_SIG_OFFSET (MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET + \ - MBEDTLS_LMOTS_Q_LEAF_ID_LEN) -#define MBEDTLS_LMS_SIG_TYPE_OFFSET(otstype) (MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + \ - MBEDTLS_LMOTS_SIG_LEN(otstype)) -#define MBEDTLS_LMS_SIG_PATH_OFFSET(otstype) (MBEDTLS_LMS_SIG_TYPE_OFFSET(otstype) + \ - MBEDTLS_LMS_TYPE_LEN) +#define SIG_Q_LEAF_ID_OFFSET (0) +#define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) +#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET + \ + MBEDTLS_LMOTS_SIG_LEN(otstype)) +#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \ + MBEDTLS_LMS_TYPE_LEN) -#define MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET (0) -#define MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET + \ - MBEDTLS_LMS_TYPE_LEN) -#define MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET + \ - MBEDTLS_LMOTS_TYPE_LEN) -#define MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET (MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET + \ - MBEDTLS_LMOTS_I_KEY_ID_LEN) +#define PUBLIC_KEY_TYPE_OFFSET (0) +#define PUBLIC_KEY_OTSTYPE_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ + MBEDTLS_LMS_TYPE_LEN) +#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_OTSTYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN) /* Currently only support H=10 */ -#define MBEDTLS_LMS_H_TREE_HEIGHT_MAX 10 -#define MERKLE_TREE_NODE_AM_MAX (1u << (MBEDTLS_LMS_H_TREE_HEIGHT_MAX + 1u)) +#define H_TREE_HEIGHT_MAX 10 +#define MERKLE_TREE_NODE_AM_MAX (1u << (H_TREE_HEIGHT_MAX + 1u)) #define MERKLE_TREE_NODE_AM(type) (1u << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u)) #define MERKLE_TREE_LEAF_NODE_AM(type) (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)) #define MERKLE_TREE_INTERNAL_NODE_AM(type) (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)) @@ -256,7 +256,7 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, } type = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, - key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); + key + PUBLIC_KEY_TYPE_OFFSET ); if( type != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); @@ -264,7 +264,7 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, ctx->params.type = type; otstype = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, - key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); + key + PUBLIC_KEY_OTSTYPE_OFFSET ); if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); @@ -272,9 +272,9 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, ctx->params.otstype = otstype; memcpy( ctx->params.I_key_identifier, - key + MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET, + key + PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - memcpy( ctx->T_1_pub_key, key + MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET, + memcpy( ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET, MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) ); ctx->have_public_key = 1; @@ -320,14 +320,14 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, } if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) + sig + SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype)) + sig + SIG_TYPE_OFFSET(ctx->params.otstype)) != MBEDTLS_LMS_SHA256_M32_H10 ) { return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); @@ -335,7 +335,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, q_leaf_identifier = mbedtls_lms_network_bytes_to_unsigned_int( - MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + SIG_Q_LEAF_ID_OFFSET ); if( q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type) ) { @@ -351,7 +351,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, ots_params.type = ctx->params.otstype; ret = mbedtls_lmots_calculate_public_key_candidate( &ots_params, msg, - msg_size, sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, + msg_size, sig + SIG_OTS_SIG_OFFSET, MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), Kc_candidate_ots_pub_key, sizeof( Kc_candidate_ots_pub_key ), NULL ); if( ret != 0 ) @@ -376,14 +376,14 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, /* Left/right node ordering matters for the hash */ if( curr_node_id & 1 ) { - left_node = sig + MBEDTLS_LMS_SIG_PATH_OFFSET(ctx->params.otstype) + + left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); right_node = Tc_candidate_root_node; } else { left_node = Tc_candidate_root_node; - right_node = sig + MBEDTLS_LMS_SIG_PATH_OFFSET(ctx->params.otstype) + + right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); } @@ -678,14 +678,14 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type, - MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBLIC_KEY_TYPE_OFFSET ); + MBEDTLS_LMS_TYPE_LEN, key + PUBLIC_KEY_TYPE_OFFSET ); mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.otstype, MBEDTLS_LMOTS_TYPE_LEN, - key + MBEDTLS_LMS_PUBLIC_KEY_OTSTYPE_OFFSET ); - memcpy( key + MBEDTLS_LMS_PUBLIC_KEY_I_KEY_ID_OFFSET, + key + PUBLIC_KEY_OTSTYPE_OFFSET ); + memcpy( key + PUBLIC_KEY_I_KEY_ID_OFFSET, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - memcpy( key + MBEDTLS_LMS_PUBLIC_KEY_ROOT_NODE_OFFSET, + memcpy( key +PUBLIC_KEY_ROOT_NODE_OFFSET, ctx->T_1_pub_key, MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) ); @@ -741,7 +741,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, ret = mbedtls_lmots_sign( &ctx->ots_private_keys[q_leaf_identifier], f_rng, p_rng, msg, msg_size, - sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET, + sig + SIG_OTS_SIG_OFFSET, MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype), NULL ); if( ret != 0 ) @@ -751,14 +751,14 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type, MBEDTLS_LMS_TYPE_LEN, - sig + MBEDTLS_LMS_SIG_TYPE_OFFSET(ctx->params.otstype) ); + sig + SIG_TYPE_OFFSET(ctx->params.otstype) ); mbedtls_lms_unsigned_int_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN, - sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET ); + sig + SIG_Q_LEAF_ID_OFFSET ); ret = get_merkle_path( ctx, MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, - sig + MBEDTLS_LMS_SIG_PATH_OFFSET(ctx->params.otstype) ); + sig + SIG_PATH_OFFSET(ctx->params.otstype) ); if( ret != 0 ) { return( ret ); From 98c504373c853b6f009e88fdb45b5f2e754c5e33 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Tue, 27 Sep 2022 12:56:34 +0100 Subject: [PATCH 030/104] Update LMS test description To correct copy-paste error Signed-off-by: Raef Coles --- tests/suites/test_suite_lms.data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index d890dd4ddc..1b1423031a 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -61,7 +61,7 @@ LMS negative test (invalid lm_ots type) #2 # (0x6) but an invalid LMOTS type, and should fail with a bad input data error. lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA -LMS negative test (invalid lm_ots type) #2 +LMS negative test (invalid leaf ID) # This test uses a null (zeroed) message/signature/public key trio, with the # only parts set being the LMS and LMOTS types and the leaf ID. In this case, # the leaf ID is 1024, which is invalid for MBEDTLS_LMS_SHA256_M32_H10. This From 0b7da1b7870a2af6942f687e1c55eccafc9c29ee Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Tue, 27 Sep 2022 13:45:30 +0100 Subject: [PATCH 031/104] Fix overflow in LMS context init Signed-off-by: Raef Coles --- library/lms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lms.c b/library/lms.c index d3801c73f3..1c66946d75 100644 --- a/library/lms.c +++ b/library/lms.c @@ -506,7 +506,7 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx, void mbedtls_lms_init_private( mbedtls_lms_private_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_private_t ) ) ; } void mbedtls_lms_free_private( mbedtls_lms_private_t *ctx ) From a7e03adef57474daf0e01ae42e4f4800b958c02c Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 28 Sep 2022 09:32:48 +0100 Subject: [PATCH 032/104] Disable LMS in all.sh when PSA isn't enabled Signed-off-by: Raef Coles --- tests/scripts/all.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 1d2ee406c5..379d6755bf 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1246,6 +1246,7 @@ component_test_full_no_cipher () { scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3 scripts/config.py unset MBEDTLS_SSL_SRV_C scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO + scripts/config.py unset MBEDTLS_LMS_C make msg "test: full minus CIPHER" @@ -1268,6 +1269,7 @@ component_test_crypto_full_no_cipher () { scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO + scripts/config.py unset MBEDTLS_LMS_C make msg "test: crypto_full minus CIPHER" @@ -1829,6 +1831,7 @@ component_test_no_use_psa_crypto_full_cmake_asan() { scripts/config.py unset MBEDTLS_PSA_ITS_FILE_C scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C + scripts/config.py unset MBEDTLS_LMS_C CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make From 47bccb7e474705cb31fc7553fe0606cbe9bb108c Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 28 Sep 2022 12:00:20 +0100 Subject: [PATCH 033/104] Disable LMS_PRIVATE in all.sh when LMS is disabled Signed-off-by: Raef Coles --- tests/scripts/all.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 379d6755bf..55d55f82c2 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1247,6 +1247,7 @@ component_test_full_no_cipher () { scripts/config.py unset MBEDTLS_SSL_SRV_C scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO scripts/config.py unset MBEDTLS_LMS_C + scripts/config.py unset MBEDTLS_LMS_PRIVATE make msg "test: full minus CIPHER" @@ -1270,6 +1271,7 @@ component_test_crypto_full_no_cipher () { scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO scripts/config.py unset MBEDTLS_LMS_C + scripts/config.py unset MBEDTLS_LMS_PRIVATE make msg "test: crypto_full minus CIPHER" @@ -1832,6 +1834,7 @@ component_test_no_use_psa_crypto_full_cmake_asan() { scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C scripts/config.py unset MBEDTLS_LMS_C + scripts/config.py unset MBEDTLS_LMS_PRIVATE CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make From b4568c5423219922a858561dafafa1067c3a9687 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 28 Sep 2022 17:11:42 +0100 Subject: [PATCH 034/104] Disable LMS in PSA crypto client test Signed-off-by: Raef Coles --- tests/scripts/all.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 55d55f82c2..c3a39bcd27 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -987,6 +987,8 @@ component_test_psa_crypto_client () { scripts/config.py unset MBEDTLS_PSA_CRYPTO_C scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C scripts/config.py set MBEDTLS_PSA_CRYPTO_CLIENT + scripts/config.py unset MBEDTLS_LMS_C + scripts/config.py unset MBEDTLS_LMS_PRIVATE make msg "test: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT, make" From ab300f15e8e3e695585a2ec9edb5b888bc13937b Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 28 Sep 2022 17:12:41 +0100 Subject: [PATCH 035/104] Move public header content from lmots.h to lms.h Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 84 +++++++++++++++++++++++++++++++++++++++++-- library/lmots.h | 83 ++---------------------------------------- 2 files changed, 84 insertions(+), 83 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 9a8afa1c40..dba8835f07 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -30,8 +30,6 @@ #include #include -#include "lmots.h" - #include "mbedtls/build_info.h" #define MBEDTLS_ERR_LMS_BAD_INPUT_DATA -0x0011 /**< Bad data has been input to an LMS function */ @@ -40,6 +38,13 @@ #define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ #define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */ +/* Currently only defined for SHA256, 32 is the max hash output size */ +#define MBEDTLS_LMOTS_N_HASH_LEN_MAX (32u) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX (34u) +#define MBEDTLS_LMOTS_N_HASH_LEN(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) +#define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u) +#define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u) + #define MBEDTLS_LMS_TYPE_LEN (4) #define MBEDTLS_LMS_H_TREE_HEIGHT(type) (type == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0) @@ -76,6 +81,81 @@ typedef enum { MBEDTLS_LMS_SHA256_M32_H10 = 0x6, } mbedtls_lms_algorithm_type_t; +/** The Identifier of the LMOTS parameter set, as per + * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml. + * We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicty. + */ +typedef enum { + MBEDTLS_LMOTS_SHA256_N32_W8 = 4 +} mbedtls_lmots_algorithm_type_t; + +/** LMOTS parameters structure. + * + * This contains the metadata associated with an LMOTS key, detailing the + * algorithm type, the key ID, and the leaf identifier should be key be part of + * a LMS key. + */ +typedef struct { + unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key + identifier. */ + unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which + leaf of the LMS key this is. + 0 if the key is not part of an LMS key. */ + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as + per IANA. Only SHA256_N32_W8 is + currently supported. */ +} mbedtls_lmots_parameters_t; + +/** LMOTS public context structure. + * + * A LMOTS public key is a hash output, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lmots_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PUBLIC_KEY -> INIT [label="free"]; + * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; + * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; + * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. + Boolean values only. */ +} mbedtls_lmots_public_t; + +#ifdef MBEDTLS_LMS_PRIVATE +/** LMOTS private context structure. + * + * A LMOTS private key is one hash output for each of digit of the digest + + * checksum, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lmots_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PRIVATE_KEY -> INIT [label="free"]; + * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; + * HAVE_PRIVATE_KEY -> INIT [label="sign"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. + Boolean values only. */ +} mbedtls_lmots_private_t; +#endif /* MBEDTLS_LMS_PRIVATE */ + /** LMS parameters structure. * diff --git a/library/lmots.h b/library/lmots.h index 05bd55a70b..db945941cb 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -30,18 +30,14 @@ #include "psa/crypto.h" +#include "mbedtls/lms.h" + #include #include -/* Currently only defined for SHA256, 32 is the max hash output size */ -#define MBEDTLS_LMOTS_N_HASH_LEN_MAX (32u) -#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX (34u) -#define MBEDTLS_LMOTS_N_HASH_LEN(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) #define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) #define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type)) #define MBEDTLS_LMOTS_TYPE_LEN (4u) -#define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u) -#define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u) #define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \ @@ -63,81 +59,6 @@ extern "C" { #endif -/** The Identifier of the LMS parameter set, as per - * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml. - * We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicty. - */ -typedef enum { - MBEDTLS_LMOTS_SHA256_N32_W8 = 4 -} mbedtls_lmots_algorithm_type_t; - - -/** LMOTS parameters structure. - * - * This contains the metadata associated with an LMOTS key, detailing the - * algorithm type, the key ID, and the leaf identifier should be key be part of - * a LMS key. - */ -typedef struct { - unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key - identifier. */ - unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which - leaf of the LMS key this is. - 0 if the key is not part of an LMS key. */ - mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as - per IANA. Only SHA256_N32_W8 is - currently supported. */ -} mbedtls_lmots_parameters_t; - -/** LMOTS public context structure. - * - * A LMOTS public key is a hash output, and the applicable parameter set. - * - * The context must be initialized before it is used. A public key must either - * be imported or generated from a private context. - * - * \dot - * digraph lmots_public_t { - * UNINITIALIZED -> INIT [label="init"]; - * HAVE_PUBLIC_KEY -> INIT [label="free"]; - * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; - * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; - * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; - * } - * \enddot - */ -typedef struct { - mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); - unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. - Boolean values only. */ -} mbedtls_lmots_public_t; - -#ifdef MBEDTLS_LMS_PRIVATE -/** LMOTS private context structure. - * - * A LMOTS private key is one hash output for each of digit of the digest + - * checksum, and the applicable parameter set. - * - * The context must be initialized before it is used. A public key must either - * be imported or generated from a private context. - * - * \dot - * digraph lmots_public_t { - * UNINITIALIZED -> INIT [label="init"]; - * HAVE_PRIVATE_KEY -> INIT [label="free"]; - * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; - * HAVE_PRIVATE_KEY -> INIT [label="sign"]; - * } - * \enddot - */ -typedef struct { - mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); - unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. - Boolean values only. */ -} mbedtls_lmots_private_t; -#endif /* MBEDTLS_LMS_PRIVATE */ #if defined(MBEDTLS_TEST_HOOKS) extern int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * ); From 56fe20a47385cd5d6d03e5da9210ad601e1bca46 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 28 Sep 2022 17:56:39 +0100 Subject: [PATCH 036/104] Move MBEDTLS_PRIVATE required defines into lms.h From lmots.h, as it is a private header Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 9 +++++++++ library/lmots.h | 8 -------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index dba8835f07..1ba4f3abc0 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -44,6 +44,15 @@ #define MBEDTLS_LMOTS_N_HASH_LEN(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) #define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u) #define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u) +#define MBEDTLS_LMOTS_TYPE_LEN (4u) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) +#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type)) + +#define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \ + (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \ + MBEDTLS_LMOTS_N_HASH_LEN(type))) + #define MBEDTLS_LMS_TYPE_LEN (4) #define MBEDTLS_LMS_H_TREE_HEIGHT(type) (type == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0) diff --git a/library/lmots.h b/library/lmots.h index db945941cb..214321a5fd 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -35,14 +35,6 @@ #include #include -#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) -#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type)) -#define MBEDTLS_LMOTS_TYPE_LEN (4u) - -#define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ - MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \ - (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \ - MBEDTLS_LMOTS_N_HASH_LEN(type))) #define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ MBEDTLS_LMOTS_I_KEY_ID_LEN + \ From 5127e859d77eb802f8a4631f9ae6be7dbda260ad Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 10:35:56 +0100 Subject: [PATCH 037/104] Update LMS and LMOTS dependency macros Signed-off-by: Raef Coles --- include/mbedtls/check_config.h | 4 ++-- include/mbedtls/lms.h | 12 ++++++------ include/mbedtls/mbedtls_config.h | 2 +- library/lmots.c | 8 ++++---- library/lmots.h | 4 ++-- library/lms.c | 8 ++++---- tests/suites/test_suite_lmots.function | 10 +++++----- tests/suites/test_suite_lms.function | 8 ++++---- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 570d9dba27..4b2783174f 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -354,8 +354,8 @@ #endif #if defined(MBEDTLS_LMS_C) && \ - ( !defined(MBEDTLS_PSA_CRYPTO_C) ) -#error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C" + ( !defined(MBEDTLS_PSA_CRYPTO_C) && !defined(PSA_WANT_ALG_SHA256) ) +#error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA256" #endif #if defined(MBEDTLS_LMS_PRIVATE) && \ diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 1ba4f3abc0..40ab783151 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -139,7 +139,7 @@ typedef struct { Boolean values only. */ } mbedtls_lmots_public_t; -#ifdef MBEDTLS_LMS_PRIVATE +#if defined(MBEDTLS_LMS_PRIVATE) /** LMOTS private context structure. * * A LMOTS private key is one hash output for each of digit of the digest + @@ -163,7 +163,7 @@ typedef struct { unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lmots_private_t; -#endif /* MBEDTLS_LMS_PRIVATE */ +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ /** LMS parameters structure. @@ -209,7 +209,7 @@ typedef struct { } mbedtls_lms_public_t; -#ifdef MBEDTLS_LMS_PRIVATE +#if defined(MBEDTLS_LMS_PRIVATE) /** LMS private context structure. * * A LMS private key is a set of LMOTS private keys, an index to the next usable @@ -237,7 +237,7 @@ typedef struct { unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lms_private_t; -#endif /* MBEDTLS_LMS_PRIVATE */ +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ /** * \brief This function initializes an LMS public context @@ -301,7 +301,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size ); -#ifdef MBEDTLS_LMS_PRIVATE +#if defined(MBEDTLS_LMS_PRIVATE) /** * \brief This function initializes an LMS private context * @@ -434,7 +434,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void* p_rng, unsigned char *msg, unsigned int msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len ); -#endif /* MBEDTLS_LMS_PRIVATE */ +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ #ifdef __cplusplus } diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index c0caf75623..4188afec98 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2485,7 +2485,7 @@ * * Uncomment to enable the LMS signature algorithm and private key operations. */ -// #define MBEDTLS_LMS_PRIVATE +//#define MBEDTLS_LMS_PRIVATE /** * \def MBEDTLS_NIST_KW_C diff --git a/library/lmots.c b/library/lmots.c index e196635c36..9a6c6be665 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -32,7 +32,7 @@ #include "common.h" -#ifdef MBEDTLS_LMS_C +#if defined(MBEDTLS_LMS_C) #include @@ -568,7 +568,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, return( 0 ); } -#ifdef MBEDTLS_LMS_PRIVATE +#if defined(MBEDTLS_LMS_PRIVATE) void mbedtls_lmots_init_private( mbedtls_lmots_private_t *ctx ) { @@ -851,5 +851,5 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, return( 0 ); } -#endif /* MBEDTLS_LMS_PRIVATE */ -#endif /* MBEDTLS_LMS_C */ +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ +#endif /* defined(MBEDTLS_LMS_C) */ diff --git a/library/lmots.h b/library/lmots.h index 214321a5fd..37466b76e8 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -189,7 +189,7 @@ int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size ); -#ifdef MBEDTLS_LMS_PRIVATE +#if defined(MBEDTLS_LMS_PRIVATE) /** * \brief This function initializes a private LMOTS context @@ -310,7 +310,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, void *p_rng, const unsigned char *msg, size_t msg_size, unsigned char *sig, size_t sig_size, size_t* sig_len ); -#endif /* MBEDTLS_LMS_PRIVATE */ +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ #ifdef __cplusplus } diff --git a/library/lms.c b/library/lms.c index 1c66946d75..6882a483e8 100644 --- a/library/lms.c +++ b/library/lms.c @@ -32,7 +32,7 @@ #include "common.h" -#ifdef MBEDTLS_LMS_C +#if defined(MBEDTLS_LMS_C) #include @@ -402,7 +402,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( 0 ); } -#ifdef MBEDTLS_LMS_PRIVATE +#if defined(MBEDTLS_LMS_PRIVATE) /* Calculate a full merkle tree based on a private key. This function * implements RFC8554 section 5.3, and is used to generate a public key (as the @@ -773,5 +773,5 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, return( 0 ); } -#endif /* MBEDTLS_LMS_PRIVATE */ -#endif /* MBEDTLS_LMS_C */ +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ +#endif /* defined(MBEDTLS_LMS_C) */ diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index dd8a665d58..85e1da71ed 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -24,11 +24,11 @@ int check_lmots_private_key_for_leak(unsigned char * sig) /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:MBEDTLS_LMS_PRIVATE:MBEDTLS_PSA_CRYPTO_C + * depends_on:MBEDTLS_LMS_C * END_DEPENDENCIES */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ void lmots_sign_verify_test ( data_t *msg, data_t *key_id, int leaf_id, data_t *seed ) { @@ -52,7 +52,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ void lmots_sign_verify_null_msg_test ( data_t *key_id, int leaf_id, data_t *seed ) { mbedtls_lmots_public_t pub_ctx; @@ -92,7 +92,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ void lmots_import_export_test ( data_t * pub_key ) { mbedtls_lmots_public_t ctx; @@ -113,7 +113,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ void lmots_reuse_test ( data_t *msg, data_t *key_id, int leaf_id, data_t *seed ) { mbedtls_lmots_private_t ctx; diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 900392334d..3c23b3b4e0 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -4,11 +4,11 @@ /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:MBEDTLS_LMS_PRIVATE:MBEDTLS_PSA_CRYPTO_C + * depends_on:MBEDTLS_LMS_C * END_DEPENDENCIES */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ void lms_sign_verify_test ( data_t *msg, data_t *seed ) { mbedtls_lms_public_t pub_ctx; @@ -44,7 +44,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ void lms_sign_verify_null_msg_test( data_t *seed ) { mbedtls_lms_public_t pub_ctx; @@ -97,7 +97,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ void lms_import_export_test ( data_t * pub_key ) { mbedtls_lms_public_t ctx; From f6ddd51bfd5d16b36f3ab7c470de6f6198787ae5 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 10:49:34 +0100 Subject: [PATCH 038/104] Sanitize LMS and LMOTS macros Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 40ab783151..c3dc3aa7a7 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -41,11 +41,11 @@ /* Currently only defined for SHA256, 32 is the max hash output size */ #define MBEDTLS_LMOTS_N_HASH_LEN_MAX (32u) #define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX (34u) -#define MBEDTLS_LMOTS_N_HASH_LEN(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) +#define MBEDTLS_LMOTS_N_HASH_LEN(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) #define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u) #define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u) #define MBEDTLS_LMOTS_TYPE_LEN (4u) -#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) (type == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) #define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type)) #define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ @@ -55,15 +55,12 @@ #define MBEDTLS_LMS_TYPE_LEN (4) -#define MBEDTLS_LMS_H_TREE_HEIGHT(type) (type == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0) +#define MBEDTLS_LMS_H_TREE_HEIGHT(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0) /* The length of a hash output, Currently only imlemented for SHA256. * Max is 32 bytes. */ -/* The length of a hash output, Currently only imlemented for SHA256. - * Max is 32 bytes. - */ -#define MBEDTLS_LMS_M_NODE_BYTES(type) (type == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0) +#define MBEDTLS_LMS_M_NODE_BYTES(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0) #define MBEDTLS_LMS_M_NODE_BYTES_MAX 32 #define MBEDTLS_LMS_SIG_LEN(type, otstype) (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ From 2ac352a3220abe016a4350a9ca36b50e9ed0a505 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 11:12:27 +0100 Subject: [PATCH 039/104] Make LMS functions args const where required Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 14 ++++++++------ library/lmots.c | 10 +++++----- library/lmots.h | 9 +++++---- library/lms.c | 13 +++++++------ 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index c3dc3aa7a7..5773c793c7 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -341,7 +341,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, mbedtls_lms_algorithm_type_t type, mbedtls_lmots_algorithm_type_t otstype, int (*f_rng)(void *, unsigned char *, size_t), - void* p_rng, unsigned char *seed, + void* p_rng, const unsigned char *seed, size_t seed_size ); /** @@ -363,7 +363,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, * \return A non-zero error code on failure. */ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, - mbedtls_lms_private_t *priv_ctx ); + const mbedtls_lms_private_t *priv_ctx ); /** * \brief This function exports an LMS public key from a @@ -388,8 +388,9 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, * \return \c 0 on success. * \return A non-zero error code on failure. */ -int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key, - size_t key_size, size_t *key_len ); +int mbedtls_lms_export_public_key( const mbedtls_lms_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len ); /** * \brief This function creates a LMS signature, using a @@ -429,8 +430,9 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, unsigned char *key */ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), - void* p_rng, unsigned char *msg, unsigned int msg_size, - unsigned char *sig, size_t sig_size, size_t *sig_len ); + void* p_rng, const unsigned char *msg, + unsigned int msg_size, unsigned char *sig, size_t sig_size, + size_t *sig_len ); #endif /* defined(MBEDTLS_LMS_PRIVATE) */ #ifdef __cplusplus diff --git a/library/lmots.c b/library/lmots.c index 9a6c6be665..055db8fb30 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -521,9 +521,9 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters return( 0 ); } -int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, - size_t msg_size, const unsigned char *sig, - size_t sig_size ) +int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx, + const unsigned char *msg, size_t msg_size, + const unsigned char *sig, size_t sig_size ) { unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -684,7 +684,7 @@ exit: } int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, - mbedtls_lmots_private_t *priv_ctx ) + const mbedtls_lmots_private_t *priv_ctx ) { unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -720,7 +720,7 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, } -int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, +int mbedtls_lmots_export_public_key( const mbedtls_lmots_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len ) { diff --git a/library/lmots.h b/library/lmots.h index 37466b76e8..2f42a592cc 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -185,7 +185,8 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters * \return \c 0 on successful verification. * \return A non-zero error code on failure. */ -int mbedtls_lmots_verify( mbedtls_lmots_public_t *ctx, const unsigned char *msg, +int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx, + const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size ); @@ -208,7 +209,7 @@ void mbedtls_lmots_init_private( mbedtls_lmots_private_t *ctx ); void mbedtls_lmots_free_private( mbedtls_lmots_private_t *ctx ); /** - * \brief This function generates an LMOTS private key, and + * \brief This function calculates an LMOTS private key, and * stores in into an LMOTS context. * * \warning This function is **not intended for use in @@ -252,7 +253,7 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, * \return A non-zero error code on failure. */ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, - mbedtls_lmots_private_t *priv_ctx ); + const mbedtls_lmots_private_t *priv_ctx ); /** @@ -274,7 +275,7 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, * \return \c 0 on success. * \return A non-zero error code on failure. */ -int mbedtls_lmots_export_public_key( mbedtls_lmots_public_t *ctx, +int mbedtls_lmots_export_public_key( const mbedtls_lmots_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len ); /** diff --git a/library/lms.c b/library/lms.c index 6882a483e8..50e6434b78 100644 --- a/library/lms.c +++ b/library/lms.c @@ -418,7 +418,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, * because the merkle tree root is 1-indexed, the 0 * index tree node is never used. */ -static int calculate_merkle_tree( mbedtls_lms_private_t *ctx, +static int calculate_merkle_tree( const mbedtls_lms_private_t *ctx, unsigned char *tree ) { unsigned int priv_key_idx; @@ -533,7 +533,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, mbedtls_lms_algorithm_type_t type, mbedtls_lmots_algorithm_type_t otstype, int (*f_rng)(void *, unsigned char *, size_t), - void* p_rng, unsigned char *seed, + void* p_rng, const unsigned char *seed, size_t seed_size ) { unsigned int idx = 0; @@ -621,7 +621,7 @@ exit: } int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, - mbedtls_lms_private_t *priv_ctx ) + const mbedtls_lms_private_t *priv_ctx ) { unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -662,7 +662,7 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, } -int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, +int mbedtls_lms_export_public_key( const mbedtls_lms_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len ) { @@ -700,8 +700,9 @@ int mbedtls_lms_export_public_key( mbedtls_lms_public_t *ctx, int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), - void* p_rng, unsigned char *msg, unsigned int msg_size, - unsigned char *sig, size_t sig_size, size_t *sig_len ) + void* p_rng, const unsigned char *msg, + unsigned int msg_size, unsigned char *sig, size_t sig_size, + size_t *sig_len ) { uint32_t q_leaf_identifier; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; From be0c2f9183457702df1d33749e8f018e0d546dd9 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 11:27:35 +0100 Subject: [PATCH 040/104] Update LMS local variable allocation To use a default failure value, and to avoid a call to psa_hash_operation_init() Signed-off-by: Raef Coles --- library/lmots.c | 22 ++++++++-------------- library/lms.c | 4 ++-- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 055db8fb30..504da2e5d8 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -152,13 +152,12 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p const unsigned char *C_random_value, unsigned char *out ) { - psa_hash_operation_t op; - psa_status_t status; + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned short checksum; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); if( ret != 0 ) @@ -250,14 +249,12 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN]; unsigned int j_hash_idx_min; unsigned int j_hash_idx_max; - psa_hash_operation_t op; - psa_status_t status; + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - op = psa_hash_operation_init( ); - for ( i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); i_digit_idx++ ) @@ -361,12 +358,11 @@ static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t const unsigned char *y_hashed_digits, unsigned char *pub_key ) { - psa_hash_operation_t op; - psa_status_t status; + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); ret = mbedtls_lms_error_from_psa( status ); if( ret != 0 ) @@ -587,8 +583,8 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, const unsigned char *seed, size_t seed_size ) { - psa_hash_operation_t op; - psa_status_t status; + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned int i_digit_idx; unsigned char i_digit_idx_bytes[2]; @@ -605,8 +601,6 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - op = psa_hash_operation_init( ); - ctx->params.type = type; memcpy( ctx->params.I_key_identifier, diff --git a/library/lms.c b/library/lms.c index 50e6434b78..93aaca1af0 100644 --- a/library/lms.c +++ b/library/lms.c @@ -107,7 +107,7 @@ static int create_merkle_leaf_value( const mbedtls_lms_parameters_t *params, unsigned char *out ) { psa_hash_operation_t op; - psa_status_t status; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char r_node_idx_bytes[4]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -182,7 +182,7 @@ static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params, unsigned char *out ) { psa_hash_operation_t op; - psa_status_t status; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char r_node_idx_bytes[4]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; From 29117d2e4e47842414341f2d0b25cb77a8cc6350 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 11:46:06 +0100 Subject: [PATCH 041/104] Update LMS PSA error conversion Signed-off-by: Raef Coles --- library/lmots.c | 108 ++++++++++++++++-------------------------------- library/lms.c | 47 +++++++-------------- 2 files changed, 51 insertions(+), 104 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 504da2e5d8..54773e12da 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -156,46 +156,38 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned short checksum; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, C_random_value, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type) ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, msg, msg_len ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_finish( &op, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type), &output_hash_len ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; checksum = lmots_checksum_calculate( params, out ); @@ -205,7 +197,7 @@ static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *p exit: psa_hash_abort( &op ); - return( ret ); + return( mbedtls_lms_error_from_psa( status ) ); } /* Hash each element of the string of digits (+ checksum), producing a hash @@ -253,7 +245,6 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; for ( i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); @@ -274,50 +265,43 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, j_hash_idx++ ) { status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; mbedtls_lms_unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, i_digit_idx_bytes ); status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; mbedtls_lms_unsigned_int_to_network_bytes( j_hash_idx, J_HASH_IDX_LEN, j_hash_idx_bytes ); status = psa_hash_update( &op, j_hash_idx_bytes, J_HASH_IDX_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_finish( &op, tmp_hash, sizeof( tmp_hash ), &output_hash_len ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; psa_hash_abort( &op ); @@ -328,15 +312,10 @@ static int hash_digit_array( const mbedtls_lmots_parameters_t *params, } exit: - if( ret != 0 ) - { - psa_hash_abort( &op ); - return( ret ); - } - + psa_hash_abort( &op ); mbedtls_platform_zeroize( tmp_hash, sizeof( tmp_hash ) ); - return ret; + return( mbedtls_lms_error_from_psa( status ) ); } /* Combine the hashes of the digit array into a public key. This is used in @@ -361,46 +340,41 @@ static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, y_hashed_digits, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) * MBEDTLS_LMOTS_N_HASH_LEN(params->type) ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_finish( &op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN(params->type), &output_hash_len ); - ret = mbedtls_lms_error_from_psa( status ); + if( status != PSA_SUCCESS ) exit: psa_hash_abort( &op ); - return( ret ); + + return( mbedtls_lms_error_from_psa( status ) ); } int mbedtls_lms_error_from_psa( psa_status_t status ) @@ -589,7 +563,6 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, unsigned int i_digit_idx; unsigned char i_digit_idx_bytes[2]; unsigned char const_bytes[1]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if( ctx->have_private_key ) { @@ -619,47 +592,40 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, i_digit_idx++ ) { status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; - ret = psa_hash_update( &op, + status = psa_hash_update( &op, ctx->params.I_key_identifier, sizeof( ctx->params.I_key_identifier ) ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, ctx->params.q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( status != PSA_SUCCESS ) goto exit; mbedtls_lms_unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN, i_digit_idx_bytes ); status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, const_bytes, sizeof( const_bytes ) ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, seed, seed_size ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_finish( &op, ctx->private_key[i_digit_idx], MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), &output_hash_len ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret ) + if( status != PSA_SUCCESS ) goto exit; psa_hash_abort( &op ); @@ -668,13 +634,9 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, ctx->have_private_key = 1; exit: - if( ret != 0 ) - { - psa_hash_abort( &op ); - return( ret ); - } + psa_hash_abort( &op ); - return ret; + return ( mbedtls_lms_error_from_psa( status ) ); } int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, diff --git a/library/lms.c b/library/lms.c index 93aaca1af0..ec6ec0c0a9 100644 --- a/library/lms.c +++ b/library/lms.c @@ -110,47 +110,40 @@ static int create_merkle_leaf_value( const mbedtls_lms_parameters_t *params, psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char r_node_idx_bytes[4]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; mbedtls_lms_unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); status = psa_hash_update( &op, r_node_idx_bytes, 4 ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN(params->otstype) ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), &output_hash_len ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; exit: psa_hash_abort( &op ); - return( ret ); + return ( mbedtls_lms_error_from_psa( status ) ); } /* Calculate the value of an internal node of the merkle tree (which is a hash @@ -185,53 +178,45 @@ static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params, psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char r_node_idx_bytes[4]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; op = psa_hash_operation_init( ); status = psa_hash_setup( &op, PSA_ALG_SHA_256 ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; mbedtls_lms_unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes ); status = psa_hash_update( &op, r_node_idx_bytes, 4 ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, D_INTR_CONSTANT_BYTES, D_CONST_LEN ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, left_node, MBEDTLS_LMS_M_NODE_BYTES(params->type) ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; status = psa_hash_update( &op, right_node, MBEDTLS_LMS_M_NODE_BYTES(params->type) ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; - ret = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), + status = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), &output_hash_len ); - ret = mbedtls_lms_error_from_psa( status ); - if( ret != 0 ) + if( status != PSA_SUCCESS ) goto exit; exit: psa_hash_abort( &op ); - return ret; + return( mbedtls_lms_error_from_psa( status ) ); } void mbedtls_lms_init_public( mbedtls_lms_public_t *ctx ) From be3bdd82401cd0e394640843ac9cbb757b04fcff Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 12:04:24 +0100 Subject: [PATCH 042/104] Rename LMS and LMOTS init/free functions To match convention Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 8 +++---- library/lmots.c | 16 ++++++------- library/lmots.h | 8 +++---- library/lms.c | 28 +++++++++++----------- tests/suites/test_suite_lmots.function | 32 +++++++++++++------------- tests/suites/test_suite_lms.function | 24 +++++++++---------- 6 files changed, 58 insertions(+), 58 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 5773c793c7..c68f7271a0 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -242,7 +242,7 @@ typedef struct { * \param ctx The uninitialized LMS context that will then be * initialized. */ -void mbedtls_lms_init_public( mbedtls_lms_public_t *ctx ); +void mbedtls_lms_public_init( mbedtls_lms_public_t *ctx ); /** * \brief This function uninitializes an LMS public context @@ -250,7 +250,7 @@ void mbedtls_lms_init_public( mbedtls_lms_public_t *ctx ); * \param ctx The initialized LMS context that will then be * uninitialized. */ -void mbedtls_lms_free_public( mbedtls_lms_public_t *ctx ); +void mbedtls_lms_public_free( mbedtls_lms_public_t *ctx ); /** * \brief This function imports an LMS public key into a @@ -304,7 +304,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, * * \param ctx The uninitialized LMS private context that will * then be initialized. */ -void mbedtls_lms_init_private( mbedtls_lms_private_t *ctx ); +void mbedtls_lms_private_init( mbedtls_lms_private_t *ctx ); /** * \brief This function uninitializes an LMS private context @@ -312,7 +312,7 @@ void mbedtls_lms_init_private( mbedtls_lms_private_t *ctx ); * \param ctx The initialized LMS private context that will then * be uninitialized. */ -void mbedtls_lms_free_private( mbedtls_lms_private_t *ctx ); +void mbedtls_lms_private_free( mbedtls_lms_private_t *ctx ); /** * \brief This function generates an LMS private key, and diff --git a/library/lmots.c b/library/lmots.c index 54773e12da..059d6c8eff 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -396,14 +396,14 @@ int mbedtls_lms_error_from_psa( psa_status_t status ) } } -void mbedtls_lmots_init_public( mbedtls_lmots_public_t *ctx ) +void mbedtls_lmots_public_init( mbedtls_lmots_public_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_public_t ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; } -void mbedtls_lmots_free_public( mbedtls_lmots_public_t *ctx ) +void mbedtls_lmots_public_free( mbedtls_lmots_public_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_public_t ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; } int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, @@ -540,14 +540,14 @@ int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx, #if defined(MBEDTLS_LMS_PRIVATE) -void mbedtls_lmots_init_private( mbedtls_lmots_private_t *ctx ) +void mbedtls_lmots_private_init( mbedtls_lmots_private_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_private_t ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; } -void mbedtls_lmots_free_private( mbedtls_lmots_private_t *ctx ) +void mbedtls_lmots_private_free( mbedtls_lmots_private_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lmots_private_t ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; } int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, diff --git a/library/lmots.h b/library/lmots.h index 2f42a592cc..05bd96703a 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -96,7 +96,7 @@ int mbedtls_lms_error_from_psa( psa_status_t status ); * \param ctx The uninitialized LMOTS context that will then be * initialized. */ -void mbedtls_lmots_init_public( mbedtls_lmots_public_t *ctx ); +void mbedtls_lmots_public_init( mbedtls_lmots_public_t *ctx ); /** * \brief This function uninitializes a public LMOTS context @@ -104,7 +104,7 @@ void mbedtls_lmots_init_public( mbedtls_lmots_public_t *ctx ); * \param ctx The initialized LMOTS context that will then be * uninitialized. */ -void mbedtls_lmots_free_public( mbedtls_lmots_public_t *ctx ); +void mbedtls_lmots_public_free( mbedtls_lmots_public_t *ctx ); /** * \brief This function imports an LMOTS public key into a @@ -198,7 +198,7 @@ int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx, * \param ctx The uninitialized LMOTS context that will then be * initialized. */ -void mbedtls_lmots_init_private( mbedtls_lmots_private_t *ctx ); +void mbedtls_lmots_private_init( mbedtls_lmots_private_t *ctx ); /** * \brief This function uninitializes a private LMOTS context @@ -206,7 +206,7 @@ void mbedtls_lmots_init_private( mbedtls_lmots_private_t *ctx ); * \param ctx The initialized LMOTS context that will then be * uninitialized. */ -void mbedtls_lmots_free_private( mbedtls_lmots_private_t *ctx ); +void mbedtls_lmots_private_free( mbedtls_lmots_private_t *ctx ); /** * \brief This function calculates an LMOTS private key, and diff --git a/library/lms.c b/library/lms.c index ec6ec0c0a9..e17d9be102 100644 --- a/library/lms.c +++ b/library/lms.c @@ -219,14 +219,14 @@ exit: return( mbedtls_lms_error_from_psa( status ) ); } -void mbedtls_lms_init_public( mbedtls_lms_public_t *ctx ) +void mbedtls_lms_public_init( mbedtls_lms_public_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; } -void mbedtls_lms_free_public( mbedtls_lms_public_t *ctx ) +void mbedtls_lms_public_free( mbedtls_lms_public_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_public_t ) ); + mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ); } int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, @@ -489,12 +489,12 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx, return( 0 ); } -void mbedtls_lms_init_private( mbedtls_lms_private_t *ctx ) +void mbedtls_lms_private_init( mbedtls_lms_private_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_private_t ) ) ; + mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; } -void mbedtls_lms_free_private( mbedtls_lms_private_t *ctx ) +void mbedtls_lms_private_free( mbedtls_lms_private_t *ctx ) { unsigned int idx; @@ -502,15 +502,15 @@ void mbedtls_lms_free_private( mbedtls_lms_private_t *ctx ) { for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) { - mbedtls_lmots_free_private( &ctx->ots_private_keys[idx] ); - mbedtls_lmots_free_public( &ctx->ots_public_keys[idx] ); + mbedtls_lmots_private_free( &ctx->ots_private_keys[idx] ); + mbedtls_lmots_public_free( &ctx->ots_public_keys[idx] ); } mbedtls_free( ctx->ots_private_keys ); mbedtls_free( ctx->ots_public_keys ); } - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_private_t ) ); + mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ); } @@ -565,8 +565,8 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) { - mbedtls_lmots_init_private( &ctx->ots_private_keys[idx] ); - mbedtls_lmots_init_public( &ctx->ots_public_keys[idx] ); + mbedtls_lmots_private_init( &ctx->ots_private_keys[idx] ); + mbedtls_lmots_public_init( &ctx->ots_public_keys[idx] ); } @@ -593,8 +593,8 @@ exit: { for ( free_idx = 0; free_idx < idx; free_idx++ ) { - mbedtls_lmots_free_private( &ctx->ots_private_keys[free_idx] ); - mbedtls_lmots_free_public( &ctx->ots_public_keys[free_idx] ); + mbedtls_lmots_private_free( &ctx->ots_private_keys[free_idx] ); + mbedtls_lmots_public_free( &ctx->ots_public_keys[free_idx] ); } mbedtls_free( ctx->ots_private_keys ); diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 85e1da71ed..de1cf2c683 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -36,8 +36,8 @@ void lmots_sign_verify_test ( data_t *msg, data_t *key_id, int leaf_id, mbedtls_lmots_private_t priv_ctx; unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; - mbedtls_lmots_init_public( &pub_ctx ); - mbedtls_lmots_init_private( &priv_ctx ); + mbedtls_lmots_public_init( &pub_ctx ); + mbedtls_lmots_private_init( &priv_ctx ); TEST_ASSERT( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, key_id->x, leaf_id, seed->x, seed->len ) == 0 ); @@ -47,8 +47,8 @@ void lmots_sign_verify_test ( data_t *msg, data_t *key_id, int leaf_id, TEST_ASSERT( mbedtls_lmots_verify(&pub_ctx, msg->x, msg->len, sig, sizeof(sig)) == 0 ); exit: - mbedtls_lmots_free_public( &pub_ctx ); - mbedtls_lmots_free_private( &priv_ctx ); + mbedtls_lmots_public_free( &pub_ctx ); + mbedtls_lmots_private_free( &priv_ctx ); } /* END_CASE */ @@ -59,8 +59,8 @@ void lmots_sign_verify_null_msg_test ( data_t *key_id, int leaf_id, data_t *seed mbedtls_lmots_private_t priv_ctx; unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; - mbedtls_lmots_init_public( &pub_ctx ); - mbedtls_lmots_init_private( &priv_ctx ); + mbedtls_lmots_public_init( &pub_ctx ); + mbedtls_lmots_private_init( &priv_ctx ); TEST_ASSERT( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, key_id->x, leaf_id, seed->x, seed->len ) == 0 ); @@ -70,8 +70,8 @@ void lmots_sign_verify_null_msg_test ( data_t *key_id, int leaf_id, data_t *seed TEST_ASSERT( mbedtls_lmots_verify(&pub_ctx, NULL, 0, sig, sizeof(sig)) == 0 ); exit: - mbedtls_lmots_free_public( &pub_ctx ); - mbedtls_lmots_free_private( &priv_ctx ); + mbedtls_lmots_public_free( &pub_ctx ); + mbedtls_lmots_private_free( &priv_ctx ); } /* END_CASE */ @@ -81,14 +81,14 @@ void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, { mbedtls_lmots_public_t ctx; - mbedtls_lmots_init_public( &ctx ); + mbedtls_lmots_public_init( &ctx ); mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ); TEST_ASSERT(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ) == expected_rc ); exit: - mbedtls_lmots_free_public( &ctx ); + mbedtls_lmots_public_free( &ctx ); } /* END_CASE */ @@ -99,7 +99,7 @@ void lmots_import_export_test ( data_t * pub_key ) uint8_t exported_pub_key[MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; size_t exported_pub_key_len; - mbedtls_lmots_init_public( &ctx ); + mbedtls_lmots_public_init( &ctx ); TEST_ASSERT( mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ) == 0 ); TEST_ASSERT( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, sizeof( exported_pub_key ), @@ -109,7 +109,7 @@ void lmots_import_export_test ( data_t * pub_key ) exported_pub_key, exported_pub_key_len ); exit: - mbedtls_lmots_free_public( &ctx ); + mbedtls_lmots_public_free( &ctx ); } /* END_CASE */ @@ -119,7 +119,7 @@ void lmots_reuse_test ( data_t *msg, data_t *key_id, int leaf_id, data_t *seed ) mbedtls_lmots_private_t ctx; unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; - mbedtls_lmots_init_private( &ctx ); + mbedtls_lmots_private_init( &ctx ); TEST_ASSERT( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, key_id->x, leaf_id, seed->x, seed->len ) == 0 ); @@ -133,7 +133,7 @@ void lmots_reuse_test ( data_t *msg, data_t *key_id, int leaf_id, data_t *seed ) msg->x, msg->len, sig, sizeof( sig ), NULL ) != 0 ); exit: - mbedtls_lmots_free_private( &ctx ); + mbedtls_lmots_private_free( &ctx ); } /* END_CASE */ @@ -149,7 +149,7 @@ void lmots_signature_leak_test ( data_t *msg, data_t *key_id, int leaf_id, /* Fill with recognisable pattern */ memset( sig, 0x7E, sizeof( sig ) ); - mbedtls_lmots_init_private( &ctx ); + mbedtls_lmots_private_init( &ctx ); TEST_ASSERT( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, key_id->x, leaf_id, seed->x, seed->len ) == 0 ); @@ -157,7 +157,7 @@ void lmots_signature_leak_test ( data_t *msg, data_t *key_id, int leaf_id, msg->x, msg->len, sig, sizeof( sig ), NULL ) == 0 ); exit: - mbedtls_lmots_free_private( &ctx ); + mbedtls_lmots_private_free( &ctx ); mbedtls_lmots_sign_private_key_invalidated_hook = NULL; } /* END_CASE */ diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 3c23b3b4e0..425e994de4 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -16,8 +16,8 @@ void lms_sign_verify_test ( data_t *msg, data_t *seed ) unsigned char sig[MBEDTLS_LMS_SIG_LEN(MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8)]; int rc; - mbedtls_lms_init_public( &pub_ctx ); - mbedtls_lms_init_private( &priv_ctx ); + mbedtls_lms_public_init( &pub_ctx ); + mbedtls_lms_private_init( &priv_ctx ); /* Allocation failure isn't a test failure, since it likely just means * there's not enough memory to run the test. @@ -39,8 +39,8 @@ void lms_sign_verify_test ( data_t *msg, data_t *seed ) sizeof( sig ) ) == 0 ); exit: - mbedtls_lms_free_public( &pub_ctx ); - mbedtls_lms_free_private( &priv_ctx ); + mbedtls_lms_public_free( &pub_ctx ); + mbedtls_lms_private_free( &priv_ctx ); } /* END_CASE */ @@ -52,8 +52,8 @@ void lms_sign_verify_null_msg_test( data_t *seed ) unsigned char sig[MBEDTLS_LMS_SIG_LEN(MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8)]; int rc; - mbedtls_lms_init_public( &pub_ctx ); - mbedtls_lms_init_private( &priv_ctx ); + mbedtls_lms_public_init( &pub_ctx ); + mbedtls_lms_private_init( &priv_ctx ); /* Allocation failure isn't a test failure, since it likely just means * there's not enough memory to run the test. @@ -75,8 +75,8 @@ void lms_sign_verify_null_msg_test( data_t *seed ) sizeof( sig ) ) == 0 ); exit: - mbedtls_lms_free_public( &pub_ctx ); - mbedtls_lms_free_private( &priv_ctx ); + mbedtls_lms_public_free( &pub_ctx ); + mbedtls_lms_private_free( &priv_ctx ); } /* END_CASE */ @@ -86,14 +86,14 @@ void lms_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, { mbedtls_lms_public_t ctx; - mbedtls_lms_init_public( &ctx); + mbedtls_lms_public_init( &ctx); mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ); TEST_ASSERT( mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ) == expected_rc ); exit: - mbedtls_lms_free_public( &ctx ); + mbedtls_lms_public_free( &ctx ); } /* END_CASE */ @@ -103,7 +103,7 @@ void lms_import_export_test ( data_t * pub_key ) mbedtls_lms_public_t ctx; uint8_t exported_pub_key[MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10)]; - mbedtls_lms_init_public(&ctx); + mbedtls_lms_public_init(&ctx); TEST_ASSERT( mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ) == 0 ); TEST_ASSERT( mbedtls_lms_export_public_key( &ctx, exported_pub_key, sizeof(exported_pub_key), NULL ) == 0 ); @@ -112,7 +112,7 @@ void lms_import_export_test ( data_t * pub_key ) exported_pub_key, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10) ); exit: - mbedtls_lms_free_public( &ctx ); + mbedtls_lms_public_free( &ctx ); } /* END_CASE */ From dc8fb79e09d729250414a124ff8a6c0d61b3d462 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 13:27:54 +0100 Subject: [PATCH 043/104] Simplify LMS private key generation error handling Signed-off-by: Raef Coles --- library/lms.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/library/lms.c b/library/lms.c index e17d9be102..06bae9dffd 100644 --- a/library/lms.c +++ b/library/lms.c @@ -506,8 +506,11 @@ void mbedtls_lms_private_free( mbedtls_lms_private_t *ctx ) mbedtls_lmots_public_free( &ctx->ots_public_keys[idx] ); } - mbedtls_free( ctx->ots_private_keys ); - mbedtls_free( ctx->ots_public_keys ); + if( ctx->ots_private_keys != NULL ) + mbedtls_free( ctx->ots_private_keys ); + + if( ctx->ots_public_keys != NULL ) + mbedtls_free( ctx->ots_public_keys ); } mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ); @@ -522,7 +525,6 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, size_t seed_size ) { unsigned int idx = 0; - unsigned int free_idx = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if( type != MBEDTLS_LMS_SHA256_M32_H10 ) @@ -548,7 +550,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, MBEDTLS_LMOTS_I_KEY_ID_LEN ); ctx->ots_private_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), - sizeof( mbedtls_lmots_private_t ) ); + sizeof( *ctx->ots_private_keys ) ); if( ctx->ots_private_keys == NULL ) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; @@ -556,13 +558,25 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, } ctx->ots_public_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), - sizeof( mbedtls_lmots_public_t ) ); + sizeof( *ctx->ots_public_keys ) ); if( ctx->ots_public_keys == NULL ) { + /* Free just the ots private keys (since they've been allocated at this + * point) so that we can pass the context to lms_private_free (which + * will not try to free the private keys since have_private_key is not + * set. + */ + mbedtls_free(ctx->ots_private_keys); + ctx->ots_private_keys = NULL; ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; } + /* Now that all the allocation has succeeded we set have_private_key, since + * that causes lms_private_free to free the ots keys. + */ + ctx->have_private_key = 1; + for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) { mbedtls_lmots_private_init( &ctx->ots_private_keys[idx] ); @@ -586,23 +600,14 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, } ctx->q_next_usable_key = 0; - ctx->have_private_key = 1; exit: if( ret != 0 ) { - for ( free_idx = 0; free_idx < idx; free_idx++ ) - { - mbedtls_lmots_private_free( &ctx->ots_private_keys[free_idx] ); - mbedtls_lmots_public_free( &ctx->ots_public_keys[free_idx] ); - } - - mbedtls_free( ctx->ots_private_keys ); - mbedtls_free( ctx->ots_public_keys ); - return( ret ); + mbedtls_lms_private_free(ctx); } - return( 0 ); + return( ret ); } int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, From f36874a53519b03d78690872061e31c4ed860892 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 13:39:22 +0100 Subject: [PATCH 044/104] Fix error type of lms_import_public_key Was returning an incorrect error when bad public key sizes were input Signed-off-by: Raef Coles --- library/lms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/lms.c b/library/lms.c index 06bae9dffd..a8411797d2 100644 --- a/library/lms.c +++ b/library/lms.c @@ -235,9 +235,9 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, mbedtls_lms_algorithm_type_t type; mbedtls_lmots_algorithm_type_t otstype; - if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) + if( key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) { - return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } type = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, From 02cf8234b4d005ecc858bb5f913272b6f70b1bb8 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 13:52:47 +0100 Subject: [PATCH 045/104] Fix ots sig length check in LMS validate function Signed-off-by: Raef Coles --- library/lms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lms.c b/library/lms.c index a8411797d2..1e0f319109 100644 --- a/library/lms.c +++ b/library/lms.c @@ -733,7 +733,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, ret = mbedtls_lmots_sign( &ctx->ots_private_keys[q_leaf_identifier], f_rng, p_rng, msg, msg_size, sig + SIG_OTS_SIG_OFFSET, - MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype), + MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) - SIG_OTS_SIG_OFFSET, NULL ); if( ret != 0 ) { From 3f6cdd7aab90fa6b4830349916d994a05d6f8f79 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 14:07:59 +0100 Subject: [PATCH 046/104] Fix LMS not checking RNG function return value Signed-off-by: Raef Coles --- library/lms.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/lms.c b/library/lms.c index 1e0f319109..a4235addc2 100644 --- a/library/lms.c +++ b/library/lms.c @@ -545,9 +545,13 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, ctx->params.type = type; ctx->params.otstype = otstype; - f_rng( p_rng, - ctx->params.I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN ); + ret = f_rng( p_rng, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + if( ret != 0 ) + { + goto exit; + } ctx->ots_private_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof( *ctx->ots_private_keys ) ); From e89488debf6d3a708c9d65eb4863251bd0e5c639 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 16:06:35 +0100 Subject: [PATCH 047/104] Fix bug in LMS public key loading To avoid using the type before it is parsed from the signature Signed-off-by: Raef Coles --- library/lmots.c | 5 +++++ library/lms.c | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 059d6c8eff..9168ef189d 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -409,6 +409,11 @@ void mbedtls_lmots_public_free( mbedtls_lmots_public_t *ctx ) int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, const unsigned char *key, size_t key_len ) { + if( key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + ctx->params.type = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); diff --git a/library/lms.c b/library/lms.c index a4235addc2..fba5d88480 100644 --- a/library/lms.c +++ b/library/lms.c @@ -235,11 +235,6 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, mbedtls_lms_algorithm_type_t type; mbedtls_lmots_algorithm_type_t otstype; - if( key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - type = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, key + PUBLIC_KEY_TYPE_OFFSET ); if( type != MBEDTLS_LMS_SHA256_M32_H10 ) @@ -248,6 +243,11 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, } ctx->params.type = type; + if( key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + otstype = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, key + PUBLIC_KEY_OTSTYPE_OFFSET ); if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 ) From 370cc436300fde6eab6789233ccaf693e13f5e85 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Fri, 7 Oct 2022 16:07:33 +0100 Subject: [PATCH 048/104] Make LMS public key export part of public key api Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 54 +++++++++---------- library/lmots.c | 75 +++++++++++++------------- library/lmots.h | 46 ++++++++-------- library/lms.c | 71 ++++++++++++------------ tests/suites/test_suite_lmots.function | 2 +- tests/suites/test_suite_lms.function | 2 +- 6 files changed, 124 insertions(+), 126 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index c68f7271a0..15a1a1b281 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -274,6 +274,33 @@ void mbedtls_lms_public_free( mbedtls_lms_public_t *ctx ); int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, const unsigned char *key, size_t key_size ); +/** + * \brief This function exports an LMS public key from a + * LMS public context that already contains a public + * key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMS public context that contains + * the public key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size. + * \param key_size The size of the key buffer. + * \param key_len If not NULL, will be written with the size of the + * key. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_export_public_key( const mbedtls_lms_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len ); + /** * \brief This function verifies a LMS signature, using a * LMS context that contains a public key. @@ -365,33 +392,6 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, const mbedtls_lms_private_t *priv_ctx ); -/** - * \brief This function exports an LMS public key from a - * LMS public context that already contains a public - * key. - * - * \note Before this function is called, the context must - * have been initialized and the context must contain - * a public key. - * - * \note See IETF RFC8554 for details of the encoding of - * this public key. - * - * \param ctx The initialized LMS public context that contains - * the public key. - * \param key The buffer into which the key will be output. Must - * be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size. - * \param key_size The size of the key buffer. - * \param key_len If not NULL, will be written with the size of the - * key. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lms_export_public_key( const mbedtls_lms_public_t *ctx, - unsigned char *key, size_t key_size, - size_t *key_len ); - /** * \brief This function creates a LMS signature, using a * LMS context that contains unused private keys. diff --git a/library/lmots.c b/library/lmots.c index 9168ef189d..bb4326e374 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -440,6 +440,43 @@ int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, return( 0 ); } +int mbedtls_lmots_export_public_key( const mbedtls_lmots_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len ) +{ + if( key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) ) + { + return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + } + + if( ! ctx->have_public_key ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type, + MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); + + memcpy( key + PUBLIC_KEY_I_KEY_ID_OFFSET, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + + memcpy( key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, + ctx->params.q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); + + memcpy( key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); + + if( key_len != NULL ) + { + *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type); + } + + return( 0 ); +} + int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters_t *params, const unsigned char *msg, size_t msg_size, @@ -680,44 +717,6 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, return( ret ); } - -int mbedtls_lmots_export_public_key( const mbedtls_lmots_public_t *ctx, - unsigned char *key, size_t key_size, - size_t *key_len ) -{ - if( key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) ) - { - return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); - } - - if( ! ctx->have_public_key ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type, - MBEDTLS_LMOTS_TYPE_LEN, - key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); - - memcpy( key + PUBLIC_KEY_I_KEY_ID_OFFSET, - ctx->params.I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN ); - - memcpy( key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, - ctx->params.q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN ); - - memcpy( key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, - MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) ); - - if( key_len != NULL ) - { - *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type); - } - - return( 0 ); -} - int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *msg, size_t msg_size, diff --git a/library/lmots.h b/library/lmots.h index 05bd96703a..2c65714800 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -127,6 +127,29 @@ void mbedtls_lmots_public_free( mbedtls_lmots_public_t *ctx ); int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, const unsigned char *key, size_t key_size ); +/** + * \brief This function exports an LMOTS public key from a + * LMOTS context that already contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMOTS context that contains the + * publc key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_export_public_key( const mbedtls_lmots_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len ); + /** * \brief This function creates a candidate public key from * an LMOTS signature. This can then be compared to @@ -255,29 +278,6 @@ int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx, int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, const mbedtls_lmots_private_t *priv_ctx ); - -/** - * \brief This function exports an LMOTS public key from a - * LMOTS context that already contains a public key. - * - * \note Before this function is called, the context must - * have been initialized and the context must contain - * a public key. - * - * \note See IETF RFC8554 for details of the encoding of - * this public key. - * - * \param ctx The initialized LMOTS context that contains the - * publc key. - * \param key The buffer into which the key will be output. Must - * be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size. - * - * \return \c 0 on success. - * \return A non-zero error code on failure. - */ -int mbedtls_lmots_export_public_key( const mbedtls_lmots_public_t *ctx, - unsigned char *key, size_t key_size, - size_t *key_len ); /** * \brief This function creates a LMOTS signature, using a * LMOTS context that contains a private key. diff --git a/library/lms.c b/library/lms.c index fba5d88480..e7ae5081c2 100644 --- a/library/lms.c +++ b/library/lms.c @@ -267,6 +267,41 @@ int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx, return( 0 ); } +int mbedtls_lms_export_public_key( const mbedtls_lms_public_t *ctx, + unsigned char *key, + size_t key_size, size_t *key_len ) +{ + if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) + { + return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + } + + if( ! ctx->have_public_key ) + { + return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); + } + + mbedtls_lms_unsigned_int_to_network_bytes( + ctx->params.type, + MBEDTLS_LMS_TYPE_LEN, key + PUBLIC_KEY_TYPE_OFFSET ); + mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.otstype, + MBEDTLS_LMOTS_TYPE_LEN, + key + PUBLIC_KEY_OTSTYPE_OFFSET ); + memcpy( key + PUBLIC_KEY_I_KEY_ID_OFFSET, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN ); + memcpy( key +PUBLIC_KEY_ROOT_NODE_OFFSET, + ctx->T_1_pub_key, + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) ); + + if( key_len != NULL ) + { + *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type); + } + + return( 0 ); +} + int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size ) @@ -656,42 +691,6 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, } -int mbedtls_lms_export_public_key( const mbedtls_lms_public_t *ctx, - unsigned char *key, - size_t key_size, size_t *key_len ) -{ - if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) ) - { - return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); - } - - if( ! ctx->have_public_key ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - - mbedtls_lms_unsigned_int_to_network_bytes( - ctx->params.type, - MBEDTLS_LMS_TYPE_LEN, key + PUBLIC_KEY_TYPE_OFFSET ); - mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.otstype, - MBEDTLS_LMOTS_TYPE_LEN, - key + PUBLIC_KEY_OTSTYPE_OFFSET ); - memcpy( key + PUBLIC_KEY_I_KEY_ID_OFFSET, - ctx->params.I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN ); - memcpy( key +PUBLIC_KEY_ROOT_NODE_OFFSET, - ctx->T_1_pub_key, - MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) ); - - if( key_len != NULL ) - { - *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type); - } - - return( 0 ); -} - - int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void* p_rng, const unsigned char *msg, diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index de1cf2c683..0d2aece443 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -92,7 +92,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ +/* BEGIN_CASE */ void lmots_import_export_test ( data_t * pub_key ) { mbedtls_lmots_public_t ctx; diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 425e994de4..e4c4b911b4 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -97,7 +97,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ +/* BEGIN_CASE */ void lms_import_export_test ( data_t * pub_key ) { mbedtls_lms_public_t ctx; From e34e3c0e599ef9551e675042b797562f3b43269c Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 11:11:30 +0100 Subject: [PATCH 049/104] Remove unneeded cast in LMS calloc Signed-off-by: Raef Coles --- library/lms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/lms.c b/library/lms.c index e7ae5081c2..adba195826 100644 --- a/library/lms.c +++ b/library/lms.c @@ -588,7 +588,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, goto exit; } - ctx->ots_private_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + ctx->ots_private_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof( *ctx->ots_private_keys ) ); if( ctx->ots_private_keys == NULL ) { @@ -596,7 +596,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, goto exit; } - ctx->ots_public_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + ctx->ots_public_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof( *ctx->ots_public_keys ) ); if( ctx->ots_public_keys == NULL ) { From 1fb2f32ef5485962e0334dbbb397b3114a18dba6 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 11:23:07 +0100 Subject: [PATCH 050/104] Check LMS offsets are sane at runtime Signed-off-by: Raef Coles --- library/lms.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/lms.c b/library/lms.c index adba195826..296adceda0 100644 --- a/library/lms.c +++ b/library/lms.c @@ -733,6 +733,12 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, */ ctx->q_next_usable_key += 1; + if ( MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) + < SIG_OTS_SIG_OFFSET ) + { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + ret = mbedtls_lmots_sign( &ctx->ots_private_keys[q_leaf_identifier], f_rng, p_rng, msg, msg_size, sig + SIG_OTS_SIG_OFFSET, From d48f7e90bb30d605525a9d2c508012acd5cf7b64 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 13:10:07 +0100 Subject: [PATCH 051/104] Allocate LMS C_RANDOM_VALUE as hash size Signed-off-by: Raef Coles --- library/lmots.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index bb4326e374..163958795a 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -60,9 +60,6 @@ #define J_HASH_IDX_LEN (1) #define D_CONST_LEN (2) -/* Currently only defined for SHA256, 32 is the max hash output size */ -#define C_RANDOM_VALUE_LEN_MAX (MBEDTLS_LMOTS_N_HASH_LEN_MAX) - #define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) #define D_CONST_LEN (2) @@ -731,7 +728,7 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, * key. */ unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - unsigned char tmp_c_random[C_RANDOM_VALUE_LEN_MAX]; + unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if( msg == NULL && msg_size != 0 ) From 75b4c7790e50752a8bccf4e4521cff6ad058672d Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 13:58:28 +0100 Subject: [PATCH 052/104] Fix LMS internal function documentation Signed-off-by: Raef Coles --- library/lms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lms.c b/library/lms.c index 296adceda0..321e51abe1 100644 --- a/library/lms.c +++ b/library/lms.c @@ -491,7 +491,7 @@ static int calculate_merkle_tree( const mbedtls_lms_private_t *ctx, * * leaf_node_id Which leaf node to calculate the path from. * - * tree The output path, which is H hash outputs. + * path The output path, which is H hash outputs. */ static int get_merkle_path( mbedtls_lms_private_t *ctx, unsigned int leaf_node_id, From f6cb5a4826bcb496bfdf6fd3af7d0e52383ab131 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 14:15:53 +0100 Subject: [PATCH 053/104] Fix LMS return statements having incorrect style Signed-off-by: Raef Coles --- library/lmots.c | 4 ++-- library/lms.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 163958795a..1e27024779 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -92,7 +92,7 @@ unsigned int mbedtls_lms_network_bytes_to_unsigned_int( size_t len, val |= ( ( unsigned int )bytes[idx] ) << (8 * ( len - 1 - idx ) ); } - return val; + return ( val ); } /* Calculate the checksum digits that are appended to the end of the LMOTS digit @@ -117,7 +117,7 @@ static unsigned short lmots_checksum_calculate( const mbedtls_lmots_parameters_t sum += DIGIT_MAX_VALUE - digest[idx]; } - return sum; + return ( sum ); } /* Create the string of digest digits (in the base determined by the Winternitz diff --git a/library/lms.c b/library/lms.c index 321e51abe1..b460353a67 100644 --- a/library/lms.c +++ b/library/lms.c @@ -736,7 +736,7 @@ int mbedtls_lms_sign( mbedtls_lms_private_t *ctx, if ( MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) < SIG_OTS_SIG_OFFSET ) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + return ( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } ret = mbedtls_lmots_sign( &ctx->ots_private_keys[q_leaf_identifier], From 9b0daf60fb64bbe33433def23d730ba4a57b901f Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 14:25:39 +0100 Subject: [PATCH 054/104] Improve LMS private function warning Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 6 ++++-- library/lmots.h | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 15a1a1b281..850bb6a008 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -347,7 +347,8 @@ void mbedtls_lms_private_free( mbedtls_lms_private_t *ctx ); * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with - * handling stateful keys. + * handling stateful keys. The API for this function + * may change considerably in future versions. * * \note The seed must have at least 256 bits of entropy. * @@ -398,7 +399,8 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with - * handling stateful keys. + * handling stateful keys. The API for this function + * may change considerably in future versions. * * \note Before this function is called, the context must * have been initialized and must contain a private diff --git a/library/lmots.h b/library/lmots.h index 2c65714800..39e8699252 100644 --- a/library/lmots.h +++ b/library/lmots.h @@ -190,7 +190,8 @@ int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with - * handling stateful keys. + * handling stateful keys. The API for this function + * may change considerably in future versions. * * \note Before this function is called, the context must * have been initialized and must contain a public key @@ -237,7 +238,8 @@ void mbedtls_lmots_private_free( mbedtls_lmots_private_t *ctx ); * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with - * handling stateful keys. + * handling stateful keys. The API for this function + * may change considerably in future versions. * * \note The seed must have at least 256 bits of entropy. * From fbd60ec77540c8fdef3ea7cbaa7758e564b0d563 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 15:09:33 +0100 Subject: [PATCH 055/104] Change LMS and LMOTS init functions to use memset Instead of zeroize Signed-off-by: Raef Coles --- library/lmots.c | 4 ++-- library/lms.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 1e27024779..8ffadb89e0 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -395,7 +395,7 @@ int mbedtls_lms_error_from_psa( psa_status_t status ) void mbedtls_lmots_public_init( mbedtls_lmots_public_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; + memset( ctx, 0, sizeof( *ctx ) ) ; } void mbedtls_lmots_public_free( mbedtls_lmots_public_t *ctx ) @@ -581,7 +581,7 @@ int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx, void mbedtls_lmots_private_init( mbedtls_lmots_private_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; + memset( ctx, 0, sizeof( *ctx ) ) ; } void mbedtls_lmots_private_free( mbedtls_lmots_private_t *ctx ) diff --git a/library/lms.c b/library/lms.c index b460353a67..c115dac9d4 100644 --- a/library/lms.c +++ b/library/lms.c @@ -221,7 +221,7 @@ exit: void mbedtls_lms_public_init( mbedtls_lms_public_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; + memset( ctx, 0, sizeof( *ctx ) ) ; } void mbedtls_lms_public_free( mbedtls_lms_public_t *ctx ) @@ -526,7 +526,7 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx, void mbedtls_lms_private_init( mbedtls_lms_private_t *ctx ) { - mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ; + memset( ctx, 0, sizeof( *ctx ) ) ; } void mbedtls_lms_private_free( mbedtls_lms_private_t *ctx ) From faf59babe846b4148af6331fcefe826a78e2dcfd Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 15:40:56 +0100 Subject: [PATCH 056/104] Make LMS verification return VERIFY_FAILED more To align with PSA error code rules on when VERIFY_FAILED is returned vs INVALID_ARGUMENT Signed-off-by: Raef Coles --- library/lmots.c | 2 +- library/lms.c | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index 8ffadb89e0..97325aa8e1 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -565,7 +565,7 @@ int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx, NULL ); if( ret ) { - return( ret ); + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } if( memcmp( &Kc_public_key_candidate, ctx->public_key, diff --git a/library/lms.c b/library/lms.c index c115dac9d4..de38c02837 100644 --- a/library/lms.c +++ b/library/lms.c @@ -322,11 +322,6 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } - if( sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) ) - { - return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); - } - if( ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10 ) { @@ -339,6 +334,16 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } + if( sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + + if( sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, sig + SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) @@ -346,6 +351,11 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } + if( sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN, sig + SIG_TYPE_OFFSET(ctx->params.otstype)) != MBEDTLS_LMS_SHA256_M32_H10 ) @@ -376,7 +386,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, sizeof( Kc_candidate_ots_pub_key ), NULL ); if( ret != 0 ) { - return( ret ); + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); } create_merkle_leaf_value( From 285d44b180e74166b70250ce39a7a35a03ccb188 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 15:44:17 +0100 Subject: [PATCH 057/104] Capitalize "Merkle" in LMS and LMOTS code As it is a proper noun Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 8 ++++---- library/lms.c | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 850bb6a008..8bf395bcd3 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -181,7 +181,7 @@ typedef struct { /** LMS public context structure. * - *A LMS public key is the hash output that is the root of the merkle tree, and + *A LMS public key is the hash output that is the root of the Merkle tree, and * the applicable parameter set * * The context must be initialized before it is used. A public key must either @@ -200,7 +200,7 @@ typedef struct { typedef struct { mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES_MAX]; /*!< The public key, in - the form of the merkle tree root node. */ + the form of the Merkle tree root node. */ unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. Boolean values only. */ } mbedtls_lms_public_t; @@ -228,9 +228,9 @@ typedef struct { uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not been used. */ mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key - for each leaf node in the merkle tree. */ + for each leaf node in the Merkle tree. */ mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to - build the merkle tree. */ + build the Merkle tree. */ unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lms_private_t; diff --git a/library/lms.c b/library/lms.c index de38c02837..f30f349ad5 100644 --- a/library/lms.c +++ b/library/lms.c @@ -83,7 +83,7 @@ static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = {0x82, 0x82}; static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = {0x83, 0x83}; -/* Calculate the value of a leaf node of the merkle tree (which is a hash of a +/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a * public key and some other parameters like the leaf index). This function * implements RFC8554 section 5.3, in the case where r >= 2^h. * @@ -95,8 +95,8 @@ static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = {0x83, 0x83}; * corresponds to the index of this leaf node. This * is a hash output. * - * r_node_idx The index of this node in the merkle tree. Note - * that the root node of the merkle tree is + * r_node_idx The index of this node in the Merkle tree. Note + * that the root node of the Merkle tree is * 1-indexed. * * out The output node value, which is a hash output. @@ -146,7 +146,7 @@ exit: return ( mbedtls_lms_error_from_psa( status ) ); } -/* Calculate the value of an internal node of the merkle tree (which is a hash +/* Calculate the value of an internal node of the Merkle tree (which is a hash * of a public key and some other parameters like the node index). This function * implements RFC8554 section 5.3, in the case where r < 2^h. * @@ -156,14 +156,14 @@ exit: * * left_node The value of the child of this node which is on * the left-hand side. As with all nodes on the - * merkle tree, this is a hash output. + * Merkle tree, this is a hash output. * * right_node The value of the child of this node which is on * the right-hand side. As with all nodes on the - * merkle tree, this is a hash output. + * Merkle tree, this is a hash output. * - * r_node_idx The index of this node in the merkle tree. Note - * that the root node of the merkle tree is + * r_node_idx The index of this node in the Merkle tree. Note + * that the root node of the Merkle tree is * 1-indexed. * * out The output node value, which is a hash output. @@ -434,9 +434,9 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, #if defined(MBEDTLS_LMS_PRIVATE) -/* Calculate a full merkle tree based on a private key. This function +/* Calculate a full Merkle tree based on a private key. This function * implements RFC8554 section 5.3, and is used to generate a public key (as the - * public key is the root node of the merkle tree). + * public key is the root node of the Merkle tree). * * ctx The LMS private context, containing a parameter * set and private key material consisting of both @@ -445,7 +445,7 @@ int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx, * tree The output tree, which is 2^(H + 1) hash outputs. * In the case of H=10 we have 2048 tree nodes (of * which 1024 of them are leaf nodes). Note that - * because the merkle tree root is 1-indexed, the 0 + * because the Merkle tree root is 1-indexed, the 0 * index tree node is never used. */ static int calculate_merkle_tree( const mbedtls_lms_private_t *ctx, @@ -491,9 +491,9 @@ static int calculate_merkle_tree( const mbedtls_lms_private_t *ctx, return( 0 ); } -/* Calculate a path from a leaf node of the merkle tree to the root of the tree, +/* Calculate a path from a leaf node of the Merkle tree to the root of the tree, * and return the full path. This function implements RFC8554 section 5.4.1, as - * the merkle path is the main component of an LMS signature. + * the Merkle path is the main component of an LMS signature. * * ctx The LMS private context, containing a parameter * set and private key material consisting of both From 3c4ae77fec28b89fcb6311898540ee129b800b85 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 15:48:24 +0100 Subject: [PATCH 058/104] Improve LMS private context documentation Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 8bf395bcd3..7505ae462d 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -228,9 +228,15 @@ typedef struct { uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not been used. */ mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key - for each leaf node in the Merkle tree. */ + for each leaf node in the Merkle tree. NULL + when have_private_key is 0 and non-NULL otherwise. + is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */ mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to - build the Merkle tree. */ + build the Merkle tree. NULL + when have_private_key is 0 and + non-NULL otherwise. + Is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) + in length. */ unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lms_private_t; From 7726678b230c102fd74a202f65994d025e6bf91e Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 16:11:50 +0100 Subject: [PATCH 059/104] Remove debugging code left in LMOTS tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 0d2aece443..1b8315c176 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -12,7 +12,6 @@ int check_lmots_private_key_for_leak(unsigned char * sig) idx++ ) { if( sig[idx] != 0x7E ) { - while(1){} return 1; } } From 4829459c9067bf924aae9a0049a8534eaaf1f92b Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 16:40:00 +0100 Subject: [PATCH 060/104] Validate LMOTS sig length before parsing type Signed-off-by: Raef Coles --- library/lmots.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/lmots.c b/library/lmots.c index 97325aa8e1..f19871873d 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -552,6 +552,11 @@ int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx, return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } + if( sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN ) + { + return( MBEDTLS_ERR_LMS_VERIFY_FAILED ); + } + if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 ) { From 0dc604ed2b3f207571dd68f0286e23f51793779e Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Mon, 10 Oct 2022 17:35:26 +0100 Subject: [PATCH 061/104] Change how LMS and LMOTS negative tests work Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 55 +++++++++++++++++++++++++- tests/suites/test_suite_lms.function | 55 +++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 1b8315c176..b699fcc7b4 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -79,12 +79,63 @@ void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, int expected_rc ) { mbedtls_lmots_public_t ctx; + unsigned int size; + unsigned char *tmp_sig = NULL; mbedtls_lmots_public_init( &ctx ); - mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ); + TEST_EQUAL(mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ), 0); - TEST_ASSERT(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ) == expected_rc ); + TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), expected_rc); + + /* Test negative cases if the input data is valid */ + if( expected_rc == 0 ) + { + /* Altering first message byte must cause verification failure */ + msg->x[0] ^= 1; + TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + msg->x[0] ^= 1; + + /* Altering last message byte must cause verification failure */ + msg->x[msg->len - 1] ^= 1; + TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + msg->x[msg->len - 1] ^= 1; + + /* Altering first signature byte must cause verification failure */ + sig->x[0] ^= 1; + TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + sig->x[0] ^= 1; + + /* Altering first signature byte must cause verification failure */ + sig->x[0] ^= 1; + TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + sig->x[0] ^= 1; + + /* Altering last signature byte must cause verification failure */ + sig->x[sig->len - 1] ^= 1; + TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + sig->x[sig->len - 1] ^= 1; + + /* Signatures of all sizes must not verify, whether shorter or longer */ + for( size = 0; size < sig->len; size++ ) { + if( size == sig->len ) + continue; + + ASSERT_ALLOC( tmp_sig, size ); + if( tmp_sig != NULL ) + memcpy( tmp_sig, sig->x, MIN(size, sig->len) ); + + TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, tmp_sig, size ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + mbedtls_free( tmp_sig ); + tmp_sig = NULL; + } + } exit: mbedtls_lmots_public_free( &ctx ); diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index e4c4b911b4..9c966cff40 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -85,12 +85,63 @@ void lms_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, int expected_rc ) { mbedtls_lms_public_t ctx; + unsigned int size; + unsigned char *tmp_sig = NULL; mbedtls_lms_public_init( &ctx); - mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ); + TEST_EQUAL(mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ), 0); - TEST_ASSERT( mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ) == expected_rc ); + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), expected_rc); + + /* Test negative cases if the input data is valid */ + if( expected_rc == 0 ) + { + /* Altering first message byte must cause verification failure */ + msg->x[0] ^= 1; + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + msg->x[0] ^= 1; + + /* Altering last message byte must cause verification failure */ + msg->x[msg->len - 1] ^= 1; + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + msg->x[msg->len - 1] ^= 1; + + /* Altering first signature byte must cause verification failure */ + sig->x[0] ^= 1; + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + sig->x[0] ^= 1; + + /* Altering first signature byte must cause verification failure */ + sig->x[0] ^= 1; + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + sig->x[0] ^= 1; + + /* Altering last signature byte must cause verification failure */ + sig->x[sig->len - 1] ^= 1; + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + sig->x[sig->len - 1] ^= 1; + + /* Signatures of all sizes must not verify, whether shorter or longer */ + for( size = 0; size < sig->len; size++ ) { + if( size == sig->len ) + continue; + + ASSERT_ALLOC( tmp_sig, size ); + if( tmp_sig != NULL ) + memcpy( tmp_sig, sig->x, MIN(size, sig->len) ); + + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, tmp_sig, size ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + mbedtls_free( tmp_sig ); + tmp_sig = NULL; + } + } exit: mbedtls_lms_public_free( &ctx ); From 90e13fc3c62132e4dd1bc3b36f6dcee4895c7ef6 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Tue, 11 Oct 2022 12:48:18 +0100 Subject: [PATCH 062/104] Add repro instructions for LMS test data Add more interop tests, and use real data for the negative tests Signed-off-by: Raef Coles --- ...sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux | Bin 0 -> 10916 bytes ...sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv | Bin 0 -> 64 bytes ...sigs_sha256_m32_h5_lmots_sha256_n32_w8.pub | Bin 0 -> 60 bytes ...shss_sha256_m32_h5_lmots_sha256_n32_w8.prv | Bin 0 -> 68 bytes ...shss_sha256_m32_h5_lmots_sha256_n32_w8.pub | Bin 0 -> 60 bytes tests/suites/test_suite_lms.data | 196 ++++++++++++++---- tests/suites/test_suite_lms.function | 52 ++--- 7 files changed, 178 insertions(+), 70 deletions(-) create mode 100644 tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux create mode 100644 tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv create mode 100644 tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.pub create mode 100644 tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv create mode 100644 tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8.pub diff --git a/tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux b/tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux new file mode 100644 index 0000000000000000000000000000000000000000..967f8f5e00a31b3cf4bb88903b95efc7c6d24ce0 GIT binary patch literal 10916 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 z z3rS~&!JElgX-rCH3#by9zS@KwF2_rT!0MN>mCMns{~R0g&%mC5$jYFA0mO{urt;|J z`0<&&$g9V54O#bT5`wp)j=$|#19aI;f4soaD&J9NyB{bSAr_OQ)v%E`I*d?BD>22V zra#L7rNi01kl6tZe>DH8P8qf3hxbIEQdXRKW<^@Ktjw>_cnRIx%#sIT%Y$lDcJ`}! z=pz97v2_zxsn24|!X~KS^JO%fP<&#se-zT!*RpT%anB8FyTt5^OxLjLbJr;YhRzjR zH7gHfoNFhD-&OwEM@&WVzpLHz5x1zs9rG4I2pK@xwXcqrHK}i|Nn8VNi+D3LggJ?7W)K&$cn)bW z1Kz}#K%>QAa_ws}RIas=X6>W`9xAZ`6S`}*Dz*mPCkUBCu3DxhKNE?aPb;Pg2sJwD z1(8;vZaaTqLi^xBP3lF=9b~+57}{M7%3HORTaw>?3U=n zO~cVA+j~=O+=;W%4q(})Gaaf!9Ff>l)R>0J^|*JI)c-FF<&}s*Crnq?|J|v9aJ(fm z8%>NFt@A!7^h1_3*maP76GIx01N)1$kJpRbhjbtH={<$R|JL?r6Z;GFi6&yM3f|Co zJKBwi42C2ecE4zzzJoN7xi4}6x~S~|^a5EDQ`7P>2xsC!%c)$Hs6;#(NZt@*b&JX6 z9{JQiikwKD2*?e{iJk+)aFw756AE9C_o4na?R0wap_ria^`I;UX)v?biB{}%1zsWt zr7fAhnp?bH_(-$`N^JL*qiqvI^zHTYCSN3ccnxe_bMNqC`OX8g%{NzJYRDW_(S;2c@%%1{H1lTKc=={f7V~a7}ZBg_7 zVrJr9ztwyQBWR=OJIHRSUM!ROTOBF9OHL#LWk}Zo4v^VR^?u77K(ndalOo~$x;&+ Quh}RnQGT%G`xN_|0Eajl4gdfE literal 0 HcmV?d00001 diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 1b1423031a..5dd901982e 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -8,65 +8,173 @@ LMS NULL-message sign-verify test # signs the message, and verifies the signature. lms_sign_verify_null_msg_test:"923a3c8e38c9b72e067996bfdaa36856" +LMS pyhsslms interop test #1 +# This test uses data from https://github.com/russhousley/pyhsslms due to the +# limited amount of available test vectors for LMS. The private key is stored in +# data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv. Note that this signature +# uses leaf key 0, so must be the first signature generated by the key if the +# signature is to be reproduced. Message data is random. Note that hash-sigs +# stores public keys and signatures in HSS form, which appends a 4-byte "levels" +# word at the start of the key/sig. We strip these 4 bytes from the signature +# and the public key before including them in a the test data. +# +# To reproduce the signature: +# * sudo pip3 install pyhsslms +# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv +# * +# * hsslms sign tmp/lms.prv message.bin +# * cat message.bin.sig | xxd +# +# To validate the signature: +# * Save message and signature in binary format +# * echo -n -e "\0\0\0\0" > message.bin.sig; cat sig.bin >> message.bin.sig (restore the +# HSS levels) +# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8 tmp/lms.pub +# * hsslms verify tmp/lms message.bin +lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 + +LMS pyhsslms interop test #2 +# This test uses data from https://github.com/russhousley/pyhsslms due to the +# limited amount of available test vectors for LMS. The private key is stored in +# data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv. Note that this signature +# uses leaf key 1, so must be the second signature generated by the key if the +# signature is to be reproduced. Message data is random. Note that hash-sigs +# stores public keys and signatures in HSS form, which appends a 4-byte "levels" +# word at the start of the key/sig. We strip these 4 bytes from the signature +# and the public key before including them in a the test data. +# +# To reproduce the signature: +# * sudo pip3 install pyhsslms +# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv +# * +# * hsslms sign tmp/lms.prv message.bin (incorrect signature using leaf node 0) +# * rm message.bin.sig +# * hsslms sign tmp/lms.prv message.bin (correct signature using leaf node 1) +# * cat message.bin.sig | xxd +# +# To validate the signature: +# * Save message and signature in binary format +# * echo -n -e "\0\0\0\0" > message.bin.sig; cat sig.bin >> message.bin.sig (restore the +# HSS levels) +# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8 tmp/lms.pub +# * hsslms verify tmp/lms message.bin +lms_verify_test:"3f4fe37f1bb9547e443e53697a12f0393efbcf87c23d91765eb36100dd5d2c48":"00000001000000046fe15c33e5f4396fe8af67d20cd9886c59edb8aa6e005a206427d55c66cffa0d552114c88c70a6e07a8e69c53568b3deac7835f5706cd76152fc6b8dd624cf42e372ffccdb6a96a0b5028e85181e8fd67b77fb0ff38fcce830c5b65dfe16762550d5450eea7a39bb3dc745c7fcc240982ed6d1ae251822b2ca210b5c612aaf559280a7b3ccb5d68c6ea1fb6784d5134004570628f5b35a8517358ba47c6c8b827eda2e16925e945f00a42a7eb6c9034891982e8b116a43cb817bd1f67c317a20f98e1b23809c614b60231c475f24f8c2437c36b452253d517cfb0ffaafa4b53248d3f516fda0417a74d0f43771f7369ca71064e2f54fb1bd98e028fdfe3157ef6f6470c32d4b7baaae57e1b104f4c81073cb9fd339349106b699b279877b2291e32675c6a8a82e35f1b337e91d8a29c8d5c046ceb6246c44467a4a11cff22abe98b10b6a6d68361d15f140b06659b90561ea43fd9c39903a4d2be84fa89642120498ff377024c42a687fc87180a29bd030455fc453ae84c1c747a35ca81f47beba61fcd6a63970b21ed8ee74e00371e7439cb790b00bdfa89628e145698c4ee04ddb528ef56dced72754659e87f25b8e92e60252ecc5580646dceae45d1ca986b307c459249ab3b0fc85f43eb22779711846f2ee13ee0f4060a7edd95c73209ff735ce44fa02145cfa6916a305e668fd08aa943c72f2167705450037dda5f688bcad385582bf1bfe3b8316f7325837c10d193d4d898776134d420107f136ff2080563d9c4bcd48af7ef9f2cfafe517082aac1b54ebab41388c171668d03c64e62208a60a8cfa81483440b17a359e95c730299a287084d49c623f3547d3ce7936d69cb478c0533693732e7aa3161370decc75f7ae52fb0065584a20851469c07d8aa78c0ae28e7d42e86b908ecd5161c3b74409d67d639c39b99bf03f9ec3ddfb607bc594dffdfa6393b37a2cfd0dcb18ff9d63aba806821dee85aac0938fdee86fe21045c0c200527ce64be88cd971902dc8adac1f14e212c6e03d89c9e268046448c5a285f287a9896f59acb93fb12e3ac62d1df44beba165a26403d4f738acd561834c3f4d554c4bc8f20eb90199b0c3f332d19c033eaca1339ef8d029026d2aa76760e11b27427236f94fcefc4a6844937559495a36ebbde0b116c2644469fda60611d9f6ff1b189a8ddf3073acc5a55f1b0605de7c42a660f4897abd14ae485457e18b24e3d71222ae79660266ce53e89d1b60ce1622d1ef8ce3ed5179828ceb7c7298f9d10a309830ae7b530a913cb6306b7d2ce7b10753e817314fd9b6ef584fab9aba0b617cbe1a54a8610096615b56fd5b6798ce98ea866da2911b351ef5ea4411a44c726c019cf375a169fa6fd66f54d59f04e4f615e8da822413e017b60e93412e6195d4d7b7ec269e6f59dc072ba1e688a651bb45a27612949bb9eb6d0fa887393707a9c7a07f2b0640fc67dbb55d288501c394f0b61ea4c2bc1af6599032a0f8f3edef2ef5b007d3618856d48aec7894e9a4b802caf9c3f0022c39c44b4a6271f81aba0f250997ddd423e3da0461fb687e56e20e9d4a2c38d78d000000063b71be980cffb4e8a8e310341d3b711ab19545ae90c3ac6adcbeb764419411a6ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 + +LMS pyhsslms interop NULL-message test +# This test uses data from https://github.com/russhousley/pyhsslms due to the limited +# amount of available test vectors for LMS. The private key is stored in +# data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. Note that this signature +# uses leaf key 2, so must be the third signature generated by the key if the +# signature is to be reproduced. Message data is random. Note that hash-sigs +# stores public keys and signatures in HSS form, which appends a 4-byte +# "levels" word at the start of the key/sig. We strip these 4 bytes from the +# signature and the public key before including them in a the test data. +# +# To reproduce the signature: +# * sudo pip3 install pyhsslms +# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv +# * touch message.bin (create empty message file) +# * hsslms sign tmp/lms.prv message.bin (incorrect signature using leaf node 0) +# * rm message.bin.sig +# * hsslms sign tmp/lms.prv message.bin (incorrect signature using leaf node 1) +# * rm message.bin.sig +# * hsslms sign tmp/lms.prv message.bin (correct signature using leaf node 2) +# * cat message.bin.sig | xxd +# +# To validate the signature: +# * +# * touch message.bin (create empty message file) +# * echo -n -e "\0\0\0\0" > message.bin.sig; cat sig.bin >> message.bin.sig (restore the +# HSS levels) +# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8 tmp/lms.pub +# * hsslms verify tmp/lms message.bin +lms_verify_test:"":"0000000200000004b219a0053b6bfe1988ade7b0a438c106262366cb6338eb6ccd161326b29076d3493e88ab5df10ab456ddbac63f9cc7bc626a832664861a61125963f6e4b1fc202b0d6421cb1307451614d4d0e9e4509bc3991ede829f3805531912af12028c33128212a6e0539a458da092e83dcced8ffb1d9280e76593a239d3e87858905d3b4ae3864cd55972f5610759bb7d929d24ae262a1e028f140e90aa7375e43032c0bc28fe5fc25d53a26f4f9e6de18da2f697f82e409308e5b316413df8e85487391c46e784f9303f133ed332c88e6d1467cebffd9547592e907ceba2992a0442410c7a87104697a4ab3483d9b2af9df574edf23811cec0e681246f07ac74e1ddf64a7f7abc72d0a23b70d5f7c9649188eec8644f2437951640af4f673e6bb7d36a10c5c4c857f518974929824011dc79f484107388b92762acb11839c7cafec7daabdbe651f500930386b403ccec90a507829c18df23a800250d412a82b4072c94de24da9fa25720f1ee433953fca2d9b38ffc5c8b6328e69bf928936218bd253cac5a7122b74639ed7f4085d27efda2a698aff4bce385b475470adb19ab2095b3979e74e63914ef5430094e2028440f4d2aa448bb41f1d4481ad76c9b6671f4a7aafdbea44316aa97993fa31c56c34f0acd6295cd2fca8be9ea6af2f4d656f89b113cb3b3ce35753bc0128629372fade890397c297ee4c22e735e2b5f3c7383ed154cf0941884136bc6e51f860803b963c145795c8f573ab43953d25c0837bb13adbcfc506795db26fbd7a277d9532a23b5c472628944a3dcfc424e42fc54b2ed2cc8166cb82e9364af9120881313c97e429bed15bd9d46fe407f229cbc6daf1442e42c57664a7e832a809364750396a0b134efccf9a31e1ef1fdd2279d1179a673feda330b9989681c94d69eb197b6c3048623e49c98cc7cfc8d845c17f9059e7f15b72af8680cad2591cc9c135b2044fe7df45b8b6ef6e8af85ddb677f0897ffbda8131fff0eba1f94200f435bc26cfe5093c63f547620efb3bf8f905fe4ca1c40e163dfb6432c4acf068540c2c81c0392d375e99e3960973447beceefbd437f51616f85236d75815c51073277cc7ceca622bb76236d05a830e024a231566fb07f6f4e3671bc7fd5e22e4da1f4d4f4e56a179325b2ea9e51d6484df0941e0b46bcf4148e98530e9b3641e351b67073ace8438fac6d9a19988af4d594048f12eac4bbaa73eb15d597b1fdbf34ce9410520d9dc4b6bb7a99a12dcdc530c49bb67ca942adecb7adf27456eba9a9b416bb98b25c8020f4c2507b74a9ddb94f197ea42f03500bde751c04ec2c6b427ce0f80322a6b356f0d9d26531843639c7c7938b83541c58fedd0398d81b93032cb4892903a5b1cfd205b333702e7f80c1461a15edd6058c2e08d8afe44e4c5bfd7d9ac2578b5a16b4c4e43bad5f7b22041de5a95c6f64422db270e1f616e379a034fb3c08cf892af6df8af91c2767eb76bcf018e35d66fbf4ac1e5a6a10033ea118f8cd2edf57c2288a93f2f85b6ff41283b029e5c7b04bdac33b5aa79bf799292a0a046b98e6d13a2bb53a970dd0a5784034600000006c3faf2b844e6f17384998ae0616755eb7578458b7096078a36f9e556a2a091be47c0f85ffd8ee916734855a6d116fa1431ad6cff45d2a8a7f6c122f4d492df32438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 + LMS hash-sigs interop test #1 -# This test uses data from https://github.com/cisco/hash-sigs due to the limited -# amount of available test vectors for LMS. A public/private key was generated -# and used to sign a randomly generated message. We expect this -# message/signature/public key trio to verify correctly. -lms_verify_test:"D5557C719EBB0DBECF563E5CDB16568BB11CD779":"0000000000000004C167A9AC495BD4EA34CD8EE5AAA2A656D518C33612FD87171421BFC3977CFA99765C6D496499C72A1DE21360DA57EB96BC83DB8AA92E560054C7805B04E336162FB4C411B509F76959F2458B0E53CF830E0145CCD439D494259EA4818CA68924A7E8B9DD36D6A9C7849B72F9338ED6C80A3E70B717E8E65B991B2FF9D8B49820E8ABC9E2ECC17DB38E855DA75D84DF9885C7F9DFB4ABC209CFF1D37D66595371D688A203CB89168945200C39169F784B19665CE1FB47D58BFA734C3E0E7E31D1206A033C6D8E25B7E45CA779A5FDE00C6B1CAC44884F2B52A380E1F6D8753549F7F4948A95AEA83703CF3AA108FA4F735AFC0DA1A03C378033D8B5959E7BE05D3C5070E709181AC09EFEC04128ABD7E8F37304FAD4B66373D4A83CFC1EF632DF6DB95577C2C6101CBDC807109ED8AE831FFB73DBC80942C58F334663B980F982C74B943BF7C57147250AADE595310387E3BB1A2705E9EC73DE7FABDA5EC0B1141A18798215B9A70F8D688357C833ED869059A2AA3360155EF84426288198D0FBB78223816B17093684C48942ED18FCD351C34E108E5B71D1CE39E318B5D991B650C46A91112E013E1180F2054C7A22429CAB31512BA34EA3AD9B68C5001EB70C993297CCF11914ECAF059922DAEE7D90ACE2567495ADA066E7DA1679CA45DAC1990B17184E7BE2E6A0F26AD77F19855D074F5B37372277484CE30B80A0540173C1B310C3E7B683A487B5D0676218EA1F65FEA444C493FC535E948EAB62252DCC90516BB45B60D4253DB6979FE342DC5CA1B86B01B2D8EBA79B0BC7B6984535616B792BB45F3C0E20B506E0694E1D5BA28FE96D34FE2BE354777D090404DD3508E9F7918FF5593ADB468478CA8A1F6AF752CC76F401E373B71471D9D70F455C8A73E4E7B6714394B1DD0E2A816AF3D5149835DAE477A70DEE0BDAC22F99A04BFB7C2D4AD53079C326F620DFD3F7CED4AB7F2E291507AA046331050F9E2205C52B36CBAEE817C5C3B1FBCDE61C54C8CB7B67E0570FA44728EC8FD091D5CEDC19C6B99840F7A0E49086F707E959D34B30E255B67BBAA24FADE532BF3D21825626E114BD8213170B0C2F01733D4ED420D01EE3ACD5F84DACE674AE7127DB0A80ACE252CAD9ADADDAFAB27281AFD6DDD72DB5AF878326C45D7DB1EFF8BC40895A3473A52461D076881310AD9937307217B5C0448B509EF9BA075936CC09E11B8838D3A6BC5EF9FAEA85A3EC87EEFDF2E38CD9732730085375A4FFC4E0A213B0E1FC3DE2D37F1EDACC3030F617F3459A03BFCF776A05FD3B7FD135782F6D6E7C5E92B56A1316525B26D3AE1CEA3C0C7CF3AA7B1E72B7599A31B50837D79A7AB61B9A9E2B7AABD2D605C97E302EB4B66C0588C24147955EA0892A54D42843568FE0863E7EFEAE336D302E672EA62689B4DAA02DD5BC99D93886EC7F411C53CE1CAEAB59FBC0B06E0E294F1900F8C626C6FF520AE2323DA797CDC120DBC19F7FEBA0E13429508C5B838A0F8B9B28A069C5DD40E2F6CC2C95FC6ACE7E1351516817BD2DC1AE08D498AD2B0BD1D8374942FF31FC6A4689C592244C919C3561E73DD4986FA500000006BBF34F6EE152B64FCDD1CB6848D2DA761798707060431761006E2EBD9312851F4F3DF3C46E10F643DDD58CB3D9F4D371F655EE26271F2DDE84A14CAA6A077DD96AF83849DE6CA8F2F3248902CBF49630C18C3EE3123D951CE9162D0E742B899AF9E5DA8D28A41C7CADF0194CDB09418BF48BF322F8C5E9563524196FA8AB785B43C4EA41A36148028D2F4C7356CDEEB09532CD7F2C80FC36589FF7A9954100C8697AEB014997C3088C242B4F70D26CE7F7E77384A9CF536EC5C5329E08BD6C1D65EFEFC1389A42D16FFB43A0E1D7661220E92A4A59703FB28410E73A677E803D4441929DFD7269E6F77AE8CA8C70B67B250A8728291EA5D4E3F03D505639408C88156DCBECC137142FA3585C09D99B84D8C380A5D29CE2ADA10A25F7CF939FE23288551F37FE2B7233BF97C0F5726B972E087BCBA095957CCD794794A4F50027":"00000006000000046B0927585C8547228D495361D73B970C287A2254BF8F1B170E55ACC9520A56CE5D2C711B6617718B49247D28CCC6D11D":0 +# This test uses data from https://github.com/cisco/hash-sigs due to the +# limited amount of available test vectors for LMS. The private key is stored in +# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv and +# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux. Note that this +# signature uses leaf key 0, so must be the first signature generated by the key +# if the signature is to be reproduced. Message data is random. Note that +# hash-sigs stores public keys and signatures in HSS form, which appends a +# 4-byte "levels" word at the start of the key/sig. We strip these 4 bytes from +# the signature and the public key before including them in a the test data. +# +# To reproduce the signature: +# * +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux tmp/lms.aux +# * +# * /demo sign tmp/lms message.bin +# * cat message.bin.sig | xxd +# +# To validate the signature: +# * Save message and signature in binary format +# * echo -n -e "\0\0\0\0" > message.bin.sig; cat sig.bin >> message.bin.sig (restore the +# HSS levels) +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.pub tmp/lms.pub +# * verify tmp/lms message.bin +lms_verify_test:"6b7439e31ef128c54f1536f745ff1246":"0000000000000004163fc2e3d3267d8c0d9fd9e7bb7a4eae84c3d98cd565de361edc426067960fc3201d9be1c30f4e4edce91844753aa13ff21e92648ac795b7c29dd6140962b5a1fb97b02570402a498a495044edcb26d1321c52e91c60cc3feb8f8e84fc77f97fb6e7afbfe4c2f2203d8d84303e2dd212b652e08a2e5a24a333df859cea3c5a547561f7ce6d182e2a3f2f018ef7e0578621916cff905c0713fa5f2bf73248ae6985aebc4086b79ebf71b8dcbb592eb61dc6303d06dbda88063690361b0dd25ea1c2c6b4d82dddbe11740864c65c228d67e9a1710506e585a748e7e02b36706e5cff83b3589613f07c636ab7784d6a8288d33e80f063165a2ddcbb0d7da815df8043dfa500c3e313c533bf6aec959237c923813d3109bdaeb195b1337f4cf21c1c863f6261dca411819603a3ea60cf34c81b462c4979b357da2bcdf3128343ca5a8a957e3ca4eebb914d743862e29ef48e43e7c5a7aaf7a2fe1251c309c65e9143dcfb298fa0d353084f60c0779e1a09b040f13c1025ec99402b844ff9996decf4b5f0d32a0858126ff293472aa93fbc2017d39fee93ff9f0ca2752b25cfa12542bf19cc1b8c102d65b70dccf760f26cb546742ce909d45345f802a985bae6a0f922a9c2a3dc992fae9f6f2fba0c52cad82564bde6ed8af880ee7a5eb5c6436611e5da1c690831bed34e3dd65acf2b8f496b6448e957afc16c48b6cd733bc84e3606a1d0609f08015c14b5619a2723f9b22950efc7ff7b733c299fcd84ed89c4d5cd43a9a54f25fc0fa1370d184f9e8011b60ba38dfca0eeeb56ae37a5823718c8210db20c2de13c39e43970b0b53b85b9cf9ea0dd025e7db558b463c683980fe59e0defde41afe825cfb8606ca861602a7fefd7506edc81b7ab4a1e0626e0bac1f99be118dbc1e291028fc73d0a0ea6559ae1dcf7477d64742c9bef88ef04b2ee4d392cf1efa23d8b05d11d2414e64f4540623e11bbf57fb8ae219331db0df459a9849f2700e6fa7ff4edb0fc01764949e279e84374e7a57fb5ee6221b2b72dbcf2ab9c988fe07d21e169b4338887129ac503cc6c0912787778d51b4b921cf7bb17d4028b7faf6c21dd616a1ac3b50d595ae0e3662e7faa16b9dec7694462c7fb8539ece0af33cc5a3dc33641b8827bf4751a708d7bf286cf2e795b8f45b76e1109abd908d0388d6ab8ecea67b187aabd80349e4bd286e3b6eeb3535cc9c343a39fe90cb443906b19d2483b4c93d0e35cd68d9f5523d5400a2b1708ba3361bd0757ed69b1da8845594edf053995b2d96bed8210aaab25fc34b2dd58004ce800360f24861e5912ac339ed0a78548e303e728a41e05c11d79013e3971eafa8034e63ecf1c842f0d9e735ff3b5badfd63ae07f051c94a9a867260b517e5c2c75e88e03d069bd39816a2255c90de81bb79622145b7469853a02eac45289fd9f9f40e2fccdd8ddb740469331f61badc1b7f6e0145dfe30141ad2f26ac8d7ff5125dc4dff1fec57629cea4f7de4401fc056e9a38ea028ac9c666ccd3f527947672408a759a5791d9efdeb1ff25392413728a03d4c641f4ce1542b6952e7595f1eecf1060000000671b0912d734442146e128d0029101ad34a6d2d586640235c828d427dfaffdb156771f06926678fa50aa7167684c1de108944b2c4a3358f5e926368009e4500a8d4d501124bc25a4c9b1cfb954503f4ae26c92221e39c680843ae55cfca972e139c82e2e4469a703a1866fa0e6d76636591f4ad07f7d1eaa19077660ad46a6f9d534970e6a49e24621b7c7c283253dd22fb24eb7819fab84bab88e42555d5437d5afe06615a7e0d103cc8595616690f1337f4345cf418724f07d0dc4d2c0899b691691f397202204ef34342b5725dc6adfe549ab0b887572ad38113c407f96fcdfeea0ffc4f333addfec296169e53e3c5b24797a20f3b2f043f5e96920de9927da466f09389d3e52a5665f380f68666a019c201e710ab4c168d5ac952a02d5909a6fcaf498a33e2124e6a828203744ee3fe70465adde0cfbccc1b4634541638ab":"0000000600000004e18760ef2c86192aee88579e376f35cd153419d622803a483e79f6d368629308a8ab6ff663c4f108b2033af290dcedfa":0 LMS hash-sigs interop test #2 -# This test uses data from https://github.com/cisco/hash-sigs due to the limited -# amount of available test vectors for LMS. A public/private key was generated -# and used to sign a randomly generated message. We expect this -# message/signature/public key trio to verify correctly. -lms_verify_test:"DA16BE0B8FB691248486ACAFD531BE6EE4C362E0":"000000000000000484FCD0D791D175A0F86D64B2E8949F793CA9FFDC0347DE125DDB2F895BB9D2B43740B9B326B24F934D67586812BE6F3FB57E76FB12FBAD60A685F22A82C95C84AFAE63F47BB3CD951D483F61F5626B2B5FB6FDCA0CF02293EFDE1EB0AF6712D635678E825099E95435B43EF83C49C6589054D0905D82D597FB11A721D2232AD168FD179724539699C21163D5ADEB52290CB711C368572FF8BB95AA61DF2AD128307E768E73D3CF2BAFEAC8B6CD165BDD0316D2663D1ED61A15FB974082FC66A55E13ABA4FD084970EF6A59B0DFA1E934BF0E056C86E9B4C5B94CF863AB9F23BE2DB6A140A9CAA8DB31C83B21BDBDCD07304A52EB8501869D86BFDB68A376D94F847EED7E4CAB6A6EEC063945AE4DAF657D5509249E7FE430F5A13B188C4DD311F01746CE28F4F6540041EF6ADB299F712F591C83B0C12C1FB3E4A878C63217E25E08C004571FFC69E9C684E46F4D36C36409EBF3EB15F32A187176F4D177E0FE0E71ADFD4DA4AD2D57A0256B29AD5DAA6867AED20CC862AF5729D030514D41BB8D74551D8E925322C81A357A586227BBC885AB683BF835E9333A056AFEE96F2AD0FF6D6E235A9E2BC342ACBCF0B8EACC95E7B74215F6C65F12829433301F004EE1D9CFD16A4A1D092F48E99AEAE9E1FA4619ECE5E05F5C19F33C4C94A774EB8955409E3CFA73D8807CAA7C55FE45E980C7E7626AAA193F18A3AA7E525FFA6466D728FA25563DD383D855A0B6F8C011AC8C79C853CBED3A016DC26EF6E90B3E78119E465B9962A42B6AC168C1CDC9DB860D740B0C797303E2A62445FA618B5EB417BD4385C15BC548FEDF4D4842CA43F95188FFF63EB5D4AC85DAE618FDFB6CF5969EA0A3A52F73A4AC4957BC4EBCFEF593923EC79196021B25ED8D7558E4AF41ED74941585AC575CF1971D4F4C7C9E9516276734FF9FAFC7DE661F3090F71C98962789B31EA0FE406E2EF02F6F16B1708258C7559B8E05E27D647AD472805C865299FE30A5FE451DA7F2C493A37AA1655D492EC891B9AF559E12104CDD2EEB2E54138A1FB5A403AA32CEEB3946471A299604FA2DD3CA3E9567D01A3CEE5D09A1C2768B521C0C6142AF297CA5BFB3878B32D37D415542C15F655CB051240F3BA8FCE0E38449A0D7010A9B56BA2283E3A2047215813ED2090F7BDF16A40ADE32AB4E669684E6DEB6A94633E6643F29D10914F5A361C964CA9145514D4B80B45F3276EB0C649622034E71925FA038EB35E64C71CBDB11E91D779339516A351BD2A722CB60C2CBF145689B2E3F6FAEB74C3B58283929F70023503A96FED6A5D7D8A9E495FE1D85E0FCEC555F86747347D2FB5219FF65EFD144A5E1E88C63BE4259C42F6899C103536D75E0526508649E2836CACB94E88BD954B88EAC26F17B27BF62546C5C7573E2BC9EF4B65B8AE4951AF532F968FF050E504CC236DC48379E4390079DE451DCE710F9674D753C85B9FF7E7B09ED051EDD14C33AAFC8A188AE06234DFB61FE5A75C7A760B5286E1D6993BCEA0AB8A2C1D632145BD6A9F109ABB04E0B102D50DCB8C607AD6BA8C5FA5B21663E5A40194CA5DC2294BE10044E8D96AA0000000694ABC63BC5B27730C5223943C8341461474033BE3A221AFFDE66242AF14510CC656480CBDFC0B35205C89258A18BF6C29C4708CB2572DE15EE5DD481BC47060254954B5C5DD881AE6B358F7CDAB6F117235AAAC625B2750DB72BA4A96D7DFAA889BE780416E1CB264A413C6713710102D1D433BC6D0A47BF08AA74FD613D292A867261181BBD73557EE3AEB0F63579B71E58E97BAC1AACA3F34646350A13BB7ACE0AB3B062C41518768ABF3D32FB2F6A5E5C7F6B8B04C943D25A82F03F977755D74FD717A4B7E7674B03B577405210E23A2FE050E036DB0730359366A9436AD2CBCCE3E649F9E40023B2C12D9F5AA824319EAF571FD4842E573BB100BE9715D7B71F75521640D9B69B889349A283D62350D3A37264C89930F40603A5458B124EA850BA59024A46A8F325C9A9776817D739692FFAEA2758249888BF79D66FD496":"00000006000000043FC8322D04908C7C06C0D8B7A0CE24FA3AC253393CF9A56CF760294A06E75223E38C9E5329DDC493D8B51B1A4BBE41F8":0 - -LMS hash-sigs interop test #3 -# This test uses data from https://github.com/cisco/hash-sigs due to the limited -# amount of available test vectors for LMS. A public/private key was generated -# and used to sign a randomly generated message. We expect this -# message/signature/public key trio to verify correctly. -lms_verify_test:"331D543362A163390508127AFB9894B8C18C6E0A":"0000000000000004F5378439E9C229550D40B725FD56BE48DB785093E62BD29B723C61FABEDCFD486EFA120445339DE2A21A8C7465073ACBFD6DE3E50F395AAC20E0BCB23B088C416199F80B540AA81B2C0B12B7785152263522E8F79AEBE3B28315CC834AEB68475CADBC724DB6B7B7F594A7F9DA2505F5F44DAA7EEF70B72665A250C1F61A19F3FA4CBF389BEB9B31DC327882D7983EEED46DA8E00AEBEF85AE179EBF6D8CC7F720E9F963C4D30DD4015DAA27993D0780AFD7A45688422B1444AD866FEFE12EBD94B4D313517708A6E652D6206A8B263E234685D8133C2258EF6CA9E9C6FFD6D153598B13B59576897DC4F77C71609427866A347AE62B5C3BACB0A2E44B60F2CCB4989B0C57F3E785CDCF22B1FC8C3460A163FF2BE7A578E82429BA823F392A13C11A5639A42453972D2185E81809EF0666F8F01F575FBD9A46135F45651AA814D9BA84F774A9E9303FD55038CA41A21484BA9C38E69BCE4E37052971690ED3EEC4ED9AD41B0AEAE4DCC913443B9FA5418FB75DC1725FA989BA8DB5D9E221804FC7F36F3135C8B93AFF66DF89408CFD50993D308E51DF00540F380C0AD06266B80F646B917BA58384B55658EAD2D453766C4843FCDD934E8352A6DF6A081A15BDE07BF67E977E72BFE1AC37F411111A0A4D101A2CCF95EBEC7FCFC82B45DBA88939B0831987AE4D15C05A2E08F713BB0B6BB0E2436B7F9C83D2D869432465DEB9185913DE215937EFB4A52DA50BEF88688F5AB4397A04B14CDBFA5BFD948CD6EA1122D9D3C2927DE9D066297AA2C6FE8E478EC0F41459287EF9B8A1A56164C72AE3DCE5E914E8BC3C3821E0ADD6D1C9048D71BD71F71F3A6E04E63687298DE5A3704ADA82AA369CCD7F342F79E988A7BE066CA55944E0E3712F472891761E5617DC048C69AA4C250AA1560D6591FC0E7492027BEED67310E3482B1487E41DEA5E070894A5FB93FF4462D1F60C4B1CA7C15275EEA2B3790ED12EA930FD7F7F07D60807E4AAB73D1F889DABF2E687A487F331AC17D8DE24E8448E672F87424F0D1A73721A1A987519D0E3BB91D15D012B1FCDB6E23EEA17E93869C5199984CE8A068CA96C3096273F8B23160A79EE0C208D9B70ED5E23CB3586DFD33E02D06F1C646250BD664C27D2BB9614FF5F043A6FEE1A235DA10DCAADB19205CB839BD616BB36B738AA28E1D4F767BD8BAB6C2F84887C7B2E16CF6E07AF90C1FCB6E6E5A4CC894072AF4393C63F7119FF694BF0A043AF5F0825557A99C40BABBDA97D5648687D493367812743335A8AD7696562538C8BA5DED182C4DC818E7E9F630B29A9534E2583E0F4B5862D4E4DB250A350BAF360EF133838FE55AA683E253746A704654EF692F4F818F5A172AB0B84673D0AF77CC1DF189AA5BB013E833D1B0943918768AC6A83E6BFB306D3C3786BD2C87129BFEA1C380A84C4983D262184427284BF3DEB9B4C58FB1899B07B9F60B4402618168B1445653E8E48CD92C048684302A6F5C217F110D6699707BA42316CB31FE8F4DA6B82243CF1264751225594AF1BB670339A9189163DB9E985A99BCF83A3039AF3E65BBCD8364745356B29D761853E00000006CDE5B63B9763DA3EABCFFDA517688BDEC2AE9213E6B0FD7003D95458798AE9449DE4F1135E093B39F597A34B14AAB7F596E25BA469533442F54C14921ABCC5D04A05486CD16C8564E6A19C11BEDA574A9800107DCEAD013A7E6A32966B5BBE9FDFDB0184FE0707209B6D9EC43066899717E487E5FDEE02061EA5069B2D6C9C87D6BEB1310F1B9E723AE372DB7BE9EF6657F51FD0DE62464D3B37755095829F625EA76F5FD7FCD5829863F963FCD7F9FFFF3729688D025DF7952B067C62198E4C6CE06E960B0BAC6ADBC9459D9AC0BE1BAD46F95A121BBBE6953BAA10252419E2AB6BCA1B0AA1FA64DF728160B4FB7A62499C24D269FF59977649064C5986D615E6952EA0DA5B1C04C443BC27A63D391D5BFAE824F0161791E65896DC100EAF80037FD800A5079337554BD990E0D0A1A4C4C45741E72FB3E840665F2881D2CCC5":"000000060000000461F2DF219685CF313043780A57C18071725490AB8D53B676D484238BA8C373572407938CC578045649964958C0A872FA":0 - -LMS hash-sigs interop negative test (altered random value) -# This test uses data from https://github.com/cisco/hash-sigs due to the limited -# amount of available test vectors for LMS. A public/private key was generated -# and used to sign a randomly generated message. This test is a negative test -# where the signature from the hash-sigs interop test #1 data has been altered, -# and is expected to fail to verify. -lms_verify_test:"D5557C719EBB0DBECF563E5CDB16568BB11CD779":"0000000000000004B167A9AC495BD4EA34CD8EE5AAA2A656D518C33612FD87171421BFC3977CFA99765C6D496499C72A1DE21360DA57EB96BC83DB8AA92E560054C7805B04E336162FB4C411B509F76959F2458B0E53CF830E0145CCD439D494259EA4818CA68924A7E8B9DD36D6A9C7849B72F9338ED6C80A3E70B717E8E65B991B2FF9D8B49820E8ABC9E2ECC17DB38E855DA75D84DF9885C7F9DFB4ABC209CFF1D37D66595371D688A203CB89168945200C39169F784B19665CE1FB47D58BFA734C3E0E7E31D1206A033C6D8E25B7E45CA779A5FDE00C6B1CAC44884F2B52A380E1F6D8753549F7F4948A95AEA83703CF3AA108FA4F735AFC0DA1A03C378033D8B5959E7BE05D3C5070E709181AC09EFEC04128ABD7E8F37304FAD4B66373D4A83CFC1EF632DF6DB95577C2C6101CBDC807109ED8AE831FFB73DBC80942C58F334663B980F982C74B943BF7C57147250AADE595310387E3BB1A2705E9EC73DE7FABDA5EC0B1141A18798215B9A70F8D688357C833ED869059A2AA3360155EF84426288198D0FBB78223816B17093684C48942ED18FCD351C34E108E5B71D1CE39E318B5D991B650C46A91112E013E1180F2054C7A22429CAB31512BA34EA3AD9B68C5001EB70C993297CCF11914ECAF059922DAEE7D90ACE2567495ADA066E7DA1679CA45DAC1990B17184E7BE2E6A0F26AD77F19855D074F5B37372277484CE30B80A0540173C1B310C3E7B683A487B5D0676218EA1F65FEA444C493FC535E948EAB62252DCC90516BB45B60D4253DB6979FE342DC5CA1B86B01B2D8EBA79B0BC7B6984535616B792BB45F3C0E20B506E0694E1D5BA28FE96D34FE2BE354777D090404DD3508E9F7918FF5593ADB468478CA8A1F6AF752CC76F401E373B71471D9D70F455C8A73E4E7B6714394B1DD0E2A816AF3D5149835DAE477A70DEE0BDAC22F99A04BFB7C2D4AD53079C326F620DFD3F7CED4AB7F2E291507AA046331050F9E2205C52B36CBAEE817C5C3B1FBCDE61C54C8CB7B67E0570FA44728EC8FD091D5CEDC19C6B99840F7A0E49086F707E959D34B30E255B67BBAA24FADE532BF3D21825626E114BD8213170B0C2F01733D4ED420D01EE3ACD5F84DACE674AE7127DB0A80ACE252CAD9ADADDAFAB27281AFD6DDD72DB5AF878326C45D7DB1EFF8BC40895A3473A52461D076881310AD9937307217B5C0448B509EF9BA075936CC09E11B8838D3A6BC5EF9FAEA85A3EC87EEFDF2E38CD9732730085375A4FFC4E0A213B0E1FC3DE2D37F1EDACC3030F617F3459A03BFCF776A05FD3B7FD135782F6D6E7C5E92B56A1316525B26D3AE1CEA3C0C7CF3AA7B1E72B7599A31B50837D79A7AB61B9A9E2B7AABD2D605C97E302EB4B66C0588C24147955EA0892A54D42843568FE0863E7EFEAE336D302E672EA62689B4DAA02DD5BC99D93886EC7F411C53CE1CAEAB59FBC0B06E0E294F1900F8C626C6FF520AE2323DA797CDC120DBC19F7FEBA0E13429508C5B838A0F8B9B28A069C5DD40E2F6CC2C95FC6ACE7E1351516817BD2DC1AE08D498AD2B0BD1D8374942FF31FC6A4689C592244C919C3561E73DD4986FA500000006BBF34F6EE152B64FCDD1CB6848D2DA761798707060431761006E2EBD9312851F4F3DF3C46E10F643DDD58CB3D9F4D371F655EE26271F2DDE84A14CAA6A077DD96AF83849DE6CA8F2F3248902CBF49630C18C3EE3123D951CE9162D0E742B899AF9E5DA8D28A41C7CADF0194CDB09418BF48BF322F8C5E9563524196FA8AB785B43C4EA41A36148028D2F4C7356CDEEB09532CD7F2C80FC36589FF7A9954100C8697AEB014997C3088C242B4F70D26CE7F7E77384A9CF536EC5C5329E08BD6C1D65EFEFC1389A42D16FFB43A0E1D7661220E92A4A59703FB28410E73A677E803D4441929DFD7269E6F77AE8CA8C70B67B250A8728291EA5D4E3F03D505639408C88156DCBECC137142FA3585C09D99B84D8C380A5D29CE2ADA10A25F7CF939FE23288551F37FE2B7233BF97C0F5726B972E087BCBA095957CCD794794A4F50027":"00000006000000046B0927585C8547228D495361D73B970C287A2254BF8F1B170E55ACC9520A56CE5D2C711B6617718B49247D28CCC6D11D":MBEDTLS_ERR_LMS_VERIFY_FAILED +# This test uses data from https://github.com/cisco/hash-sigs due to the +# limited amount of available test vectors for LMS. The private key is stored in +# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv and +# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux. Note that this +# signature uses leaf key 1, so must be the second signature generated by the key +# if the signature is to be reproduced. Message data is random. Note that +# hash-sigs stores public keys and signatures in HSS form, which appends a +# 4-byte "levels" word at the start of the key/sig. We strip these 4 bytes from +# the signature and the public key before including them in a the test data. +# +# To reproduce the signature: +# * +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux tmp/lms.aux +# * +# * /demo sign tmp/lms message.bin (incorrect signature using leaf node 0) +# * rm message.bin.sig +# * /demo sign tmp/lms message.bin (correct signature using leaf node 1) +# * cat message.bin.sig | xxd +# +# To validate the signature: +# * Save message and signature in binary format +# * echo -n -e "\0\0\0\0" > message.bin.sig; cat sig.bin >> message.bin.sig (restore the +# HSS levels) +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.pub tmp/lms.pub +# * verify tmp/lms message.bin +lms_verify_test:"0705ba8297c7b9fa5f08e37825ad24a0":"00000001000000040a432454b99750f7b703f0280f92818b0570d0267a423b377be7cf0561305d4ce987b9d8dbc1c3f8ba410bbe6b921406eb802688d2dd8a1a6fa4a124cbcae9b5a210f583a956384c06311953b038b4ad2c2808224fc3a6410cd3b89274371956bcd4253a251cba6409b09c822e1d29d7a037648a6f2562d0df6359a043622f256f5ac79736c08fc4185758ff002a8397e560d5812373946348afba2ccf2cc0f3ba741ec076d4587a54b8b625804b814c30540152a3dc843a590c94cc23ba857e4c458c8ab687b5b9b68837ee890454cc19bb5f42a1e6dc051803fab50b440067a903013f675a774b5d02cd56289518d65f869f22b2e2b58d499e9e3929ec5a9f5d6d6e03cf91486094aba7c88491cde35b81c175c40410bc402d20f0a73a4da844d3a1d47e57618b7f18fa5ac85e877b5faa1e0b6733c2d96b2970fdd6e606435e3ec50eafa88f84fb7512217aa4be5858a140f242603bda634d76c484a184298c4da903094468d032b88586fd2f35182405cd85115af6a0bbd431f2e44217a1691dd8887db91d3b97264ff552ae7dc110a3a111f2bf74ce42079055dfb8390a16d67f28b738f837aa7880f3134deabcf6ec74cdb521bff44df61c999bf7a8ddc43b64812cd4f3bfb15104867d5e585d1cbf99738e0df92660b3e9135a4377d1199b8b97362fc87ce3c99db3b8aba63ba35eb353e5ec79bcee82b9ccc1b4f7d1b8ce7e5f8813d007be3d0e45cb8e7173337a5a7c4d32ea5116e0fdbd7846ea1f366a531449c78cd7a16ce5bffcd6cccf54b7f249a74e0df6b07f6b48db42eb958ff18b06995368af0cadd82f44cf44e4b53f0993de5f06b289bee41cd25f90a9fbd1bfb1ab2451c96b07adcfb5210d291dd505ea30e5d30395c8d84eabccdd2c7d6f28a88f5e5d245a6980c57810cfe17c9a37ef5e79b7b9ca755d56a789d21985372bed42ae2830d81ebf0fad6c721bd1d3ee91ae363f40d386aac23e7c0db965539ce9bff38f0f24bec3227b5a24f4cd7fa71ca9d306faa3fc4726cdb6634f218897b79a4aed67a58799285104eed74703ec4af6d5738b27b4d6fb71e52c1149069483a7cca6c3fccbdff77312ff5c635d8b0ccd53dbaf7b498727f7c7a70d3fd1c3f217e2cbd0dfe91258acb7f79f53f56012a82da997ea777b76dac0472e5f9830a93fb09703b1c0e45cbfbf641de94fcc6c609f02a5b31ad5821ba6cd48829fc5e0c4ad78e11e4cac8efbb1b170c794b7b131b0c1c4e39fdef81db9e7acced5ec824aed0c4e6b57fd1add4191e87be1446c7c519eb671205ce8c5855ad7a2b9ff7a9cd5c45336f508d0f8d2c1152dc2656650bdaf8fced642f3a4d445b5fc49910bdbdc9635de0086ee9582a796ca9f6052de805f41dfbd3e94982a05cbd36bab583dd5b1586ddbb3b1a45f1a265bec062c1a50d220870c0c622d852e650a67f31e8eb3d19e964de0926712b7f429ad05024b8db51eb6702c39580f62f037388862251bf66f02edee9615a63957eab75b28501f9f26cecd09a5c949127c9a3095036667fce8e45ba75568d5160fa1725a9e0038145d948f437640dc4441000000066e8db13a9e79d10a4e067aad448a1847b5489a62cde3054ee1e5ff2e37549d516771f06926678fa50aa7167684c1de108944b2c4a3358f5e926368009e4500a8d4d501124bc25a4c9b1cfb954503f4ae26c92221e39c680843ae55cfca972e139c82e2e4469a703a1866fa0e6d76636591f4ad07f7d1eaa19077660ad46a6f9d534970e6a49e24621b7c7c283253dd22fb24eb7819fab84bab88e42555d5437d5afe06615a7e0d103cc8595616690f1337f4345cf418724f07d0dc4d2c0899b691691f397202204ef34342b5725dc6adfe549ab0b887572ad38113c407f96fcdfeea0ffc4f333addfec296169e53e3c5b24797a20f3b2f043f5e96920de9927da466f09389d3e52a5665f380f68666a019c201e710ab4c168d5ac952a02d5909a6fcaf498a33e2124e6a828203744ee3fe70465adde0cfbccc1b4634541638ab":"0000000600000004e18760ef2c86192aee88579e376f35cd153419d622803a483e79f6d368629308a8ab6ff663c4f108b2033af290dcedfa":0 LMS negative test (invalid lms type) #1 -# This test uses a null (zeroed) message/signature/public key trio, with the -# only parts set being the LMS and LMOTS types. This test has a valid LMOTS type -# (0x4) but an invalid LMS type, and should fail with a bad input data error. -lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000700000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA +# This test uses the data from hash-sigs interop test #1. This test has a valid +# LMOTS type (0x4) but an invalid LMS type (0x7), and should fail with a bad +# input data error. +lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000058b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lms type) #2 -# This test uses a null (zeroed) message/signature/public key trio, with the -# only parts set being the LMS and LMOTS types. This test has a valid LMOTS type -# (0x4) but an invalid LMS type, and should fail with a bad input data error. -lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000500000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA +# This test uses the data from hash-sigs interop test #1. This test has a valid +# LMOTS type (0x4) but an invalid LMS type (0x5), and should fail with a bad +# input data error. +lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000078b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lm_ots type) #1 -# This test uses a null (zeroed) message/signature/public key trio, with the -# only parts set being the LMS and LMOTS types. This test has a valid LMS type -# (0x6) but an invalid LMOTS type, and should fail with a bad input data error. -lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA +# This test uses the data from hash-sigs interop test #1. This test has an +# invalid LMOTS type (0x3) but an invalid LMS type (0x6), and should fail with a +# bad input data error. +lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000003e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lm_ots type) #2 -# This test uses a null (zeroed) message/signature/public key trio, with the -# only parts set being the LMS and LMOTS types. This test has a valid LMS type -# (0x6) but an invalid LMOTS type, and should fail with a bad input data error. -lms_verify_test:"0000000000000000000000000000000000000000":"000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA +# This test uses the data from hash-sigs interop test #1. This test has an +# invalid LMOTS type (0x5) but an invalid LMS type (0x6), and should fail with a +# bad input data error. +lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000005e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid leaf ID) -# This test uses a null (zeroed) message/signature/public key trio, with the -# only parts set being the LMS and LMOTS types and the leaf ID. In this case, +# This test uses the data from hash-sigs interop test #1. In this case, # the leaf ID is 1024, which is invalid for MBEDTLS_LMS_SHA256_M32_H10. This # test should fail to verify the signature. -lms_verify_test:"0000000000000000000000000000000000000000":"000004000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000600000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_VERIFY_FAILED +lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000040000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS import/export test # This test uses a randomly generated LMS public key. It imports the key, and diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 9c966cff40..f69ca9e96c 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -97,35 +97,35 @@ void lms_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, /* Test negative cases if the input data is valid */ if( expected_rc == 0 ) { - /* Altering first message byte must cause verification failure */ - msg->x[0] ^= 1; - TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), - MBEDTLS_ERR_LMS_VERIFY_FAILED); - msg->x[0] ^= 1; + if( msg->len >= 1 ) + { + /* Altering first message byte must cause verification failure */ + msg->x[0] ^= 1; + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + msg->x[0] ^= 1; - /* Altering last message byte must cause verification failure */ - msg->x[msg->len - 1] ^= 1; - TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), - MBEDTLS_ERR_LMS_VERIFY_FAILED); - msg->x[msg->len - 1] ^= 1; + /* Altering last message byte must cause verification failure */ + msg->x[msg->len - 1] ^= 1; + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + msg->x[msg->len - 1] ^= 1; + } - /* Altering first signature byte must cause verification failure */ - sig->x[0] ^= 1; - TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), - MBEDTLS_ERR_LMS_VERIFY_FAILED); - sig->x[0] ^= 1; + if( sig->len >= 1 ) + { + /* Altering first signature byte must cause verification failure */ + sig->x[0] ^= 1; + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + sig->x[0] ^= 1; - /* Altering first signature byte must cause verification failure */ - sig->x[0] ^= 1; - TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), - MBEDTLS_ERR_LMS_VERIFY_FAILED); - sig->x[0] ^= 1; - - /* Altering last signature byte must cause verification failure */ - sig->x[sig->len - 1] ^= 1; - TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), - MBEDTLS_ERR_LMS_VERIFY_FAILED); - sig->x[sig->len - 1] ^= 1; + /* Altering last signature byte must cause verification failure */ + sig->x[sig->len - 1] ^= 1; + TEST_EQUAL(mbedtls_lms_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + sig->x[sig->len - 1] ^= 1; + } /* Signatures of all sizes must not verify, whether shorter or longer */ for( size = 0; size < sig->len; size++ ) { From 810612e14ec26021f56e065fcdab09600f93fb4e Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Tue, 11 Oct 2022 13:16:53 +0100 Subject: [PATCH 063/104] Update LMS and LMOTS to use TEST_EQUAL Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 56 +++++++++++++------------- tests/suites/test_suite_lms.function | 6 +-- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index b699fcc7b4..4821ce5ce1 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -38,12 +38,12 @@ void lmots_sign_verify_test ( data_t *msg, data_t *key_id, int leaf_id, mbedtls_lmots_public_init( &pub_ctx ); mbedtls_lmots_private_init( &priv_ctx ); - TEST_ASSERT( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, - key_id->x, leaf_id, seed->x, seed->len ) == 0 ); - TEST_ASSERT( mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx) == 0 ); - TEST_ASSERT( mbedtls_lmots_sign(&priv_ctx, &mbedtls_test_rnd_std_rand, NULL, - msg->x, msg->len, sig, sizeof(sig), NULL ) == 0 ); - TEST_ASSERT( mbedtls_lmots_verify(&pub_ctx, msg->x, msg->len, sig, sizeof(sig)) == 0 ); + TEST_EQUAL( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, + key_id->x, leaf_id, seed->x, seed->len ), 0 ); + TEST_EQUAL( mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx), 0 ); + TEST_EQUAL( mbedtls_lmots_sign(&priv_ctx, &mbedtls_test_rnd_std_rand, NULL, + msg->x, msg->len, sig, sizeof(sig), NULL ), 0 ); + TEST_EQUAL( mbedtls_lmots_verify(&pub_ctx, msg->x, msg->len, sig, sizeof(sig)), 0 ); exit: mbedtls_lmots_public_free( &pub_ctx ); @@ -61,12 +61,12 @@ void lmots_sign_verify_null_msg_test ( data_t *key_id, int leaf_id, data_t *seed mbedtls_lmots_public_init( &pub_ctx ); mbedtls_lmots_private_init( &priv_ctx ); - TEST_ASSERT( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, - key_id->x, leaf_id, seed->x, seed->len ) == 0 ); - TEST_ASSERT( mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx) == 0 ); - TEST_ASSERT( mbedtls_lmots_sign(&priv_ctx, &mbedtls_test_rnd_std_rand, NULL, - NULL, 0, sig, sizeof(sig), NULL ) == 0 ); - TEST_ASSERT( mbedtls_lmots_verify(&pub_ctx, NULL, 0, sig, sizeof(sig)) == 0 ); + TEST_EQUAL( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, + key_id->x, leaf_id, seed->x, seed->len ), 0 ); + TEST_EQUAL( mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx), 0 ); + TEST_EQUAL( mbedtls_lmots_sign(&priv_ctx, &mbedtls_test_rnd_std_rand, NULL, + NULL, 0, sig, sizeof(sig), NULL ), 0 ); + TEST_EQUAL( mbedtls_lmots_verify(&pub_ctx, NULL, 0, sig, sizeof(sig)), 0 ); exit: mbedtls_lmots_public_free( &pub_ctx ); @@ -150,10 +150,10 @@ void lmots_import_export_test ( data_t * pub_key ) size_t exported_pub_key_len; mbedtls_lmots_public_init( &ctx ); - TEST_ASSERT( mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ) == 0 ); - TEST_ASSERT( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, - sizeof( exported_pub_key ), - &exported_pub_key_len ) == 0 ); + TEST_EQUAL( mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ), 0 ); + TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, + sizeof( exported_pub_key ), + &exported_pub_key_len ), 0 ); ASSERT_COMPARE( pub_key->x, pub_key->len, exported_pub_key, exported_pub_key_len ); @@ -170,17 +170,17 @@ void lmots_reuse_test ( data_t *msg, data_t *key_id, int leaf_id, data_t *seed ) unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; mbedtls_lmots_private_init( &ctx ); - TEST_ASSERT( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, - key_id->x, leaf_id, seed->x, - seed->len ) == 0 ); - TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, - msg->x, msg->len, sig, sizeof( sig ), NULL ) == 0 ); + TEST_EQUAL( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, + key_id->x, leaf_id, seed->x, + seed->len ), 0 ); + TEST_EQUAL( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, + msg->x, msg->len, sig, sizeof( sig ), NULL ), 0 ); /* Running another sign operation should fail, since the key should now have * been erased. */ - TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, - msg->x, msg->len, sig, sizeof( sig ), NULL ) != 0 ); + TEST_EQUAL( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, + msg->x, msg->len, sig, sizeof( sig ), NULL ), MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); exit: mbedtls_lmots_private_free( &ctx ); @@ -200,11 +200,11 @@ void lmots_signature_leak_test ( data_t *msg, data_t *key_id, int leaf_id, memset( sig, 0x7E, sizeof( sig ) ); mbedtls_lmots_private_init( &ctx ); - TEST_ASSERT( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, - key_id->x, leaf_id, seed->x, - seed->len ) == 0 ); - TEST_ASSERT( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, - msg->x, msg->len, sig, sizeof( sig ), NULL ) == 0 ); + TEST_EQUAL( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, + key_id->x, leaf_id, seed->x, + seed->len ), 0 ); + TEST_EQUAL( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, + msg->x, msg->len, sig, sizeof( sig ), NULL ), 0 ); exit: mbedtls_lmots_private_free( &ctx ); diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index f69ca9e96c..7ba02c58a5 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -155,9 +155,9 @@ void lms_import_export_test ( data_t * pub_key ) uint8_t exported_pub_key[MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10)]; mbedtls_lms_public_init(&ctx); - TEST_ASSERT( mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ) == 0 ); - TEST_ASSERT( mbedtls_lms_export_public_key( &ctx, exported_pub_key, - sizeof(exported_pub_key), NULL ) == 0 ); + TEST_EQUAL( mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ), 0 ); + TEST_EQUAL( mbedtls_lms_export_public_key( &ctx, exported_pub_key, + sizeof(exported_pub_key), NULL ), 0 ); ASSERT_COMPARE( pub_key->x, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10), exported_pub_key, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10) ); From d6adcb61467ee2146f89a0fdc069c47276f278db Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Tue, 11 Oct 2022 15:34:56 +0100 Subject: [PATCH 064/104] Add negative LMS import/export tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lms.data | 8 +++++-- tests/suites/test_suite_lms.function | 34 +++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 5dd901982e..5acf69caf1 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -179,5 +179,9 @@ lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91 LMS import/export test # This test uses a randomly generated LMS public key. It imports the key, and # then exports it, and verifies that the exported key is identical to the -# original key. -lms_import_export_test:"00000006000000046B0927585C8547228D495361D73B970C287A2254BF8F1B170E55ACC9520A56CE5D2C711B6617718B49247D28CCC6D11D" +# original key. It also tests handling of too-small key export buffers. +lms_import_export_test:"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 + +LMS import/export negative test #1 +# This test uses the randomly generated LMS public key +lms_import_export_test:"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 7ba02c58a5..860304e025 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -149,18 +149,40 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void lms_import_export_test ( data_t * pub_key ) +void lms_import_export_test ( data_t * pub_key, int expected_import_rc ) { mbedtls_lms_public_t ctx; - uint8_t exported_pub_key[MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10)]; + size_t exported_pub_key_buf_size = 0; + size_t exported_pub_key_size = 0; + unsigned char *exported_pub_key = NULL; mbedtls_lms_public_init(&ctx); TEST_EQUAL( mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ), 0 ); - TEST_EQUAL( mbedtls_lms_export_public_key( &ctx, exported_pub_key, - sizeof(exported_pub_key), NULL ), 0 ); - ASSERT_COMPARE( pub_key->x, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10), - exported_pub_key, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10) ); + if( expected_import_rc == 0 ) + { + exported_pub_key_buf_size = MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10); + ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size ); + + TEST_EQUAL( mbedtls_lms_export_public_key( &ctx, exported_pub_key, + exported_pub_key_buf_size, + &exported_pub_key_size ), 0 ); + + TEST_EQUAL( exported_pub_key_buf_size, exported_pub_key_size ); + ASSERT_COMPARE( pub_key->x, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10), + exported_pub_key, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10) ); + mbedtls_free(exported_pub_key); + exported_pub_key = NULL; + + /* Export into too-small buffer should fail */ + exported_pub_key_buf_size = MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10) - 1; + ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size); + TEST_EQUAL( mbedtls_lms_export_public_key( &ctx, exported_pub_key, + exported_pub_key_buf_size, NULL ), + MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + mbedtls_free(exported_pub_key); + exported_pub_key = NULL; + } exit: mbedtls_lms_public_free( &ctx ); From a6b47c0aace2965c1722923964973b63aef6ac7f Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Tue, 11 Oct 2022 16:54:15 +0100 Subject: [PATCH 065/104] Add LMS hsslms interop tests Signed-off-by: Raef Coles --- ...shss_sha256_m32_h5_lmots_sha256_n32_w8.prv | Bin 0 -> 71932 bytes tests/suites/test_suite_lms.data | 47 ++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv diff --git a/tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv b/tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv new file mode 100644 index 0000000000000000000000000000000000000000..db85e01b7d222d0404ea64a43630ca456366cb72 GIT binary patch literal 71932 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໰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 FVlI*UgQWlf literal 0 HcmV?d00001 diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 5acf69caf1..1201156ceb 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -146,6 +146,53 @@ LMS hash-sigs interop test #2 # * verify tmp/lms message.bin lms_verify_test:"0705ba8297c7b9fa5f08e37825ad24a0":"00000001000000040a432454b99750f7b703f0280f92818b0570d0267a423b377be7cf0561305d4ce987b9d8dbc1c3f8ba410bbe6b921406eb802688d2dd8a1a6fa4a124cbcae9b5a210f583a956384c06311953b038b4ad2c2808224fc3a6410cd3b89274371956bcd4253a251cba6409b09c822e1d29d7a037648a6f2562d0df6359a043622f256f5ac79736c08fc4185758ff002a8397e560d5812373946348afba2ccf2cc0f3ba741ec076d4587a54b8b625804b814c30540152a3dc843a590c94cc23ba857e4c458c8ab687b5b9b68837ee890454cc19bb5f42a1e6dc051803fab50b440067a903013f675a774b5d02cd56289518d65f869f22b2e2b58d499e9e3929ec5a9f5d6d6e03cf91486094aba7c88491cde35b81c175c40410bc402d20f0a73a4da844d3a1d47e57618b7f18fa5ac85e877b5faa1e0b6733c2d96b2970fdd6e606435e3ec50eafa88f84fb7512217aa4be5858a140f242603bda634d76c484a184298c4da903094468d032b88586fd2f35182405cd85115af6a0bbd431f2e44217a1691dd8887db91d3b97264ff552ae7dc110a3a111f2bf74ce42079055dfb8390a16d67f28b738f837aa7880f3134deabcf6ec74cdb521bff44df61c999bf7a8ddc43b64812cd4f3bfb15104867d5e585d1cbf99738e0df92660b3e9135a4377d1199b8b97362fc87ce3c99db3b8aba63ba35eb353e5ec79bcee82b9ccc1b4f7d1b8ce7e5f8813d007be3d0e45cb8e7173337a5a7c4d32ea5116e0fdbd7846ea1f366a531449c78cd7a16ce5bffcd6cccf54b7f249a74e0df6b07f6b48db42eb958ff18b06995368af0cadd82f44cf44e4b53f0993de5f06b289bee41cd25f90a9fbd1bfb1ab2451c96b07adcfb5210d291dd505ea30e5d30395c8d84eabccdd2c7d6f28a88f5e5d245a6980c57810cfe17c9a37ef5e79b7b9ca755d56a789d21985372bed42ae2830d81ebf0fad6c721bd1d3ee91ae363f40d386aac23e7c0db965539ce9bff38f0f24bec3227b5a24f4cd7fa71ca9d306faa3fc4726cdb6634f218897b79a4aed67a58799285104eed74703ec4af6d5738b27b4d6fb71e52c1149069483a7cca6c3fccbdff77312ff5c635d8b0ccd53dbaf7b498727f7c7a70d3fd1c3f217e2cbd0dfe91258acb7f79f53f56012a82da997ea777b76dac0472e5f9830a93fb09703b1c0e45cbfbf641de94fcc6c609f02a5b31ad5821ba6cd48829fc5e0c4ad78e11e4cac8efbb1b170c794b7b131b0c1c4e39fdef81db9e7acced5ec824aed0c4e6b57fd1add4191e87be1446c7c519eb671205ce8c5855ad7a2b9ff7a9cd5c45336f508d0f8d2c1152dc2656650bdaf8fced642f3a4d445b5fc49910bdbdc9635de0086ee9582a796ca9f6052de805f41dfbd3e94982a05cbd36bab583dd5b1586ddbb3b1a45f1a265bec062c1a50d220870c0c622d852e650a67f31e8eb3d19e964de0926712b7f429ad05024b8db51eb6702c39580f62f037388862251bf66f02edee9615a63957eab75b28501f9f26cecd09a5c949127c9a3095036667fce8e45ba75568d5160fa1725a9e0038145d948f437640dc4441000000066e8db13a9e79d10a4e067aad448a1847b5489a62cde3054ee1e5ff2e37549d516771f06926678fa50aa7167684c1de108944b2c4a3358f5e926368009e4500a8d4d501124bc25a4c9b1cfb954503f4ae26c92221e39c680843ae55cfca972e139c82e2e4469a703a1866fa0e6d76636591f4ad07f7d1eaa19077660ad46a6f9d534970e6a49e24621b7c7c283253dd22fb24eb7819fab84bab88e42555d5437d5afe06615a7e0d103cc8595616690f1337f4345cf418724f07d0dc4d2c0899b691691f397202204ef34342b5725dc6adfe549ab0b887572ad38113c407f96fcdfeea0ffc4f333addfec296169e53e3c5b24797a20f3b2f043f5e96920de9927da466f09389d3e52a5665f380f68666a019c201e710ab4c168d5ac952a02d5909a6fcaf498a33e2124e6a828203744ee3fe70465adde0cfbccc1b4634541638ab":"0000000600000004e18760ef2c86192aee88579e376f35cd153419d622803a483e79f6d368629308a8ab6ff663c4f108b2033af290dcedfa":0 +LMS hsslms interop test #1 +# This test uses data from https://github.com/pmvr/python-hsslms due to the +# limited amount of available test vectors for LMS. The private key is stored in +# data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv +# +# To reproduce the signature: +# sudo pip3 install hsslms==0.1.2 +# +# from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE +# import pickle +# +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# private_key = pickle.load(private_key_file) +# +# public_key = private_key.gen_pub() +# +# message = bytes.fromhex('60da1a17c88c59da8a730e6ca8effd37') +# sig = private_key.sign(message) +# +# print('lms_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), public_key.get_pubkey().hex())) +lms_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"00000000000000041394a893e40be29923751880ca3cd10b5a67c2356c87c240e0733c3a3781b421f89dcedd553f5c1c0fdf4e53e4e484766860bf77e6a1e5911c9a389390f7d62accb581ddd4d6479c88a9ba3c20235805bb544db1da6667c5bd6caec6a5cc0afb02ebb35c1db7aac5d16446d4f8fc3518ed44ceb4eab20974627ccea5b1571a292bb2fa08ccb284957605083bfba07a33f233c66187bebd4523d095e21546be84ba56ed61768b9210fc754c78ca2d6a788e1558533d5407c45b04a0bbe6a20d0660efec80e1e468874d81c98d81acc87981c236b68695fbaf70d188617fdb86a5840c835687249f688434159035778260026d536570f24a422d5255d2572603fdf631668074dce5fc469710aa99a1f21280708e73bcd4e50492d2ff1dbaea1058974fbe9bc393a4f837987faf0175b814ebafa02095bffee2518a6fbb3555de9b3ff0c87c0c7b2c61ce3ef25e70e1a2ff5aa6dc7dfb3533e53192bc68807727b76c8752bdaa2c8d0c66e6bd94ff4df2f9fcb5609cf9bd04635743340736b84a98c3769bef074c081ebdd0fd17e853165dfa4764b23c63dd8a4a8c10b58a790ab92f81a32973f0f60d9f33d801a2c476190a7f8521a998220d8f838c3932da4dab89f62e028973b1891aa0954faf3da6174ea445c0e6ec27a58bb74000253fd3d76909298d44b3beaea58f130102cba5d928afcec92991f9483294f0fb52c16df4e98c0839e058d064921582b144602306d0a1ff623bbc1b1de106045384cb0f20db3198d99b266f83cb7c4585786477cb38b140f7cc48fecb9c5c272df2881750af48da8ace04e1b109de3a295c91373c55e8dd36cdf455c17a0b9c27cbbaa80a7571cf5d5074c384948a7e006ea6346e2e8fd1082f0d7a498c6445ed2da31014f4476e41e1367cffac8ac93b7a59bab5e23dcc9130f8e3264b2920e503246e11fbb15b599e58350cdd60e3a370c7cb0a81e73fa17eb2f12702ff3c1cb6a75d7718687d545cf9d00d4bb277905291ee86f1dfc045d9c59d6aca2faa90d2654dffc652fe89c4b37048f8c46a6410aff4e46c281c1d4b2f6ea1408d0615bac721ece31a9a69c70f3b860d730996ad735eeb376022c4828135466101cdfb2c88cf02864c40bf5c5aa63e44d58c8f28933d8d3c53883a95f4109a185b7fe6eb1d87d76823e63bf9d72d96b60d2cdcf942ca06d4f278711eb1eaadf11e9bffc7af361ae0c0fa23ba2bbc2f673a05c1ee3f3ccb3bfab4dffc4b9c234b0b9c34fd1b5f0d01c4e10cfd0800f90ade702dff2c893f098de1637de094fd959440009ccb34dff6cab72fe80e839e6e89551274e6cf6e862532f524c804259a0c8e4622c106df6431dbac870cac64f7099674c8050f5149326d961af7486e8229f5b5eba743ef78dc56b4f3acb1ed5029fba223223a5e835abd61409316a68c899abe85c0514642dff696da0be97416d774fa7f5dcc3aa2c8469b47516f7b27cbbc66faa4e62b6a3201f7976ea20b89ef349a497967c093e3431df9d619a11ed2cd930324438f4cc9d11654e0c9d229d6bd239487598a3482f63294e9e85c29a576b1c86d0884000000064c6b6388b7436123dac99e0ec7fe53b075e2ba9844505ce1eb3c7f70332c6ac543dcda2e63b26f5efa39ced6095a54625e67ab25d3df068e903eaaee894ac0f1fdeb4a2f1390f655db3608583eacfb0be4282f7bd1c42c5d748d524d7cdcd45878dea56cbc11a63bebbd74a5413ce72a931b1d4794c78c4cf16315bf2e055bb3305fe0272c8b916856cc27aa7a773ddce62afa7bb4da76c287e0ed3ed10452512de82c051f17b49c608b1a259e16a3812c0de684f2cb1ee59296c375376f146e2b0cc299ef41ed8e6fdf0557ec8d95fa026970f8d47c8347fed1e37e018413c5e813d1726ea18bc926ed02840349ab3b2adc8758a9cd57be38e9e76869762a81bb79721ca1c031c9dfdc3735fe9318064b62c2a7e8e2ec099963257b0705aac812dbc8cc3fbeea81af7c0d592c7e2ad1c21e877d4ae392b13ac1b57a8311d406":"000000060000000447cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":0 + +LMS hsslms interop test #2 +# This test uses data from https://github.com/pmvr/python-hsslms due to the +# limited amount of available test vectors for LMS. The private key is stored in +# data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv +# +# To reproduce the signature: +# sudo pip3 install hsslms==0.1.2 +# +# from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE +# import pickle +# +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# private_key = pickle.load(private_key_file) +# +# public_key = private_key.gen_pub() +# +# message = bytes.fromhex('60da1a17c88c59da8a730e6ca8effd37') +# sig = private_key.sign(message) +# +# message = bytes.fromhex('92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1') +# sig = private_key.sign(message) +# +# print('lms_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), public_key.get_pubkey().hex())) +lms_verify_test:"92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1":"00000001000000042e758f2a0e8f301af58847b6973a15fe4856b91af88a1ff601e2f0e87bde33afbc39202a66e38931fbecd7d493cf957b37eeb57ed2e4d8f693b97adafa8241746d775cfb9471688d935e090581eb8586e7004d6b8855963d82ccb6f79df2d93dd35848556da6735def0f0c6c8fc969c1df692341f6a99626eff37d20226cef361c8802a995fa43535fe2336d8ae468c78eb6a7082e27c2c6317c034369b588e3d65a2eeac9804b427702dc49f681a841076813ed407399aa778259e7c34c750baa6d296a384e1274facaba9e2214d197628f5df7b2bf3896fedeab377b8edb775d6e8d67f1474ba3066794447f8f8e0c13552a007557a1f1c3b9bd2b41d9b446c6bcf36c828fd4c80850a31ee603065f5cc90d198df03835195b14e27da7bf727a16081fcc787f1dc7fa6da8b9ff908fb2c02d6f2a183486de0e39cd7da7fcdee0c8e96876c56ad9b0b18e4e4999e2c81a618aa4b27e050ce488dbb1e79089131afacc446cdf15b625f4e011f8d8160bb93f326bca3bb56fa41e34893d55f17d746fc142297997c5dbbba8f6b6c80678168ba455f12bac6982e5192de5462a46e14a45a01ce9e07279aa301dfd0fa9a12c6a55059b19a19d7afbe99779ea130ddeeb5ecb67d2ddb6c1c5d198e421b78091efa5aa429e1eb052760c0d8e2eb0c0ced000e93f7f265611a385f77c0cece0496eb29010f710e70a768d3713f0b7fc60c8ce372dc3234f27c7a1c2776a939ef70c7be869337b967df2223d4f20dca697e3bb6d0e53bbad153ff08d579f60c8535710f253b90e73ee9a19e1e57df66ec6c85ad1b4cea28a9d62fc5a4cf130f70b910dbc7e6f0e6b0cce1a1b5ff106b7f0b101405c0989084b2c94977116b98d15d6062a8d77d660aa813d432cf3338484308b7beed10236081f52da44eb807f9a75fd4cc1ba998ef3fc2e4791712597c786dd46431468bb4a1975a6cd854a1da23912fc99160f51df484efc9371c2d8e028d9468635cf93226f5a8834d14cead59e5d2a61dd6440d7b91c903ae8823907b75595c4828c7710036b347dcfb67f8561e835a53f569c8b3a1cd4317b2a6b2243100ee3d9468f9191acf2276d18dde9ebf2e11a48ba1fc1a15dc51091d3358d8d1f65ec7d84b97bb1669a9141f74065454f08e5ef25432b7635b8ec673ca70e4b3c25d07975a6fb725a56f28c1b5a81a6da2fe0a2c3474275926f9819a25b942462a68097e1cf6d9ae94f6b1f76b54addaeda04f9fc8db025fd6c453e1ad928f9323bf1381fce1893938828612728185d22a3d45d21ce762c066ab53a582c487d76d431e5b8f65a382142dd823d4620931e5572a4e6aee69986421afa119634bc8ea88aa6535c4d619ca0e0af94934637bc0c834e5e2a7a2853fa73835d00e13e5f26ad085ef66c8efb60097860cb199e03596a3b8f0ec78690d527bbc9363dd9702226788b1529871df74918ae2a4e02745043bd5ee8ab027826fb4cd54b0c27d99076757a1b41e2725ec02adc7926e8213796a8aa1740a2dc675437771e0364a83b0bd64c9620f6c203d92626ff29ef736eac0e13c71fd1957333ee0048000000061f7b7d6f916710efe9ed625ae689c67b3cc1cdf0d672e58c0b86b3839bbba2c243dcda2e63b26f5efa39ced6095a54625e67ab25d3df068e903eaaee894ac0f1fdeb4a2f1390f655db3608583eacfb0be4282f7bd1c42c5d748d524d7cdcd45878dea56cbc11a63bebbd74a5413ce72a931b1d4794c78c4cf16315bf2e055bb3305fe0272c8b916856cc27aa7a773ddce62afa7bb4da76c287e0ed3ed10452512de82c051f17b49c608b1a259e16a3812c0de684f2cb1ee59296c375376f146e2b0cc299ef41ed8e6fdf0557ec8d95fa026970f8d47c8347fed1e37e018413c5e813d1726ea18bc926ed02840349ab3b2adc8758a9cd57be38e9e76869762a81bb79721ca1c031c9dfdc3735fe9318064b62c2a7e8e2ec099963257b0705aac812dbc8cc3fbeea81af7c0d592c7e2ad1c21e877d4ae392b13ac1b57a8311d406":"000000060000000447cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":0 + LMS negative test (invalid lms type) #1 # This test uses the data from hash-sigs interop test #1. This test has a valid # LMOTS type (0x4) but an invalid LMS type (0x7), and should fail with a bad From 8b55ba623e268a4612cd8110f4ac7f6d86c85c2c Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 09:28:26 +0100 Subject: [PATCH 066/104] Source LMOTS data from hsslms So it can be reproduced Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.data | 85 ++++++++++++++++++++------ tests/suites/test_suite_lmots.function | 25 ++++---- 2 files changed, 81 insertions(+), 29 deletions(-) diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index 0845a17d09..7ae80e92f5 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -13,26 +13,75 @@ LMOTS NULL-message sign-verify test # signs the message, and verifies the signature. lmots_sign_verify_null_msg_test::"00000000000000000000000000000000":12:"be5fa89144f2d665c66ead8216bc02006e0eccd8b3697a0aea44f6c93afe7955" -LMOTS hash-sigs interop test #1 -# This test uses data from https://github.com/cisco/hash-sigs due to the limited -# amount of available test vectors for LMOTS. A public/private key was generated -# and used to sign a randomly generated message. We expect this -# message/signature/public key trio to verify correctly. -lmots_verify_test:"C80B24A82D52963AB241C84DCF0EEE55BB24F9F0":"00000004DB3B6B24FD191CE8894AE3C4E2CE2DE0C3F5D508691A9162F37704E07838488466CCD746E55BC8E3055C7A4D4DA2E10775DAFA2E8E5FEFB1CEB25973BC3323B61DE5E2EA7DCFF15DA482320F958023CA2E718C69B977019E8F2FCD47151388E2E5E11170AFE93BDEB508362B3A317835A9DDEB18F0CDCCC0731902DB3D37F441C93A490DE53962A915AB5060A1C157D61DDF061F272362AB7FD9EE95AE48D3448F204C81A3F260792784E1BFB49871A27C09CC549A406520F0B40BC74CAAD082EAAB12C994B8495B8C80E96384FF2222255BE6C4EE5AF439534E616F9C0B53E951F69D59BD0506C0C0366A679A8329ACF6E2D1D4E4EF49D35375A8EA46FCF3C9B2F8E033C242EC61B796E43B901407077A2AF3F0AABD2D0CB9004F10D91B57C2D5E8BA7BA9268FF94962CC102F55B5120D7D2F7A3BE281BA01D78895ADA2F05B77967EDA0E1EDEAFBB9BBC3D68DCBF682FBC70467FA2BEE5DE65F54247C4BE5BEF41F5108B6CD09E7698E3AAEA04B60746EDD0E2623B66B092DDA21EFA5A0D36805D101D805CC06F0E818B46059B3984C8B8A526C4239F66ED34B8CA57E178DC5E7B8D2BE029114B4CE466E2B5A081729B3F3A3F3845DDE177062F201C09125ED3CC381AF35EAD795440C421A136F941F09F3E4BA9E0203CBA875AF477AB0246342700F323E65DC327D27966377D871FD9C58BEC8797DEF35E1D0751A554719828B87332F601884EBFECB63A8D4F390785B3826BFA384BE502D2322C919ABD12A486C2AB124DCB7B74DE91241A30EF0388411E52145A88971C6C0A4E7C4F23EDD8D6008065A3D108C6B1EC5219BB0DFDBD37EE3A7A8DD37E3563A5777838FCA61E9E744813F39CF70B5A0F50E1BD4FF8733A3BDA76D2135969809D91A9786F22DC2ACBA4E0164C411019EC77A0BD253A42AC7528FC7C0DA1711FBD6C23825207060463080F9E04B7D819C8B150C22B8BA87C6277696EC409369C48AC0E3233DE52D31EF6D2207D2B57DFC2D0C43BE8212EAE6CB1BACBC2D3568E5527A14065D5F1F56AAE2AFB5FB1CEFFC228A30692BD030C71F4872DB54F2632CD919DA61576CF58D1EBE3D7988183A9C789EB74A3D7F6BBEBAC035A43397BF684C9E1130B252940DBA4454311A6A3D54D9386D48E1D5A3E70944EDF725AEDC5440CD610F79AB05A43C917FFC15213295EB8CB8432B6554A47C2AD419ADD52E0F5E0BD7A1E0F873257E69F8647F3A07093387B7A64C4812CDBEE536E45D531F89653AC5F14A4715CFF40692346FE6CBF2F9B92D9F1101C379AFD5E6154605059C1DA463B407E79C139396623DC7F15EEFCE424C8E214C6A645EF002F90A230D8F62177CBCF2A688D4F822B119835AD3D3A619F46230257A5AD59CB0924B2584DBA96AADE0A2487E7409EE5993A4F0E3DC46C10B96595CDD17D72C35EF4A52C5906655B0AE649B5DE03B7D46F3839E808761EE05E9300050647593C048669A952324B0188ED225AD11BED3FD94E44E134FB9D6DAD53CC34ECF62695E30637C4528C450D62174E2F8ABA2C09F134412EF889C24B36224BE4259B363A9D8EB89BAEE16BE1898D46":"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A":0 +LMOTS hsslms interop test #1 +# This test uses data from https://github.com/pmvr/python-hsslms due to the +# limited amount of available test vectors for LMOTS, and few implementations +# providing direct access to the underlying OTS signature scheme. The private +# key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. +# This test uses the same OTS key as the LMS hsslms interop test 1 (leaf 0 of +# the LMS key), and the same message. +# +# To reproduce the signature: +# sudo pip3 install hsslms==0.1.2 +# +# from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE +# import pickle +# +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# private_key = pickle.load(private_key_file) +# +# ots_private_key = LM_OTS_Priv(private_key.otstypecode, private_key.I, 0, private_key.SEED) +# ots_public_key = ots_private_key.gen_pub() +# message = bytes.fromhex('60da1a17c88c59da8a730e6ca8effd37') +# sig = ots_private_key.sign(message) +# print('lmots_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), ots_public_key.pubkey.hex())) +lmots_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"000000040bb462a8f59a277c1706ab69b1a40b0d56a3ffe1ddf0dfa890096c7a9c48b360e1e8f7abe4dc1950c4a64545ce6c0fe2a34477ec40f56db4eec37c1a2168e3059d4338a4eb368a64be5f98b5452f2c2fad23dcac585f5fe308bfc3df0b5cbc6cf3545236ed6c5a863e677521b5b5cee0aa1e755c3bbf5fb7326fac1a88cb12dd7f8d68ebe8bad07195a12fa11299073731e67f2452009252c595fc7d9285b90aaa912eb6cf0b5debc0996ca55ad5186702b244a616c4b9e0ceeea229e1e821c1ab0db906ce87640d128f1d8c4742d9baf340a8030df726a99a9b97f139ec57d8d87efdfca235f12de64e0a993804b95227cdfd26220a84502e350faaf5f91f3f49610eda211f9409005679e32068def22a2dcce3d226d0f68c4abc727b90d9c01daa05db24d7c0c9e9e48202e3420992ba78c36bc21c45cdf218801dc7053e3cbf39c141784e7a861671588622d540187912234ce628ea9cbd1800d215641163c762d2fd9194fa54bd9b46c83754579476398a5c2fece4642f1ee286a4e9a310b5e23088c75a68b123044c1c365c8b53fe9f895fa5d76fe1277c7c0f2a39f5b233f7d2acd5358feec2255feadb1c2513c4351c9bd1afe22d159f2d392c83bf7ec26b59e78330cd346adb85ef62fee3da63150ab5e0d7ce5d0ef353895360017faf3f35aca2cf3b8eda65389e2ba86f78ebfbe73382dfe9002331f24e96e1a6e56e7cc99ee848b82ad1ade3229e9e28168acfa8c059ed03028e8c872e72ff4cf8a50b84ade908ecf229a26ff1007c476d1aa376323fc567c9471085336496b231b5245a43c6c86c6a71c1b1fb4bd87c2d0b026bff55de121620a089ed9ade51c3bd91c703844c180ef9ad0ab550b9560ba9f1452463ce20987a402213ca5c16c927a0a85091dd74fbee22cac6b1afbc7e7dec229325c25ea3b3cc5a1c48c80665f9903e482b143f7cd051bdb990355f79c62553453c72ccbcc578df77069a7b0cf6fdc6853ec2f96fb7cc100216ae1b17aa20782fb0cd0f261b76a48b5d6f7bb48fa5f78c02a11ee81a8c0c81183910af770f2e907ebd5b2dc3a2b83529f62da074ca73c434f8f30b68a5dfee740f78d2c13b53c904e46dddf723923bfbffa437a4130c8c9b6d79a57db1c408b9c023f80fb3d766cb915e722f3b3152625d77bce3ca0c01e77f3750d7d1bef1ddda8b9b4233b09c89abe5913db50847a7ea219c3f406aa4cf41b6310bafa99a7b14f94b8ccd4dc7edb1a1e963ce26a53f3be71b4151ce5fae10ca30055e754880680e38cf2f21251f229341f7af9536360a428c2593c43fd2ae471bc1fa2b45ad55742a2f12f31eed6cb67945a898650c13650c4cffeecba8655f87e49ce921ced7ab00cf54eedf0c70e5c6cfa7f006763f0ac14d80cfb1662321cdccca8b1adf426eb9ca16ef2b978bb9ac229131fa5c1266a4980449c324ebdd8bcc98916089ee0b6966da7dc25350bdc758431884359d02f5fa567b39f49a6e410da2d0363944a090926308ed0ce7d565e6c4585ea010bc38ef1c976ae16ec1fbe6fb9d4d50e49a7be8273d2d56bf4e72acbadd90d5f8dee0":"0000000447cc5b29dd0cecd01c382434a6d1686400000000761e8e577fb4d12058806fc7bdaaef0ba64e454dc59b0230a77b43bbd83dc8c6":0 -LMOTS hash-sigs interop test #2 -# This test uses data from https://github.com/cisco/hash-sigs due to the limited -# amount of available test vectors for LMOTS. A public/private key was generated -# and used to sign a randomly generated message. We expect this -# message/signature/public key trio to verify correctly. -lmots_verify_test:"85A77D026E8C704B14EF665DEB0A648350FA8859":"00000004BEEF900CA9A14982E011A5A94503D566288932AD4B9CB85D1551C766A56F788B0D223FBA0E1AD722BE48365B4CE5DA21051B3A79EAD8C1046944192EE51E162DE1E9AE9B13DD8FA90867A17666CB8967F7CD7F4F5383703CCFF555EEBDC8123AF3C4E39D0A5D61725B6A7F23CE587D256C08D31510BCD895106CD524B432A9211CDCBDF5ADDAD5F1D76D428A76DF2556FFA8AB546CFAAA7F2FE86164B976FDA2940498DB0D1A2DE29972FFD55D83E7CA3318DBAC31670565A1E5F59E36342F887E0EF7855AD93CA5F1951307D79EEA375168BC35A3A0B053AEBDB4D7157AD929B0D7DE9FC1E8C32C9A2D679843CBC77560EEDA5959D0AC8407648344C6952649A303E7B6FCC2EE979E1B2786B898A01E2918894DB4E37A0ED79A30260A45959B4BB3016F081181190CB740376389827B2D56DF7EC00871DC9A198B74C7C6086C940A845D54198F2D5DD7A47F97A192F33A85AAA1304A3251B82AC33C5E7B3BA20D2A9BD49BBEE0B2DA2338E578E6F139BB7596DC3BD89E86CB393C42765B9FE85457116906C3F9A8499CF5E539A5CCB3F6D1F36CA209DE6942F807E579AF0EBF072EA110A812C9E420647CE7C8B2BDBB5F56C5B3B7EA80A53C3574F4ED32E4708DFEED60280ABBE2021B3791B0CB09C1F0731353234A6A327CDDFD4E3E2D9DD5A16FCDE3EEF09C67065BD702C07B53A005D3FE7D23FFD77D40E49C82165EB104343A166E808A3CAEDE1A43AE3A82E1788B49C565CF88A2AB8E2FD37657D53E3679D7A818D864F55144011AB498A4A985C46342F3562FD80ECB86497C3DBB759006E5FFFDC01CAA15C69B716174EDCB6E9870CF391003D3826451D1BEFDCC84C093428EE01DAF883190F5D2542B36A7DE44A453AECD5E93B768ACEE75076BE3D73A66F17CFD8E4A49B1F61CE9446815A86FF5FB0EA070A751893C85360C038A161D3DD4D2C66F440E7265153AB346EF620156605C028DD9636FAE0C9A20DF09303ECC5E57A6424505530F70D25F1C95FE51CBD82C2AD0015EB9AD5379CEC463FA0331A14DD971B7C2311FC45979C531653E7252884BAB7C49F8CD652BDF6FDFA76984445C63B54ED22B4A8A267D091381BE7B9B7608133968BA46106BF42B9091F78C085E674D1F70FB91C68D07733F6412B1583DD2F37C6ECAD6BCCE1A1C7D0A7CA80677F679A5AFE08D15427E5C78CE6EB9AA90F51F40343DC9FD1316DCEB2C1EF8EA217B714B0DE1AEECE04D19D0D7757481EDA6E8C51BE85B7B24720E8D62B8AEC56C1A1B9D278B874AACC0B492CF44ED4E7B1200C82323C1AFA0FC776E92B227E8979E3A92EAB05FCF18A43AE648397088F4991F73ECE22C03B3F42F51C0C0FE0DF37919D048FB473F7AB0E33310B9782DE56384BD888CE5E2A644E20A52DD47F710DB0D3169991E29E716ABFD84CA4850080B6C252CB96CD8979189819E532DF56ECB172F773919733BF4D442901EBFB656EBFED4C6D83FAFF288279779499091C94432ECDF83188048AB596D65BC48FA708D485F9CDC50C8B470DFE22157E8F5EE366722A04E8CE7B861573E5FC97D34055BB50B562738F803B202F7F8":"00000004DE9CE10EA7125AC6399B6B3C7EE24224000000161D61E675F3EA19C5B95DA4EE2E35BA061B39E7639F3989F8AE4B0696B3F87E4E":0 +LMOTS hsslms interop test #2 +# This test uses data from https://github.com/pmvr/python-hsslms due to the +# limited amount of available test vectors for LMOTS, and few implementations +# providing direct access to the underlying OTS signature scheme. The private +# key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. +# This test uses the same OTS key as the LMS hsslms interop test 2 (leaf 1 of +# the LMS key), and the same message. +# +# To reproduce the signature: +# sudo pip3 install hsslms==0.1.2 +# +# from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE +# import pickle +# +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# private_key = pickle.load(private_key_file) +# +#ots_private_key = LM_OTS_Priv(private_key.otstypecode, private_key.I, 1, private_key.SEED) +#ots_public_key = ots_private_key.gen_pub() +#message = bytes.fromhex('92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1') +#sig = ots_private_key.sign(message) +#print('lmots_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), ots_public_key.pubkey.hex())) +lmots_verify_test:"92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1":"00000004e29f47d2314ebaf22ebb821dec653f5bd105aced5d24829787a93da910baa495cd5a8576dad606cc7407c4d8a38a715ded879274c5347a200cc1c08a6fcc7288e280bb2e66b682c4b20c514f7a990ce01594001917be8d1cb5a23c22dc00c81b18b8047177cc109a1ff862f535319b703be8e4439062348b7bc73e85e69f7d3f033767146130991f78b497e2a0eee1059d2cd87e0a99c1aae47a6496664735cdb383a8f7a1d686199cf2e07a67e9ef409048efb76cf0c689c1c6c67a5b6966e4b4773710bdff3f72a4f85428187f912c9f13a8bd06533450ce04dbbd2c022eab44a5f6a822d78918f692fa5c6c90aab8941072d679b89388160556597acf17b95b3ffdf8c4c21df5327bd756772a45fdde182004d91cff5aba111fbb70b5970a7d7416220de31e6e76646372e4a1606fbbd5be215a32bbb84da99c63af271edbd42ee87de174cabec7734b6d924d329640bdb84059cbcea89caa703667f5e1b3c1c71b53213f1cd7d1da3e42da70edeb7c0b596bcb981c08eb0f02408ee028a57165cbdc36c9edafa559826c2e690e73da7c7fa1b0fa0e6041a692a2e8f27af80513c07ecd89caaf78ddf8e2edaa17bece335068153b253ceef38b491801c1ef7c648045ce7c517afab888603648b17d3a98a3b5622b469a829b023c5cb2ce42462c28d22bc3de91dd8b38bab539971b0c7596dcd0d8c0d84bfd7925d6e2f2d114ca4f91fca12178a451ac0dabc8c21396ad5be57ea0648bd1054de00aa7fd3d46453ebacf6b611e05842f5f019aeca3c798ae063631fd5e56ea1f7a21bbea5c30e6d60a724ce187e7c497d918d2a4d5094224dde94a02e851eae1626533992a599a641466e4d683e40b5a28695aababd2d7f7d2ccee72c289876c8d581babaeb3d738f1d1fc765e9fee3f70670913e07cd38fc7b37e2caba0a735352aa3f4b2467010bb1b725d4bbd86d8c98eece10e925d8bb5c0e993dfa45621f91596f5d1e1446b118c48bc1e403627fdd299ad4d3d5f3a2dfb239bf22e7ff25d83287ba3a96b24cda0252df1907af1cb74d31d720c5baca0f316769f7f98b409c17bb543c39628446183e326d0745b4424520a9d582fc817eac55b0efc2ca4659a60a95e1d3b77bf1454e5cd4d1d54d51159d3df70a78345d1d6a7e0746b3deb080883f6506e9e7d0fb4bddaa66aa7cf555df1bb9d3f848b7e604b690a403f4e40188110e0ef9af15dc4952a8ed100987e39e8184be8dc62441ac2a561c7cbe431c45b0ec03c41c4867e38925977fc240ed2a04d73d4319435de354dfe0184220c71bd59be4e7f6dc9a1a27f4eefc990d615b2c12e13f1821727a607afdab359d2bad5b1be689a36662e052cfade2c0f5cc842c090082068d324f0e338830030d255ee6e6d9303c0037c24985338dfa16b5980a99782af1b3aca9123b5063e0b9f1a31105e2c9eaae2353b2ed53dab5b4fb43b4697d05fcf4941be071edf3456ac8e35eba39800ad968155574c14b6ce109982177b00ea5fbb739dc7553e40c98824d4932185e61ccc380b07476ae210ce3657b24f4639261a5e7e0c52d6afdea97bb2fc":"0000000447cc5b29dd0cecd01c382434a6d1686400000001f337dde97685d008a4440b59550277390018d3f1d485fa4b8c91796032de494b":0 -LMOTS hash-sigs interop test #3 -# This test uses data from https://github.com/cisco/hash-sigs due to the limited -# amount of available test vectors for LMOTS. A public/private key was generated -# and used to sign a randomly generated message. We expect this -# message/signature/public key trio to verify correctly. -lmots_verify_test:"C32F83EFBFD87F386A6C0850CBB93A75F2506A35":"00000004BD2D174BEBEEF1CAF06E4BF1088DE2AAB17C0528579BD4E1C4A1ED583C36BDACA49798373961B605EAEFAEFC0B4BC39C7AD30572CD29BEBE9AEE503CA2D8BF8C31C8A1B71CF67A18EE01A8A878699F22A1AEE32731E51E3EAD3775EFD8339E263C5A4544559506BA5502B9AEF59217ABC24923EC5E28D18BA18B0D964DB277007A76B8075B39F48CDA92148C9BAE1C7E5421CA753FA2D6BEAE8F49977E4E5B6F38D35BA28A526A53061E57BB92DA0EBBD4AE01AE9FADBED74F503DC39FA2E10C20B47DFB3DFBE25EC35618D2307D21716B10F8FB5095B42C289D1847E5D6F9988C6763D288667D3B658A4F3613E084DAE8B78E0B295A6ED28E88C676995AA5EB1533CDF8EB6F95A5E5117F06B1759495A9CB6E40FBF1F97FF73FDCBFD315C48DA631AB0425CA0633817C46F25E84AEEA37DD77310EE56815E83F862EF14E15FC1246243AA02F40EA32567237D5ADC2944BD63CF55FA4F0DE251B3F5C067D9EC396D5E20F9CEF2C555D89DA721D91D6D607653B97636AB10B74F39FA984D23A3D276EFF5F49C336274A66AC491EDE34686C6CFC17F5312FD3E3E5749A2E472011FA391A5ACF09D918B01704B447FD5E3EA6BB726A3475775DFE6A98CE5473CDEDB630EA4D604BAF36A8B8A8E567F05929E8A74970AA742FBC945021017E464E753D5AC497925AA4AECA0CBF562B2E39F891E177FD8E4E61A698B099D21F13EFD0DE5357A1970314D8E3AA1D2A84D3BCF75A7876C16F585322CC4C613FE3AC8FEA5F258FC9C7200765E9209378C362AFC1A478A117D913CE2BEFEB51103E48D0802618C50918005F1AA4228B67BA1A1B001A91A032019A135B8AEEE3D0158A602C8DCCE5A6580DECC16204E410CBB15FCF36704BB2ECB826A229E45C454B4A5DFC12796E636B300C624DB4E6EAB424B17A18A5A5F52399F247A1507A5985D06F90889FE381129148AF8447B392D4EC0775D91502B48D9F212FCE3F81639901C462F752E27FBEEC9E2B7F8CCD16053FB839E8ADF8CD3E8FF8AF3B3E884F4F524C2026BD3B337B7058B53CFC7596F9C813FFD746B8AC0012C60E96140934B4EED1D8602E57A1A6EBC01FCFD66053AF9614FAF0D0F7320D50D440F2A3148A0DAEF5E2FA31F854D56045065AFAA52A60DC3321E2D7C104FF505057D55CD94C53C31C14DB0DAA4D55C4065CD9BCD78E1B8532A680F7DC3544021346CC59ADEC061DDA1B7606BAF28AD87C39AB8AF3D03E981EFFE50B4D5347175517EF212E61F02B594A96492091AC82625D334504EF19BEEE52E01B111D43313F35EC69C88EF38926071506AB3A5B372DD6F2B901AC1E12E61CCB3ACD3D0777A7A10F137126DAD0D1970D369A067C3A1F19D9CB8756D7130B7EB0C08CF725EB2ADFAD61204195CE14F3C99A88A9B8FA2FDCBD612DF9266614DEA073C9EDABE07B3793048167D4DA49B305AE27974D48A296871350DE036CAA348D2F9A9CB19DC094E5904E25DDCF5657227DCD2A4E620121FBDA032A58836EDC14F3A7C4E51319A60F91F941CC61757498B769799394574C9D198426AC3499F0D0BA1770AD6BAA0D3716333F785A9D7D":"00000004DA66203A7E7BCA2362DB3C8E897A84B10000000D1BD4EE08FAA341C2CE018BD12776E1B8E6B8B2C1EEDAE6BD0998E52F089936FE":0 +LMOTS hsslms interop NULL-message test +# This test uses data from https://github.com/pmvr/python-hsslms due to the +# limited amount of available test vectors for LMOTS, and few implementations +# providing direct access to the underlying OTS signature scheme. The private +# key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. +# +# To reproduce the signature: +# sudo pip3 install hsslms==0.1.2 +# +# from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE +# import pickle +# +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# private_key = pickle.load(private_key_file) +# +#ots_private_key = LM_OTS_Priv(private_key.otstypecode, private_key.I, 3, private_key.SEED) +#ots_public_key = ots_private_key.gen_pub() +#message = bytes() +#sig = ots_private_key.sign(message) +#print('lmots_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), ots_public_key.pubkey.hex())) +lmots_verify_test:"":"00000004862327ead0b0eee8bde100614b3369e183f97812c13f0979f7d37482a2ae719a811ba3a5c65cc036270d4b31ed6caa900ba0a98e3e5d6f7e4286571e003fd7f8fd523c7707eb00d25ce6b0d2c92317b2531b8ebb184ed65f7bd4c20611154409acb5134389c8aca9cb98c380fc8de4f48078a1859126967275219ca0168c6f0cfec0c2f63f98fb2a741fc15a5d59b50a97efe2564bd8a4f05fe250d4ec316e6a833a2dafaea47efa359840fb887e3a5ae0b07c75ed1dda3cc253365c5b9320180e5273a2c5078cdc0d3aefeaa94d8888c3112c2b68f85fdfaa13b5088f4bdf570f5a2ae32114497d28a6b46abe602f142a9382651a4b5fe7aeda3e54deaf85d51d59bc945e3970d4f603cb1617137c182087dcecb7f97016e138ae4c7f8926a9fbf7d1154cd53971e3c86e230fe783efdc44f4459143eeddec73612a11f6c4796bb734b703b94b3ee02a136f676ff959bd9dcba3a6cdf8244310b4125a07ef7a364d47c2d0067370f9024bb02217ea19baafa6111dbe1daa6f4d3ae287f8b4675934a8cb124b64f3d2baac01504a66b5cb80d5fe88281c92eb2d9e6105368ce748c2269f28444d20f8fa06f96738942606fd2ee1ae17b45953af9cc8aa10089b80c951ae7d4c6496476e0f9d88050a09433a99b92f1bd2bc2cc4e712fbba650e8c61716a2396bd802679096b2ed113dcf9107196f41185c9baa295c1000879dae4e36344b7ca9a4f040ceec064ff4a654a561a21fbdd0c28a4d0245da9fdb37a7ce20875e323db04197b6ec9d0265a840687a4067b6670482e3a765895a57f26fb971e359f30fa3c65b6197fbfe6433364f0062cc20d8ee2ebed5c3b96dfcd46aa99956b5b1602d9ea16b05ed54f1a72557148ec3a43baaac2474f735ce82979c87df358d175f4686aebde24b768f0f8dfa3c20d9c33db8244f47793eae676afe7485b08163ebd5c4b02c227a38824bb58d034e0a00395ce19e34846b8f6ce3cd3ba877a6ee953738c0ebffdc6eee63bff648e1530f611e9b5de0e5c41bf2f50375347dbe3c332ec523d516aa9478fdf61952f44068447d1474bc3a33f0d973f7b36360ddefd21ba57916dc0ee7a21082ec9c024d78938616e8bbaff451c8da9675cef9d0610872e8cd2b7673a86148e3abba473d0e4e1579ca3faa891d475a6bab9dc3a90537c701a62f41198b0e86f101b506a8a5b102ddd6fdafca56e7f32f4217f8bb7c228066c53fcd78b8541c3ffeb88fe685c796711bbe2d8fee6e9adcc077c140216438c5db25e7b7b34164fce6343dd8de5aa8310d18c9cf91992a25e6f71eb39fb7c267dc3b87d1781b34a4f3c84e2ecc04f73104d50e00631e2e7b157a8374c2b08dbcb3210b2852738a16cc580fa6df62b93f27151bfa77eaeb726ab18137e14962676836a573a6ac62b1bb8d40b402d2da0b37bb5a29e2ef154a78f61b632c2e9279670ba9a7a2c2ceda3f931940a5766738ad8ee62761c87d94e50ec995c01484fe6c96d0fb2ae97394e6497a4a8087c366edd038d72b01f4eb351a2ac41d19df56db40491da464a6f0c646b859e7ea3b0584be618fd7fb48c":"0000000447cc5b29dd0cecd01c382434a6d16864000000033fa1330497e44e2773f08e4727eb4d745db9051d6a60779e58a922dc8a7d4ede":0 LMOTS hash-sigs interop negative test (altered random value) # This test uses data from https://github.com/cisco/hash-sigs due to the limited diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 4821ce5ce1..27a74b6d36 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -76,7 +76,7 @@ exit: /* BEGIN_CASE */ void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, - int expected_rc ) + int expected_rc ) { mbedtls_lmots_public_t ctx; unsigned int size; @@ -91,17 +91,20 @@ void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, /* Test negative cases if the input data is valid */ if( expected_rc == 0 ) { - /* Altering first message byte must cause verification failure */ - msg->x[0] ^= 1; - TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), - MBEDTLS_ERR_LMS_VERIFY_FAILED); - msg->x[0] ^= 1; + if( msg->len >= 1 ) + { + /* Altering first message byte must cause verification failure */ + msg->x[0] ^= 1; + TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + msg->x[0] ^= 1; - /* Altering last message byte must cause verification failure */ - msg->x[msg->len - 1] ^= 1; - TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), - MBEDTLS_ERR_LMS_VERIFY_FAILED); - msg->x[msg->len - 1] ^= 1; + /* Altering last message byte must cause verification failure */ + msg->x[msg->len - 1] ^= 1; + TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), + MBEDTLS_ERR_LMS_VERIFY_FAILED); + msg->x[msg->len - 1] ^= 1; + } /* Altering first signature byte must cause verification failure */ sig->x[0] ^= 1; From 66edf6a833baa592758becceea2f9a4047ad5085 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 09:36:58 +0100 Subject: [PATCH 067/104] Use hsslms data for LMOTS import/export test Also, test that export fails when the buffer is too small. Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.data | 8 +++--- tests/suites/test_suite_lmots.function | 39 ++++++++++++++++++++------ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index 7ae80e92f5..8fdce0cd19 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -104,10 +104,10 @@ LMOTS negative test (invalid type) #2 lmots_verify_test:"0000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMOTS key import / export test -# This test uses a randomly generated LMOTS public key. It imports the key, and -# then exports it, and verifies that the exported key is identical to the -# original key. -lmots_import_export_test:"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A" +# This test uses the valid public key for hsslms interop test 1, imports it, and +# then exports it. It also checks if the export correctly fails when the export +# buffer is too small. +lmots_import_export_test:"0000000447cc5b29dd0cecd01c382434a6d1686400000001f337dde97685d008a4440b59550277390018d3f1d485fa4b8c91796032de494b":0 LMOTS key reuse test # This test uses a fixed message, and then generates a private key, signs the diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 27a74b6d36..367e55aaa2 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -146,20 +146,41 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void lmots_import_export_test ( data_t * pub_key ) +void lmots_import_export_test ( data_t * pub_key, int expected_import_rc ) { mbedtls_lmots_public_t ctx; - uint8_t exported_pub_key[MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; - size_t exported_pub_key_len; + unsigned char *exported_pub_key = NULL; + size_t exported_pub_key_buf_size; + size_t exported_pub_key_size; mbedtls_lmots_public_init( &ctx ); - TEST_EQUAL( mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ), 0 ); - TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, - sizeof( exported_pub_key ), - &exported_pub_key_len ), 0 ); + TEST_EQUAL( mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ), + expected_import_rc ); - ASSERT_COMPARE( pub_key->x, pub_key->len, - exported_pub_key, exported_pub_key_len ); + if( expected_import_rc == 0 ) + { + exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8); + ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size ); + + TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, + exported_pub_key_buf_size, + &exported_pub_key_size ), 0 ); + + TEST_EQUAL( exported_pub_key_buf_size, exported_pub_key_size ); + ASSERT_COMPARE( pub_key->x, MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8), + exported_pub_key, MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ); + mbedtls_free(exported_pub_key); + exported_pub_key = NULL; + + /* Export into too-small buffer should fail */ + exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) - 1; + ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size); + TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, + exported_pub_key_buf_size, NULL ), + MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); + mbedtls_free(exported_pub_key); + exported_pub_key = NULL; + } exit: mbedtls_lmots_public_free( &ctx ); From 71f554b48fcd562193d4a0f53beb54f3612ffa25 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 10:02:09 +0100 Subject: [PATCH 068/104] Use real data for negative LMOTS tests To avoid errors caused by the null public keys and signatures Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.data | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index 8fdce0cd19..3c28df7d05 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -84,24 +84,22 @@ LMOTS hsslms interop NULL-message test lmots_verify_test:"":"00000004862327ead0b0eee8bde100614b3369e183f97812c13f0979f7d37482a2ae719a811ba3a5c65cc036270d4b31ed6caa900ba0a98e3e5d6f7e4286571e003fd7f8fd523c7707eb00d25ce6b0d2c92317b2531b8ebb184ed65f7bd4c20611154409acb5134389c8aca9cb98c380fc8de4f48078a1859126967275219ca0168c6f0cfec0c2f63f98fb2a741fc15a5d59b50a97efe2564bd8a4f05fe250d4ec316e6a833a2dafaea47efa359840fb887e3a5ae0b07c75ed1dda3cc253365c5b9320180e5273a2c5078cdc0d3aefeaa94d8888c3112c2b68f85fdfaa13b5088f4bdf570f5a2ae32114497d28a6b46abe602f142a9382651a4b5fe7aeda3e54deaf85d51d59bc945e3970d4f603cb1617137c182087dcecb7f97016e138ae4c7f8926a9fbf7d1154cd53971e3c86e230fe783efdc44f4459143eeddec73612a11f6c4796bb734b703b94b3ee02a136f676ff959bd9dcba3a6cdf8244310b4125a07ef7a364d47c2d0067370f9024bb02217ea19baafa6111dbe1daa6f4d3ae287f8b4675934a8cb124b64f3d2baac01504a66b5cb80d5fe88281c92eb2d9e6105368ce748c2269f28444d20f8fa06f96738942606fd2ee1ae17b45953af9cc8aa10089b80c951ae7d4c6496476e0f9d88050a09433a99b92f1bd2bc2cc4e712fbba650e8c61716a2396bd802679096b2ed113dcf9107196f41185c9baa295c1000879dae4e36344b7ca9a4f040ceec064ff4a654a561a21fbdd0c28a4d0245da9fdb37a7ce20875e323db04197b6ec9d0265a840687a4067b6670482e3a765895a57f26fb971e359f30fa3c65b6197fbfe6433364f0062cc20d8ee2ebed5c3b96dfcd46aa99956b5b1602d9ea16b05ed54f1a72557148ec3a43baaac2474f735ce82979c87df358d175f4686aebde24b768f0f8dfa3c20d9c33db8244f47793eae676afe7485b08163ebd5c4b02c227a38824bb58d034e0a00395ce19e34846b8f6ce3cd3ba877a6ee953738c0ebffdc6eee63bff648e1530f611e9b5de0e5c41bf2f50375347dbe3c332ec523d516aa9478fdf61952f44068447d1474bc3a33f0d973f7b36360ddefd21ba57916dc0ee7a21082ec9c024d78938616e8bbaff451c8da9675cef9d0610872e8cd2b7673a86148e3abba473d0e4e1579ca3faa891d475a6bab9dc3a90537c701a62f41198b0e86f101b506a8a5b102ddd6fdafca56e7f32f4217f8bb7c228066c53fcd78b8541c3ffeb88fe685c796711bbe2d8fee6e9adcc077c140216438c5db25e7b7b34164fce6343dd8de5aa8310d18c9cf91992a25e6f71eb39fb7c267dc3b87d1781b34a4f3c84e2ecc04f73104d50e00631e2e7b157a8374c2b08dbcb3210b2852738a16cc580fa6df62b93f27151bfa77eaeb726ab18137e14962676836a573a6ac62b1bb8d40b402d2da0b37bb5a29e2ef154a78f61b632c2e9279670ba9a7a2c2ceda3f931940a5766738ad8ee62761c87d94e50ec995c01484fe6c96d0fb2ae97394e6497a4a8087c366edd038d72b01f4eb351a2ac41d19df56db40491da464a6f0c646b859e7ea3b0584be618fd7fb48c":"0000000447cc5b29dd0cecd01c382434a6d16864000000033fa1330497e44e2773f08e4727eb4d745db9051d6a60779e58a922dc8a7d4ede":0 LMOTS hash-sigs interop negative test (altered random value) -# This test uses data from https://github.com/cisco/hash-sigs due to the limited -# amount of available test vectors for LMOTS. A public/private key was generated -# and used to sign a randomly generated message. This test is a negative test -# where the signature from the hash-sigs interop test #1 data has been altered, -# and is expected to fail to verify. -lmots_verify_test:"C80B24A82D52963AB241C84DCF0EEE55BB24F9F0":"00000004CB3B6B24FD191CE8894AE3C4E2CE2DE0C3F5D508691A9162F37704E07838488466CCD746E55BC8E3055C7A4D4DA2E10775DAFA2E8E5FEFB1CEB25973BC3323B61DE5E2EA7DCFF15DA482320F958023CA2E718C69B977019E8F2FCD47151388E2E5E11170AFE93BDEB508362B3A317835A9DDEB18F0CDCCC0731902DB3D37F441C93A490DE53962A915AB5060A1C157D61DDF061F272362AB7FD9EE95AE48D3448F204C81A3F260792784E1BFB49871A27C09CC549A406520F0B40BC74CAAD082EAAB12C994B8495B8C80E96384FF2222255BE6C4EE5AF439534E616F9C0B53E951F69D59BD0506C0C0366A679A8329ACF6E2D1D4E4EF49D35375A8EA46FCF3C9B2F8E033C242EC61B796E43B901407077A2AF3F0AABD2D0CB9004F10D91B57C2D5E8BA7BA9268FF94962CC102F55B5120D7D2F7A3BE281BA01D78895ADA2F05B77967EDA0E1EDEAFBB9BBC3D68DCBF682FBC70467FA2BEE5DE65F54247C4BE5BEF41F5108B6CD09E7698E3AAEA04B60746EDD0E2623B66B092DDA21EFA5A0D36805D101D805CC06F0E818B46059B3984C8B8A526C4239F66ED34B8CA57E178DC5E7B8D2BE029114B4CE466E2B5A081729B3F3A3F3845DDE177062F201C09125ED3CC381AF35EAD795440C421A136F941F09F3E4BA9E0203CBA875AF477AB0246342700F323E65DC327D27966377D871FD9C58BEC8797DEF35E1D0751A554719828B87332F601884EBFECB63A8D4F390785B3826BFA384BE502D2322C919ABD12A486C2AB124DCB7B74DE91241A30EF0388411E52145A88971C6C0A4E7C4F23EDD8D6008065A3D108C6B1EC5219BB0DFDBD37EE3A7A8DD37E3563A5777838FCA61E9E744813F39CF70B5A0F50E1BD4FF8733A3BDA76D2135969809D91A9786F22DC2ACBA4E0164C411019EC77A0BD253A42AC7528FC7C0DA1711FBD6C23825207060463080F9E04B7D819C8B150C22B8BA87C6277696EC409369C48AC0E3233DE52D31EF6D2207D2B57DFC2D0C43BE8212EAE6CB1BACBC2D3568E5527A14065D5F1F56AAE2AFB5FB1CEFFC228A30692BD030C71F4872DB54F2632CD919DA61576CF58D1EBE3D7988183A9C789EB74A3D7F6BBEBAC035A43397BF684C9E1130B252940DBA4454311A6A3D54D9386D48E1D5A3E70944EDF725AEDC5440CD610F79AB05A43C917FFC15213295EB8CB8432B6554A47C2AD419ADD52E0F5E0BD7A1E0F873257E69F8647F3A07093387B7A64C4812CDBEE536E45D531F89653AC5F14A4715CFF40692346FE6CBF2F9B92D9F1101C379AFD5E6154605059C1DA463B407E79C139396623DC7F15EEFCE424C8E214C6A645EF002F90A230D8F62177CBCF2A688D4F822B119835AD3D3A619F46230257A5AD59CB0924B2584DBA96AADE0A2487E7409EE5993A4F0E3DC46C10B96595CDD17D72C35EF4A52C5906655B0AE649B5DE03B7D46F3839E808761EE05E9300050647593C048669A952324B0188ED225AD11BED3FD94E44E134FB9D6DAD53CC34ECF62695E30637C4528C450D62174E2F8ABA2C09F134412EF889C24B36224BE4259B363A9D8EB89BAEE16BE1898D46":"000000048440BBD3F47A167DD2D0E446DBCEA774000000138686E25BC07C69B43A2D3B7165DFF85C134177C876EA47D96FEF069BC96A981A":MBEDTLS_ERR_LMS_VERIFY_FAILED +# This test uses the valid signature from hsslms interop test 1, and then +# permutes the random value (C) of the signature, and is expected to fail to +# verify. +lmots_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"000000041bb462a8f59a277c1706ab69b1a40b0d56a3ffe1ddf0dfa890096c7a9c48b360e1e8f7abe4dc1950c4a64545ce6c0fe2a34477ec40f56db4eec37c1a2168e3059d4338a4eb368a64be5f98b5452f2c2fad23dcac585f5fe308bfc3df0b5cbc6cf3545236ed6c5a863e677521b5b5cee0aa1e755c3bbf5fb7326fac1a88cb12dd7f8d68ebe8bad07195a12fa11299073731e67f2452009252c595fc7d9285b90aaa912eb6cf0b5debc0996ca55ad5186702b244a616c4b9e0ceeea229e1e821c1ab0db906ce87640d128f1d8c4742d9baf340a8030df726a99a9b97f139ec57d8d87efdfca235f12de64e0a993804b95227cdfd26220a84502e350faaf5f91f3f49610eda211f9409005679e32068def22a2dcce3d226d0f68c4abc727b90d9c01daa05db24d7c0c9e9e48202e3420992ba78c36bc21c45cdf218801dc7053e3cbf39c141784e7a861671588622d540187912234ce628ea9cbd1800d215641163c762d2fd9194fa54bd9b46c83754579476398a5c2fece4642f1ee286a4e9a310b5e23088c75a68b123044c1c365c8b53fe9f895fa5d76fe1277c7c0f2a39f5b233f7d2acd5358feec2255feadb1c2513c4351c9bd1afe22d159f2d392c83bf7ec26b59e78330cd346adb85ef62fee3da63150ab5e0d7ce5d0ef353895360017faf3f35aca2cf3b8eda65389e2ba86f78ebfbe73382dfe9002331f24e96e1a6e56e7cc99ee848b82ad1ade3229e9e28168acfa8c059ed03028e8c872e72ff4cf8a50b84ade908ecf229a26ff1007c476d1aa376323fc567c9471085336496b231b5245a43c6c86c6a71c1b1fb4bd87c2d0b026bff55de121620a089ed9ade51c3bd91c703844c180ef9ad0ab550b9560ba9f1452463ce20987a402213ca5c16c927a0a85091dd74fbee22cac6b1afbc7e7dec229325c25ea3b3cc5a1c48c80665f9903e482b143f7cd051bdb990355f79c62553453c72ccbcc578df77069a7b0cf6fdc6853ec2f96fb7cc100216ae1b17aa20782fb0cd0f261b76a48b5d6f7bb48fa5f78c02a11ee81a8c0c81183910af770f2e907ebd5b2dc3a2b83529f62da074ca73c434f8f30b68a5dfee740f78d2c13b53c904e46dddf723923bfbffa437a4130c8c9b6d79a57db1c408b9c023f80fb3d766cb915e722f3b3152625d77bce3ca0c01e77f3750d7d1bef1ddda8b9b4233b09c89abe5913db50847a7ea219c3f406aa4cf41b6310bafa99a7b14f94b8ccd4dc7edb1a1e963ce26a53f3be71b4151ce5fae10ca30055e754880680e38cf2f21251f229341f7af9536360a428c2593c43fd2ae471bc1fa2b45ad55742a2f12f31eed6cb67945a898650c13650c4cffeecba8655f87e49ce921ced7ab00cf54eedf0c70e5c6cfa7f006763f0ac14d80cfb1662321cdccca8b1adf426eb9ca16ef2b978bb9ac229131fa5c1266a4980449c324ebdd8bcc98916089ee0b6966da7dc25350bdc758431884359d02f5fa567b39f49a6e410da2d0363944a090926308ed0ce7d565e6c4585ea010bc38ef1c976ae16ec1fbe6fb9d4d50e49a7be8273d2d56bf4e72acbadd90d5f8dee0":"0000000447cc5b29dd0cecd01c382434a6d1686400000000761e8e577fb4d12058806fc7bdaaef0ba64e454dc59b0230a77b43bbd83dc8c6":MBEDTLS_ERR_LMS_VERIFY_FAILED LMOTS negative test (invalid type) #1 -# This test uses a null (zeroed) message/signature/public key trio, with the -# only parts set being the LMOTS type. This test has an invalid LMOTS type, and -# should fail with a bad input data error. -lmots_verify_test:"0000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA +# This test uses the valid signature from hsslms interop test 1, and then +# sets an invalid LMOTS type (0x5), and is expected to fail to +# verify. +lmots_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"000000050bb462a8f59a277c1706ab69b1a40b0d56a3ffe1ddf0dfa890096c7a9c48b360e1e8f7abe4dc1950c4a64545ce6c0fe2a34477ec40f56db4eec37c1a2168e3059d4338a4eb368a64be5f98b5452f2c2fad23dcac585f5fe308bfc3df0b5cbc6cf3545236ed6c5a863e677521b5b5cee0aa1e755c3bbf5fb7326fac1a88cb12dd7f8d68ebe8bad07195a12fa11299073731e67f2452009252c595fc7d9285b90aaa912eb6cf0b5debc0996ca55ad5186702b244a616c4b9e0ceeea229e1e821c1ab0db906ce87640d128f1d8c4742d9baf340a8030df726a99a9b97f139ec57d8d87efdfca235f12de64e0a993804b95227cdfd26220a84502e350faaf5f91f3f49610eda211f9409005679e32068def22a2dcce3d226d0f68c4abc727b90d9c01daa05db24d7c0c9e9e48202e3420992ba78c36bc21c45cdf218801dc7053e3cbf39c141784e7a861671588622d540187912234ce628ea9cbd1800d215641163c762d2fd9194fa54bd9b46c83754579476398a5c2fece4642f1ee286a4e9a310b5e23088c75a68b123044c1c365c8b53fe9f895fa5d76fe1277c7c0f2a39f5b233f7d2acd5358feec2255feadb1c2513c4351c9bd1afe22d159f2d392c83bf7ec26b59e78330cd346adb85ef62fee3da63150ab5e0d7ce5d0ef353895360017faf3f35aca2cf3b8eda65389e2ba86f78ebfbe73382dfe9002331f24e96e1a6e56e7cc99ee848b82ad1ade3229e9e28168acfa8c059ed03028e8c872e72ff4cf8a50b84ade908ecf229a26ff1007c476d1aa376323fc567c9471085336496b231b5245a43c6c86c6a71c1b1fb4bd87c2d0b026bff55de121620a089ed9ade51c3bd91c703844c180ef9ad0ab550b9560ba9f1452463ce20987a402213ca5c16c927a0a85091dd74fbee22cac6b1afbc7e7dec229325c25ea3b3cc5a1c48c80665f9903e482b143f7cd051bdb990355f79c62553453c72ccbcc578df77069a7b0cf6fdc6853ec2f96fb7cc100216ae1b17aa20782fb0cd0f261b76a48b5d6f7bb48fa5f78c02a11ee81a8c0c81183910af770f2e907ebd5b2dc3a2b83529f62da074ca73c434f8f30b68a5dfee740f78d2c13b53c904e46dddf723923bfbffa437a4130c8c9b6d79a57db1c408b9c023f80fb3d766cb915e722f3b3152625d77bce3ca0c01e77f3750d7d1bef1ddda8b9b4233b09c89abe5913db50847a7ea219c3f406aa4cf41b6310bafa99a7b14f94b8ccd4dc7edb1a1e963ce26a53f3be71b4151ce5fae10ca30055e754880680e38cf2f21251f229341f7af9536360a428c2593c43fd2ae471bc1fa2b45ad55742a2f12f31eed6cb67945a898650c13650c4cffeecba8655f87e49ce921ced7ab00cf54eedf0c70e5c6cfa7f006763f0ac14d80cfb1662321cdccca8b1adf426eb9ca16ef2b978bb9ac229131fa5c1266a4980449c324ebdd8bcc98916089ee0b6966da7dc25350bdc758431884359d02f5fa567b39f49a6e410da2d0363944a090926308ed0ce7d565e6c4585ea010bc38ef1c976ae16ec1fbe6fb9d4d50e49a7be8273d2d56bf4e72acbadd90d5f8dee0":"0000000447cc5b29dd0cecd01c382434a6d1686400000000761e8e577fb4d12058806fc7bdaaef0ba64e454dc59b0230a77b43bbd83dc8c6":MBEDTLS_ERR_LMS_VERIFY_FAILED LMOTS negative test (invalid type) #2 -# This test uses a null (zeroed) message/signature/public key trio, with the -# only parts set being the LMOTS type. This test has an invalid LMOTS type, and -# should fail with a bad input data error. -lmots_verify_test:"0000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA +# This test uses the valid signature from hsslms interop test 1, and then +# sets an invalid LMOTS type (0x3), and is expected to fail to +# verify. +lmots_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"000000030bb462a8f59a277c1706ab69b1a40b0d56a3ffe1ddf0dfa890096c7a9c48b360e1e8f7abe4dc1950c4a64545ce6c0fe2a34477ec40f56db4eec37c1a2168e3059d4338a4eb368a64be5f98b5452f2c2fad23dcac585f5fe308bfc3df0b5cbc6cf3545236ed6c5a863e677521b5b5cee0aa1e755c3bbf5fb7326fac1a88cb12dd7f8d68ebe8bad07195a12fa11299073731e67f2452009252c595fc7d9285b90aaa912eb6cf0b5debc0996ca55ad5186702b244a616c4b9e0ceeea229e1e821c1ab0db906ce87640d128f1d8c4742d9baf340a8030df726a99a9b97f139ec57d8d87efdfca235f12de64e0a993804b95227cdfd26220a84502e350faaf5f91f3f49610eda211f9409005679e32068def22a2dcce3d226d0f68c4abc727b90d9c01daa05db24d7c0c9e9e48202e3420992ba78c36bc21c45cdf218801dc7053e3cbf39c141784e7a861671588622d540187912234ce628ea9cbd1800d215641163c762d2fd9194fa54bd9b46c83754579476398a5c2fece4642f1ee286a4e9a310b5e23088c75a68b123044c1c365c8b53fe9f895fa5d76fe1277c7c0f2a39f5b233f7d2acd5358feec2255feadb1c2513c4351c9bd1afe22d159f2d392c83bf7ec26b59e78330cd346adb85ef62fee3da63150ab5e0d7ce5d0ef353895360017faf3f35aca2cf3b8eda65389e2ba86f78ebfbe73382dfe9002331f24e96e1a6e56e7cc99ee848b82ad1ade3229e9e28168acfa8c059ed03028e8c872e72ff4cf8a50b84ade908ecf229a26ff1007c476d1aa376323fc567c9471085336496b231b5245a43c6c86c6a71c1b1fb4bd87c2d0b026bff55de121620a089ed9ade51c3bd91c703844c180ef9ad0ab550b9560ba9f1452463ce20987a402213ca5c16c927a0a85091dd74fbee22cac6b1afbc7e7dec229325c25ea3b3cc5a1c48c80665f9903e482b143f7cd051bdb990355f79c62553453c72ccbcc578df77069a7b0cf6fdc6853ec2f96fb7cc100216ae1b17aa20782fb0cd0f261b76a48b5d6f7bb48fa5f78c02a11ee81a8c0c81183910af770f2e907ebd5b2dc3a2b83529f62da074ca73c434f8f30b68a5dfee740f78d2c13b53c904e46dddf723923bfbffa437a4130c8c9b6d79a57db1c408b9c023f80fb3d766cb915e722f3b3152625d77bce3ca0c01e77f3750d7d1bef1ddda8b9b4233b09c89abe5913db50847a7ea219c3f406aa4cf41b6310bafa99a7b14f94b8ccd4dc7edb1a1e963ce26a53f3be71b4151ce5fae10ca30055e754880680e38cf2f21251f229341f7af9536360a428c2593c43fd2ae471bc1fa2b45ad55742a2f12f31eed6cb67945a898650c13650c4cffeecba8655f87e49ce921ced7ab00cf54eedf0c70e5c6cfa7f006763f0ac14d80cfb1662321cdccca8b1adf426eb9ca16ef2b978bb9ac229131fa5c1266a4980449c324ebdd8bcc98916089ee0b6966da7dc25350bdc758431884359d02f5fa567b39f49a6e410da2d0363944a090926308ed0ce7d565e6c4585ea010bc38ef1c976ae16ec1fbe6fb9d4d50e49a7be8273d2d56bf4e72acbadd90d5f8dee0":"0000000447cc5b29dd0cecd01c382434a6d1686400000000761e8e577fb4d12058806fc7bdaaef0ba64e454dc59b0230a77b43bbd83dc8c6":MBEDTLS_ERR_LMS_VERIFY_FAILED LMOTS key import / export test # This test uses the valid public key for hsslms interop test 1, imports it, and From 9fc303a99a151806d2aca629609169cfc920b3d8 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 10:32:15 +0100 Subject: [PATCH 069/104] Add extra LMOTS import negative tests And fix failures that are related to the new tests Signed-off-by: Raef Coles --- library/lmots.c | 2 +- tests/suites/test_suite_lmots.data | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/library/lmots.c b/library/lmots.c index f19871873d..a172f77d7c 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -415,7 +415,7 @@ int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx, mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ); - if( key_len < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) ) + if( key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) ) { return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); } diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index 3c28df7d05..fdb6e43f22 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -107,6 +107,33 @@ LMOTS key import / export test # buffer is too small. lmots_import_export_test:"0000000447cc5b29dd0cecd01c382434a6d1686400000001f337dde97685d008a4440b59550277390018d3f1d485fa4b8c91796032de494b":0 +LMOTS key import too large key test +# This test uses the valid public key for hsslms interop test 1, add an extra +# byte, and then imports it. This should fail. +lmots_import_export_test:"0000000447cc5b29dd0cecd01c382434a6d1686400000001f337dde97685d008a4440b59550277390018d3f1d485fa4b8c91796032de494b00":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMOTS key import too small key test +# This test uses the valid public key for hsslms interop test 1, removes a byte, +# and then imports it. This should fail. +lmots_import_export_test:"0000000447cc5b29dd0cecd01c382434a6d1686400000001f337dde97685d008a4440b59550277390018d3f1d485fa4b8c91796032de49":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMOTS key import no type test +# This test uses the valid public key for hsslms interop test 1, cuts it down so +# it's smaller than the LMOTS type offset, and imports it. This should fail, and +# not attempt to read invalidly outside the buffer. +lmots_import_export_test:"000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMOTS key import invalid type test #1 +# This test uses the valid public key for hsslms interop test 1, alters the +# LMOTS type to 0x3, and imports it. This should fail. +lmots_import_export_test:"0000000347cc5b29dd0cecd01c382434a6d1686400000001f337dde97685d008a4440b59550277390018d3f1d485fa4b8c91796032de494b":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMOTS key import invalid type test #2 +# This test uses the valid public key for hsslms interop test 1, alters the +# LMOTS type to 0x5, and imports it. This should fail, and not attempt to read +# invalidly outside the buffer. +lmots_import_export_test:"0000000547cc5b29dd0cecd01c382434a6d1686400000001f337dde97685d008a4440b59550277390018d3f1d485fa4b8c91796032de494b":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + LMOTS key reuse test # This test uses a fixed message, and then generates a private key, signs the # message, and then attempts to sign the message again. The second signature From 142e577c34af335567bd003a99c20358f5f95ced Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 10:47:27 +0100 Subject: [PATCH 070/104] Add extra zeroization to LMS and LMOTS Signed-off-by: Raef Coles --- library/lmots.c | 19 ++++++++++++++----- library/lms.c | 18 ++++++++++++++---- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/library/lmots.c b/library/lmots.c index a172f77d7c..788063c549 100644 --- a/library/lmots.c +++ b/library/lmots.c @@ -700,7 +700,7 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, NULL, ( unsigned char * )y_hashed_digits ); if( ret ) { - return( ret ); + goto exit; } ret = public_key_from_hashed_digit_array( &priv_ctx->params, @@ -708,7 +708,7 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, ctx->public_key ); if( ret ) { - return( ret ); + goto exit; } memcpy( &ctx->params, &priv_ctx->params, @@ -716,6 +716,9 @@ int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx, ctx->have_public_key = 1; +exit: + mbedtls_platform_zeroize( y_hashed_digits, sizeof( y_hashed_digits ) ); + return( ret ); } @@ -765,14 +768,14 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, tmp_digit_array ); if( ret ) { - return( ret ); + goto exit; } ret = hash_digit_array( &ctx->params, ( unsigned char * )ctx->private_key, NULL, tmp_digit_array, ( unsigned char * )tmp_sig ); if( ret ) { - return( ret ); + goto exit; } mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type, @@ -810,7 +813,13 @@ int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx, *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type); } - return( 0 ); + ret = 0; + +exit: + mbedtls_platform_zeroize( tmp_digit_array, sizeof( tmp_digit_array ) ); + mbedtls_platform_zeroize( tmp_sig, sizeof( tmp_sig ) ); + + return ( ret ); } #endif /* defined(MBEDTLS_LMS_PRIVATE) */ diff --git a/library/lms.c b/library/lms.c index f30f349ad5..876deeb5c7 100644 --- a/library/lms.c +++ b/library/lms.c @@ -516,7 +516,7 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx, ret = calculate_merkle_tree( ctx, ( unsigned char * )tree ); if( ret != 0 ) { - return( ret ); + goto exit; } for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); @@ -531,7 +531,12 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx, curr_node_id >>=1; } - return( 0 ); + ret = 0; + +exit: + mbedtls_platform_zeroize( tree, sizeof( tree ) ); + + return( ret ); } void mbedtls_lms_private_init( mbedtls_lms_private_t *ctx ) @@ -688,7 +693,7 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, ret = calculate_merkle_tree( priv_ctx, ( unsigned char * )tree ); if( ret != 0 ) { - return( ret ); + goto exit; } /* Root node is always at position 1, due to 1-based indexing */ @@ -697,7 +702,12 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx, ctx->have_public_key = 1; - return( 0 ); + ret = 0; + +exit: + mbedtls_platform_zeroize( tree, sizeof( tree ) ); + + return( ret ); } From 4511055511b358487132cd946335f22f0089abaa Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 12:28:52 +0100 Subject: [PATCH 071/104] Exclude binary LMS keys from file checking Signed-off-by: Raef Coles --- tests/scripts/check_files.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/scripts/check_files.py b/tests/scripts/check_files.py index a0f5e1f538..3d2ca3ea0d 100755 --- a/tests/scripts/check_files.py +++ b/tests/scripts/check_files.py @@ -119,6 +119,7 @@ BINARY_FILE_PATH_RE_LIST = [ r'tests/data_files/.*\.req\.[^/]+\Z', r'tests/data_files/.*malformed[^/]+\Z', r'tests/data_files/format_pkcs12\.fmt\Z', + r'tests/data_files/lms_.*\Z', ] BINARY_FILE_PATH_RE = re.compile('|'.join(BINARY_FILE_PATH_RE_LIST)) From f9b85028659e7769ac1cbadbd819e79c4626789a Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 12:42:28 +0100 Subject: [PATCH 072/104] Add LMS import/export negative tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lms.data | 54 ++++++++++++++++++++++++---- tests/suites/test_suite_lms.function | 3 +- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 1201156ceb..85aad52ed9 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -224,11 +224,51 @@ LMS negative test (invalid leaf ID) lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000040000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS import/export test -# This test uses a randomly generated LMS public key. It imports the key, and -# then exports it, and verifies that the exported key is identical to the -# original key. It also tests handling of too-small key export buffers. -lms_import_export_test:"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 +# This test uses the key from hsslms interop test 1, imports it, exports it and +# tests that it is the same. It also checks if the export correctly fail when +# the buffer is too small. +lms_import_export_test:"000000060000000447cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":0 -LMS import/export negative test #1 -# This test uses the randomly generated LMS public key -lms_import_export_test:"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 +LMS key import too large key test +# This test uses the valid public key for hsslms interop test 1, add an extra +# byte, and then imports it. This should fail. +lms_import_export_test:"000000060000000447cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d00":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS key import too small key test +# This test uses the valid public key for hsslms interop test 1, removes a byte, +# and then imports it. This should fail. +lms_import_export_test:"000000060000000447cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS key import no LMS type test +# This test uses the valid public key for hsslms interop test 1, cuts it down so +# it's smaller than the LMS type offset, and imports it. This should fail, and +# not attempt to read invalidly outside the buffer. +lms_import_export_test:"000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS key import no LMOTS type test +# This test uses the valid public key for hsslms interop test 1, cuts it down so +# it's smaller than the LMOTS type offset, and imports it. This should fail, and +# not attempt to read invalidly outside the buffer. +lms_import_export_test:"00000006000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS key import invalid LMS type test #1 +# This test uses the valid public key for hsslms interop test 1, alters the +# LMS type to 0x7, and imports it. This should fail. +lms_import_export_test:"000000050000000447cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS key import invalid LMS type test #2 +# This test uses the valid public key for hsslms interop test 1, alters the +# LMS type to 0x5, and imports it. This should fail, and not attempt to read +# invalidly outside the buffer. +lms_import_export_test:"000000070000000447cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS key import invalid LMOTS type test #1 +# This test uses the valid public key for hsslms interop test 1, alters the +# LMS type to 0x7, and imports it. This should fail. +lms_import_export_test:"000000060000000347cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":MBEDTLS_ERR_LMS_BAD_INPUT_DATA + +LMS key import invalid LMOTS type test #2 +# This test uses the valid public key for hsslms interop test 1, alters the +# LMS type to 0x5, and imports it. This should fail, and not attempt to read +# invalidly outside the buffer. +lms_import_export_test:"000000060000000547cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":MBEDTLS_ERR_LMS_BAD_INPUT_DATA diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 860304e025..709db8ce2b 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -157,7 +157,8 @@ void lms_import_export_test ( data_t * pub_key, int expected_import_rc ) unsigned char *exported_pub_key = NULL; mbedtls_lms_public_init(&ctx); - TEST_EQUAL( mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ), 0 ); + TEST_EQUAL( mbedtls_lms_import_public_key( &ctx, pub_key->x, pub_key->len ), + expected_import_rc ); if( expected_import_rc == 0 ) { From d0c701237a2c8d1938677a80d40fc9bd3fc6794b Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 14:19:52 +0100 Subject: [PATCH 073/104] Replace TEST_ASSERT with TEST_EQUAL in LMS tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lms.function | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 709db8ce2b..4e525c452e 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -27,16 +27,16 @@ void lms_sign_verify_test ( data_t *msg, data_t *seed ) mbedtls_test_rnd_std_rand, NULL, seed->x, seed->len ); TEST_ASSUME( rc != MBEDTLS_ERR_LMS_ALLOC_FAILED ); - TEST_ASSERT( rc == 0 ); + TEST_EQUAL( rc, 0 ); - TEST_ASSERT( mbedtls_lms_calculate_public_key( &pub_ctx, &priv_ctx ) == 0 ); + TEST_EQUAL( mbedtls_lms_calculate_public_key( &pub_ctx, &priv_ctx ), 0 ); - TEST_ASSERT( mbedtls_lms_sign( &priv_ctx, mbedtls_test_rnd_std_rand, NULL, + TEST_EQUAL( mbedtls_lms_sign( &priv_ctx, mbedtls_test_rnd_std_rand, NULL, msg->x, msg->len, sig, sizeof( sig ), - NULL ) == 0 ); + NULL ), 0 ); - TEST_ASSERT( mbedtls_lms_verify( &pub_ctx, msg->x, msg->len, sig, - sizeof( sig ) ) == 0 ); + TEST_EQUAL( mbedtls_lms_verify( &pub_ctx, msg->x, msg->len, sig, + sizeof( sig ) ), 0 ); exit: mbedtls_lms_public_free( &pub_ctx ); @@ -63,16 +63,16 @@ void lms_sign_verify_null_msg_test( data_t *seed ) mbedtls_test_rnd_std_rand, NULL, seed->x, seed->len ); TEST_ASSUME( rc != MBEDTLS_ERR_LMS_ALLOC_FAILED ); - TEST_ASSERT( rc == 0 ); + TEST_EQUAL( rc, 0 ); - TEST_ASSERT( mbedtls_lms_calculate_public_key( &pub_ctx, &priv_ctx ) == 0 ); + TEST_EQUAL( mbedtls_lms_calculate_public_key( &pub_ctx, &priv_ctx ), 0 ); - TEST_ASSERT( mbedtls_lms_sign( &priv_ctx, mbedtls_test_rnd_std_rand, NULL, + TEST_EQUAL( mbedtls_lms_sign( &priv_ctx, mbedtls_test_rnd_std_rand, NULL, NULL, 0, sig, sizeof( sig ), - NULL ) == 0 ); + NULL ), 0 ); - TEST_ASSERT( mbedtls_lms_verify( &pub_ctx, NULL, 0, sig, - sizeof( sig ) ) == 0 ); + TEST_EQUAL( mbedtls_lms_verify( &pub_ctx, NULL, 0, sig, + sizeof( sig ) ), 0 ); exit: mbedtls_lms_public_free( &pub_ctx ); From 59eb0d0f2b8a5a8cef78359fbb0da47e341e0868 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 15:19:17 +0100 Subject: [PATCH 074/104] Fix LMOTS signature leak test dependencies As it requires MBEDTLS_LMS_PRIVATE Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 367e55aaa2..d540454230 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -211,7 +211,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */ +/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_LMS_PRIVATE */ void lmots_signature_leak_test ( data_t *msg, data_t *key_id, int leaf_id, data_t *seed ) { From 45c4ff93c9674f59136b8999842322f7868d733d Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 15:22:48 +0100 Subject: [PATCH 075/104] Fix windows requiring explicit cast in LMS calloc Signed-off-by: Raef Coles --- library/lms.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/lms.c b/library/lms.c index 876deeb5c7..ccbcd8bffd 100644 --- a/library/lms.c +++ b/library/lms.c @@ -603,7 +603,9 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, goto exit; } - ctx->ots_private_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + /* Requires a cast to size_t to avoid an implicit cast warning on certain + * platforms (particularly Windows) */ + ctx->ots_private_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof( *ctx->ots_private_keys ) ); if( ctx->ots_private_keys == NULL ) { @@ -611,7 +613,9 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, goto exit; } - ctx->ots_public_keys = mbedtls_calloc( MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + /* Requires a cast to size_t to avoid an implicit cast warning on certain + * platforms (particularly Windows) */ + ctx->ots_public_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof( *ctx->ots_public_keys ) ); if( ctx->ots_public_keys == NULL ) { From 76563399fd10c835b40ff5f8cc770e0c629752b9 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 15:50:57 +0100 Subject: [PATCH 076/104] Fix LMS and LMOTS test dependencies Mark them as depending on PSA_WANT_ALG_SHA256 so that test_depends_hashes_psa doesn't fail Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 2 +- tests/suites/test_suite_lms.function | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index d540454230..4382421d0b 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -23,7 +23,7 @@ int check_lmots_private_key_for_leak(unsigned char * sig) /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C + * depends_on:MBEDTLS_LMS_C:PSA_WANT_ALG_SHA_256 * END_DEPENDENCIES */ diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 4e525c452e..4f49e8e65d 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -4,7 +4,7 @@ /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C + * depends_on:MBEDTLS_LMS_C:PSA_WANT_ALG_SHA_256 * END_DEPENDENCIES */ From d137c8612572546995f47809aae93ab47f7660a8 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Wed, 12 Oct 2022 15:55:25 +0100 Subject: [PATCH 077/104] Don't skip LMS tests due to out of memory error Signed-off-by: Raef Coles --- tests/suites/test_suite_lms.function | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 4f49e8e65d..c0cf02cb8d 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -14,7 +14,6 @@ void lms_sign_verify_test ( data_t *msg, data_t *seed ) mbedtls_lms_public_t pub_ctx; mbedtls_lms_private_t priv_ctx; unsigned char sig[MBEDTLS_LMS_SIG_LEN(MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8)]; - int rc; mbedtls_lms_public_init( &pub_ctx ); mbedtls_lms_private_init( &priv_ctx ); @@ -22,12 +21,10 @@ void lms_sign_verify_test ( data_t *msg, data_t *seed ) /* Allocation failure isn't a test failure, since it likely just means * there's not enough memory to run the test. */ - rc = mbedtls_lms_generate_private_key( &priv_ctx, MBEDTLS_LMS_SHA256_M32_H10, + TEST_EQUAL( mbedtls_lms_generate_private_key( &priv_ctx, MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8, mbedtls_test_rnd_std_rand, NULL, - seed->x, seed->len ); - TEST_ASSUME( rc != MBEDTLS_ERR_LMS_ALLOC_FAILED ); - TEST_EQUAL( rc, 0 ); + seed->x, seed->len ), 0 ); TEST_EQUAL( mbedtls_lms_calculate_public_key( &pub_ctx, &priv_ctx ), 0 ); @@ -50,7 +47,6 @@ void lms_sign_verify_null_msg_test( data_t *seed ) mbedtls_lms_public_t pub_ctx; mbedtls_lms_private_t priv_ctx; unsigned char sig[MBEDTLS_LMS_SIG_LEN(MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8)]; - int rc; mbedtls_lms_public_init( &pub_ctx ); mbedtls_lms_private_init( &priv_ctx ); @@ -58,12 +54,10 @@ void lms_sign_verify_null_msg_test( data_t *seed ) /* Allocation failure isn't a test failure, since it likely just means * there's not enough memory to run the test. */ - rc = mbedtls_lms_generate_private_key( &priv_ctx, MBEDTLS_LMS_SHA256_M32_H10, + TEST_EQUAL( mbedtls_lms_generate_private_key( &priv_ctx, MBEDTLS_LMS_SHA256_M32_H10, MBEDTLS_LMOTS_SHA256_N32_W8, mbedtls_test_rnd_std_rand, NULL, - seed->x, seed->len ); - TEST_ASSUME( rc != MBEDTLS_ERR_LMS_ALLOC_FAILED ); - TEST_EQUAL( rc, 0 ); + seed->x, seed->len ), 0 ); TEST_EQUAL( mbedtls_lms_calculate_public_key( &pub_ctx, &priv_ctx ), 0 ); From 781f7bedb0a3c9d7d99c5d71a9dfac61966249d6 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 09:23:11 +0100 Subject: [PATCH 078/104] Properly mark LMOTS leak test as failed Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 4382421d0b..c582ce700f 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -11,12 +11,13 @@ int check_lmots_private_key_for_leak(unsigned char * sig) idx < MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8); idx++ ) { - if( sig[idx] != 0x7E ) { - return 1; - } + TEST_EQUAL( sig[idx], 0x7E ); } - return 0; + return( 0 ); + +exit: + return( -1 ); } #endif /* defined(MBEDTLS_TEST_HOOKS) */ From 20d2e06ca48f4babeb7308ba5637e32ee8c4bcd2 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 09:28:18 +0100 Subject: [PATCH 079/104] Add cleanup frees in LMS and LMOTS tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 2 ++ tests/suites/test_suite_lms.function | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index c582ce700f..1fec900fc8 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -142,6 +142,8 @@ void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, } exit: + if( tmp_sig != NULL ) + mbedtls_free( tmp_sig ); mbedtls_lmots_public_free( &ctx ); } /* END_CASE */ diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index c0cf02cb8d..b6ae309186 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -138,6 +138,8 @@ void lms_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, } exit: + if( tmp_sig != NULL ) + mbedtls_free( tmp_sig ); mbedtls_lms_public_free( &ctx ); } /* END_CASE */ @@ -180,6 +182,8 @@ void lms_import_export_test ( data_t * pub_key, int expected_import_rc ) } exit: + if( exported_pub_key != NULL ) + mbedtls_free( exported_pub_key ); mbedtls_lms_public_free( &ctx ); } /* END_CASE */ From d1c2a8031976641863fadf5bd91e650ee0cc304a Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 09:32:53 +0100 Subject: [PATCH 080/104] Remove duplicated assert from LMOTS tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 1fec900fc8..8857326fba 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -113,12 +113,6 @@ void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, MBEDTLS_ERR_LMS_VERIFY_FAILED); sig->x[0] ^= 1; - /* Altering first signature byte must cause verification failure */ - sig->x[0] ^= 1; - TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), - MBEDTLS_ERR_LMS_VERIFY_FAILED); - sig->x[0] ^= 1; - /* Altering last signature byte must cause verification failure */ sig->x[sig->len - 1] ^= 1; TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), From 534f66f3f04e549ad9efa9dba2b4edb608b2f229 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 09:39:01 +0100 Subject: [PATCH 081/104] Fix assert arguments in LMS and LMOTS export tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 7 ++++--- tests/suites/test_suite_lms.function | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 8857326fba..f18b79c0dc 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -163,9 +163,10 @@ void lmots_import_export_test ( data_t * pub_key, int expected_import_rc ) exported_pub_key_buf_size, &exported_pub_key_size ), 0 ); - TEST_EQUAL( exported_pub_key_buf_size, exported_pub_key_size ); - ASSERT_COMPARE( pub_key->x, MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8), - exported_pub_key, MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ); + TEST_EQUAL( exported_pub_key_buf_size, + MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ); + ASSERT_COMPARE( pub_key->x, pub_key->len, + exported_pub_key, exported_pub_key_size ); mbedtls_free(exported_pub_key); exported_pub_key = NULL; diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index b6ae309186..97f45e6428 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -165,9 +165,10 @@ void lms_import_export_test ( data_t * pub_key, int expected_import_rc ) exported_pub_key_buf_size, &exported_pub_key_size ), 0 ); - TEST_EQUAL( exported_pub_key_buf_size, exported_pub_key_size ); - ASSERT_COMPARE( pub_key->x, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10), - exported_pub_key, MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10) ); + TEST_EQUAL( exported_pub_key_size, + MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10 ) ); + ASSERT_COMPARE( pub_key->x, pub_key->len, + exported_pub_key, exported_pub_key_size ); mbedtls_free(exported_pub_key); exported_pub_key = NULL; From 6b2c573b3d4e72a17694858dbb4c34a7ee7f8ace Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 09:41:39 +0100 Subject: [PATCH 082/104] And export buffer too large test to LMS and LMOTS Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 9 +++++++++ tests/suites/test_suite_lms.function | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index f18b79c0dc..94d6b8e036 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -178,6 +178,15 @@ void lmots_import_export_test ( data_t * pub_key, int expected_import_rc ) MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); mbedtls_free(exported_pub_key); exported_pub_key = NULL; + + /* Export into too-large buffer should succeed */ + exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) + 1; + ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size); + TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, + exported_pub_key_buf_size, NULL ), + 0 ); + mbedtls_free(exported_pub_key); + exported_pub_key = NULL; } exit: diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 97f45e6428..51addea0f7 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -180,6 +180,15 @@ void lms_import_export_test ( data_t * pub_key, int expected_import_rc ) MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); mbedtls_free(exported_pub_key); exported_pub_key = NULL; + + /* Export into too-large buffer should succeed */ + exported_pub_key_buf_size = MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10) + 1; + ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size); + TEST_EQUAL( mbedtls_lms_export_public_key( &ctx, exported_pub_key, + exported_pub_key_buf_size, NULL ), + 0 ); + mbedtls_free(exported_pub_key); + exported_pub_key = NULL; } exit: From 1b43a7448d949a0de5c5a9beabd58ba9bdb7e192 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 09:44:27 +0100 Subject: [PATCH 083/104] Clean up LMS and LMOTS feature dependencies Remove SHA256 dependencies from tests, fix incorrect boolean logic in check_config, and change depends_hashes.pl to disable LMS in one test Signed-off-by: Raef Coles --- include/mbedtls/check_config.h | 2 +- tests/scripts/depends-hashes.pl | 2 +- tests/suites/test_suite_lmots.function | 2 +- tests/suites/test_suite_lms.function | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 4b2783174f..e6488c09c2 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -354,7 +354,7 @@ #endif #if defined(MBEDTLS_LMS_C) && \ - ( !defined(MBEDTLS_PSA_CRYPTO_C) && !defined(PSA_WANT_ALG_SHA256) ) + ! ( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA256) ) #error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA256" #endif diff --git a/tests/scripts/depends-hashes.pl b/tests/scripts/depends-hashes.pl index 68297a6a2e..db18a92ae8 100755 --- a/tests/scripts/depends-hashes.pl +++ b/tests/scripts/depends-hashes.pl @@ -57,7 +57,7 @@ my @hash_configs = ( ['unset MBEDTLS_MD5_C'], ['unset MBEDTLS_SHA512_C', 'unset MBEDTLS_SHA384_C '], ['unset MBEDTLS_SHA384_C'], - ['unset MBEDTLS_SHA256_C', 'unset MBEDTLS_SHA224_C'], + ['unset MBEDTLS_SHA256_C', 'unset MBEDTLS_SHA224_C', 'unset MBEDTLS_LMS_C', 'unset MBEDTLS_LMS_PRIVATE'], ['unset MBEDTLS_SHA1_C'], ); diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 94d6b8e036..f2ce29a34b 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -24,7 +24,7 @@ exit: /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:PSA_WANT_ALG_SHA_256 + * depends_on:MBEDTLS_LMS_C * END_DEPENDENCIES */ diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 51addea0f7..dd37f31979 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -4,7 +4,7 @@ /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_LMS_C:PSA_WANT_ALG_SHA_256 + * depends_on:MBEDTLS_LMS_C * END_DEPENDENCIES */ From a21671123a6105aa03336ae77427cd73bb0f71eb Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 10:05:33 +0100 Subject: [PATCH 084/104] Remove `sudo pip3` in LM(OT)S tests instructions Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.data | 6 +++--- tests/suites/test_suite_lms.data | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index fdb6e43f22..6b34078c36 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -22,7 +22,7 @@ LMOTS hsslms interop test #1 # the LMS key), and the same message. # # To reproduce the signature: -# sudo pip3 install hsslms==0.1.2 +# pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle @@ -46,7 +46,7 @@ LMOTS hsslms interop test #2 # the LMS key), and the same message. # # To reproduce the signature: -# sudo pip3 install hsslms==0.1.2 +# pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle @@ -68,7 +68,7 @@ LMOTS hsslms interop NULL-message test # key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. # # To reproduce the signature: -# sudo pip3 install hsslms==0.1.2 +# pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 85aad52ed9..207d943c4e 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -19,7 +19,7 @@ LMS pyhsslms interop test #1 # and the public key before including them in a the test data. # # To reproduce the signature: -# * sudo pip3 install pyhsslms +# * pip3 install --user pyhsslms # * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv # * # * hsslms sign tmp/lms.prv message.bin @@ -44,7 +44,7 @@ LMS pyhsslms interop test #2 # and the public key before including them in a the test data. # # To reproduce the signature: -# * sudo pip3 install pyhsslms +# * pip3 install --user pyhsslms # * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv # * # * hsslms sign tmp/lms.prv message.bin (incorrect signature using leaf node 0) @@ -71,7 +71,7 @@ LMS pyhsslms interop NULL-message test # signature and the public key before including them in a the test data. # # To reproduce the signature: -# * sudo pip3 install pyhsslms +# * pip3 install --user pyhsslms # * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv # * touch message.bin (create empty message file) # * hsslms sign tmp/lms.prv message.bin (incorrect signature using leaf node 0) @@ -152,7 +152,7 @@ LMS hsslms interop test #1 # data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv # # To reproduce the signature: -# sudo pip3 install hsslms==0.1.2 +# pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle @@ -174,7 +174,7 @@ LMS hsslms interop test #2 # data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv # # To reproduce the signature: -# sudo pip3 install hsslms==0.1.2 +# pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle From 07b70d91967d42a9913f7b42a24eef3c41de0fa3 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 10:46:16 +0100 Subject: [PATCH 085/104] Correct typo in LMS config check Signed-off-by: Raef Coles --- include/mbedtls/check_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index e6488c09c2..0081ca3d60 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -354,8 +354,8 @@ #endif #if defined(MBEDTLS_LMS_C) && \ - ! ( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA256) ) -#error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA256" + ! ( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_256) ) +#error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256" #endif #if defined(MBEDTLS_LMS_PRIVATE) && \ From d1c1f7f7bec94a3c6399bf09737962e36dd0bc9b Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 13:00:08 +0100 Subject: [PATCH 086/104] Disable LMS in all.sh tests that lack _WANT_SHA256 Signed-off-by: Raef Coles --- tests/scripts/all.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index c3a39bcd27..f7da34a3bc 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -2248,6 +2248,8 @@ component_build_psa_accel_alg_md5() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_384 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_512 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_MD5 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" } @@ -2268,6 +2270,8 @@ component_build_psa_accel_alg_ripemd160() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_384 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_512 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RIPEMD160 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" } @@ -2288,6 +2292,8 @@ component_build_psa_accel_alg_sha1() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_384 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_512 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_1 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" } @@ -2345,6 +2351,8 @@ component_build_psa_accel_alg_sha384() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_224 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_256 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_384 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" } @@ -2365,6 +2373,8 @@ component_build_psa_accel_alg_sha512() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_256 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_384 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C + scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_512 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" } From cbd02adc6e4f888d2dabef6e2ecb87ab31705132 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 14:11:49 +0100 Subject: [PATCH 087/104] Simplify LMS context freeing Signed-off-by: Raef Coles --- library/lms.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/library/lms.c b/library/lms.c index ccbcd8bffd..35ca890b50 100644 --- a/library/lms.c +++ b/library/lms.c @@ -550,17 +550,24 @@ void mbedtls_lms_private_free( mbedtls_lms_private_t *ctx ) if( ctx->have_private_key ) { - for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) + if( ctx->ots_private_keys != NULL ) { - mbedtls_lmots_private_free( &ctx->ots_private_keys[idx] ); - mbedtls_lmots_public_free( &ctx->ots_public_keys[idx] ); + for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) + { + mbedtls_lmots_private_free( &ctx->ots_private_keys[idx] ); + } } - if( ctx->ots_private_keys != NULL ) - mbedtls_free( ctx->ots_private_keys ); - if( ctx->ots_public_keys != NULL ) - mbedtls_free( ctx->ots_public_keys ); + { + for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) + { + mbedtls_lmots_public_free( &ctx->ots_public_keys[idx] ); + } + } + + mbedtls_free( ctx->ots_private_keys ); + mbedtls_free( ctx->ots_public_keys ); } mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ); @@ -594,6 +601,7 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, ctx->params.type = type; ctx->params.otstype = otstype; + ctx->have_private_key = 1; ret = f_rng( p_rng, ctx->params.I_key_identifier, @@ -619,22 +627,10 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, sizeof( *ctx->ots_public_keys ) ); if( ctx->ots_public_keys == NULL ) { - /* Free just the ots private keys (since they've been allocated at this - * point) so that we can pass the context to lms_private_free (which - * will not try to free the private keys since have_private_key is not - * set. - */ - mbedtls_free(ctx->ots_private_keys); - ctx->ots_private_keys = NULL; ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; } - /* Now that all the allocation has succeeded we set have_private_key, since - * that causes lms_private_free to free the ots keys. - */ - ctx->have_private_key = 1; - for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ ) { mbedtls_lmots_private_init( &ctx->ots_private_keys[idx] ); From 29c490db9796cb21a2eebadf38c0e9447f62703f Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 14:16:35 +0100 Subject: [PATCH 088/104] Update LMS calculate_public_key docs To avoid the word "generate" Signed-off-by: Raef Coles --- include/mbedtls/lms.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h index 7505ae462d..5e03d9b5f9 100644 --- a/include/mbedtls/lms.h +++ b/include/mbedtls/lms.h @@ -379,14 +379,14 @@ int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx, size_t seed_size ); /** - * \brief This function generates an LMS public key from a + * \brief This function calculates an LMS public key from a * LMS context that already contains a private key. * * \note Before this function is called, the context must * have been initialized and the context must contain * a private key. * - * \param ctx The initialized LMS public context to generate the key + * \param ctx The initialized LMS public context to calculate the key * from and store it into. * * \param priv_ctx The LMS private context to read the private key From 1d88ea870f80459c896c056fc95246b4e8c29ed9 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 14:18:16 +0100 Subject: [PATCH 089/104] Remove unneeded NULL pointer checks in LMS tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 3 +-- tests/suites/test_suite_lms.function | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index f2ce29a34b..0f339259cb 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -136,8 +136,7 @@ void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, } exit: - if( tmp_sig != NULL ) - mbedtls_free( tmp_sig ); + mbedtls_free( tmp_sig ); mbedtls_lmots_public_free( &ctx ); } /* END_CASE */ diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index dd37f31979..ff117ea27f 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -138,8 +138,7 @@ void lms_verify_test ( data_t * msg, data_t * sig, data_t * pub_key, } exit: - if( tmp_sig != NULL ) - mbedtls_free( tmp_sig ); + mbedtls_free( tmp_sig ); mbedtls_lms_public_free( &ctx ); } /* END_CASE */ @@ -192,8 +191,7 @@ void lms_import_export_test ( data_t * pub_key, int expected_import_rc ) } exit: - if( exported_pub_key != NULL ) - mbedtls_free( exported_pub_key ); + mbedtls_free( exported_pub_key ); mbedtls_lms_public_free( &ctx ); } /* END_CASE */ From 33f7d66304cf7f98205bfa89d16a2122d3f36d42 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 14:24:08 +0100 Subject: [PATCH 090/104] Add output check to export too-big buffer tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 2 ++ tests/suites/test_suite_lms.function | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 0f339259cb..13d1ee4cb4 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -184,6 +184,8 @@ void lmots_import_export_test ( data_t * pub_key, int expected_import_rc ) TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, exported_pub_key_buf_size, NULL ), 0 ); + ASSERT_COMPARE( pub_key->x, pub_key->len, + exported_pub_key, exported_pub_key_size ); mbedtls_free(exported_pub_key); exported_pub_key = NULL; } diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index ff117ea27f..1e5ac42a65 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -186,6 +186,8 @@ void lms_import_export_test ( data_t * pub_key, int expected_import_rc ) TEST_EQUAL( mbedtls_lms_export_public_key( &ctx, exported_pub_key, exported_pub_key_buf_size, NULL ), 0 ); + ASSERT_COMPARE( pub_key->x, pub_key->len, + exported_pub_key, exported_pub_key_size ); mbedtls_free(exported_pub_key); exported_pub_key = NULL; } From ed0e4591dc5bdf4f709efc8eb6301f8472d95ad0 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 15:05:47 +0100 Subject: [PATCH 091/104] Add output length test for LMS export too-big test Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 2 ++ tests/suites/test_suite_lms.function | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 13d1ee4cb4..616c39fa9e 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -184,6 +184,8 @@ void lmots_import_export_test ( data_t * pub_key, int expected_import_rc ) TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, exported_pub_key_buf_size, NULL ), 0 ); + TEST_EQUAL( exported_pub_key_buf_size, + MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ); ASSERT_COMPARE( pub_key->x, pub_key->len, exported_pub_key, exported_pub_key_size ); mbedtls_free(exported_pub_key); diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index 1e5ac42a65..baf74abc97 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -186,6 +186,8 @@ void lms_import_export_test ( data_t * pub_key, int expected_import_rc ) TEST_EQUAL( mbedtls_lms_export_public_key( &ctx, exported_pub_key, exported_pub_key_buf_size, NULL ), 0 ); + TEST_EQUAL( exported_pub_key_size, + MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10 ) ); ASSERT_COMPARE( pub_key->x, pub_key->len, exported_pub_key, exported_pub_key_size ); mbedtls_free(exported_pub_key); From 493724e3c25ef649300ad691dc20179938922015 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 15:43:07 +0100 Subject: [PATCH 092/104] Check correct output size in LMOTS export test Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index 616c39fa9e..b5b18b50f8 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -162,7 +162,7 @@ void lmots_import_export_test ( data_t * pub_key, int expected_import_rc ) exported_pub_key_buf_size, &exported_pub_key_size ), 0 ); - TEST_EQUAL( exported_pub_key_buf_size, + TEST_EQUAL( exported_pub_key_size, MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ); ASSERT_COMPARE( pub_key->x, pub_key->len, exported_pub_key, exported_pub_key_size ); @@ -184,7 +184,7 @@ void lmots_import_export_test ( data_t * pub_key, int expected_import_rc ) TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, exported_pub_key_buf_size, NULL ), 0 ); - TEST_EQUAL( exported_pub_key_buf_size, + TEST_EQUAL( exported_pub_key_size, MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ); ASSERT_COMPARE( pub_key->x, pub_key->len, exported_pub_key, exported_pub_key_size ); From e4d96b804c3c7a1dc2097a8f1b9eafb402f92d22 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 16:29:22 +0100 Subject: [PATCH 093/104] Update LMS and LMOTS test comments Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.data | 11 +++++---- tests/suites/test_suite_lms.data | 37 ++++++++++++++++++------------ 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index 6b34078c36..08b8faddf6 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -21,7 +21,8 @@ LMOTS hsslms interop test #1 # This test uses the same OTS key as the LMS hsslms interop test 1 (leaf 0 of # the LMS key), and the same message. # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE @@ -45,7 +46,8 @@ LMOTS hsslms interop test #2 # This test uses the same OTS key as the LMS hsslms interop test 2 (leaf 1 of # the LMS key), and the same message. # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE @@ -67,7 +69,8 @@ LMOTS hsslms interop NULL-message test # providing direct access to the underlying OTS signature scheme. The private # key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE @@ -85,7 +88,7 @@ lmots_verify_test:"":"00000004862327ead0b0eee8bde100614b3369e183f97812c13f0979f7 LMOTS hash-sigs interop negative test (altered random value) # This test uses the valid signature from hsslms interop test 1, and then -# permutes the random value (C) of the signature, and is expected to fail to +# alters the random value (C) of the signature, and is expected to fail to # verify. lmots_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"000000041bb462a8f59a277c1706ab69b1a40b0d56a3ffe1ddf0dfa890096c7a9c48b360e1e8f7abe4dc1950c4a64545ce6c0fe2a34477ec40f56db4eec37c1a2168e3059d4338a4eb368a64be5f98b5452f2c2fad23dcac585f5fe308bfc3df0b5cbc6cf3545236ed6c5a863e677521b5b5cee0aa1e755c3bbf5fb7326fac1a88cb12dd7f8d68ebe8bad07195a12fa11299073731e67f2452009252c595fc7d9285b90aaa912eb6cf0b5debc0996ca55ad5186702b244a616c4b9e0ceeea229e1e821c1ab0db906ce87640d128f1d8c4742d9baf340a8030df726a99a9b97f139ec57d8d87efdfca235f12de64e0a993804b95227cdfd26220a84502e350faaf5f91f3f49610eda211f9409005679e32068def22a2dcce3d226d0f68c4abc727b90d9c01daa05db24d7c0c9e9e48202e3420992ba78c36bc21c45cdf218801dc7053e3cbf39c141784e7a861671588622d540187912234ce628ea9cbd1800d215641163c762d2fd9194fa54bd9b46c83754579476398a5c2fece4642f1ee286a4e9a310b5e23088c75a68b123044c1c365c8b53fe9f895fa5d76fe1277c7c0f2a39f5b233f7d2acd5358feec2255feadb1c2513c4351c9bd1afe22d159f2d392c83bf7ec26b59e78330cd346adb85ef62fee3da63150ab5e0d7ce5d0ef353895360017faf3f35aca2cf3b8eda65389e2ba86f78ebfbe73382dfe9002331f24e96e1a6e56e7cc99ee848b82ad1ade3229e9e28168acfa8c059ed03028e8c872e72ff4cf8a50b84ade908ecf229a26ff1007c476d1aa376323fc567c9471085336496b231b5245a43c6c86c6a71c1b1fb4bd87c2d0b026bff55de121620a089ed9ade51c3bd91c703844c180ef9ad0ab550b9560ba9f1452463ce20987a402213ca5c16c927a0a85091dd74fbee22cac6b1afbc7e7dec229325c25ea3b3cc5a1c48c80665f9903e482b143f7cd051bdb990355f79c62553453c72ccbcc578df77069a7b0cf6fdc6853ec2f96fb7cc100216ae1b17aa20782fb0cd0f261b76a48b5d6f7bb48fa5f78c02a11ee81a8c0c81183910af770f2e907ebd5b2dc3a2b83529f62da074ca73c434f8f30b68a5dfee740f78d2c13b53c904e46dddf723923bfbffa437a4130c8c9b6d79a57db1c408b9c023f80fb3d766cb915e722f3b3152625d77bce3ca0c01e77f3750d7d1bef1ddda8b9b4233b09c89abe5913db50847a7ea219c3f406aa4cf41b6310bafa99a7b14f94b8ccd4dc7edb1a1e963ce26a53f3be71b4151ce5fae10ca30055e754880680e38cf2f21251f229341f7af9536360a428c2593c43fd2ae471bc1fa2b45ad55742a2f12f31eed6cb67945a898650c13650c4cffeecba8655f87e49ce921ced7ab00cf54eedf0c70e5c6cfa7f006763f0ac14d80cfb1662321cdccca8b1adf426eb9ca16ef2b978bb9ac229131fa5c1266a4980449c324ebdd8bcc98916089ee0b6966da7dc25350bdc758431884359d02f5fa567b39f49a6e410da2d0363944a090926308ed0ce7d565e6c4585ea010bc38ef1c976ae16ec1fbe6fb9d4d50e49a7be8273d2d56bf4e72acbadd90d5f8dee0":"0000000447cc5b29dd0cecd01c382434a6d1686400000000761e8e577fb4d12058806fc7bdaaef0ba64e454dc59b0230a77b43bbd83dc8c6":MBEDTLS_ERR_LMS_VERIFY_FAILED diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 207d943c4e..7ff6a7c68f 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -18,7 +18,8 @@ LMS pyhsslms interop test #1 # word at the start of the key/sig. We strip these 4 bytes from the signature # and the public key before including them in a the test data. # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # * pip3 install --user pyhsslms # * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv # * @@ -43,7 +44,8 @@ LMS pyhsslms interop test #2 # word at the start of the key/sig. We strip these 4 bytes from the signature # and the public key before including them in a the test data. # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # * pip3 install --user pyhsslms # * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv # * @@ -70,7 +72,8 @@ LMS pyhsslms interop NULL-message test # "levels" word at the start of the key/sig. We strip these 4 bytes from the # signature and the public key before including them in a the test data. # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # * pip3 install --user pyhsslms # * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv # * touch message.bin (create empty message file) @@ -101,7 +104,8 @@ LMS hash-sigs interop test #1 # 4-byte "levels" word at the start of the key/sig. We strip these 4 bytes from # the signature and the public key before including them in a the test data. # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # * # * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv # * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux tmp/lms.aux @@ -128,7 +132,8 @@ LMS hash-sigs interop test #2 # 4-byte "levels" word at the start of the key/sig. We strip these 4 bytes from # the signature and the public key before including them in a the test data. # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # * # * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv # * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux tmp/lms.aux @@ -151,7 +156,8 @@ LMS hsslms interop test #1 # limited amount of available test vectors for LMS. The private key is stored in # data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE @@ -173,7 +179,8 @@ LMS hsslms interop test #2 # limited amount of available test vectors for LMS. The private key is stored in # data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv # -# To reproduce the signature: +# To produce another signature with this message and key (note that the actual +# signature bytes will differ due to randomization): # pip3 install --user hsslms==0.1.2 # # from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE @@ -195,26 +202,26 @@ lms_verify_test:"92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a LMS negative test (invalid lms type) #1 # This test uses the data from hash-sigs interop test #1. This test has a valid -# LMOTS type (0x4) but an invalid LMS type (0x7), and should fail with a bad +# LMOTS type (0x4) but an invalid LMS type (0x5), and should fail with a bad # input data error. lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000058b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lms type) #2 # This test uses the data from hash-sigs interop test #1. This test has a valid -# LMOTS type (0x4) but an invalid LMS type (0x5), and should fail with a bad +# LMOTS type (0x4) but an invalid LMS type (0x7), and should fail with a bad # input data error. lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000078b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lm_ots type) #1 # This test uses the data from hash-sigs interop test #1. This test has an -# invalid LMOTS type (0x3) but an invalid LMS type (0x6), and should fail with a -# bad input data error. +# invalid LMOTS type (0x3) but a valid LMS type (0x6), and should fail with a +# verify-fail error. lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000003e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lm_ots type) #2 # This test uses the data from hash-sigs interop test #1. This test has an -# invalid LMOTS type (0x5) but an invalid LMS type (0x6), and should fail with a -# bad input data error. +# invalid LMOTS type (0x5) but a valid LMS type (0x6), and should fail with a +# verify-fail error. lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000005e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid leaf ID) @@ -264,11 +271,11 @@ lms_import_export_test:"000000070000000447cc5b29dd0cecd01c382434a6d16864d51b60cd LMS key import invalid LMOTS type test #1 # This test uses the valid public key for hsslms interop test 1, alters the -# LMS type to 0x7, and imports it. This should fail. +# LMOTS type to 0x3, and imports it. This should fail. lms_import_export_test:"000000060000000347cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMS key import invalid LMOTS type test #2 # This test uses the valid public key for hsslms interop test 1, alters the -# LMS type to 0x5, and imports it. This should fail, and not attempt to read +# LMOTS type to 0x5, and imports it. This should fail, and not attempt to read # invalidly outside the buffer. lms_import_export_test:"000000060000000547cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":MBEDTLS_ERR_LMS_BAD_INPUT_DATA From ce18e528ffb8304cb51f5a802dde18185a9edc15 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 16:40:48 +0100 Subject: [PATCH 094/104] Rename LMS private key files And remove now-unnecessary modification to check_files.py Signed-off-by: Raef Coles --- ...igs_sha256_m32_h5_lmots_sha256_n32_w8_aux} | Bin ...igs_sha256_m32_h5_lmots_sha256_n32_w8_prv} | Bin ...igs_sha256_m32_h5_lmots_sha256_n32_w8_pub} | Bin ...hss_sha256_m32_h5_lmots_sha256_n32_w8_prv} | Bin ...hss_sha256_m32_h5_lmots_sha256_n32_w8_prv} | Bin ...hss_sha256_m32_h5_lmots_sha256_n32_w8_pub} | Bin tests/scripts/check_files.py | 1 - tests/suites/test_suite_lmots.data | 12 +++---- tests/suites/test_suite_lms.data | 32 +++++++++--------- 9 files changed, 22 insertions(+), 23 deletions(-) rename tests/data_files/{lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux => lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_aux} (100%) rename tests/data_files/{lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv => lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_prv} (100%) rename tests/data_files/{lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.pub => lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_pub} (100%) rename tests/data_files/{lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv => lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv} (100%) rename tests/data_files/{lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv => lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv} (100%) rename tests/data_files/{lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8.pub => lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_pub} (100%) diff --git a/tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux b/tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_aux similarity index 100% rename from tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux rename to tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_aux diff --git a/tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv b/tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_prv similarity index 100% rename from tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv rename to tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_prv diff --git a/tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.pub b/tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_pub similarity index 100% rename from tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.pub rename to tests/data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_pub diff --git a/tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv b/tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv similarity index 100% rename from tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv rename to tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv diff --git a/tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv b/tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv similarity index 100% rename from tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv rename to tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv diff --git a/tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8.pub b/tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_pub similarity index 100% rename from tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8.pub rename to tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_pub diff --git a/tests/scripts/check_files.py b/tests/scripts/check_files.py index 3d2ca3ea0d..a0f5e1f538 100755 --- a/tests/scripts/check_files.py +++ b/tests/scripts/check_files.py @@ -119,7 +119,6 @@ BINARY_FILE_PATH_RE_LIST = [ r'tests/data_files/.*\.req\.[^/]+\Z', r'tests/data_files/.*malformed[^/]+\Z', r'tests/data_files/format_pkcs12\.fmt\Z', - r'tests/data_files/lms_.*\Z', ] BINARY_FILE_PATH_RE = re.compile('|'.join(BINARY_FILE_PATH_RE_LIST)) diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index 08b8faddf6..e6d71d33b6 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -17,7 +17,7 @@ LMOTS hsslms interop test #1 # This test uses data from https://github.com/pmvr/python-hsslms due to the # limited amount of available test vectors for LMOTS, and few implementations # providing direct access to the underlying OTS signature scheme. The private -# key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. +# key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv. # This test uses the same OTS key as the LMS hsslms interop test 1 (leaf 0 of # the LMS key), and the same message. # @@ -28,7 +28,7 @@ LMOTS hsslms interop test #1 # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # # ots_private_key = LM_OTS_Priv(private_key.otstypecode, private_key.I, 0, private_key.SEED) @@ -42,7 +42,7 @@ LMOTS hsslms interop test #2 # This test uses data from https://github.com/pmvr/python-hsslms due to the # limited amount of available test vectors for LMOTS, and few implementations # providing direct access to the underlying OTS signature scheme. The private -# key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. +# key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv. # This test uses the same OTS key as the LMS hsslms interop test 2 (leaf 1 of # the LMS key), and the same message. # @@ -53,7 +53,7 @@ LMOTS hsslms interop test #2 # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # #ots_private_key = LM_OTS_Priv(private_key.otstypecode, private_key.I, 1, private_key.SEED) @@ -67,7 +67,7 @@ LMOTS hsslms interop NULL-message test # This test uses data from https://github.com/pmvr/python-hsslms due to the # limited amount of available test vectors for LMOTS, and few implementations # providing direct access to the underlying OTS signature scheme. The private -# key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. +# key is stored in data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv. # # To produce another signature with this message and key (note that the actual # signature bytes will differ due to randomization): @@ -76,7 +76,7 @@ LMOTS hsslms interop NULL-message test # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # #ots_private_key = LM_OTS_Priv(private_key.otstypecode, private_key.I, 3, private_key.SEED) diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 7ff6a7c68f..93a10f6ded 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -65,7 +65,7 @@ lms_verify_test:"3f4fe37f1bb9547e443e53697a12f0393efbcf87c23d91765eb36100dd5d2c4 LMS pyhsslms interop NULL-message test # This test uses data from https://github.com/russhousley/pyhsslms due to the limited # amount of available test vectors for LMS. The private key is stored in -# data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv. Note that this signature +# data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv. Note that this signature # uses leaf key 2, so must be the third signature generated by the key if the # signature is to be reproduced. Message data is random. Note that hash-sigs # stores public keys and signatures in HSS form, which appends a 4-byte @@ -75,7 +75,7 @@ LMS pyhsslms interop NULL-message test # To produce another signature with this message and key (note that the actual # signature bytes will differ due to randomization): # * pip3 install --user pyhsslms -# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv +# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv # * touch message.bin (create empty message file) # * hsslms sign tmp/lms.prv message.bin (incorrect signature using leaf node 0) # * rm message.bin.sig @@ -96,8 +96,8 @@ lms_verify_test:"":"0000000200000004b219a0053b6bfe1988ade7b0a438c106262366cb6338 LMS hash-sigs interop test #1 # This test uses data from https://github.com/cisco/hash-sigs due to the # limited amount of available test vectors for LMS. The private key is stored in -# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv and -# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux. Note that this +# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_prv and +# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_aux. Note that this # signature uses leaf key 0, so must be the first signature generated by the key # if the signature is to be reproduced. Message data is random. Note that # hash-sigs stores public keys and signatures in HSS form, which appends a @@ -107,8 +107,8 @@ LMS hash-sigs interop test #1 # To produce another signature with this message and key (note that the actual # signature bytes will differ due to randomization): # * -# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv -# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux tmp/lms.aux +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_aux tmp/lms.aux # * # * /demo sign tmp/lms message.bin # * cat message.bin.sig | xxd @@ -117,15 +117,15 @@ LMS hash-sigs interop test #1 # * Save message and signature in binary format # * echo -n -e "\0\0\0\0" > message.bin.sig; cat sig.bin >> message.bin.sig (restore the # HSS levels) -# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.pub tmp/lms.pub +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_pub tmp/lms.pub # * verify tmp/lms message.bin lms_verify_test:"6b7439e31ef128c54f1536f745ff1246":"0000000000000004163fc2e3d3267d8c0d9fd9e7bb7a4eae84c3d98cd565de361edc426067960fc3201d9be1c30f4e4edce91844753aa13ff21e92648ac795b7c29dd6140962b5a1fb97b02570402a498a495044edcb26d1321c52e91c60cc3feb8f8e84fc77f97fb6e7afbfe4c2f2203d8d84303e2dd212b652e08a2e5a24a333df859cea3c5a547561f7ce6d182e2a3f2f018ef7e0578621916cff905c0713fa5f2bf73248ae6985aebc4086b79ebf71b8dcbb592eb61dc6303d06dbda88063690361b0dd25ea1c2c6b4d82dddbe11740864c65c228d67e9a1710506e585a748e7e02b36706e5cff83b3589613f07c636ab7784d6a8288d33e80f063165a2ddcbb0d7da815df8043dfa500c3e313c533bf6aec959237c923813d3109bdaeb195b1337f4cf21c1c863f6261dca411819603a3ea60cf34c81b462c4979b357da2bcdf3128343ca5a8a957e3ca4eebb914d743862e29ef48e43e7c5a7aaf7a2fe1251c309c65e9143dcfb298fa0d353084f60c0779e1a09b040f13c1025ec99402b844ff9996decf4b5f0d32a0858126ff293472aa93fbc2017d39fee93ff9f0ca2752b25cfa12542bf19cc1b8c102d65b70dccf760f26cb546742ce909d45345f802a985bae6a0f922a9c2a3dc992fae9f6f2fba0c52cad82564bde6ed8af880ee7a5eb5c6436611e5da1c690831bed34e3dd65acf2b8f496b6448e957afc16c48b6cd733bc84e3606a1d0609f08015c14b5619a2723f9b22950efc7ff7b733c299fcd84ed89c4d5cd43a9a54f25fc0fa1370d184f9e8011b60ba38dfca0eeeb56ae37a5823718c8210db20c2de13c39e43970b0b53b85b9cf9ea0dd025e7db558b463c683980fe59e0defde41afe825cfb8606ca861602a7fefd7506edc81b7ab4a1e0626e0bac1f99be118dbc1e291028fc73d0a0ea6559ae1dcf7477d64742c9bef88ef04b2ee4d392cf1efa23d8b05d11d2414e64f4540623e11bbf57fb8ae219331db0df459a9849f2700e6fa7ff4edb0fc01764949e279e84374e7a57fb5ee6221b2b72dbcf2ab9c988fe07d21e169b4338887129ac503cc6c0912787778d51b4b921cf7bb17d4028b7faf6c21dd616a1ac3b50d595ae0e3662e7faa16b9dec7694462c7fb8539ece0af33cc5a3dc33641b8827bf4751a708d7bf286cf2e795b8f45b76e1109abd908d0388d6ab8ecea67b187aabd80349e4bd286e3b6eeb3535cc9c343a39fe90cb443906b19d2483b4c93d0e35cd68d9f5523d5400a2b1708ba3361bd0757ed69b1da8845594edf053995b2d96bed8210aaab25fc34b2dd58004ce800360f24861e5912ac339ed0a78548e303e728a41e05c11d79013e3971eafa8034e63ecf1c842f0d9e735ff3b5badfd63ae07f051c94a9a867260b517e5c2c75e88e03d069bd39816a2255c90de81bb79622145b7469853a02eac45289fd9f9f40e2fccdd8ddb740469331f61badc1b7f6e0145dfe30141ad2f26ac8d7ff5125dc4dff1fec57629cea4f7de4401fc056e9a38ea028ac9c666ccd3f527947672408a759a5791d9efdeb1ff25392413728a03d4c641f4ce1542b6952e7595f1eecf1060000000671b0912d734442146e128d0029101ad34a6d2d586640235c828d427dfaffdb156771f06926678fa50aa7167684c1de108944b2c4a3358f5e926368009e4500a8d4d501124bc25a4c9b1cfb954503f4ae26c92221e39c680843ae55cfca972e139c82e2e4469a703a1866fa0e6d76636591f4ad07f7d1eaa19077660ad46a6f9d534970e6a49e24621b7c7c283253dd22fb24eb7819fab84bab88e42555d5437d5afe06615a7e0d103cc8595616690f1337f4345cf418724f07d0dc4d2c0899b691691f397202204ef34342b5725dc6adfe549ab0b887572ad38113c407f96fcdfeea0ffc4f333addfec296169e53e3c5b24797a20f3b2f043f5e96920de9927da466f09389d3e52a5665f380f68666a019c201e710ab4c168d5ac952a02d5909a6fcaf498a33e2124e6a828203744ee3fe70465adde0cfbccc1b4634541638ab":"0000000600000004e18760ef2c86192aee88579e376f35cd153419d622803a483e79f6d368629308a8ab6ff663c4f108b2033af290dcedfa":0 LMS hash-sigs interop test #2 # This test uses data from https://github.com/cisco/hash-sigs due to the # limited amount of available test vectors for LMS. The private key is stored in -# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv and -# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux. Note that this +# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_prv and +# data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_aux. Note that this # signature uses leaf key 1, so must be the second signature generated by the key # if the signature is to be reproduced. Message data is random. Note that # hash-sigs stores public keys and signatures in HSS form, which appends a @@ -135,8 +135,8 @@ LMS hash-sigs interop test #2 # To produce another signature with this message and key (note that the actual # signature bytes will differ due to randomization): # * -# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.prv tmp/lms.prv -# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.aux tmp/lms.aux +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_aux tmp/lms.aux # * # * /demo sign tmp/lms message.bin (incorrect signature using leaf node 0) # * rm message.bin.sig @@ -147,14 +147,14 @@ LMS hash-sigs interop test #2 # * Save message and signature in binary format # * echo -n -e "\0\0\0\0" > message.bin.sig; cat sig.bin >> message.bin.sig (restore the # HSS levels) -# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8.pub tmp/lms.pub +# * cp data_files/lms_hash-sigs_sha256_m32_h5_lmots_sha256_n32_w8_pub tmp/lms.pub # * verify tmp/lms message.bin lms_verify_test:"0705ba8297c7b9fa5f08e37825ad24a0":"00000001000000040a432454b99750f7b703f0280f92818b0570d0267a423b377be7cf0561305d4ce987b9d8dbc1c3f8ba410bbe6b921406eb802688d2dd8a1a6fa4a124cbcae9b5a210f583a956384c06311953b038b4ad2c2808224fc3a6410cd3b89274371956bcd4253a251cba6409b09c822e1d29d7a037648a6f2562d0df6359a043622f256f5ac79736c08fc4185758ff002a8397e560d5812373946348afba2ccf2cc0f3ba741ec076d4587a54b8b625804b814c30540152a3dc843a590c94cc23ba857e4c458c8ab687b5b9b68837ee890454cc19bb5f42a1e6dc051803fab50b440067a903013f675a774b5d02cd56289518d65f869f22b2e2b58d499e9e3929ec5a9f5d6d6e03cf91486094aba7c88491cde35b81c175c40410bc402d20f0a73a4da844d3a1d47e57618b7f18fa5ac85e877b5faa1e0b6733c2d96b2970fdd6e606435e3ec50eafa88f84fb7512217aa4be5858a140f242603bda634d76c484a184298c4da903094468d032b88586fd2f35182405cd85115af6a0bbd431f2e44217a1691dd8887db91d3b97264ff552ae7dc110a3a111f2bf74ce42079055dfb8390a16d67f28b738f837aa7880f3134deabcf6ec74cdb521bff44df61c999bf7a8ddc43b64812cd4f3bfb15104867d5e585d1cbf99738e0df92660b3e9135a4377d1199b8b97362fc87ce3c99db3b8aba63ba35eb353e5ec79bcee82b9ccc1b4f7d1b8ce7e5f8813d007be3d0e45cb8e7173337a5a7c4d32ea5116e0fdbd7846ea1f366a531449c78cd7a16ce5bffcd6cccf54b7f249a74e0df6b07f6b48db42eb958ff18b06995368af0cadd82f44cf44e4b53f0993de5f06b289bee41cd25f90a9fbd1bfb1ab2451c96b07adcfb5210d291dd505ea30e5d30395c8d84eabccdd2c7d6f28a88f5e5d245a6980c57810cfe17c9a37ef5e79b7b9ca755d56a789d21985372bed42ae2830d81ebf0fad6c721bd1d3ee91ae363f40d386aac23e7c0db965539ce9bff38f0f24bec3227b5a24f4cd7fa71ca9d306faa3fc4726cdb6634f218897b79a4aed67a58799285104eed74703ec4af6d5738b27b4d6fb71e52c1149069483a7cca6c3fccbdff77312ff5c635d8b0ccd53dbaf7b498727f7c7a70d3fd1c3f217e2cbd0dfe91258acb7f79f53f56012a82da997ea777b76dac0472e5f9830a93fb09703b1c0e45cbfbf641de94fcc6c609f02a5b31ad5821ba6cd48829fc5e0c4ad78e11e4cac8efbb1b170c794b7b131b0c1c4e39fdef81db9e7acced5ec824aed0c4e6b57fd1add4191e87be1446c7c519eb671205ce8c5855ad7a2b9ff7a9cd5c45336f508d0f8d2c1152dc2656650bdaf8fced642f3a4d445b5fc49910bdbdc9635de0086ee9582a796ca9f6052de805f41dfbd3e94982a05cbd36bab583dd5b1586ddbb3b1a45f1a265bec062c1a50d220870c0c622d852e650a67f31e8eb3d19e964de0926712b7f429ad05024b8db51eb6702c39580f62f037388862251bf66f02edee9615a63957eab75b28501f9f26cecd09a5c949127c9a3095036667fce8e45ba75568d5160fa1725a9e0038145d948f437640dc4441000000066e8db13a9e79d10a4e067aad448a1847b5489a62cde3054ee1e5ff2e37549d516771f06926678fa50aa7167684c1de108944b2c4a3358f5e926368009e4500a8d4d501124bc25a4c9b1cfb954503f4ae26c92221e39c680843ae55cfca972e139c82e2e4469a703a1866fa0e6d76636591f4ad07f7d1eaa19077660ad46a6f9d534970e6a49e24621b7c7c283253dd22fb24eb7819fab84bab88e42555d5437d5afe06615a7e0d103cc8595616690f1337f4345cf418724f07d0dc4d2c0899b691691f397202204ef34342b5725dc6adfe549ab0b887572ad38113c407f96fcdfeea0ffc4f333addfec296169e53e3c5b24797a20f3b2f043f5e96920de9927da466f09389d3e52a5665f380f68666a019c201e710ab4c168d5ac952a02d5909a6fcaf498a33e2124e6a828203744ee3fe70465adde0cfbccc1b4634541638ab":"0000000600000004e18760ef2c86192aee88579e376f35cd153419d622803a483e79f6d368629308a8ab6ff663c4f108b2033af290dcedfa":0 LMS hsslms interop test #1 # This test uses data from https://github.com/pmvr/python-hsslms due to the # limited amount of available test vectors for LMS. The private key is stored in -# data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv +# data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv # # To produce another signature with this message and key (note that the actual # signature bytes will differ due to randomization): @@ -163,7 +163,7 @@ LMS hsslms interop test #1 # from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # # public_key = private_key.gen_pub() @@ -177,7 +177,7 @@ lms_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"00000000000000041394a893e40b LMS hsslms interop test #2 # This test uses data from https://github.com/pmvr/python-hsslms due to the # limited amount of available test vectors for LMS. The private key is stored in -# data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8.prv +# data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv # # To produce another signature with this message and key (note that the actual # signature bytes will differ due to randomization): @@ -186,7 +186,7 @@ LMS hsslms interop test #2 # from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8.prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # # public_key = private_key.gen_pub() From 1951259a10e9d1caac58df2aa516b2913ddd53d5 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 16:47:13 +0100 Subject: [PATCH 095/104] Update how lms.c imports platform.h Signed-off-by: Raef Coles --- library/lms.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/library/lms.c b/library/lms.c index 35ca890b50..46ea567f2f 100644 --- a/library/lms.c +++ b/library/lms.c @@ -44,15 +44,7 @@ #include "mbedtls/error.h" #include "mbedtls/platform_util.h" -#if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif #define SIG_Q_LEAF_ID_OFFSET (0) #define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \ From a2514f622f4f43ed65041b6289db6c13b3f4070e Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 17:04:21 +0100 Subject: [PATCH 096/104] Update pyhsslms test instructions with script Due to tool name conflict hampering data reproduction Signed-off-by: Raef Coles --- tests/suites/test_suite_lms.data | 46 +++++++++++++++++--------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 93a10f6ded..722def7d2d 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -22,17 +22,17 @@ LMS pyhsslms interop test #1 # signature bytes will differ due to randomization): # * pip3 install --user pyhsslms # * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv -# * -# * hsslms sign tmp/lms.prv message.bin -# * cat message.bin.sig | xxd +# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_pub tmp/lms.pub # -# To validate the signature: -# * Save message and signature in binary format -# * echo -n -e "\0\0\0\0" > message.bin.sig; cat sig.bin >> message.bin.sig (restore the -# HSS levels) -# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8 tmp/lms.pub -# * hsslms verify tmp/lms message.bin -lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 +# import pyhsslms +# +# private_key = pyhsslms.HssLmsPrivateKey('tmp/lms') +# +# message = bytes.fromhex('60da1a17c88c59da8a730e6ca8effd37') +# public_key = private_key.hss_pub +# sig = private_key.sign(message) +# print('lms_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), public_key.serialize().hex())) +lms_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"0000000000000000000000042c85763d2abaedaecd484517ff85138e8ab7f621585a6f8f5e072c9c0851e89aa6bb116a2cef094155cb142f0bdb84dddfa3ab236dd3bd1019b2a4caa8e26c011d3f9fc8f7df57d8f475564d5b5bd92af9f62137e176cda914bac6e07a086d287d2d9e6d7b9ad768462a39930c19761905136345a0a9f2e28f5bcd288c9137cc828bc790be3020405f4e273b6749dc35d1f4bfea3eb679ca1b46fe26196dbb7ba7f0d56643e716ca3a2f0491fbe5c5aec80ab1a4f718577655e3e56ced0e562f137c7f2be6a9c4589442f23e0c51f19fed5b9e834ffb26dca160d4fe11b7e66bf4fa099bea131620e2906fcbbf5071348cedcb70c372a8a99f7e582f02858d0d7c66ea45728a11420cf20937362dce440f0b8a96fa47e6d03470044555e5a46ec758d4e86b773afe5f5b97c328990a2e4ed59e879ec5f4c59eaaec13cc6790d38a4754a5f0029e53b4461406f6e958dc7ca3a88984e675533cac7f54c00fdfb879acd13404b091e599248eb69624bb2a8f73be37e3ec9fb5d6b9cf65f738333d93d82558c7552ba39f6afce7a7bb6756083e1e61c4a02c36a501c19b08856ba9ff07de3a0e1a6a44abcd0a663643bd8dddf5949eb4ce86feb93ba59f15b18fba26098a8a3a2aa1e5ad79155728c28904a1b218426744b4897a263be0954440e0a85ec378f922a91bbdb098b07d5873667277d22218a3b3a64292648da86b4aaa6af23fd6efa6567b184781159ca9d69619da9b7c1e9c2f9cafcc1f6ca244ae6ced58d880b72cd3fa1269b1d634fd4f551815ce59701773f6454edca537138bc00540c01f0735946151747a3ecb591775b86ecdb58d24aebb67e204e1e17882563a089c13ccea1e8baa5ed3515fd3d691697d826829fbf33a234198abac4bebc6ea6e56cba0925412b8f37bc1e532012b1d1fabf99d1b5ff15ba323ac6b5ba89353a115a5619755d1481fdce82180430fbeef3466e188b6508713ec958074ab6c81a30141a6f14b7768b7f5b25712f9a2aedd0a0b9fae183472b290b51ee92a5ddbcca3994dbb7860f13b9fde81ade00c2c29a0692033d8d2a6827fcc9b50b15b94c2507636710ce681b5b2d5792ea2e0c3a8bb4e8a3c00ab0fa924c228d88a47d649e6804394767db291d2e6b0976f56209d0cf8d2804f402342e98764cb8cee65dde7df65cb241fd2af599ffd8063fd5a28ff4f105c15f7b836cc792402c78c2281302e3cdf7f5e11beacef8b5c5a41ed8a6c30d622cca1fd7075aa12e3d7d54f2c4b7375b8eac6c1be8f8b7e97c17f73b698d01d5f0fa3c644b0b225b390cd613c18ea141ecd1801ad9a4518db5c1c115360b09dda5071ff130d3bff4809e3a1ce9ab5115d86f46cf8b8733271415582d97fa479ede1393d455cf9d227a4248e7d56d280075af69fe8946ac4a98056ac5e4f89a54d813222fb76fcf700bc34e3c9e3650c16cafc83d16e6f3240c443c64e807495a482a66a77d3b552d167c0d0355a25266a3d55ba593b68eaab6c24b0264e3832f08ca0dd91cc8a711c9e23ad37b76e8e658f6b1f61d5e448787fb57f13bcbf88e6939c265d3d6c07295703000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"000000010000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 LMS pyhsslms interop test #2 # This test uses data from https://github.com/russhousley/pyhsslms due to the @@ -48,19 +48,21 @@ LMS pyhsslms interop test #2 # signature bytes will differ due to randomization): # * pip3 install --user pyhsslms # * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv -# * -# * hsslms sign tmp/lms.prv message.bin (incorrect signature using leaf node 0) -# * rm message.bin.sig -# * hsslms sign tmp/lms.prv message.bin (correct signature using leaf node 1) -# * cat message.bin.sig | xxd +# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_pub tmp/lms.pub # -# To validate the signature: -# * Save message and signature in binary format -# * echo -n -e "\0\0\0\0" > message.bin.sig; cat sig.bin >> message.bin.sig (restore the -# HSS levels) -# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8 tmp/lms.pub -# * hsslms verify tmp/lms message.bin -lms_verify_test:"3f4fe37f1bb9547e443e53697a12f0393efbcf87c23d91765eb36100dd5d2c48":"00000001000000046fe15c33e5f4396fe8af67d20cd9886c59edb8aa6e005a206427d55c66cffa0d552114c88c70a6e07a8e69c53568b3deac7835f5706cd76152fc6b8dd624cf42e372ffccdb6a96a0b5028e85181e8fd67b77fb0ff38fcce830c5b65dfe16762550d5450eea7a39bb3dc745c7fcc240982ed6d1ae251822b2ca210b5c612aaf559280a7b3ccb5d68c6ea1fb6784d5134004570628f5b35a8517358ba47c6c8b827eda2e16925e945f00a42a7eb6c9034891982e8b116a43cb817bd1f67c317a20f98e1b23809c614b60231c475f24f8c2437c36b452253d517cfb0ffaafa4b53248d3f516fda0417a74d0f43771f7369ca71064e2f54fb1bd98e028fdfe3157ef6f6470c32d4b7baaae57e1b104f4c81073cb9fd339349106b699b279877b2291e32675c6a8a82e35f1b337e91d8a29c8d5c046ceb6246c44467a4a11cff22abe98b10b6a6d68361d15f140b06659b90561ea43fd9c39903a4d2be84fa89642120498ff377024c42a687fc87180a29bd030455fc453ae84c1c747a35ca81f47beba61fcd6a63970b21ed8ee74e00371e7439cb790b00bdfa89628e145698c4ee04ddb528ef56dced72754659e87f25b8e92e60252ecc5580646dceae45d1ca986b307c459249ab3b0fc85f43eb22779711846f2ee13ee0f4060a7edd95c73209ff735ce44fa02145cfa6916a305e668fd08aa943c72f2167705450037dda5f688bcad385582bf1bfe3b8316f7325837c10d193d4d898776134d420107f136ff2080563d9c4bcd48af7ef9f2cfafe517082aac1b54ebab41388c171668d03c64e62208a60a8cfa81483440b17a359e95c730299a287084d49c623f3547d3ce7936d69cb478c0533693732e7aa3161370decc75f7ae52fb0065584a20851469c07d8aa78c0ae28e7d42e86b908ecd5161c3b74409d67d639c39b99bf03f9ec3ddfb607bc594dffdfa6393b37a2cfd0dcb18ff9d63aba806821dee85aac0938fdee86fe21045c0c200527ce64be88cd971902dc8adac1f14e212c6e03d89c9e268046448c5a285f287a9896f59acb93fb12e3ac62d1df44beba165a26403d4f738acd561834c3f4d554c4bc8f20eb90199b0c3f332d19c033eaca1339ef8d029026d2aa76760e11b27427236f94fcefc4a6844937559495a36ebbde0b116c2644469fda60611d9f6ff1b189a8ddf3073acc5a55f1b0605de7c42a660f4897abd14ae485457e18b24e3d71222ae79660266ce53e89d1b60ce1622d1ef8ce3ed5179828ceb7c7298f9d10a309830ae7b530a913cb6306b7d2ce7b10753e817314fd9b6ef584fab9aba0b617cbe1a54a8610096615b56fd5b6798ce98ea866da2911b351ef5ea4411a44c726c019cf375a169fa6fd66f54d59f04e4f615e8da822413e017b60e93412e6195d4d7b7ec269e6f59dc072ba1e688a651bb45a27612949bb9eb6d0fa887393707a9c7a07f2b0640fc67dbb55d288501c394f0b61ea4c2bc1af6599032a0f8f3edef2ef5b007d3618856d48aec7894e9a4b802caf9c3f0022c39c44b4a6271f81aba0f250997ddd423e3da0461fb687e56e20e9d4a2c38d78d000000063b71be980cffb4e8a8e310341d3b711ab19545ae90c3ac6adcbeb764419411a6ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 +#import pyhsslms +# +#private_key = pyhsslms.HssLmsPrivateKey('tmp/lms') +# +#message = bytes.fromhex('60da1a17c88c59da8a730e6ca8effd37') +#public_key = private_key.hss_pub +#sig = private_key.sign(message) +# +#message = bytes.fromhex('92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1') +#public_key = private_key.hss_pub +#sig = private_key.sign(message) +#print('lms_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), public_key.serialize().hex())) +lms_verify_test:"92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1":"0000000000000001000000042115dafc81fb6404f904c6037b00c970a0790ceadf0d39f93eddae43ee0daffa0088358a8f89ca5c2b2af0d55c4ecdcbdd84953ce4043d2657ada39f4344ace04e3c4ae3d72788214d28d1b5c85af7a6d3d9d85594a907a9a39b258d4385700a6c001b52923846f68a991a86ddad9b272c98064d43142d339c1cc64e833f7f5346a70b1ef77cb197c66ef68e7a41678ec1dedfe5b6d6e22746b839df8ffdf6d6830f86e47a0370a17646ada2e3f13ee68e6cfdcbb20c0b05e47c088bc27a1e4010aca6f42f2e4c92b28d4f8591fcab60c57fea248b6e8c412b6806f956e459252df4dedbbbecdbaa57f0f15e91ab9fc1c8dae1e1ba5556faa8d618bef9f977b3571b6438f13583f5a2e4036f450a89881b108d44bd8a6700c544d12e1ba48eaa9f53eed260f0dc2bf8bd630565af7d9e182539957780b0771365d4fe57d9fb0f76b2e4e7737fd3d8e8ba67d16af59c13563ceda4d632a0f7d742c98e05d29fb752ccddca2b8e8cc0bb3e57547dbe62d77fb792568cfc8218291a057fc61d94137556f17301e4b7ab3b8f33610925aa5160397665212e16bdc3fffc7ae0ce22c83eb357409bb08b38585628b1475931e09d65986dadf01aff0f7b0e7d19cce8318ea2fcf112710da63b25b3fb1f28fa387e0dc4eea17e0cd7f1e09e2a0cf0797199750f88d4b1d597c15a8694c68e6ac04564f5ee826d612839e2a26c4e7db4e4bd4919ef5ab1730a97bc5ec0c89c93dea4e8bca06426b121bf065ed43a7f2c91ee7211c53d6111de7ccff339a99203de88fb1ec592af5a4e9b2bfc437d0be7dd3aad57f5a84a4a87522cca5fc64176acf033f25f6ec10c673f38c0a3eca954c2acdad80674bac208c0c8be1ed50ed3f41e14c4edef82fe878444c4c874fbd0019e697b3401971b9ae1b73824079de84fc889f6108ea53b94fd50eaa56ccc0fa466168b6fb4322ac01d3429a109e55d6a2459ebfb0297b32bf1eea33fec4317eab77f2d415bfe5ac243e6e6ba26f9a4dccd5bf921c813218268106c129081da409b1808eedaeebf420f768935c0c91981dc48bc07926649926cf62f596582e8b3b9f9a18e0a91221a1d03913245792269ed260071dbfb27240d78a3d98945414da4bc7e4267b8a56cc18d2a8cc2fbe0206989541be84c181dc8aea74654514d894098534963449fc7e5ecd98218c93b38c925761fae62056dd7156b215fdf48ab36d230ab6feb3df3a590fa267e8c0cb78c2f2c90ab7c71dfa97e148a03c427077ec2abc08a3ec2ec7b2503a3dc988f6a9e5362e1043be819e78c71ae96646431eb83d6c9f91edbca6507c31a44f0b643c0028813559e8b5894575461d728ed633b89d660be1635e921fac6844071687b9c82b4aedfdc7cadfee07f113906cf4f78b7e8397f6be3872a53a31e15b54443753b4197e942e2512a9703d729116e683ad9a718f0fa15cf94cc2676498e6d2f207b2d3fd61dba1ad0291eb9e243c4ab771ee4f92ac782fd72b35abff18fd91198007d604b74b7d2741e36fa74c3a1732217b06f1d2e4e34d61012e83f99d03f1e83c97150dedd04f67978620da7e0e5000000063b71be980cffb4e8a8e310341d3b711ab19545ae90c3ac6adcbeb764419411a6ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"000000010000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 LMS pyhsslms interop NULL-message test # This test uses data from https://github.com/russhousley/pyhsslms due to the limited From d543697092b0155669fccf4837f0d27cf9cb0ce2 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 17:06:42 +0100 Subject: [PATCH 097/104] Fix minor type in LMS test description Signed-off-by: Raef Coles --- tests/suites/test_suite_lms.data | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 722def7d2d..de0ee5a61f 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -262,12 +262,12 @@ lms_import_export_test:"00000006000000":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMS key import invalid LMS type test #1 # This test uses the valid public key for hsslms interop test 1, alters the -# LMS type to 0x7, and imports it. This should fail. +# LMS type to 0x5, and imports it. This should fail. lms_import_export_test:"000000050000000447cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":MBEDTLS_ERR_LMS_BAD_INPUT_DATA LMS key import invalid LMS type test #2 # This test uses the valid public key for hsslms interop test 1, alters the -# LMS type to 0x5, and imports it. This should fail, and not attempt to read +# LMS type to 0x7, and imports it. This should fail, and not attempt to read # invalidly outside the buffer. lms_import_export_test:"000000070000000447cc5b29dd0cecd01c382434a6d16864d51b60cdb2a9eed2419015d8524c717ce38a865d7a37da6c84f94621ad595f5d":MBEDTLS_ERR_LMS_BAD_INPUT_DATA From f8bfe2783b2a2c4c7fcb5ac6ce776443f3345d22 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 17:35:28 +0100 Subject: [PATCH 098/104] Remove bad character from LMS test case Signed-off-by: Raef Coles --- tests/suites/test_suite_lms.data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index de0ee5a61f..eccdd61ea0 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -32,7 +32,7 @@ LMS pyhsslms interop test #1 # public_key = private_key.hss_pub # sig = private_key.sign(message) # print('lms_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), public_key.serialize().hex())) -lms_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"0000000000000000000000042c85763d2abaedaecd484517ff85138e8ab7f621585a6f8f5e072c9c0851e89aa6bb116a2cef094155cb142f0bdb84dddfa3ab236dd3bd1019b2a4caa8e26c011d3f9fc8f7df57d8f475564d5b5bd92af9f62137e176cda914bac6e07a086d287d2d9e6d7b9ad768462a39930c19761905136345a0a9f2e28f5bcd288c9137cc828bc790be3020405f4e273b6749dc35d1f4bfea3eb679ca1b46fe26196dbb7ba7f0d56643e716ca3a2f0491fbe5c5aec80ab1a4f718577655e3e56ced0e562f137c7f2be6a9c4589442f23e0c51f19fed5b9e834ffb26dca160d4fe11b7e66bf4fa099bea131620e2906fcbbf5071348cedcb70c372a8a99f7e582f02858d0d7c66ea45728a11420cf20937362dce440f0b8a96fa47e6d03470044555e5a46ec758d4e86b773afe5f5b97c328990a2e4ed59e879ec5f4c59eaaec13cc6790d38a4754a5f0029e53b4461406f6e958dc7ca3a88984e675533cac7f54c00fdfb879acd13404b091e599248eb69624bb2a8f73be37e3ec9fb5d6b9cf65f738333d93d82558c7552ba39f6afce7a7bb6756083e1e61c4a02c36a501c19b08856ba9ff07de3a0e1a6a44abcd0a663643bd8dddf5949eb4ce86feb93ba59f15b18fba26098a8a3a2aa1e5ad79155728c28904a1b218426744b4897a263be0954440e0a85ec378f922a91bbdb098b07d5873667277d22218a3b3a64292648da86b4aaa6af23fd6efa6567b184781159ca9d69619da9b7c1e9c2f9cafcc1f6ca244ae6ced58d880b72cd3fa1269b1d634fd4f551815ce59701773f6454edca537138bc00540c01f0735946151747a3ecb591775b86ecdb58d24aebb67e204e1e17882563a089c13ccea1e8baa5ed3515fd3d691697d826829fbf33a234198abac4bebc6ea6e56cba0925412b8f37bc1e532012b1d1fabf99d1b5ff15ba323ac6b5ba89353a115a5619755d1481fdce82180430fbeef3466e188b6508713ec958074ab6c81a30141a6f14b7768b7f5b25712f9a2aedd0a0b9fae183472b290b51ee92a5ddbcca3994dbb7860f13b9fde81ade00c2c29a0692033d8d2a6827fcc9b50b15b94c2507636710ce681b5b2d5792ea2e0c3a8bb4e8a3c00ab0fa924c228d88a47d649e6804394767db291d2e6b0976f56209d0cf8d2804f402342e98764cb8cee65dde7df65cb241fd2af599ffd8063fd5a28ff4f105c15f7b836cc792402c78c2281302e3cdf7f5e11beacef8b5c5a41ed8a6c30d622cca1fd7075aa12e3d7d54f2c4b7375b8eac6c1be8f8b7e97c17f73b698d01d5f0fa3c644b0b225b390cd613c18ea141ecd1801ad9a4518db5c1c115360b09dda5071ff130d3bff4809e3a1ce9ab5115d86f46cf8b8733271415582d97fa479ede1393d455cf9d227a4248e7d56d280075af69fe8946ac4a98056ac5e4f89a54d813222fb76fcf700bc34e3c9e3650c16cafc83d16e6f3240c443c64e807495a482a66a77d3b552d167c0d0355a25266a3d55ba593b68eaab6c24b0264e3832f08ca0dd91cc8a711c9e23ad37b76e8e658f6b1f61d5e448787fb57f13bcbf88e6939c265d3d6c07295703000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"000000010000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 +lms_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"0000000000000000000000042c85763d2abaedaecd484517ff85138e8ab7f621585a6f8f5e072c9c0851e89aa6bb116a2cef094155cb142f0bdb84dddfa3ab236dd3bd1019b2a4caa8e26c011d3f9fc8f7df57d8f475564d5b5bd92af9f62137e176cda914bac6e07a086d287d2d9e6d7b9ad768462a39930c19761905136345a0a9f2e28f5bcd288c9137cc828bc790be3020405f4e273b6749dc35d1f4bfea3eb679ca1b46fe26196dbb7ba7f0d56643e716ca3a2f0491fbe5c5aec80ab1a4f718577655e3e56ced0e562f137c7f2be6a9c4589442f23e0c51f19fed5b9e834ffb26dca160d4fe11b7e66bf4fa099bea131620e2906fcbbf5071348cedcb70c372a8a99f7e582f02858d0d7c66ea45728a11420cf20937362dce440f0b8a96fa47e6d03470044555e5a46ec758d4e86b773afe5f5b97c328990a2e4ed59e879ec5f4c59eaaec13cc6790d38a4754a5f0029e53b4461406f6e958dc7ca3a88984e675533cac7f54c00fdfb879acd13404b091e599248eb69624bb2a8f73be37e3ec9fb5d6b9cf65f738333d93d82558c7552ba39f6afce7a7bb6756083e1e61c4a02c36a501c19b08856ba9ff07de3a0e1a6a44abcd0a663643bd8dddf5949eb4ce86feb93ba59f15b18fba26098a8a3a2aa1e5ad79155728c28904a1b218426744b4897a263be0954440e0a85ec378f922a91bbdb098b07d5873667277d22218a3b3a64292648da86b4aaa6af23fd6efa6567b184781159ca9d69619da9b7c1e9c2f9cafcc1f6ca244ae6ced58d880b72cd3fa1269b1d634fd4f551815ce59701773f6454edca537138bc00540c01f0735946151747a3ecb591775b86ecdb58d24aebb67e204e1e17882563a089c13ccea1e8baa5ed3515fd3d691697d826829fbf33a234198abac4bebc6ea6e56cba0925412b8f37bc1e532012b1d1fabf99d1b5ff15ba323ac6b5ba89353a115a5619755d1481fdce82180430fbeef3466e188b6508713ec958074ab6c81a30141a6f14b7768b7f5b25712f9a2aedd0a0b9fae183472b290b51ee92a5ddbcca3994dbb7860f13b9fde81ade00c2c29a0692033d8d2a6827fcc9b50b15b94c2507636710ce681b5b2d5792ea2e0c3a8bb4e8a3c00ab0fa924c228d88a47d649e6804394767db291d2e6b0976f56209d0cf8d2804f402342e98764cb8cee65dde7df65cb241fd2af599ffd8063fd5a28ff4f105c15f7b836cc792402c78c2281302e3cdf7f5e11beacef8b5c5a41ed8a6c30d622cca1fd7075aa12e3d7d54f2c4b7375b8eac6c1be8f8b7e97c17f73b698d01d5f0fa3c644b0b225b390cd613c18ea141ecd1801ad9a4518db5c1c115360b09dda5071ff130d3bff4809e3a1ce9ab5115d86f46cf8b8733271415582d97fa479ede1393d455cf9d227a4248e7d56d280075af69fe8946ac4a98056ac5e4f89a54d813222fb76fcf700bc34e3c9e3650c16cafc83d16e6f3240c443c64e807495a482a66a77d3b552d167c0d0355a25266a3d55ba593b68eaab6c24b0264e3832f08ca0dd91cc8a711c9e23ad37b76e8e658f6b1f61d5e448787fb57f13bcbf88e6939c265d3d6c07295703000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"000000010000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 LMS pyhsslms interop test #2 # This test uses data from https://github.com/russhousley/pyhsslms due to the From aa9d52bcdc3bd6fb591a32df0954143ec1de3fd1 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 17:53:40 +0100 Subject: [PATCH 099/104] Rename LMS private key files to match library name Signed-off-by: Raef Coles --- ...ms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv} | Bin ..._pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv} | Bin ..._pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_pub} | Bin tests/suites/test_suite_lms.data | 4 ++-- 4 files changed, 2 insertions(+), 2 deletions(-) rename tests/data_files/{lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv => lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv} (100%) rename tests/data_files/{lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv => lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv} (100%) rename tests/data_files/{lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_pub => lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_pub} (100%) diff --git a/tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv b/tests/data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv similarity index 100% rename from tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv rename to tests/data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv diff --git a/tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv b/tests/data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv similarity index 100% rename from tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv rename to tests/data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv diff --git a/tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_pub b/tests/data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_pub similarity index 100% rename from tests/data_files/lms_pylmshss_sha256_m32_h5_lmots_sha256_n32_w8_pub rename to tests/data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_pub diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index eccdd61ea0..89ad581965 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -165,7 +165,7 @@ LMS hsslms interop test #1 # from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # # public_key = private_key.gen_pub() @@ -188,7 +188,7 @@ LMS hsslms interop test #2 # from hsslms import LMS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # # public_key = private_key.gen_pub() From 6d7d94a821425f0efc7daec621d83aa930715ca8 Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 17:55:46 +0100 Subject: [PATCH 100/104] Use correct export length in LMS export tests Signed-off-by: Raef Coles --- tests/suites/test_suite_lmots.function | 5 ++--- tests/suites/test_suite_lms.function | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_lmots.function b/tests/suites/test_suite_lmots.function index b5b18b50f8..53ab02ff6e 100644 --- a/tests/suites/test_suite_lmots.function +++ b/tests/suites/test_suite_lmots.function @@ -182,10 +182,9 @@ void lmots_import_export_test ( data_t * pub_key, int expected_import_rc ) exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) + 1; ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size); TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, - exported_pub_key_buf_size, NULL ), + exported_pub_key_buf_size, + &exported_pub_key_size ), 0 ); - TEST_EQUAL( exported_pub_key_size, - MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ); ASSERT_COMPARE( pub_key->x, pub_key->len, exported_pub_key, exported_pub_key_size ); mbedtls_free(exported_pub_key); diff --git a/tests/suites/test_suite_lms.function b/tests/suites/test_suite_lms.function index baf74abc97..c5c8aa4b90 100644 --- a/tests/suites/test_suite_lms.function +++ b/tests/suites/test_suite_lms.function @@ -184,10 +184,9 @@ void lms_import_export_test ( data_t * pub_key, int expected_import_rc ) exported_pub_key_buf_size = MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10) + 1; ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size); TEST_EQUAL( mbedtls_lms_export_public_key( &ctx, exported_pub_key, - exported_pub_key_buf_size, NULL ), + exported_pub_key_buf_size, + &exported_pub_key_size ), 0 ); - TEST_EQUAL( exported_pub_key_size, - MBEDTLS_LMS_PUBLIC_KEY_LEN(MBEDTLS_LMS_SHA256_M32_H10 ) ); ASSERT_COMPARE( pub_key->x, pub_key->len, exported_pub_key, exported_pub_key_size ); mbedtls_free(exported_pub_key); From 8bccc999d9dd0e04ee83ea01348267cec6c7512f Mon Sep 17 00:00:00 2001 From: Raef Coles Date: Thu, 13 Oct 2022 17:57:31 +0100 Subject: [PATCH 101/104] Don't mention error type in LMS test comments Signed-off-by: Raef Coles --- tests/suites/test_suite_lms.data | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 89ad581965..869153f786 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -204,26 +204,22 @@ lms_verify_test:"92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a LMS negative test (invalid lms type) #1 # This test uses the data from hash-sigs interop test #1. This test has a valid -# LMOTS type (0x4) but an invalid LMS type (0x5), and should fail with a bad -# input data error. +# LMOTS type (0x4) but an invalid LMS type (0x5), and should fail. lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000058b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lms type) #2 # This test uses the data from hash-sigs interop test #1. This test has a valid -# LMOTS type (0x4) but an invalid LMS type (0x7), and should fail with a bad -# input data error. +# LMOTS type (0x4) but an invalid LMS type (0x7), and should fail. lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000004e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000078b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lm_ots type) #1 # This test uses the data from hash-sigs interop test #1. This test has an -# invalid LMOTS type (0x3) but a valid LMS type (0x6), and should fail with a -# verify-fail error. +# invalid LMOTS type (0x3) but a valid LMS type (0x6), and should fail. lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000003e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid lm_ots type) #2 # This test uses the data from hash-sigs interop test #1. This test has an -# invalid LMOTS type (0x5) but a valid LMS type (0x6), and should fail with a -# verify-fail error. +# invalid LMOTS type (0x5) but a valid LMS type (0x6), and should fail. lms_verify_test:"bfff9cd687351db88a98c71fd2f9b927a0ee600130a112533b791041d30cb91665fc369a5ac7cc9a04547414ac45288081d19d4a600579c73ac4bc953de03ad6":"0000000000000005e474c96c496b231ecedcd92566ab3e1cdfac83f7e56abaae6571401e212e59bdbcc18105e0709249510d13d7ae1091558c217033316ac70a36aae764bd0f4032e369453c634b81061079d216d03d3c55976a1aabc00287b307297ae03587ba20839460daae85d26dfcef7638c10a1d8559612e5e9ced1a4205a52ca0ce88e58602e59cf9ab34adf2e958e56570573297b99f733fbbf58d2440526fd4dc15c5509e8a11405f6c08772abcf58731fbf9a73642670e3247c5f70905f0fa81f6174bf32977209923507525a170fcd260e81f04193583fbcd305ac245c80eb337ca326fd1105e73748fab8a1f0c8d8a99f011718e7aae027a34d2a85ff18769fa277810126a86b51b096a04d8e28a4fb8c5e14e50a67cb1ee88e43e5cc077902442f5d9c55ac2b8acdd76c67bc740c6083aba4e3cb404c23f1f3118337563fef6a4b01fb476810c5b5682d0aecdccd55c85a4af50e9150f7d83dcccd8e822a302e6e5a52e00505e6e65338dcfb9cfbe22594e9e18ebde36af29450c5ea31523019cf64fd6eca8c77d98c2a146dcedd51bf6c61c1f7cacbce3ab20c8606930cc42737e17f2703cf0980aef560768d1ac5585c05a60a5f94db15f5ac4d4df5cbd81430878d4e9b77346e3a6538b80b80873e3e6c37860470091979296631440adb8cc71991aba2a4dd2884764878306fe774a25512cfbf080f2829ea2903ffa748dd187c21aef918ee3436a1bd336c3d09cc1f748d7528db90a98f69078b82c4d23de7bcec092a292d2b8cac71a5c87d008f128b89a5e608a4501aef41e9f17e4056ed4767957188f780159daebf327751386980b0fca5a2d36b141acff957f46ce2381897099619475db9d3a613e7ef98b056f42b4d6eafb1d62eebbe46a7502f893fbd36ccfb12a280f45ffb93f050eb280bf0a6cd640abdea8590bffb98bdb29ee3a31daa0fa3ab35fee11dc1b7d1fcea82b0e284b2e35b34e77c3f401ed887e7fc6c97b327f76f99caca2f355afa2753a8923bfb06fb2a9df08d31c93882e34ef5a3cccc9d078855334bdf909ae418b177724c42fb1d586d212c4474932acce295236030f4379158957300fe9fdc5cc9145e3ded50cf9f5a8e19321961536c4a47fffc3eb4383fb78a5d2aeed5b45b92132b5e2a53e3b67841fa2e1bd217ee2c30812c4eb1bd4f8c85b328e23d27f12a2fad5c6b236c87f8fd1aad441416e53ebd4d45d4bf601b94eb37dc9a065218ae58e69dba1250bb20626baeda961b3ef11d217697e73f41fa3870d726a032bc4a388fb12c023822945df058e22f54e5f6377eab34297c57883515204fc189d0d4b0ad9bacb24acf7f9d55e7c6368bb8ababd7622f586ec22683306c5d88d5244219a3952adbd85c89893a441a58b532e15600cd5afdbb5b441e1670b72656c7995189bdf993154e09912db8c4ddaff0e75591720230cf99c8b71cd841dffc4372c5e0f9ff906a379d28d6884351609bf7c849ebfabfb049ae986bbb8467251dbf5ccdd05a86ff6ce1392f7ca1bd49595ad9ad805d71b389afab1865f7f69dc24662af19934f025ced212536509500c132aec000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":MBEDTLS_ERR_LMS_VERIFY_FAILED LMS negative test (invalid leaf ID) From 2875aa7b0140c923e69e402ed9e30faf3d752092 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 13 Oct 2022 20:45:05 +0200 Subject: [PATCH 102/104] Fix instructions and test data for pyhsslms interop tests The test data was invalid because it had the extra 4-byte prefix for HSS. Regenerate it (which produces completely new signatures since it is randomized). Rearrange the reproduction instructions for the second test case so that it shows more clearly how to generate a second signature with the same private key. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_lms.data | 46 +++++++++++--------------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/tests/suites/test_suite_lms.data b/tests/suites/test_suite_lms.data index 869153f786..7802a70e68 100644 --- a/tests/suites/test_suite_lms.data +++ b/tests/suites/test_suite_lms.data @@ -13,7 +13,7 @@ LMS pyhsslms interop test #1 # limited amount of available test vectors for LMS. The private key is stored in # data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv. Note that this signature # uses leaf key 0, so must be the first signature generated by the key if the -# signature is to be reproduced. Message data is random. Note that hash-sigs +# signature is to be reproduced. Message data is random. Note that pyhsslms # stores public keys and signatures in HSS form, which appends a 4-byte "levels" # word at the start of the key/sig. We strip these 4 bytes from the signature # and the public key before including them in a the test data. @@ -27,42 +27,26 @@ LMS pyhsslms interop test #1 # import pyhsslms # # private_key = pyhsslms.HssLmsPrivateKey('tmp/lms') -# -# message = bytes.fromhex('60da1a17c88c59da8a730e6ca8effd37') # public_key = private_key.hss_pub -# sig = private_key.sign(message) -# print('lms_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), public_key.serialize().hex())) -lms_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"0000000000000000000000042c85763d2abaedaecd484517ff85138e8ab7f621585a6f8f5e072c9c0851e89aa6bb116a2cef094155cb142f0bdb84dddfa3ab236dd3bd1019b2a4caa8e26c011d3f9fc8f7df57d8f475564d5b5bd92af9f62137e176cda914bac6e07a086d287d2d9e6d7b9ad768462a39930c19761905136345a0a9f2e28f5bcd288c9137cc828bc790be3020405f4e273b6749dc35d1f4bfea3eb679ca1b46fe26196dbb7ba7f0d56643e716ca3a2f0491fbe5c5aec80ab1a4f718577655e3e56ced0e562f137c7f2be6a9c4589442f23e0c51f19fed5b9e834ffb26dca160d4fe11b7e66bf4fa099bea131620e2906fcbbf5071348cedcb70c372a8a99f7e582f02858d0d7c66ea45728a11420cf20937362dce440f0b8a96fa47e6d03470044555e5a46ec758d4e86b773afe5f5b97c328990a2e4ed59e879ec5f4c59eaaec13cc6790d38a4754a5f0029e53b4461406f6e958dc7ca3a88984e675533cac7f54c00fdfb879acd13404b091e599248eb69624bb2a8f73be37e3ec9fb5d6b9cf65f738333d93d82558c7552ba39f6afce7a7bb6756083e1e61c4a02c36a501c19b08856ba9ff07de3a0e1a6a44abcd0a663643bd8dddf5949eb4ce86feb93ba59f15b18fba26098a8a3a2aa1e5ad79155728c28904a1b218426744b4897a263be0954440e0a85ec378f922a91bbdb098b07d5873667277d22218a3b3a64292648da86b4aaa6af23fd6efa6567b184781159ca9d69619da9b7c1e9c2f9cafcc1f6ca244ae6ced58d880b72cd3fa1269b1d634fd4f551815ce59701773f6454edca537138bc00540c01f0735946151747a3ecb591775b86ecdb58d24aebb67e204e1e17882563a089c13ccea1e8baa5ed3515fd3d691697d826829fbf33a234198abac4bebc6ea6e56cba0925412b8f37bc1e532012b1d1fabf99d1b5ff15ba323ac6b5ba89353a115a5619755d1481fdce82180430fbeef3466e188b6508713ec958074ab6c81a30141a6f14b7768b7f5b25712f9a2aedd0a0b9fae183472b290b51ee92a5ddbcca3994dbb7860f13b9fde81ade00c2c29a0692033d8d2a6827fcc9b50b15b94c2507636710ce681b5b2d5792ea2e0c3a8bb4e8a3c00ab0fa924c228d88a47d649e6804394767db291d2e6b0976f56209d0cf8d2804f402342e98764cb8cee65dde7df65cb241fd2af599ffd8063fd5a28ff4f105c15f7b836cc792402c78c2281302e3cdf7f5e11beacef8b5c5a41ed8a6c30d622cca1fd7075aa12e3d7d54f2c4b7375b8eac6c1be8f8b7e97c17f73b698d01d5f0fa3c644b0b225b390cd613c18ea141ecd1801ad9a4518db5c1c115360b09dda5071ff130d3bff4809e3a1ce9ab5115d86f46cf8b8733271415582d97fa479ede1393d455cf9d227a4248e7d56d280075af69fe8946ac4a98056ac5e4f89a54d813222fb76fcf700bc34e3c9e3650c16cafc83d16e6f3240c443c64e807495a482a66a77d3b552d167c0d0355a25266a3d55ba593b68eaab6c24b0264e3832f08ca0dd91cc8a711c9e23ad37b76e8e658f6b1f61d5e448787fb57f13bcbf88e6939c265d3d6c07295703000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"000000010000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 +# +# message1 = bytes.fromhex('60da1a17c88c59da8a730e6ca8effd37') +# sig1 = private_key.sign(message1)[4:] +# print('lms_verify_test:"{}":"{}":"{}":0'.format(message1.hex(), sig1.hex(), public_key.serialize()[4:].hex())) +lms_verify_test:"60da1a17c88c59da8a730e6ca8effd37":"000000000000000436c1e7d365851f12310f77341f4f994da12f39ad5d4cddf51563e80c98640f7edcc6ca027a76e48fe8f01f077f2733026c75e76fdb236b981e7bbe92e37527a5dc64d67449106387ab0ffffd5b5d4187165b4f03965dbdc5c652a4fc81ab83e951b24b61bf86d4d9a7e8d15206cac92c866b5bb358745306525955c56dfc925c48d0259865372043643c3b11daedd40d474c386daa36e3887bb65633cab290078eb2bc24c478a9ae18ac9fbd7c4a6e5338410b22adf02a27178c5a6e2d9ad403120d76c4dd27ec8974943b8226f86834364ac40984a96f1a1201e50eaf31c44e1c12b03a0cab40f6dcfc8acacfbd46333b48985e8b3a843c8f562a8007f69586444114adade8931adbdd636ee055423e33e4fddeff509a64b4589d25034adca9d55359c1489699cc6438c21da4b01d5403f53c2308fa28a9318235b788c15b37d359217301e9d0fa1b9a3b71ef95aca3657a976fd021ce20bbd4674d1a0cc551050b21ecd96f74a591bd84b5e9ae8b966592721a24bf0e16a44102c86999697ade9f7c937277fe8447b65573776507eda7725fbdf5ce27cdf6552d57b76e6f807a575dae1c9abaeb4667bcf0534ce78796f542b65a109bd9650b880d0ca638cf5de1ad97f6c52fa24951404cad923f649aabe664fabf318fc5910a8fecae45479b36c4961572a9d472b6de23cd601ae0d79ec98dcf9d0d5de6ebc9e71665d2b7066a8cdb93a5f65f48978fee68ed8c94a43af8759a2603321af84d22a4a37d7dfe6811f3d9b3c1bd9940214678f784658bf224a6e7efe22e30b962c7cbd18bb92df3d5e86b81493db30d761fb4775dab56a6c446f2b34d906944a72cf71f4f637f0668069f24ebb55e1c50b52c2f35b568b66fa648f5ebf10f74ff48246c3ead6cd6a5901c35f3411584760574c2db86ee5d23a094bffc16369f9845fe2570b1357315f401f1bc201ba165ee16a9afd811e4f9f34b8414134346598cd5fe76c883c5215d75106eceff18135c65473186ed1bcc45246d30aa7b1e561c46d0d1cca3da2e19cca1cfe4e89ca61de070d3cad2f96270962cd770c9154ce7bb5844171293e1a2722d3e340602895ae3c6848c83e264709af8677ff1d49580348d6084e41146410e537e6fdf91881fb8b858aaa04f064671971d082e1f7681eb9ac11da7b4776bedb0bdff6dcdab8facec17df48928e3be3603262cf39d0828ceca9230ccb610e8a6c7ea8e9a3a1d4e43d2f9c204d9327d6a2e8b4dc7b9a13838e1b08b414d9ef3495aee4f4fc05d71a5e8bd828f155a8a3b7ca6e22be59901fe627408a2e8ca8dc28458a4eda726b9e8f511c27495ea3bd3a50997d17a0de3394ccd51329e386ff39708e851cec61335e6b2bc6ad5aac9851a5467eba51cfc59804d674ca23232f8da4ad28c22f7dd54461e366e247e2ef28df07f6b3e4bc2c2e0b0233aee191c2efae467b2bd511c7cfd61dc96148b69b967b9d5eb0efe41a8b0197f8cdef88060d80ce1a2f3f649ab552b52bb1123eec2848c9dceff7ce5a1768d87e67105eda66493a017771170e3462566a08366aa01dfb2b0ca838c8018f0545000000068b991bed50319a6cb9ff040b92f1563889b3787c37145fc9737d4643f66ade33ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 LMS pyhsslms interop test #2 -# This test uses data from https://github.com/russhousley/pyhsslms due to the -# limited amount of available test vectors for LMS. The private key is stored in -# data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv. Note that this signature -# uses leaf key 1, so must be the second signature generated by the key if the -# signature is to be reproduced. Message data is random. Note that hash-sigs -# stores public keys and signatures in HSS form, which appends a 4-byte "levels" -# word at the start of the key/sig. We strip these 4 bytes from the signature -# and the public key before including them in a the test data. +# This test case continues from "LMS pyhsslms interop test #1". +# The signature uses leaf key 1, so must be the second signature generated by +# the key if the signature is to be reproduced. # # To produce another signature with this message and key (note that the actual -# signature bytes will differ due to randomization): -# * pip3 install --user pyhsslms -# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv tmp/lms.prv -# * cp data_files/lms_pyhsslms_sha256_m32_h5_lmots_sha256_n32_w8_pub tmp/lms.pub +# signature bytes will differ due to randomization), after generating the +# first signature: # -#import pyhsslms -# -#private_key = pyhsslms.HssLmsPrivateKey('tmp/lms') -# -#message = bytes.fromhex('60da1a17c88c59da8a730e6ca8effd37') -#public_key = private_key.hss_pub -#sig = private_key.sign(message) -# -#message = bytes.fromhex('92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1') -#public_key = private_key.hss_pub -#sig = private_key.sign(message) -#print('lms_verify_test:"{}":"{}":"{}":0'.format(message.hex(), sig.hex(), public_key.serialize().hex())) -lms_verify_test:"92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1":"0000000000000001000000042115dafc81fb6404f904c6037b00c970a0790ceadf0d39f93eddae43ee0daffa0088358a8f89ca5c2b2af0d55c4ecdcbdd84953ce4043d2657ada39f4344ace04e3c4ae3d72788214d28d1b5c85af7a6d3d9d85594a907a9a39b258d4385700a6c001b52923846f68a991a86ddad9b272c98064d43142d339c1cc64e833f7f5346a70b1ef77cb197c66ef68e7a41678ec1dedfe5b6d6e22746b839df8ffdf6d6830f86e47a0370a17646ada2e3f13ee68e6cfdcbb20c0b05e47c088bc27a1e4010aca6f42f2e4c92b28d4f8591fcab60c57fea248b6e8c412b6806f956e459252df4dedbbbecdbaa57f0f15e91ab9fc1c8dae1e1ba5556faa8d618bef9f977b3571b6438f13583f5a2e4036f450a89881b108d44bd8a6700c544d12e1ba48eaa9f53eed260f0dc2bf8bd630565af7d9e182539957780b0771365d4fe57d9fb0f76b2e4e7737fd3d8e8ba67d16af59c13563ceda4d632a0f7d742c98e05d29fb752ccddca2b8e8cc0bb3e57547dbe62d77fb792568cfc8218291a057fc61d94137556f17301e4b7ab3b8f33610925aa5160397665212e16bdc3fffc7ae0ce22c83eb357409bb08b38585628b1475931e09d65986dadf01aff0f7b0e7d19cce8318ea2fcf112710da63b25b3fb1f28fa387e0dc4eea17e0cd7f1e09e2a0cf0797199750f88d4b1d597c15a8694c68e6ac04564f5ee826d612839e2a26c4e7db4e4bd4919ef5ab1730a97bc5ec0c89c93dea4e8bca06426b121bf065ed43a7f2c91ee7211c53d6111de7ccff339a99203de88fb1ec592af5a4e9b2bfc437d0be7dd3aad57f5a84a4a87522cca5fc64176acf033f25f6ec10c673f38c0a3eca954c2acdad80674bac208c0c8be1ed50ed3f41e14c4edef82fe878444c4c874fbd0019e697b3401971b9ae1b73824079de84fc889f6108ea53b94fd50eaa56ccc0fa466168b6fb4322ac01d3429a109e55d6a2459ebfb0297b32bf1eea33fec4317eab77f2d415bfe5ac243e6e6ba26f9a4dccd5bf921c813218268106c129081da409b1808eedaeebf420f768935c0c91981dc48bc07926649926cf62f596582e8b3b9f9a18e0a91221a1d03913245792269ed260071dbfb27240d78a3d98945414da4bc7e4267b8a56cc18d2a8cc2fbe0206989541be84c181dc8aea74654514d894098534963449fc7e5ecd98218c93b38c925761fae62056dd7156b215fdf48ab36d230ab6feb3df3a590fa267e8c0cb78c2f2c90ab7c71dfa97e148a03c427077ec2abc08a3ec2ec7b2503a3dc988f6a9e5362e1043be819e78c71ae96646431eb83d6c9f91edbca6507c31a44f0b643c0028813559e8b5894575461d728ed633b89d660be1635e921fac6844071687b9c82b4aedfdc7cadfee07f113906cf4f78b7e8397f6be3872a53a31e15b54443753b4197e942e2512a9703d729116e683ad9a718f0fa15cf94cc2676498e6d2f207b2d3fd61dba1ad0291eb9e243c4ab771ee4f92ac782fd72b35abff18fd91198007d604b74b7d2741e36fa74c3a1732217b06f1d2e4e34d61012e83f99d03f1e83c97150dedd04f67978620da7e0e5000000063b71be980cffb4e8a8e310341d3b711ab19545ae90c3ac6adcbeb764419411a6ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"000000010000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 +# message2 = bytes.fromhex('92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1') +# sig2 = private_key.sign(message2)[4:] +# print('lms_verify_test:"{}":"{}":"{}":0'.format(message2.hex(), sig2.hex(), public_key.serialize()[4:].hex())) +lms_verify_test:"92d036bde8c45b8bb5dea2a072560b1e29fc4bb7dc4549ce90bccee8a6e962a1":"00000001000000042fd4410a9c1947c00419216c64bc236a1620bde03ca9221e67f933bd2664f065e0cfc910c6a4317de4bda8c7fc1244ee1c102e8acc281d96c6a25d1925e087623fcb4faa00219e1f04a2c191ceceee98f2acd0fb1395fd984892f893a3ad862ff6def851e81915b9111288f84fb131e14979f1df6eecc774db45054041bfe74ec0446a0e6a6e01f9b402f41e784a2fcdc0cdccf0b89c2c8a9d2ab28e95e133b33dfb631619e75ec80a9c5d8f634f1d60feec2a5d9a5d6316fa7968734c26c3f60e53613096330a6fc1f779fe501db94b2a932ddc05740a872a8ec34c6d79c6689cd2cd6620d92ea89b39a62053c0bdd7596b360ff45de04bef0cd9b985f00681875e9f3465a71e5055e202dc51bf9ab29d227e8d2b09c6089f82cd356eb1622ada2233209f096cb35086fa2415434ef3ecd660bddf328d70e204d9a8be18319df1bd5c64072b30b72ec792c0a200b29429e262435b03f7fbb6dfcd76b9a84621c91e0ef646bd7367eead3582028a8ed9b40b1fe1562863ea43af350cdf0c965dc8329131df3f00b4b8a33548d7f7f1b03e952064e0f4cd9662af5a0d25ec8dc126d9621bf4707fbd525023ce91cbe05517bf2491e6455f2273b354c9d2f4a4364c3caf44c98ad23601cf1fc9cb490d2a9b9cdb1d60f0328e40734201e9e03f7af30fe6f0d6c7437fdd13573b012cd060a1a325b35d1a3d77e94a666d3873e267223a4e5bcf0752395570ad51d1ac7480cba32fcc8bf93439b8feafd0fb3520ab76d9ae2fba3b4600afce5fd96ff07d0e62579c16f993715f363982409ba38a46d09e6b448738f2bdb4277c65c933ea4a991fdc8021e3b9bbe5d00078b94ed1a78c61ee9d1dec014f99d23905a8fff335a9cca0228e7244a2a8b461970655b8a7f0f684c3f271c5f76924d851850b74754e24abaa9828d353976509dc4c4a241a0c314b80e400aceefe234fbdfb9af60d7c65752a4a396c4cdea1fec3478c263fb5883aa009f1845c4cb3f128c5eb9b290639c7c82fe33b17bd5ddb460a68d54be472769f77c73f7b4bfead2af4a9af6322f5bec9159d234e94a7d496cb6349a4b36fc7ca4e2c42168034bff62e687089fdd27a78484c788556edb58d7c911199752ca609a7906355f226756cd7c6c167b2a2929e8913fb2ec7c46c5caf73252f06cd51c5ca979d0b552831beeb5bcc25fba8ac83c8857633e3873adab0d23f1bb326a6c960e8bb1119e2f917c3892e9ad83f8af74abe0a0beee1734fdf5fe04024a6a644c2bbf88c6019d7115b0742898e90cc2d001efbc6f8e38eeedd5e9e9c777d1ecc6a2a9cf6d67a68781d99db1bbecdfe2e40dbe9074e7a69f0fa9037aecc31c9305c67129e0dbc8a66c8de6c18ed41746d794809bb3a5cc68c17db3052fe31e390ca862be3163660a1f70c5d2f026ed7649437600e38ee08e33f05aac9bcd8b7db309f2f41c34ba44304115ef8bbdba63629607daf67e2e642a726e021f6599032a0f8f3edef2ef5b007d3618856d48aec7894e9a4b802caf9c3f0022c6e61d34c38ba2ddef3c1b0797e7dc74faacb44ac72b5ea078f1a21c2cffc46ba000000063b71be980cffb4e8a8e310341d3b711ab19545ae90c3ac6adcbeb764419411a6ebd85a2c29b8c64a581cff01b89d59807d6fade2d2c88872f77d0ed83d97c4b5438681d0b95feb973125e4ee70ebe11699290b831e86571e36513a71f159d48ce563f6814cc2a89851d2520c5275b34cc83614cab14c0d197166580d800ee6b9004b8fd72daac8d73c36c1623c37be93ba49a06c4efde238a3a10a05daba5d4942f7de52648af2be31f33e723b3605346282f5d5e356c5d0004eea40fe0b80abf658f6c96c56319ab53d7fefb5879e0136d1cf320973a2f47c1ee3d21554910f09d17afac4607657c4309890957a4954bf86e2a8491ba37dd88b2c3fe3c7edebd767c400bc23e40d165b27133c726b90bc26cbb2a86a6aa400c47aa7ffc538388de8490b9349afa53b814ffe2a56ff16a496e9648284193754f989f6f12aeb6e":"0000000600000004d96bb26744d99ef624e32161c36d3d6efcdd0484e2b17a6dd183125be4b1af1cda931a91a3acb1151877c174f7943fd9":0 LMS pyhsslms interop NULL-message test # This test uses data from https://github.com/russhousley/pyhsslms due to the limited From 31c2dcb61104912a895b3e2e0292379eb382dc82 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 13 Oct 2022 20:48:15 +0200 Subject: [PATCH 103/104] Fix file names in reproduction instructions in test data Signed-off-by: Gilles Peskine --- tests/suites/test_suite_lmots.data | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_lmots.data b/tests/suites/test_suite_lmots.data index e6d71d33b6..2737272bdd 100644 --- a/tests/suites/test_suite_lmots.data +++ b/tests/suites/test_suite_lmots.data @@ -28,7 +28,7 @@ LMOTS hsslms interop test #1 # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # # ots_private_key = LM_OTS_Priv(private_key.otstypecode, private_key.I, 0, private_key.SEED) @@ -53,7 +53,7 @@ LMOTS hsslms interop test #2 # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # #ots_private_key = LM_OTS_Priv(private_key.otstypecode, private_key.I, 1, private_key.SEED) @@ -76,7 +76,7 @@ LMOTS hsslms interop NULL-message test # from hsslms import LMS_Priv, LM_OTS_Priv, LMS_ALGORITHM_TYPE, LMOTS_ALGORITHM_TYPE # import pickle # -# with open('tests/data_files/lms_lmshss_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: +# with open('tests/data_files/lms_hsslms_sha256_m32_h5_lmots_sha256_n32_w8_prv', 'rb') as private_key_file: # private_key = pickle.load(private_key_file) # #ots_private_key = LM_OTS_Priv(private_key.otstypecode, private_key.I, 3, private_key.SEED) From fa65237fd4b27f1406d30e5464d38be74c5dd675 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 13 Oct 2022 22:05:38 +0200 Subject: [PATCH 104/104] Fix which config header MBEDTLS_LMS_xxx is unset from Signed-off-by: Gilles Peskine --- tests/scripts/all.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index f7da34a3bc..2ee99b3fc1 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -2248,8 +2248,8 @@ component_build_psa_accel_alg_md5() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_384 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_512 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE + scripts/config.py unset MBEDTLS_LMS_C + scripts/config.py unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_MD5 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" } @@ -2270,8 +2270,8 @@ component_build_psa_accel_alg_ripemd160() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_384 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_512 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE + scripts/config.py unset MBEDTLS_LMS_C + scripts/config.py unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RIPEMD160 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" } @@ -2292,8 +2292,8 @@ component_build_psa_accel_alg_sha1() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_384 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_512 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE + scripts/config.py unset MBEDTLS_LMS_C + scripts/config.py unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_1 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" } @@ -2351,8 +2351,8 @@ component_build_psa_accel_alg_sha384() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_224 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_256 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE + scripts/config.py unset MBEDTLS_LMS_C + scripts/config.py unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_384 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" } @@ -2373,8 +2373,8 @@ component_build_psa_accel_alg_sha512() { scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_256 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_384 scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_C - scripts/config.py -f include/psa/crypto_config.h unset MBEDTLS_LMS_PRIVATE + scripts/config.py unset MBEDTLS_LMS_C + scripts/config.py unset MBEDTLS_LMS_PRIVATE # Need to define the correct symbol and include the test driver header path in order to build with the test driver make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_512 -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" }