quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

lms.c (26488B)


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