1 /* 2 * The LM-OTS one-time public-key signature scheme 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may 8 * not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 /* 21 * The following sources were referenced in the design of this implementation 22 * of the LM-OTS algorithm: 23 * 24 * [1] IETF RFC8554 25 * D. McGrew, M. Curcio, S.Fluhrer 26 * https://datatracker.ietf.org/doc/html/rfc8554 27 * 28 * [2] NIST Special Publication 800-208 29 * David A. Cooper et. al. 30 * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf 31 */ 32 33 #include "common.h" 34 35 #if defined(MBEDTLS_LMS_C) 36 37 #include <string.h> 38 39 #include "lmots.h" 40 41 #include "mbedtls/lms.h" 42 #include "mbedtls/platform_util.h" 43 #include "mbedtls/error.h" 44 #include "mbedtls/psa_util.h" 45 46 #include "psa/crypto.h" 47 48 #define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ 49 psa_to_lms_errors, \ 50 psa_generic_status_to_mbedtls) 51 52 #define PUBLIC_KEY_TYPE_OFFSET (0) 53 #define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ 54 MBEDTLS_LMOTS_TYPE_LEN) 55 #define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ 56 MBEDTLS_LMOTS_I_KEY_ID_LEN) 57 #define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \ 58 MBEDTLS_LMOTS_Q_LEAF_ID_LEN) 59 60 /* We only support parameter sets that use 8-bit digits, as it does not require 61 * translation logic between digits and bytes */ 62 #define W_WINTERNITZ_PARAMETER (8u) 63 #define CHECKSUM_LEN (2) 64 #define I_DIGIT_IDX_LEN (2) 65 #define J_HASH_IDX_LEN (1) 66 #define D_CONST_LEN (2) 67 68 #define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) 69 70 #define D_CONST_LEN (2) 71 static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 }; 72 static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 }; 73 74 #if defined(MBEDTLS_TEST_HOOKS) 75 int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL; 76 #endif /* defined(MBEDTLS_TEST_HOOKS) */ 77 78 void mbedtls_lms_unsigned_int_to_network_bytes(unsigned int val, size_t len, 79 unsigned char *bytes) 80 { 81 size_t idx; 82 83 for (idx = 0; idx < len; idx++) { 84 bytes[idx] = (val >> ((len - 1 - idx) * 8)) & 0xFF; 85 } 86 } 87 88 unsigned int mbedtls_lms_network_bytes_to_unsigned_int(size_t len, 89 const unsigned char *bytes) 90 { 91 size_t idx; 92 unsigned int val = 0; 93 94 for (idx = 0; idx < len; idx++) { 95 val |= ((unsigned int) bytes[idx]) << (8 * (len - 1 - idx)); 96 } 97 98 return val; 99 } 100 101 /* Calculate the checksum digits that are appended to the end of the LMOTS digit 102 * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of 103 * the checksum algorithm. 104 * 105 * params The LMOTS parameter set, I and q values which 106 * describe the key being used. 107 * 108 * digest The digit string to create the digest from. As 109 * this does not contain a checksum, it is the same 110 * size as a hash output. 111 */ 112 static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params, 113 const unsigned char *digest) 114 { 115 size_t idx; 116 unsigned sum = 0; 117 118 for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) { 119 sum += DIGIT_MAX_VALUE - digest[idx]; 120 } 121 122 return sum; 123 } 124 125 /* Create the string of digest digits (in the base determined by the Winternitz 126 * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST 127 * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm 128 * 4b step 3) for details. 129 * 130 * params The LMOTS parameter set, I and q values which 131 * describe the key being used. 132 * 133 * msg The message that will be hashed to create the 134 * digest. 135 * 136 * msg_size The size of the message. 137 * 138 * C_random_value The random value that will be combined with the 139 * message digest. This is always the same size as a 140 * hash output for whichever hash algorithm is 141 * determined by the parameter set. 142 * 143 * output An output containing the digit string (+ 144 * checksum) of length P digits (in the case of 145 * MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of 146 * size P bytes). 147 */ 148 static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params, 149 const unsigned char *msg, 150 size_t msg_len, 151 const unsigned char *C_random_value, 152 unsigned char *out) 153 { 154 psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; 155 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 156 size_t output_hash_len; 157 unsigned short checksum; 158 159 status = psa_hash_setup(&op, PSA_ALG_SHA_256); 160 if (status != PSA_SUCCESS) { 161 goto exit; 162 } 163 164 status = psa_hash_update(&op, params->I_key_identifier, 165 MBEDTLS_LMOTS_I_KEY_ID_LEN); 166 if (status != PSA_SUCCESS) { 167 goto exit; 168 } 169 170 status = psa_hash_update(&op, params->q_leaf_identifier, 171 MBEDTLS_LMOTS_Q_LEAF_ID_LEN); 172 if (status != PSA_SUCCESS) { 173 goto exit; 174 } 175 176 status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN); 177 if (status != PSA_SUCCESS) { 178 goto exit; 179 } 180 181 status = psa_hash_update(&op, C_random_value, 182 MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type)); 183 if (status != PSA_SUCCESS) { 184 goto exit; 185 } 186 187 status = psa_hash_update(&op, msg, msg_len); 188 if (status != PSA_SUCCESS) { 189 goto exit; 190 } 191 192 status = psa_hash_finish(&op, out, 193 MBEDTLS_LMOTS_N_HASH_LEN(params->type), 194 &output_hash_len); 195 if (status != PSA_SUCCESS) { 196 goto exit; 197 } 198 199 checksum = lmots_checksum_calculate(params, out); 200 mbedtls_lms_unsigned_int_to_network_bytes(checksum, CHECKSUM_LEN, 201 out + MBEDTLS_LMOTS_N_HASH_LEN(params->type)); 202 203 exit: 204 psa_hash_abort(&op); 205 206 return PSA_TO_MBEDTLS_ERR(status); 207 } 208 209 /* Hash each element of the string of digits (+ checksum), producing a hash 210 * output for each element. This is used in several places (by varying the 211 * hash_idx_min/max_values) in order to calculate a public key from a private 212 * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554 213 * Algorithm 3 step 5), and to calculate a public key candidate from a 214 * signature and message (RFC8554 Algorithm 4b step 3). 215 * 216 * params The LMOTS parameter set, I and q values which 217 * describe the key being used. 218 * 219 * x_digit_array The array of digits (of size P, 34 in the case of 220 * MBEDTLS_LMOTS_SHA256_N32_W8). 221 * 222 * hash_idx_min_values An array of the starting values of the j iterator 223 * for each of the members of the digit array. If 224 * this value in NULL, then all iterators will start 225 * at 0. 226 * 227 * hash_idx_max_values An array of the upper bound values of the j 228 * iterator for each of the members of the digit 229 * array. If this value in NULL, then iterator is 230 * bounded to be less than 2^w - 1 (255 in the case 231 * of MBEDTLS_LMOTS_SHA256_N32_W8) 232 * 233 * output An array containing a hash output for each member 234 * of the digit string P. In the case of 235 * MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 * 236 * 34. 237 */ 238 static int hash_digit_array(const mbedtls_lmots_parameters_t *params, 239 const unsigned char *x_digit_array, 240 const unsigned char *hash_idx_min_values, 241 const unsigned char *hash_idx_max_values, 242 unsigned char *output) 243 { 244 unsigned int i_digit_idx; 245 unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN]; 246 unsigned int j_hash_idx; 247 unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN]; 248 unsigned int j_hash_idx_min; 249 unsigned int j_hash_idx_max; 250 psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; 251 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 252 size_t output_hash_len; 253 unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; 254 255 for (i_digit_idx = 0; 256 i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); 257 i_digit_idx++) { 258 259 memcpy(tmp_hash, 260 &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], 261 MBEDTLS_LMOTS_N_HASH_LEN(params->type)); 262 263 j_hash_idx_min = hash_idx_min_values != NULL ? 264 hash_idx_min_values[i_digit_idx] : 0; 265 j_hash_idx_max = hash_idx_max_values != NULL ? 266 hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; 267 268 for (j_hash_idx = j_hash_idx_min; 269 j_hash_idx < j_hash_idx_max; 270 j_hash_idx++) { 271 status = psa_hash_setup(&op, PSA_ALG_SHA_256); 272 if (status != PSA_SUCCESS) { 273 goto exit; 274 } 275 276 status = psa_hash_update(&op, 277 params->I_key_identifier, 278 MBEDTLS_LMOTS_I_KEY_ID_LEN); 279 if (status != PSA_SUCCESS) { 280 goto exit; 281 } 282 283 status = psa_hash_update(&op, 284 params->q_leaf_identifier, 285 MBEDTLS_LMOTS_Q_LEAF_ID_LEN); 286 if (status != PSA_SUCCESS) { 287 goto exit; 288 } 289 290 mbedtls_lms_unsigned_int_to_network_bytes(i_digit_idx, 291 I_DIGIT_IDX_LEN, 292 i_digit_idx_bytes); 293 status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); 294 if (status != PSA_SUCCESS) { 295 goto exit; 296 } 297 298 mbedtls_lms_unsigned_int_to_network_bytes(j_hash_idx, 299 J_HASH_IDX_LEN, 300 j_hash_idx_bytes); 301 status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN); 302 if (status != PSA_SUCCESS) { 303 goto exit; 304 } 305 306 status = psa_hash_update(&op, tmp_hash, 307 MBEDTLS_LMOTS_N_HASH_LEN(params->type)); 308 if (status != PSA_SUCCESS) { 309 goto exit; 310 } 311 312 status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash), 313 &output_hash_len); 314 if (status != PSA_SUCCESS) { 315 goto exit; 316 } 317 318 psa_hash_abort(&op); 319 } 320 321 memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], 322 tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); 323 } 324 325 exit: 326 psa_hash_abort(&op); 327 mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash)); 328 329 return PSA_TO_MBEDTLS_ERR(status); 330 } 331 332 /* Combine the hashes of the digit array into a public key. This is used in 333 * in order to calculate a public key from a private key (RFC8554 Algorithm 1 334 * step 4), and to calculate a public key candidate from a signature and message 335 * (RFC8554 Algorithm 4b step 3). 336 * 337 * params The LMOTS parameter set, I and q values which describe 338 * the key being used. 339 * y_hashed_digits The array of hashes, one hash for each digit of the 340 * symbol array (which is of size P, 34 in the case of 341 * MBEDTLS_LMOTS_SHA256_N32_W8) 342 * 343 * pub_key The output public key (or candidate public key in 344 * case this is being run as part of signature 345 * verification), in the form of a hash output. 346 */ 347 static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params, 348 const unsigned char *y_hashed_digits, 349 unsigned char *pub_key) 350 { 351 psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; 352 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 353 size_t output_hash_len; 354 355 status = psa_hash_setup(&op, PSA_ALG_SHA_256); 356 if (status != PSA_SUCCESS) { 357 goto exit; 358 } 359 360 status = psa_hash_update(&op, 361 params->I_key_identifier, 362 MBEDTLS_LMOTS_I_KEY_ID_LEN); 363 if (status != PSA_SUCCESS) { 364 goto exit; 365 } 366 367 status = psa_hash_update(&op, params->q_leaf_identifier, 368 MBEDTLS_LMOTS_Q_LEAF_ID_LEN); 369 if (status != PSA_SUCCESS) { 370 goto exit; 371 } 372 373 status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN); 374 if (status != PSA_SUCCESS) { 375 goto exit; 376 } 377 378 status = psa_hash_update(&op, y_hashed_digits, 379 MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) * 380 MBEDTLS_LMOTS_N_HASH_LEN(params->type)); 381 if (status != PSA_SUCCESS) { 382 goto exit; 383 } 384 385 status = psa_hash_finish(&op, pub_key, 386 MBEDTLS_LMOTS_N_HASH_LEN(params->type), 387 &output_hash_len); 388 if (status != PSA_SUCCESS) { 389 390 exit: 391 psa_hash_abort(&op); 392 } 393 394 return PSA_TO_MBEDTLS_ERR(status); 395 } 396 397 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 398 int mbedtls_lms_error_from_psa(psa_status_t status) 399 { 400 switch (status) { 401 case PSA_SUCCESS: 402 return 0; 403 case PSA_ERROR_HARDWARE_FAILURE: 404 return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 405 case PSA_ERROR_NOT_SUPPORTED: 406 return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; 407 case PSA_ERROR_BUFFER_TOO_SMALL: 408 return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; 409 case PSA_ERROR_INVALID_ARGUMENT: 410 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 411 default: 412 return MBEDTLS_ERR_ERROR_GENERIC_ERROR; 413 } 414 } 415 #endif /* !MBEDTLS_DEPRECATED_REMOVED */ 416 417 void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx) 418 { 419 memset(ctx, 0, sizeof(*ctx)); 420 } 421 422 void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx) 423 { 424 mbedtls_platform_zeroize(ctx, sizeof(*ctx)); 425 } 426 427 int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, 428 const unsigned char *key, size_t key_len) 429 { 430 if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { 431 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 432 } 433 434 ctx->params.type = 435 mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN, 436 key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET); 437 438 if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { 439 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 440 } 441 442 memcpy(ctx->params.I_key_identifier, 443 key + PUBLIC_KEY_I_KEY_ID_OFFSET, 444 MBEDTLS_LMOTS_I_KEY_ID_LEN); 445 446 memcpy(ctx->params.q_leaf_identifier, 447 key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, 448 MBEDTLS_LMOTS_Q_LEAF_ID_LEN); 449 450 memcpy(ctx->public_key, 451 key + PUBLIC_KEY_KEY_HASH_OFFSET, 452 MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); 453 454 ctx->have_public_key = 1; 455 456 return 0; 457 } 458 459 int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, 460 unsigned char *key, size_t key_size, 461 size_t *key_len) 462 { 463 if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { 464 return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; 465 } 466 467 if (!ctx->have_public_key) { 468 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 469 } 470 471 mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type, 472 MBEDTLS_LMOTS_TYPE_LEN, 473 key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET); 474 475 memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, 476 ctx->params.I_key_identifier, 477 MBEDTLS_LMOTS_I_KEY_ID_LEN); 478 479 memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, 480 ctx->params.q_leaf_identifier, 481 MBEDTLS_LMOTS_Q_LEAF_ID_LEN); 482 483 memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, 484 MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); 485 486 if (key_len != NULL) { 487 *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type); 488 } 489 490 return 0; 491 } 492 493 int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, 494 const unsigned char *msg, 495 size_t msg_size, 496 const unsigned char *sig, 497 size_t sig_size, 498 unsigned char *out, 499 size_t out_size, 500 size_t *out_len) 501 { 502 unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; 503 unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; 504 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 505 506 if (msg == NULL && msg_size != 0) { 507 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 508 } 509 510 if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) || 511 out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) { 512 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 513 } 514 515 ret = create_digit_array_with_checksum(params, msg, msg_size, 516 sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, 517 tmp_digit_array); 518 if (ret) { 519 return ret; 520 } 521 522 ret = hash_digit_array(params, 523 sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type), 524 tmp_digit_array, NULL, (unsigned char *) y_hashed_digits); 525 if (ret) { 526 return ret; 527 } 528 529 ret = public_key_from_hashed_digit_array(params, 530 (unsigned char *) y_hashed_digits, 531 out); 532 if (ret) { 533 return ret; 534 } 535 536 if (out_len != NULL) { 537 *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type); 538 } 539 540 return 0; 541 } 542 543 int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, 544 const unsigned char *msg, size_t msg_size, 545 const unsigned char *sig, size_t sig_size) 546 { 547 unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; 548 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 549 550 if (msg == NULL && msg_size != 0) { 551 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 552 } 553 554 if (!ctx->have_public_key) { 555 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 556 } 557 558 if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) { 559 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 560 } 561 562 if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { 563 return MBEDTLS_ERR_LMS_VERIFY_FAILED; 564 } 565 566 if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN, 567 sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != 568 MBEDTLS_LMOTS_SHA256_N32_W8) { 569 return MBEDTLS_ERR_LMS_VERIFY_FAILED; 570 } 571 572 ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params, 573 msg, msg_size, sig, sig_size, 574 Kc_public_key_candidate, 575 MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), 576 NULL); 577 if (ret) { 578 return MBEDTLS_ERR_LMS_VERIFY_FAILED; 579 } 580 581 if (memcmp(&Kc_public_key_candidate, ctx->public_key, 582 sizeof(ctx->public_key))) { 583 return MBEDTLS_ERR_LMS_VERIFY_FAILED; 584 } 585 586 return 0; 587 } 588 589 #if defined(MBEDTLS_LMS_PRIVATE) 590 591 void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx) 592 { 593 memset(ctx, 0, sizeof(*ctx)); 594 } 595 596 void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx) 597 { 598 mbedtls_platform_zeroize(ctx, 599 sizeof(*ctx)); 600 } 601 602 int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, 603 mbedtls_lmots_algorithm_type_t type, 604 const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], 605 uint32_t q_leaf_identifier, 606 const unsigned char *seed, 607 size_t seed_size) 608 { 609 psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; 610 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 611 size_t output_hash_len; 612 unsigned int i_digit_idx; 613 unsigned char i_digit_idx_bytes[2]; 614 unsigned char const_bytes[1]; 615 616 if (ctx->have_private_key) { 617 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 618 } 619 620 if (type != MBEDTLS_LMOTS_SHA256_N32_W8) { 621 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 622 } 623 624 ctx->params.type = type; 625 626 memcpy(ctx->params.I_key_identifier, 627 I_key_identifier, 628 sizeof(ctx->params.I_key_identifier)); 629 630 mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier, 631 MBEDTLS_LMOTS_Q_LEAF_ID_LEN, 632 ctx->params.q_leaf_identifier); 633 634 mbedtls_lms_unsigned_int_to_network_bytes(0xFF, sizeof(const_bytes), 635 const_bytes); 636 637 for (i_digit_idx = 0; 638 i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type); 639 i_digit_idx++) { 640 status = psa_hash_setup(&op, PSA_ALG_SHA_256); 641 if (status != PSA_SUCCESS) { 642 goto exit; 643 } 644 645 status = psa_hash_update(&op, 646 ctx->params.I_key_identifier, 647 sizeof(ctx->params.I_key_identifier)); 648 if (status != PSA_SUCCESS) { 649 goto exit; 650 } 651 652 status = psa_hash_update(&op, 653 ctx->params.q_leaf_identifier, 654 MBEDTLS_LMOTS_Q_LEAF_ID_LEN); 655 if (status != PSA_SUCCESS) { 656 goto exit; 657 } 658 659 mbedtls_lms_unsigned_int_to_network_bytes(i_digit_idx, I_DIGIT_IDX_LEN, 660 i_digit_idx_bytes); 661 status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); 662 if (status != PSA_SUCCESS) { 663 goto exit; 664 } 665 666 status = psa_hash_update(&op, const_bytes, sizeof(const_bytes)); 667 if (status != PSA_SUCCESS) { 668 goto exit; 669 } 670 671 status = psa_hash_update(&op, seed, seed_size); 672 if (status != PSA_SUCCESS) { 673 goto exit; 674 } 675 676 status = psa_hash_finish(&op, 677 ctx->private_key[i_digit_idx], 678 MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), 679 &output_hash_len); 680 if (status != PSA_SUCCESS) { 681 goto exit; 682 } 683 684 psa_hash_abort(&op); 685 } 686 687 ctx->have_private_key = 1; 688 689 exit: 690 psa_hash_abort(&op); 691 692 return PSA_TO_MBEDTLS_ERR(status); 693 } 694 695 int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, 696 const mbedtls_lmots_private_t *priv_ctx) 697 { 698 unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; 699 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 700 701 /* Check that a private key is loaded */ 702 if (!priv_ctx->have_private_key) { 703 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 704 } 705 706 ret = hash_digit_array(&priv_ctx->params, 707 (unsigned char *) priv_ctx->private_key, NULL, 708 NULL, (unsigned char *) y_hashed_digits); 709 if (ret) { 710 goto exit; 711 } 712 713 ret = public_key_from_hashed_digit_array(&priv_ctx->params, 714 (unsigned char *) y_hashed_digits, 715 ctx->public_key); 716 if (ret) { 717 goto exit; 718 } 719 720 memcpy(&ctx->params, &priv_ctx->params, 721 sizeof(ctx->params)); 722 723 ctx->have_public_key = 1; 724 725 exit: 726 mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits)); 727 728 return ret; 729 } 730 731 int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, 732 int (*f_rng)(void *, unsigned char *, size_t), 733 void *p_rng, const unsigned char *msg, size_t msg_size, 734 unsigned char *sig, size_t sig_size, size_t *sig_len) 735 { 736 unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; 737 /* Create a temporary buffer to prepare the signature in. This allows us to 738 * finish creating a signature (ensuring the process doesn't fail), and then 739 * erase the private key **before** writing any data into the sig parameter 740 * buffer. If data were directly written into the sig buffer, it might leak 741 * a partial signature on failure, which effectively compromises the private 742 * key. 743 */ 744 unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; 745 unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; 746 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 747 748 if (msg == NULL && msg_size != 0) { 749 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 750 } 751 752 if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) { 753 return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; 754 } 755 756 /* Check that a private key is loaded */ 757 if (!ctx->have_private_key) { 758 return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; 759 } 760 761 ret = f_rng(p_rng, tmp_c_random, 762 MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); 763 if (ret) { 764 return ret; 765 } 766 767 ret = create_digit_array_with_checksum(&ctx->params, 768 msg, msg_size, 769 tmp_c_random, 770 tmp_digit_array); 771 if (ret) { 772 goto exit; 773 } 774 775 ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key, 776 NULL, tmp_digit_array, (unsigned char *) tmp_sig); 777 if (ret) { 778 goto exit; 779 } 780 781 mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type, 782 MBEDTLS_LMOTS_TYPE_LEN, 783 sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET); 784 785 /* Test hook to check if sig is being written to before we invalidate the 786 * private key. 787 */ 788 #if defined(MBEDTLS_TEST_HOOKS) 789 if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) { 790 ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig); 791 if (ret != 0) { 792 return ret; 793 } 794 } 795 #endif /* defined(MBEDTLS_TEST_HOOKS) */ 796 797 /* We've got a valid signature now, so it's time to make sure the private 798 * key can't be reused. 799 */ 800 ctx->have_private_key = 0; 801 mbedtls_platform_zeroize(ctx->private_key, 802 sizeof(ctx->private_key)); 803 804 memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random, 805 MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type)); 806 807 memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig, 808 MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type) 809 * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); 810 811 if (sig_len != NULL) { 812 *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type); 813 } 814 815 ret = 0; 816 817 exit: 818 mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array)); 819 mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig)); 820 821 return ret; 822 } 823 824 #endif /* defined(MBEDTLS_LMS_PRIVATE) */ 825 #endif /* defined(MBEDTLS_LMS_C) */ 826