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