1 /**
2  * \file lmots.h
3  *
4  * \brief This file provides an API for the LM-OTS post-quantum-safe one-time
5  *        public-key signature scheme as defined in RFC8554 and NIST.SP.200-208.
6  *        This implementation currently only supports a single parameter set
7  *        MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity.
8  */
9 /*
10  *  Copyright The Mbed TLS Contributors
11  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
12  */
13 
14 #ifndef MBEDTLS_LMOTS_H
15 #define MBEDTLS_LMOTS_H
16 
17 #include "mbedtls/build_info.h"
18 
19 #include "psa/crypto.h"
20 
21 #include "mbedtls/lms.h"
22 
23 #include <stdint.h>
24 #include <stddef.h>
25 
26 
27 #define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \
28                                             MBEDTLS_LMOTS_I_KEY_ID_LEN + \
29                                             MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \
30                                             MBEDTLS_LMOTS_N_HASH_LEN(type))
31 
32 #define MBEDTLS_LMOTS_SIG_TYPE_OFFSET       (0)
33 #define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \
34                                            MBEDTLS_LMOTS_TYPE_LEN)
35 #define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \
36                                                   MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type))
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 
43 #if defined(MBEDTLS_TEST_HOOKS)
44 extern int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *);
45 #endif /* defined(MBEDTLS_TEST_HOOKS) */
46 
47 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
48 /**
49  * \brief                    This function converts a \ref psa_status_t to a
50  *                           low-level LMS error code.
51  *
52  * \param status             The psa_status_t to convert
53  *
54  * \return                   The corresponding LMS error code.
55  */
56 int MBEDTLS_DEPRECATED mbedtls_lms_error_from_psa(psa_status_t status);
57 #endif
58 
59 /**
60  * \brief                    This function initializes a public LMOTS context
61  *
62  * \param ctx                The uninitialized LMOTS context that will then be
63  *                           initialized.
64  */
65 void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx);
66 
67 /**
68  * \brief                    This function uninitializes a public LMOTS context
69  *
70  * \param ctx                The initialized LMOTS context that will then be
71  *                           uninitialized.
72  */
73 void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx);
74 
75 /**
76  * \brief                    This function imports an LMOTS public key into a
77  *                           LMOTS context.
78  *
79  * \note                     Before this function is called, the context must
80  *                           have been initialized.
81  *
82  * \note                     See IETF RFC8554 for details of the encoding of
83  *                           this public key.
84  *
85  * \param ctx                The initialized LMOTS context store the key in.
86  * \param key                The buffer from which the key will be read.
87  *                           #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read
88  *                           from this.
89  *
90  * \return         \c 0 on success.
91  * \return         A non-zero error code on failure.
92  */
93 int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,
94                                     const unsigned char *key, size_t key_size);
95 
96 /**
97  * \brief                    This function exports an LMOTS public key from a
98  *                           LMOTS context that already contains a public key.
99  *
100  * \note                     Before this function is called, the context must
101  *                           have been initialized and the context must contain
102  *                           a public key.
103  *
104  * \note                     See IETF RFC8554 for details of the encoding of
105  *                           this public key.
106  *
107  * \param ctx                The initialized LMOTS context that contains the
108  *                           public key.
109  * \param key                The buffer into which the key will be output. Must
110  *                           be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size.
111  *
112  * \return         \c 0 on success.
113  * \return         A non-zero error code on failure.
114  */
115 int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,
116                                     unsigned char *key, size_t key_size,
117                                     size_t *key_len);
118 
119 /**
120  * \brief                    This function creates a candidate public key from
121  *                           an LMOTS signature. This can then be compared to
122  *                           the real public key to determine the validity of
123  *                           the signature.
124  *
125  * \note                     This function is exposed publicly to be used in LMS
126  *                           signature verification, it is expected that
127  *                           mbedtls_lmots_verify will be used for LMOTS
128  *                           signature verification.
129  *
130  * \param params             The LMOTS parameter set, q and I values as an
131  *                           mbedtls_lmots_parameters_t struct.
132  * \param msg                The buffer from which the message will be read.
133  * \param msg_size           The size of the message that will be read.
134  * \param sig                The buffer from which the signature will be read.
135  *                           #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
136  *                           this.
137  * \param out                The buffer where the candidate public key will be
138  *                           stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN
139  *                           bytes in size.
140  *
141  * \return         \c 0 on success.
142  * \return         A non-zero error code on failure.
143  */
144 int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params,
145                                                  const unsigned char *msg,
146                                                  size_t msg_size,
147                                                  const unsigned char *sig,
148                                                  size_t sig_size,
149                                                  unsigned char *out,
150                                                  size_t out_size,
151                                                  size_t *out_len);
152 
153 /**
154  * \brief                    This function verifies a LMOTS signature, using a
155  *                           LMOTS context that contains a public key.
156  *
157  * \warning                  This function is **not intended for use in
158  *                           production**, due to as-yet unsolved problems with
159  *                           handling stateful keys. The API for this function
160  *                           may change considerably in future versions.
161  *
162  * \note                     Before this function is called, the context must
163  *                           have been initialized and must contain a public key
164  *                           (either by import or calculation from a private
165  *                           key).
166  *
167  * \param ctx                The initialized LMOTS context from which the public
168  *                           key will be read.
169  * \param msg                The buffer from which the message will be read.
170  * \param msg_size           The size of the message that will be read.
171  * \param sig                The buf from which the signature will be read.
172  *                           #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
173  *                           this.
174  *
175  * \return         \c 0 on successful verification.
176  * \return         A non-zero error code on failure.
177  */
178 int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,
179                          const unsigned char *msg,
180                          size_t msg_size, const unsigned char *sig,
181                          size_t sig_size);
182 
183 #if defined(MBEDTLS_LMS_PRIVATE)
184 
185 /**
186  * \brief                    This function initializes a private LMOTS context
187  *
188  * \param ctx                The uninitialized LMOTS context that will then be
189  *                           initialized.
190  */
191 void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx);
192 
193 /**
194  * \brief                    This function uninitializes a private LMOTS context
195  *
196  * \param ctx                The initialized LMOTS context that will then be
197  *                           uninitialized.
198  */
199 void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx);
200 
201 /**
202  * \brief                    This function calculates an LMOTS private key, and
203  *                           stores in into an LMOTS context.
204  *
205  * \warning                  This function is **not intended for use in
206  *                           production**, due to as-yet unsolved problems with
207  *                           handling stateful keys. The API for this function
208  *                           may change considerably in future versions.
209  *
210  * \note                     The seed must have at least 256 bits of entropy.
211  *
212  * \param ctx                The initialized LMOTS context to generate the key
213  *                           into.
214  * \param I_key_identifier   The key identifier of the key, as a 16-byte string.
215  * \param q_leaf_identifier  The leaf identifier of key. If this LMOTS key is
216  *                           not being used as part of an LMS key, this should
217  *                           be set to 0.
218  * \param seed               The seed used to deterministically generate the
219  *                           key.
220  * \param seed_size          The length of the seed.
221  *
222  * \return         \c 0 on success.
223  * \return         A non-zero error code on failure.
224  */
225 int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
226                                        mbedtls_lmots_algorithm_type_t type,
227                                        const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
228                                        uint32_t q_leaf_identifier,
229                                        const unsigned char *seed,
230                                        size_t seed_size);
231 
232 /**
233  * \brief                    This function generates an LMOTS public key from a
234  *                           LMOTS context that already contains a private key.
235  *
236  * \note                     Before this function is called, the context must
237  *                           have been initialized and the context must contain
238  *                           a private key.
239  *
240  * \param ctx                The initialized LMOTS context to generate the key
241  *                           from and store it into.
242  *
243  * \return         \c 0 on success.
244  * \return         A non-zero error code on failure.
245  */
246 int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,
247                                        const mbedtls_lmots_private_t *priv_ctx);
248 
249 /**
250  * \brief                    This function creates a LMOTS signature, using a
251  *                           LMOTS context that contains a private key.
252  *
253  * \note                     Before this function is called, the context must
254  *                           have been initialized and must contain a private
255  *                           key.
256  *
257  * \note                     LMOTS private keys can only be used once, otherwise
258  *                           attackers may be able to create forged signatures.
259  *                           If the signing operation is successful, the private
260  *                           key in the context will be erased, and no further
261  *                           signing will be possible until another private key
262  *                           is loaded
263  *
264  * \param ctx                The initialized LMOTS context from which the
265  *                           private key will be read.
266  * \param f_rng              The RNG function to be used for signature
267  *                           generation.
268  * \param p_rng              The RNG context to be passed to f_rng
269  * \param msg                The buffer from which the message will be read.
270  * \param msg_size           The size of the message that will be read.
271  * \param sig                The buf into which the signature will be stored.
272  *                           Must be at least #MBEDTLS_LMOTS_SIG_LEN in size.
273  *
274  * \return         \c 0 on success.
275  * \return         A non-zero error code on failure.
276  */
277 int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,
278                        int (*f_rng)(void *, unsigned char *, size_t),
279                        void *p_rng, const unsigned char *msg, size_t msg_size,
280                        unsigned char *sig, size_t sig_size, size_t *sig_len);
281 
282 #endif /* defined(MBEDTLS_LMS_PRIVATE) */
283 
284 #ifdef __cplusplus
285 }
286 #endif
287 
288 #endif /* MBEDTLS_LMOTS_H */
289