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