xref: /third_party/mbedtls/library/lms.c (revision a8e1175b)
1/*
2 *  The LMS stateful-hash public-key signature scheme
3 *
4 *  Copyright The Mbed TLS Contributors
5 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 */
7
8/*
9 *  The following sources were referenced in the design of this implementation
10 *  of the LMS algorithm:
11 *
12 *  [1] IETF RFC8554
13 *      D. McGrew, M. Curcio, S.Fluhrer
14 *      https://datatracker.ietf.org/doc/html/rfc8554
15 *
16 *  [2] NIST Special Publication 800-208
17 *      David A. Cooper et. al.
18 *      https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
19 */
20
21#include "common.h"
22
23#if defined(MBEDTLS_LMS_C)
24
25#include <string.h>
26
27#include "lmots.h"
28
29#include "psa/crypto.h"
30#include "psa_util_internal.h"
31#include "mbedtls/lms.h"
32#include "mbedtls/error.h"
33#include "mbedtls/platform_util.h"
34
35#include "mbedtls/platform.h"
36
37/* Define a local translating function to save code size by not using too many
38 * arguments in each translating place. */
39static int local_err_translation(psa_status_t status)
40{
41    return psa_status_to_mbedtls(status, psa_to_lms_errors,
42                                 ARRAY_LENGTH(psa_to_lms_errors),
43                                 psa_generic_status_to_mbedtls);
44}
45#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
46
47#define SIG_Q_LEAF_ID_OFFSET     (0)
48#define SIG_OTS_SIG_OFFSET       (SIG_Q_LEAF_ID_OFFSET + \
49                                  MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
50#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET   + \
51                                  MBEDTLS_LMOTS_SIG_LEN(otstype))
52#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \
53                                  MBEDTLS_LMS_TYPE_LEN)
54
55#define PUBLIC_KEY_TYPE_OFFSET      (0)
56#define PUBLIC_KEY_OTSTYPE_OFFSET   (PUBLIC_KEY_TYPE_OFFSET + \
57                                     MBEDTLS_LMS_TYPE_LEN)
58#define PUBLIC_KEY_I_KEY_ID_OFFSET  (PUBLIC_KEY_OTSTYPE_OFFSET  + \
59                                     MBEDTLS_LMOTS_TYPE_LEN)
60#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
61                                     MBEDTLS_LMOTS_I_KEY_ID_LEN)
62
63
64/* Currently only support H=10 */
65#define H_TREE_HEIGHT_MAX                  10
66#define MERKLE_TREE_NODE_AM(type)          ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
67#define MERKLE_TREE_LEAF_NODE_AM(type)     ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
68#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \
69                                            (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)))
70
71#define D_CONST_LEN           (2)
72static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 };
73static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 };
74
75
76/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a
77 * public key and some other parameters like the leaf index). This function
78 * implements RFC8554 section 5.3, in the case where r >= 2^h.
79 *
80 *  params              The LMS parameter set, the underlying LMOTS
81 *                      parameter set, and I value which describe the key
82 *                      being used.
83 *
84 *  pub_key             The public key of the private whose index
85 *                      corresponds to the index of this leaf node. This
86 *                      is a hash output.
87 *
88 *  r_node_idx          The index of this node in the Merkle tree. Note
89 *                      that the root node of the Merkle tree is
90 *                      1-indexed.
91 *
92 *  out                 The output node value, which is a hash output.
93 */
94static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params,
95                                    unsigned char *pub_key,
96                                    unsigned int r_node_idx,
97                                    unsigned char *out)
98{
99    psa_hash_operation_t op;
100    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
101    size_t output_hash_len;
102    unsigned char r_node_idx_bytes[4];
103
104    op = psa_hash_operation_init();
105    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
106    if (status != PSA_SUCCESS) {
107        goto exit;
108    }
109
110    status = psa_hash_update(&op, params->I_key_identifier,
111                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
112    if (status != PSA_SUCCESS) {
113        goto exit;
114    }
115
116    MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
117    status = psa_hash_update(&op, r_node_idx_bytes, 4);
118    if (status != PSA_SUCCESS) {
119        goto exit;
120    }
121
122    status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN);
123    if (status != PSA_SUCCESS) {
124        goto exit;
125    }
126
127    status = psa_hash_update(&op, pub_key,
128                             MBEDTLS_LMOTS_N_HASH_LEN(params->otstype));
129    if (status != PSA_SUCCESS) {
130        goto exit;
131    }
132
133    status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
134                             &output_hash_len);
135    if (status != PSA_SUCCESS) {
136        goto exit;
137    }
138
139exit:
140    psa_hash_abort(&op);
141
142    return PSA_TO_MBEDTLS_ERR(status);
143}
144
145/* Calculate the value of an internal node of the Merkle tree (which is a hash
146 * of a public key and some other parameters like the node index). This function
147 * implements RFC8554 section 5.3, in the case where r < 2^h.
148 *
149 *  params              The LMS parameter set, the underlying LMOTS
150 *                      parameter set, and I value which describe the key
151 *                      being used.
152 *
153 *  left_node           The value of the child of this node which is on
154 *                      the left-hand side. As with all nodes on the
155 *                      Merkle tree, this is a hash output.
156 *
157 *  right_node          The value of the child of this node which is on
158 *                      the right-hand side. As with all nodes on the
159 *                      Merkle tree, this is a hash output.
160 *
161 *  r_node_idx          The index of this node in the Merkle tree. Note
162 *                      that the root node of the Merkle tree is
163 *                      1-indexed.
164 *
165 *  out                 The output node value, which is a hash output.
166 */
167static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params,
168                                        const unsigned char *left_node,
169                                        const unsigned char *right_node,
170                                        unsigned int r_node_idx,
171                                        unsigned char *out)
172{
173    psa_hash_operation_t op;
174    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
175    size_t output_hash_len;
176    unsigned char r_node_idx_bytes[4];
177
178    op = psa_hash_operation_init();
179    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
180    if (status != PSA_SUCCESS) {
181        goto exit;
182    }
183
184    status = psa_hash_update(&op, params->I_key_identifier,
185                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
186    if (status != PSA_SUCCESS) {
187        goto exit;
188    }
189
190    MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
191    status = psa_hash_update(&op, r_node_idx_bytes, 4);
192    if (status != PSA_SUCCESS) {
193        goto exit;
194    }
195
196    status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN);
197    if (status != PSA_SUCCESS) {
198        goto exit;
199    }
200
201    status = psa_hash_update(&op, left_node,
202                             MBEDTLS_LMS_M_NODE_BYTES(params->type));
203    if (status != PSA_SUCCESS) {
204        goto exit;
205    }
206
207    status = psa_hash_update(&op, right_node,
208                             MBEDTLS_LMS_M_NODE_BYTES(params->type));
209    if (status != PSA_SUCCESS) {
210        goto exit;
211    }
212
213    status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
214                             &output_hash_len);
215    if (status != PSA_SUCCESS) {
216        goto exit;
217    }
218
219exit:
220    psa_hash_abort(&op);
221
222    return PSA_TO_MBEDTLS_ERR(status);
223}
224
225void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx)
226{
227    memset(ctx, 0, sizeof(*ctx));
228}
229
230void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx)
231{
232    mbedtls_platform_zeroize(ctx, sizeof(*ctx));
233}
234
235int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,
236                                  const unsigned char *key, size_t key_size)
237{
238    mbedtls_lms_algorithm_type_t type;
239    mbedtls_lmots_algorithm_type_t otstype;
240
241    type = (mbedtls_lms_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET);
242    if (type != MBEDTLS_LMS_SHA256_M32_H10) {
243        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
244    }
245    ctx->params.type = type;
246
247    if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
248        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
249    }
250
251    otstype = (mbedtls_lmots_algorithm_type_t)
252              MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET);
253    if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
254        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
255    }
256    ctx->params.otstype = otstype;
257
258    memcpy(ctx->params.I_key_identifier,
259           key + PUBLIC_KEY_I_KEY_ID_OFFSET,
260           MBEDTLS_LMOTS_I_KEY_ID_LEN);
261    memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET,
262           MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
263
264    ctx->have_public_key = 1;
265
266    return 0;
267}
268
269int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx,
270                                  unsigned char *key,
271                                  size_t key_size, size_t *key_len)
272{
273    if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
274        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
275    }
276
277    if (!ctx->have_public_key) {
278        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
279    }
280
281    MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET);
282    MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET);
283    memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
284           ctx->params.I_key_identifier,
285           MBEDTLS_LMOTS_I_KEY_ID_LEN);
286    memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET,
287           ctx->T_1_pub_key,
288           MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
289
290    if (key_len != NULL) {
291        *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type);
292    }
293
294    return 0;
295}
296
297int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,
298                       const unsigned char *msg, size_t msg_size,
299                       const unsigned char *sig, size_t sig_size)
300{
301    unsigned int q_leaf_identifier;
302    unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
303    unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX];
304    unsigned int height;
305    unsigned int curr_node_id;
306    unsigned int parent_node_id;
307    const unsigned char *left_node;
308    const unsigned char *right_node;
309    mbedtls_lmots_parameters_t ots_params;
310    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
311
312    if (!ctx->have_public_key) {
313        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
314    }
315
316    if (ctx->params.type
317        != MBEDTLS_LMS_SHA256_M32_H10) {
318        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
319    }
320
321    if (ctx->params.otstype
322        != MBEDTLS_LMOTS_SHA256_N32_W8) {
323        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
324    }
325
326    if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
327        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
328    }
329
330    if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
331        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
332    }
333
334    if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET)
335        != MBEDTLS_LMOTS_SHA256_N32_W8) {
336        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
337    }
338
339    if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) {
340        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
341    }
342
343    if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype))
344        != MBEDTLS_LMS_SHA256_M32_H10) {
345        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
346    }
347
348
349    q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET);
350
351    if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
352        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
353    }
354
355    memcpy(ots_params.I_key_identifier,
356           ctx->params.I_key_identifier,
357           MBEDTLS_LMOTS_I_KEY_ID_LEN);
358    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0);
359    ots_params.type = ctx->params.otstype;
360
361    ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params,
362                                                       msg,
363                                                       msg_size,
364                                                       sig + SIG_OTS_SIG_OFFSET,
365                                                       MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype),
366                                                       Kc_candidate_ots_pub_key,
367                                                       sizeof(Kc_candidate_ots_pub_key),
368                                                       NULL);
369    if (ret != 0) {
370        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
371    }
372
373    create_merkle_leaf_value(
374        &ctx->params,
375        Kc_candidate_ots_pub_key,
376        MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
377        Tc_candidate_root_node);
378
379    curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) +
380                   q_leaf_identifier;
381
382    for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
383         height++) {
384        parent_node_id = curr_node_id / 2;
385
386        /* Left/right node ordering matters for the hash */
387        if (curr_node_id & 1) {
388            left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
389                        height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
390            right_node = Tc_candidate_root_node;
391        } else {
392            left_node = Tc_candidate_root_node;
393            right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
394                         height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
395        }
396
397        create_merkle_internal_value(&ctx->params, left_node, right_node,
398                                     parent_node_id, Tc_candidate_root_node);
399
400        curr_node_id /= 2;
401    }
402
403    if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key,
404               MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) {
405        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
406    }
407
408    return 0;
409}
410
411#if defined(MBEDTLS_LMS_PRIVATE)
412
413/* Calculate a full Merkle tree based on a private key. This function
414 * implements RFC8554 section 5.3, and is used to generate a public key (as the
415 * public key is the root node of the Merkle tree).
416 *
417 *  ctx                 The LMS private context, containing a parameter
418 *                      set and private key material consisting of both
419 *                      public and private OTS.
420 *
421 *  tree                The output tree, which is 2^(H + 1) hash outputs.
422 *                      In the case of H=10 we have 2048 tree nodes (of
423 *                      which 1024 of them are leaf nodes). Note that
424 *                      because the Merkle tree root is 1-indexed, the 0
425 *                      index tree node is never used.
426 */
427static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx,
428                                 unsigned char *tree)
429{
430    unsigned int priv_key_idx;
431    unsigned int r_node_idx;
432    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
433
434    /* First create the leaf nodes, in ascending order */
435    for (priv_key_idx = 0;
436         priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type);
437         priv_key_idx++) {
438        r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx;
439
440        ret = create_merkle_leaf_value(&ctx->params,
441                                       ctx->ots_public_keys[priv_key_idx].public_key,
442                                       r_node_idx,
443                                       &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(
444                                                 ctx->params.type)]);
445        if (ret != 0) {
446            return ret;
447        }
448    }
449
450    /* Then the internal nodes, in reverse order so that we can guarantee the
451     * parent has been created */
452    for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1;
453         r_node_idx > 0;
454         r_node_idx--) {
455        ret = create_merkle_internal_value(&ctx->params,
456                                           &tree[(r_node_idx * 2) *
457                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
458                                           &tree[(r_node_idx * 2 + 1) *
459                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
460                                           r_node_idx,
461                                           &tree[r_node_idx *
462                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]);
463        if (ret != 0) {
464            return ret;
465        }
466    }
467
468    return 0;
469}
470
471/* Calculate a path from a leaf node of the Merkle tree to the root of the tree,
472 * and return the full path. This function implements RFC8554 section 5.4.1, as
473 * the Merkle path is the main component of an LMS signature.
474 *
475 *  ctx                 The LMS private context, containing a parameter
476 *                      set and private key material consisting of both
477 *                      public and private OTS.
478 *
479 *  leaf_node_id        Which leaf node to calculate the path from.
480 *
481 *  path                The output path, which is H hash outputs.
482 */
483static int get_merkle_path(mbedtls_lms_private_t *ctx,
484                           unsigned int leaf_node_id,
485                           unsigned char *path)
486{
487    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
488    unsigned int curr_node_id = leaf_node_id;
489    unsigned int adjacent_node_id;
490    unsigned char *tree = NULL;
491    unsigned int height;
492    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
493
494    tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type),
495                          node_bytes);
496    if (tree == NULL) {
497        return MBEDTLS_ERR_LMS_ALLOC_FAILED;
498    }
499
500    ret = calculate_merkle_tree(ctx, tree);
501    if (ret != 0) {
502        goto exit;
503    }
504
505    for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
506         height++) {
507        adjacent_node_id = curr_node_id ^ 1;
508
509        memcpy(&path[height * node_bytes],
510               &tree[adjacent_node_id * node_bytes], node_bytes);
511
512        curr_node_id >>= 1;
513    }
514
515    ret = 0;
516
517exit:
518    mbedtls_zeroize_and_free(tree, node_bytes *
519                             (size_t) MERKLE_TREE_NODE_AM(ctx->params.type));
520
521    return ret;
522}
523
524void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx)
525{
526    memset(ctx, 0, sizeof(*ctx));
527}
528
529void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx)
530{
531    unsigned int idx;
532
533    if (ctx->have_private_key) {
534        if (ctx->ots_private_keys != NULL) {
535            for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
536                mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]);
537            }
538        }
539
540        if (ctx->ots_public_keys != NULL) {
541            for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
542                mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]);
543            }
544        }
545
546        mbedtls_free(ctx->ots_private_keys);
547        mbedtls_free(ctx->ots_public_keys);
548    }
549
550    mbedtls_platform_zeroize(ctx, sizeof(*ctx));
551}
552
553
554int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx,
555                                     mbedtls_lms_algorithm_type_t type,
556                                     mbedtls_lmots_algorithm_type_t otstype,
557                                     int (*f_rng)(void *, unsigned char *, size_t),
558                                     void *p_rng, const unsigned char *seed,
559                                     size_t seed_size)
560{
561    unsigned int idx = 0;
562    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
563
564    if (type != MBEDTLS_LMS_SHA256_M32_H10) {
565        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
566    }
567
568    if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
569        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
570    }
571
572    if (ctx->have_private_key) {
573        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
574    }
575
576    ctx->params.type = type;
577    ctx->params.otstype = otstype;
578    ctx->have_private_key = 1;
579
580    ret = f_rng(p_rng,
581                ctx->params.I_key_identifier,
582                MBEDTLS_LMOTS_I_KEY_ID_LEN);
583    if (ret != 0) {
584        goto exit;
585    }
586
587    /* Requires a cast to size_t to avoid an implicit cast warning on certain
588     * platforms (particularly Windows) */
589    ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
590                                           sizeof(*ctx->ots_private_keys));
591    if (ctx->ots_private_keys == NULL) {
592        ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
593        goto exit;
594    }
595
596    /* Requires a cast to size_t to avoid an implicit cast warning on certain
597     * platforms (particularly Windows) */
598    ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
599                                          sizeof(*ctx->ots_public_keys));
600    if (ctx->ots_public_keys == NULL) {
601        ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
602        goto exit;
603    }
604
605    for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
606        mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]);
607        mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]);
608    }
609
610
611    for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
612        ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx],
613                                                 otstype,
614                                                 ctx->params.I_key_identifier,
615                                                 idx, seed, seed_size);
616        if (ret != 0) {
617            goto exit;
618        }
619
620        ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx],
621                                                 &ctx->ots_private_keys[idx]);
622        if (ret != 0) {
623            goto exit;
624        }
625    }
626
627    ctx->q_next_usable_key = 0;
628
629exit:
630    if (ret != 0) {
631        mbedtls_lms_private_free(ctx);
632    }
633
634    return ret;
635}
636
637int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,
638                                     const mbedtls_lms_private_t *priv_ctx)
639{
640    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type);
641    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
642    unsigned char *tree = NULL;
643
644    if (!priv_ctx->have_private_key) {
645        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
646    }
647
648    if (priv_ctx->params.type
649        != MBEDTLS_LMS_SHA256_M32_H10) {
650        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
651    }
652
653    if (priv_ctx->params.otstype
654        != MBEDTLS_LMOTS_SHA256_N32_W8) {
655        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
656    }
657
658    tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type),
659                          node_bytes);
660    if (tree == NULL) {
661        return MBEDTLS_ERR_LMS_ALLOC_FAILED;
662    }
663
664    memcpy(&ctx->params, &priv_ctx->params,
665           sizeof(mbedtls_lmots_parameters_t));
666
667    ret = calculate_merkle_tree(priv_ctx, tree);
668    if (ret != 0) {
669        goto exit;
670    }
671
672    /* Root node is always at position 1, due to 1-based indexing */
673    memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes);
674
675    ctx->have_public_key = 1;
676
677    ret = 0;
678
679exit:
680    mbedtls_zeroize_and_free(tree, node_bytes *
681                             (size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type));
682
683    return ret;
684}
685
686
687int mbedtls_lms_sign(mbedtls_lms_private_t *ctx,
688                     int (*f_rng)(void *, unsigned char *, size_t),
689                     void *p_rng, const unsigned char *msg,
690                     unsigned int msg_size, unsigned char *sig, size_t sig_size,
691                     size_t *sig_len)
692{
693    uint32_t q_leaf_identifier;
694    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
695
696    if (!ctx->have_private_key) {
697        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
698    }
699
700    if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
701        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
702    }
703
704    if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) {
705        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
706    }
707
708    if (ctx->params.otstype
709        != MBEDTLS_LMOTS_SHA256_N32_W8) {
710        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
711    }
712
713    if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
714        return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS;
715    }
716
717
718    q_leaf_identifier = ctx->q_next_usable_key;
719    /* This new value must _always_ be written back to the disk before the
720     * signature is returned.
721     */
722    ctx->q_next_usable_key += 1;
723
724    if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)
725        < SIG_OTS_SIG_OFFSET) {
726        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
727    }
728
729    ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier],
730                             f_rng,
731                             p_rng,
732                             msg,
733                             msg_size,
734                             sig + SIG_OTS_SIG_OFFSET,
735                             MBEDTLS_LMS_SIG_LEN(ctx->params.type,
736                                                 ctx->params.otstype) - SIG_OTS_SIG_OFFSET,
737                             NULL);
738    if (ret != 0) {
739        return ret;
740    }
741
742    MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype));
743    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET);
744
745    ret = get_merkle_path(ctx,
746                          MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
747                          sig + SIG_PATH_OFFSET(ctx->params.otstype));
748    if (ret != 0) {
749        return ret;
750    }
751
752    if (sig_len != NULL) {
753        *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype);
754    }
755
756
757    return 0;
758}
759
760#endif /* defined(MBEDTLS_LMS_PRIVATE) */
761#endif /* defined(MBEDTLS_LMS_C) */
762