Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-27 09:37:32

0001 /**
0002  * \file lms.h
0003  *
0004  * \brief This file provides an API for the LMS post-quantum-safe stateful-hash
0005           public-key signature scheme as defined in RFC8554 and NIST.SP.200-208.
0006  *        This implementation currently only supports a single parameter set
0007  *        MBEDTLS_LMS_SHA256_M32_H10 in order to reduce complexity. This is one
0008  *        of the signature schemes recommended by the IETF draft SUIT standard
0009  *        for IOT firmware upgrades (RFC9019).
0010  */
0011 /*
0012  *  Copyright The Mbed TLS Contributors
0013  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
0014  */
0015 #ifndef MBEDTLS_LMS_H
0016 #define MBEDTLS_LMS_H
0017 
0018 #include <stdint.h>
0019 #include <stddef.h>
0020 
0021 #include "mbedtls/private_access.h"
0022 #include "mbedtls/build_info.h"
0023 
0024 #define MBEDTLS_ERR_LMS_BAD_INPUT_DATA   -0x0011 /**< Bad data has been input to an LMS function */
0025 #define MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */
0026 #define MBEDTLS_ERR_LMS_VERIFY_FAILED    -0x0015 /**< LMS signature verification failed */
0027 #define MBEDTLS_ERR_LMS_ALLOC_FAILED     -0x0017 /**< LMS failed to allocate space for a private key */
0028 #define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */
0029 
0030 /* Currently only defined for SHA256, 32 is the max hash output size */
0031 #define MBEDTLS_LMOTS_N_HASH_LEN_MAX           (32u)
0032 #define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX    (34u)
0033 #define MBEDTLS_LMOTS_N_HASH_LEN(type)         ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0)
0034 #define MBEDTLS_LMOTS_I_KEY_ID_LEN             (16u)
0035 #define MBEDTLS_LMOTS_Q_LEAF_ID_LEN            (4u)
0036 #define MBEDTLS_LMOTS_TYPE_LEN                 (4u)
0037 #define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type)  ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0)
0038 #define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type))
0039 
0040 #define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \
0041                                      MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \
0042                                      (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \
0043                                       MBEDTLS_LMOTS_N_HASH_LEN(type)))
0044 
0045 
0046 #define MBEDTLS_LMS_TYPE_LEN            (4)
0047 #define MBEDTLS_LMS_H_TREE_HEIGHT(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0)
0048 
0049 /* The length of a hash output, Currently only implemented for SHA256.
0050  * Max is 32 bytes.
0051  */
0052 #define MBEDTLS_LMS_M_NODE_BYTES(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0)
0053 #define MBEDTLS_LMS_M_NODE_BYTES_MAX 32
0054 
0055 #define MBEDTLS_LMS_SIG_LEN(type, otstype) (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \
0056                                             MBEDTLS_LMOTS_SIG_LEN(otstype) + \
0057                                             MBEDTLS_LMS_TYPE_LEN + \
0058                                             (MBEDTLS_LMS_H_TREE_HEIGHT(type) * \
0059                                              MBEDTLS_LMS_M_NODE_BYTES(type)))
0060 
0061 #define MBEDTLS_LMS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMS_TYPE_LEN + \
0062                                           MBEDTLS_LMOTS_TYPE_LEN + \
0063                                           MBEDTLS_LMOTS_I_KEY_ID_LEN + \
0064                                           MBEDTLS_LMS_M_NODE_BYTES(type))
0065 
0066 
0067 #ifdef __cplusplus
0068 extern "C" {
0069 #endif
0070 
0071 /** The Identifier of the LMS parameter set, as per
0072  * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml
0073  * We are only implementing a subset of the types, particularly H10, for the sake of simplicity.
0074  */
0075 typedef enum {
0076     MBEDTLS_LMS_SHA256_M32_H10 = 0x6,
0077 } mbedtls_lms_algorithm_type_t;
0078 
0079 /** The Identifier of the LMOTS parameter set, as per
0080  *  https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml.
0081  *  We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicity.
0082  */
0083 typedef enum {
0084     MBEDTLS_LMOTS_SHA256_N32_W8 = 4
0085 } mbedtls_lmots_algorithm_type_t;
0086 
0087 /** LMOTS parameters structure.
0088  *
0089  * This contains the metadata associated with an LMOTS key, detailing the
0090  * algorithm type, the key ID, and the leaf identifier should be key be part of
0091  * a LMS key.
0092  */
0093 typedef struct {
0094     unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key
0095                                                                                     identifier. */
0096     unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which
0097                                                                                       leaf of the LMS key this is.
0098                                                                                       0 if the key is not part of an LMS key. */
0099     mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as
0100                                                                per IANA. Only SHA256_N32_W8 is
0101                                                                currently supported. */
0102 } mbedtls_lmots_parameters_t;
0103 
0104 /** LMOTS public context structure.
0105  *
0106  * A LMOTS public key is a hash output, and the applicable parameter set.
0107  *
0108  * The context must be initialized before it is used. A public key must either
0109  * be imported or generated from a private context.
0110  *
0111  * \dot
0112  * digraph lmots_public_t {
0113  *   UNINITIALIZED -> INIT [label="init"];
0114  *   HAVE_PUBLIC_KEY -> INIT [label="free"];
0115  *   INIT -> HAVE_PUBLIC_KEY [label="import_public_key"];
0116  *   INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"];
0117  *   HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"];
0118  * }
0119  * \enddot
0120  */
0121 typedef struct {
0122     mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params);
0123     unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
0124     unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key.
0125                                                        Boolean values only. */
0126 } mbedtls_lmots_public_t;
0127 
0128 #if defined(MBEDTLS_LMS_PRIVATE)
0129 /** LMOTS private context structure.
0130  *
0131  * A LMOTS private key is one hash output for each of digit of the digest +
0132  * checksum, and the applicable parameter set.
0133  *
0134  * The context must be initialized before it is used. A public key must either
0135  * be imported or generated from a private context.
0136  *
0137  * \dot
0138  * digraph lmots_public_t {
0139  *   UNINITIALIZED -> INIT [label="init"];
0140  *   HAVE_PRIVATE_KEY -> INIT [label="free"];
0141  *   INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"];
0142  *   HAVE_PRIVATE_KEY -> INIT [label="sign"];
0143  * }
0144  * \enddot
0145  */
0146 typedef struct {
0147     mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params);
0148     unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][
0149         MBEDTLS_LMOTS_N_HASH_LEN_MAX];
0150     unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key.
0151                                                         Boolean values only. */
0152 } mbedtls_lmots_private_t;
0153 #endif /* defined(MBEDTLS_LMS_PRIVATE) */
0154 
0155 
0156 /** LMS parameters structure.
0157  *
0158  * This contains the metadata associated with an LMS key, detailing the
0159  * algorithm type, the type of the underlying OTS algorithm, and the key ID.
0160  */
0161 typedef struct {
0162     unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key
0163                                                                                     identifier. */
0164     mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as
0165                                                                 per IANA. Only SHA256_N32_W8 is
0166                                                                 currently supported. */
0167     mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per
0168                                                              IANA. Only SHA256_M32_H10 is currently
0169                                                              supported. */
0170 } mbedtls_lms_parameters_t;
0171 
0172 /** LMS public context structure.
0173  *
0174  * A LMS public key is the hash output that is the root of the Merkle tree, and
0175  * the applicable parameter set
0176  *
0177  * The context must be initialized before it is used. A public key must either
0178  * be imported or generated from a private context.
0179  *
0180  * \dot
0181  * digraph lms_public_t {
0182  *   UNINITIALIZED -> INIT [label="init"];
0183  *   HAVE_PUBLIC_KEY -> INIT [label="free"];
0184  *   INIT -> HAVE_PUBLIC_KEY [label="import_public_key"];
0185  *   INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"];
0186  *   HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"];
0187  * }
0188  * \enddot
0189  */
0190 typedef struct {
0191     mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params);
0192     unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES_MAX]; /*!< The public key, in
0193                                                                                  the form of the Merkle tree root node. */
0194     unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key.
0195                                                        Boolean values only. */
0196 } mbedtls_lms_public_t;
0197 
0198 
0199 #if defined(MBEDTLS_LMS_PRIVATE)
0200 /** LMS private context structure.
0201  *
0202  * A LMS private key is a set of LMOTS private keys, an index to the next usable
0203  * key, and the applicable parameter set.
0204  *
0205  * The context must be initialized before it is used. A public key must either
0206  * be imported or generated from a private context.
0207  *
0208  * \dot
0209  * digraph lms_public_t {
0210  *   UNINITIALIZED -> INIT [label="init"];
0211  *   HAVE_PRIVATE_KEY -> INIT [label="free"];
0212  *   INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"];
0213  * }
0214  * \enddot
0215  */
0216 typedef struct {
0217     mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params);
0218     uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not
0219                                                       been used. */
0220     mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key
0221                                                                    for each leaf node in the Merkle tree. NULL
0222                                                                    when have_private_key is 0 and non-NULL otherwise.
0223                                                                    is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */
0224     mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to
0225                                                                    build the Merkle tree. NULL
0226                                                                    when have_private_key is 0 and
0227                                                                    non-NULL otherwise.
0228                                                                    Is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type)
0229                                                                    in length. */
0230     unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key.
0231                                                         Boolean values only. */
0232 } mbedtls_lms_private_t;
0233 #endif /* defined(MBEDTLS_LMS_PRIVATE) */
0234 
0235 /**
0236  * \brief                    This function initializes an LMS public context
0237  *
0238  * \param ctx                The uninitialized LMS context that will then be
0239  *                           initialized.
0240  */
0241 void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx);
0242 
0243 /**
0244  * \brief                    This function uninitializes an LMS public context
0245  *
0246  * \param ctx                The initialized LMS context that will then be
0247  *                           uninitialized.
0248  */
0249 void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx);
0250 
0251 /**
0252  * \brief                    This function imports an LMS public key into a
0253  *                           public LMS context.
0254  *
0255  * \note                     Before this function is called, the context must
0256  *                           have been initialized.
0257  *
0258  * \note                     See IETF RFC8554 for details of the encoding of
0259  *                           this public key.
0260  *
0261  * \param ctx                The initialized LMS context store the key in.
0262  * \param key                The buffer from which the key will be read.
0263  *                           #MBEDTLS_LMS_PUBLIC_KEY_LEN bytes will be read from
0264  *                           this.
0265  * \param key_size           The size of the key being imported.
0266  *
0267  * \return         \c 0 on success.
0268  * \return         A non-zero error code on failure.
0269  */
0270 int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,
0271                                   const unsigned char *key, size_t key_size);
0272 
0273 /**
0274  * \brief                    This function exports an LMS public key from a
0275  *                           LMS public context that already contains a public
0276  *                           key.
0277  *
0278  * \note                     Before this function is called, the context must
0279  *                           have been initialized and the context must contain
0280  *                           a public key.
0281  *
0282  * \note                     See IETF RFC8554 for details of the encoding of
0283  *                           this public key.
0284  *
0285  * \param ctx                The initialized LMS public context that contains
0286  *                           the public key.
0287  * \param key                The buffer into which the key will be output. Must
0288  *                           be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size.
0289  * \param key_size           The size of the key buffer.
0290  * \param key_len            If not NULL, will be written with the size of the
0291  *                           key.
0292  *
0293  * \return         \c 0 on success.
0294  * \return         A non-zero error code on failure.
0295  */
0296 int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx,
0297                                   unsigned char *key, size_t key_size,
0298                                   size_t *key_len);
0299 
0300 /**
0301  * \brief                    This function verifies a LMS signature, using a
0302  *                           LMS context that contains a public key.
0303  *
0304  * \note                     Before this function is called, the context must
0305  *                           have been initialized and must contain a public key
0306  *                           (either by import or generation).
0307  *
0308  * \param ctx                The initialized LMS public context from which the
0309  *                           public key will be read.
0310  * \param msg                The buffer from which the message will be read.
0311  * \param msg_size           The size of the message that will be read.
0312  * \param sig                The buf from which the signature will be read.
0313  *                           #MBEDTLS_LMS_SIG_LEN bytes will be read from
0314  *                           this.
0315  * \param sig_size           The size of the signature to be verified.
0316  *
0317  * \return         \c 0 on successful verification.
0318  * \return         A non-zero error code on failure.
0319  */
0320 int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,
0321                        const unsigned char *msg, size_t msg_size,
0322                        const unsigned char *sig, size_t sig_size);
0323 
0324 #if defined(MBEDTLS_LMS_PRIVATE)
0325 /**
0326  * \brief                    This function initializes an LMS private context
0327  *
0328  * \param ctx                The uninitialized LMS private context that will
0329  *                           then be initialized. */
0330 void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx);
0331 
0332 /**
0333  * \brief                    This function uninitializes an LMS private context
0334  *
0335  * \param ctx                The initialized LMS private context that will then
0336  *                           be uninitialized.
0337  */
0338 void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx);
0339 
0340 /**
0341  * \brief                    This function generates an LMS private key, and
0342  *                           stores in into an LMS private context.
0343  *
0344  * \warning                  This function is **not intended for use in
0345  *                           production**, due to as-yet unsolved problems with
0346  *                           handling stateful keys. The API for this function
0347  *                           may change considerably in future versions.
0348  *
0349  * \note                     The seed must have at least 256 bits of entropy.
0350  *
0351  * \param ctx                The initialized LMOTS context to generate the key
0352  *                           into.
0353  * \param type               The LMS parameter set identifier.
0354  * \param otstype            The LMOTS parameter set identifier.
0355  * \param f_rng              The RNG function to be used to generate the key ID.
0356  * \param p_rng              The RNG context to be passed to f_rng
0357  * \param seed               The seed used to deterministically generate the
0358  *                           key.
0359  * \param seed_size          The length of the seed.
0360  *
0361  * \return         \c 0 on success.
0362  * \return         A non-zero error code on failure.
0363  */
0364 int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx,
0365                                      mbedtls_lms_algorithm_type_t type,
0366                                      mbedtls_lmots_algorithm_type_t otstype,
0367                                      int (*f_rng)(void *, unsigned char *, size_t),
0368                                      void *p_rng, const unsigned char *seed,
0369                                      size_t seed_size);
0370 
0371 /**
0372  * \brief                    This function calculates an LMS public key from a
0373  *                           LMS context that already contains a private key.
0374  *
0375  * \note                     Before this function is called, the context must
0376  *                           have been initialized and the context must contain
0377  *                           a private key.
0378  *
0379  * \param ctx                The initialized LMS public context to calculate the key
0380  *                           from and store it into.
0381  *
0382  * \param priv_ctx           The LMS private context to read the private key
0383  *                           from. This must have been initialized and contain a
0384  *                           private key.
0385  *
0386  * \return         \c 0 on success.
0387  * \return         A non-zero error code on failure.
0388  */
0389 int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,
0390                                      const mbedtls_lms_private_t *priv_ctx);
0391 
0392 /**
0393  * \brief                    This function creates a LMS signature, using a
0394  *                           LMS context that contains unused private keys.
0395  *
0396  * \warning                  This function is **not intended for use in
0397  *                           production**, due to as-yet unsolved problems with
0398  *                           handling stateful keys. The API for this function
0399  *                           may change considerably in future versions.
0400  *
0401  * \note                     Before this function is called, the context must
0402  *                           have been initialized and must contain a private
0403  *                           key.
0404  *
0405  * \note                     Each of the LMOTS private keys inside a LMS private
0406  *                           key can only be used once. If they are reused, then
0407  *                           attackers may be able to forge signatures with that
0408  *                           key. This is all handled transparently, but it is
0409  *                           important to not perform copy operations on LMS
0410  *                           contexts that contain private key material.
0411  *
0412  * \param ctx                The initialized LMS private context from which the
0413  *                           private key will be read.
0414  * \param f_rng              The RNG function to be used for signature
0415  *                           generation.
0416  * \param p_rng              The RNG context to be passed to f_rng
0417  * \param msg                The buffer from which the message will be read.
0418  * \param msg_size           The size of the message that will be read.
0419  * \param sig                The buf into which the signature will be stored.
0420  *                           Must be at least #MBEDTLS_LMS_SIG_LEN in size.
0421  * \param sig_size           The size of the buffer the signature will be
0422  *                           written into.
0423  * \param sig_len            If not NULL, will be written with the size of the
0424  *                           signature.
0425  *
0426  * \return         \c 0 on success.
0427  * \return         A non-zero error code on failure.
0428  */
0429 int mbedtls_lms_sign(mbedtls_lms_private_t *ctx,
0430                      int (*f_rng)(void *, unsigned char *, size_t),
0431                      void *p_rng, const unsigned char *msg,
0432                      unsigned int msg_size, unsigned char *sig, size_t sig_size,
0433                      size_t *sig_len);
0434 #endif /* defined(MBEDTLS_LMS_PRIVATE) */
0435 
0436 #ifdef __cplusplus
0437 }
0438 #endif
0439 
0440 #endif /* MBEDTLS_LMS_H */