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