blob: d8969ba390053df64098b636ec9fc62a62166e75 [file] [log] [blame]
Raef Coles8ff6df52021-07-21 12:42:15 +01001/*
2 * The LMS stateful-hash 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 LMS 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#ifdef MBEDTLS_LMS_C
36
37#include <string.h>
38
Raef Coles7dce69a2022-08-24 14:07:06 +010039#include "lmots.h"
40
Raef Coles8ff6df52021-07-21 12:42:15 +010041#include "mbedtls/lms.h"
Raef Coles8ff6df52021-07-21 12:42:15 +010042#include "mbedtls/md.h"
43#include "mbedtls/error.h"
44#include "mbedtls/platform_util.h"
45
46#if defined(MBEDTLS_PLATFORM_C)
47#include "mbedtls/platform.h"
48#else
49#include <stdlib.h>
50#include <stdio.h>
51#define mbedtls_printf printf
52#define mbedtls_calloc calloc
53#define mbedtls_free free
54#endif
55
56#define MERKLE_TREE_NODE_AM (1 << (MBEDTLS_LMS_H_TREE_HEIGHT + 1))
57#define MERKLE_TREE_LEAF_AM (1 << MBEDTLS_LMS_H_TREE_HEIGHT)
58#define MERKLE_TREE_INTR_AM (1 << MBEDTLS_LMS_H_TREE_HEIGHT)
59
60#define D_CONST_LEN (2)
61
62#define D_LEAF_CONSTANT (0x8282)
63#define D_INTR_CONSTANT (0x8383)
64
65static void val_to_network_bytes(unsigned int val, size_t len, unsigned char *bytes)
66{
67 size_t idx;
68
69 for (idx = 0; idx < len; idx++) {
70 bytes[idx] = (val >> ((len - 1 - idx) * 8)) & 0xFF;
71 }
72}
73
74static unsigned int network_bytes_to_val(size_t len, const unsigned char *bytes)
75{
76 size_t idx;
77 unsigned int val = 0;
78
79 for (idx = 0; idx < len; idx++) {
80 val |= ((unsigned int)bytes[idx]) << (8 * (len - 1 - idx));
81 }
82
83 return val;
84}
85
86static int create_merkle_leaf_node( const mbedtls_lms_context *ctx,
87 unsigned char pub_key[MBEDTLS_LMOTS_N_HASH_LEN],
88 unsigned int r_node_idx,
89 unsigned char out[32] )
90{
91 mbedtls_md_context_t hash_ctx;
92 unsigned char D_LEAF_bytes[D_CONST_LEN];
93 unsigned char r_node_idx_bytes[4];
94 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
95
96 mbedtls_md_init( &hash_ctx );
97 ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 );
98 if( ret )
99 {
100 goto out;
101 }
102 ret = mbedtls_md_starts( &hash_ctx );
103 if( ret )
104 {
105 goto out;
106 }
107
108 ret = mbedtls_md_update( &hash_ctx,
109 ctx->MBEDTLS_PRIVATE(I_key_identifier),
110 MBEDTLS_LMOTS_I_KEY_ID_LEN );
111 if( ret )
112 {
113 goto out;
114 }
115
116 val_to_network_bytes( r_node_idx, 4, r_node_idx_bytes );
117 ret = mbedtls_md_update( &hash_ctx, r_node_idx_bytes, 4 );
118 if( ret )
119 {
120 goto out;
121 }
122
123 val_to_network_bytes( D_LEAF_CONSTANT, D_CONST_LEN, D_LEAF_bytes );
124 ret = mbedtls_md_update( &hash_ctx, D_LEAF_bytes, D_CONST_LEN );
125 if( ret )
126 {
127 goto out;
128 }
129
130 ret = mbedtls_md_update( &hash_ctx, pub_key, MBEDTLS_LMOTS_N_HASH_LEN );
131 if( ret )
132 {
133 goto out;
134 }
135
136 ret = mbedtls_md_finish( &hash_ctx, out );
137 if( ret )
138 {
139 goto out;
140 }
141
142out:
143 mbedtls_md_free( &hash_ctx );
144
145 return( ret );
146}
147
148static int create_merkle_intr_node( const mbedtls_lms_context *ctx,
149 const unsigned char left_node[32],
150 const unsigned char rght_node[32],
151 unsigned int r_node_idx,
152 unsigned char out[32] )
153{
154 mbedtls_md_context_t hash_ctx;
155 unsigned char D_INTR_bytes[D_CONST_LEN];
156 unsigned char r_node_idx_bytes[4];
157 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
158
159 mbedtls_md_init( &hash_ctx );
160 ret = mbedtls_md_setup( &hash_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 );
161 if( ret )
162 {
163 goto out;
164 }
165 ret = mbedtls_md_starts( &hash_ctx );
166 if( ret )
167 {
168 goto out;
169 }
170
171 ret = mbedtls_md_update( &hash_ctx, ctx->MBEDTLS_PRIVATE(I_key_identifier),
172 MBEDTLS_LMOTS_I_KEY_ID_LEN );
173 if( ret )
174 {
175 goto out;
176 }
177
178 val_to_network_bytes( r_node_idx, 4, r_node_idx_bytes );
179 ret = mbedtls_md_update( &hash_ctx, r_node_idx_bytes, 4 );
180 if( ret )
181 {
182 goto out;
183 }
184
185 val_to_network_bytes( D_INTR_CONSTANT, D_CONST_LEN, D_INTR_bytes );
186 ret = mbedtls_md_update( &hash_ctx, D_INTR_bytes, D_CONST_LEN );
187 if( ret )
188 {
189 goto out;
190 }
191
192 ret = mbedtls_md_update( &hash_ctx, left_node, MBEDTLS_LMOTS_N_HASH_LEN );
193 if( ret )
194 {
195 goto out;
196 }
197
198 ret = mbedtls_md_update( &hash_ctx, rght_node, MBEDTLS_LMOTS_N_HASH_LEN );
199 if( ret )
200 {
201 goto out;
202 }
203
204 ret = mbedtls_md_finish( &hash_ctx, out );
205 if( ret )
206 {
207 goto out;
208 }
209
210out:
211 mbedtls_md_free( &hash_ctx );
212
213 return ret;
214}
215
216static int generate_merkle_tree( mbedtls_lms_context *ctx,
217 unsigned char tree[MERKLE_TREE_NODE_AM][32] )
218{
219 unsigned int priv_key_idx;
220 unsigned int r_node_idx;
221 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
222
223 /* First create the leaf nodes, in ascending order */
224 for( priv_key_idx = 0; priv_key_idx < MERKLE_TREE_INTR_AM; priv_key_idx++ )
225 {
226 r_node_idx = MERKLE_TREE_INTR_AM + priv_key_idx;
227
228 ret = create_merkle_leaf_node( ctx, ctx->MBEDTLS_PRIVATE(priv_keys)[priv_key_idx].pub_key,
229 r_node_idx, tree[r_node_idx] );
230 if( ret )
231 {
232 return( ret );
233 }
234 }
235
236 /* Then the internal nodes, in reverse order so that we can guarantee the
237 * parent has been created */
238 for( r_node_idx = MERKLE_TREE_INTR_AM - 1; r_node_idx > 0; r_node_idx-- )
239 {
240 ret = create_merkle_intr_node( ctx, tree[(r_node_idx * 2)],
241 tree[(r_node_idx * 2 + 1)],
242 r_node_idx, tree[r_node_idx] );
243 if( ret )
244 {
245 return( ret );
246 }
247 }
248
249 return( 0 );
250}
251
252static int get_merkle_path( mbedtls_lms_context *ctx,
253 unsigned int leaf_node_id, unsigned char path[MBEDTLS_LMS_H_TREE_HEIGHT][32] )
254{
255 unsigned char tree[MERKLE_TREE_NODE_AM][32];
256 unsigned int curr_node_id = leaf_node_id;
257 unsigned int parent_node_id;
258 unsigned char sibling_relative_id;
259 unsigned int adjacent_node_id;
260 unsigned int height;
261 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
262
263 ret = generate_merkle_tree( ctx, tree);
264 if( ret )
265 {
266 return( ret );
267 }
268
269 for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ )
270 {
271 parent_node_id = ( curr_node_id / 2 );
272
273 /* 0 if the node is a left child, 1 if the node is a right child */
274 sibling_relative_id = curr_node_id & 1;
275
276 adjacent_node_id = ( parent_node_id * 2 ) + ( 1 - sibling_relative_id );
277
278 memcpy( &path[height], &tree[adjacent_node_id], MBEDTLS_LMOTS_N_HASH_LEN );
279
280 curr_node_id = parent_node_id;
281 }
282
283 return( 0 );
284}
285
286void mbedtls_lms_init( mbedtls_lms_context *ctx )
287{
288 if( ctx == NULL )
289 {
290 return;
291 }
292
293 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_context ) ) ;
294}
295
296void mbedtls_lms_free( mbedtls_lms_context *ctx )
297{
298 unsigned int idx;
299
300 if( ctx == NULL )
301 {
302 return;
303 }
304
305 if( ctx->MBEDTLS_PRIVATE(have_privkey) )
306 {
307 for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ )
308 {
309 mbedtls_lmots_free( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx] );
310 }
311
312 mbedtls_free( ctx->MBEDTLS_PRIVATE(priv_keys) );
313 }
314
315 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_lms_context ) );
316}
317
318int mbedtls_lms_set_algorithm_type( mbedtls_lms_context *ctx,
319 mbedtls_lms_algorithm_type_t type,
320 mbedtls_lmots_algorithm_type_t otstype )
321{
322 if( ctx == NULL )
323 {
324 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
325 }
326
327 ctx->MBEDTLS_PRIVATE(type) = type;
328 ctx->MBEDTLS_PRIVATE(otstype) = otstype;
329
330 return( 0 );
331}
332
333int mbedtls_lms_sign( mbedtls_lms_context *ctx,
334 int ( *f_rng)(void *, unsigned char *, size_t),
335 void* p_rng, unsigned char *msg, unsigned int msg_len,
336 unsigned char *sig )
337{
338 unsigned int q_leaf_identifier;
339 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
340
341 if( ctx == NULL )
342 {
343 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
344 }
345
346 if( ! ctx->MBEDTLS_PRIVATE(have_privkey) )
347 {
348 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
349 }
350
351 if( msg == NULL )
352 {
353 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
354 }
355
356 if( sig == NULL )
357 {
358 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
359 }
360
361
362 if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 )
363 {
364 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
365 }
366
367 if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 )
368 {
369 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
370 }
371
372
373 if( ctx->MBEDTLS_PRIVATE(q_next_usable_key) >= MERKLE_TREE_LEAF_AM )
374 {
375 return( MBEDTLS_ERR_LMS_OUT_OF_PRIV_KEYS );
376 }
377
378
379 q_leaf_identifier = ctx->MBEDTLS_PRIVATE(q_next_usable_key);
380 /* This new value must _always_ be written back to the disk before the
381 * signature is returned.
382 */
383 ctx->MBEDTLS_PRIVATE(q_next_usable_key) += 1;
384
385 ret = mbedtls_lmots_sign( &ctx->MBEDTLS_PRIVATE(priv_keys)[q_leaf_identifier],
386 f_rng, p_rng, msg, msg_len,
387 sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET );
388 if( ret )
389 {
390 return( ret );
391 }
392
393 val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type), MBEDTLS_LMS_TYPE_LEN,
394 sig + MBEDTLS_LMS_SIG_TYPE_OFFSET );
395 val_to_network_bytes( q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
396 sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET);
397
398 ret = get_merkle_path( ctx, MERKLE_TREE_INTR_AM + q_leaf_identifier,
399 ( unsigned char( * )[32] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) );
400 if( ret )
401 {
402 return( ret );
403 }
404
405 return( 0 );
406}
407
408int mbedtls_lms_verify( const mbedtls_lms_context *ctx,
409 const unsigned char *msg, unsigned int msg_len,
410 const unsigned char *sig )
411{
412 unsigned int q_leaf_identifier;
413 unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN];
414 unsigned char Tc_candidate_root_node[32];
415 unsigned int height;
416 unsigned int curr_node_id;
417 unsigned int parent_node_id;
418 const unsigned char* left_node;
419 const unsigned char* rght_node;
420 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
421
422 if( ctx == NULL )
423 {
424 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
425 }
426
427 if( ! ctx->MBEDTLS_PRIVATE(have_pubkey) )
428 {
429 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
430 }
431
432 if( msg == NULL)
433 {
434 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
435 }
436
437 if( sig == NULL)
438 {
439 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
440 }
441
442 if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 )
443 {
444 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
445 }
446
447 if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 )
448 {
449 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
450 }
451
452
453 if( network_bytes_to_val( MBEDTLS_LMS_TYPE_LEN,
454 sig + MBEDTLS_LMS_SIG_TYPE_OFFSET) != MBEDTLS_LMS_SHA256_M32_H10 )
455 {
456 return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
457 }
458
459 if( network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN,
460 sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET)
461 != MBEDTLS_LMOTS_SHA256_N32_W8 )
462 {
463 return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
464 }
465
466
467 q_leaf_identifier = network_bytes_to_val( MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
468 sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET );
469
470 if( q_leaf_identifier >= MERKLE_TREE_LEAF_AM )
471 {
472 return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
473 }
474
475 ret = mbedtls_lmots_generate_pub_key_candidate( ctx->MBEDTLS_PRIVATE(I_key_identifier),
476 sig + MBEDTLS_LMS_SIG_Q_LEAF_ID_OFFSET,
477 msg, msg_len,
478 sig + MBEDTLS_LMS_SIG_OTS_SIG_OFFSET,
479 Kc_candidate_ots_pub_key );
480 if( ret )
481 {
482 return( ret );
483 }
484
485 create_merkle_leaf_node( ctx, Kc_candidate_ots_pub_key,
486 MERKLE_TREE_INTR_AM + q_leaf_identifier,
487 Tc_candidate_root_node );
488
489 curr_node_id = MERKLE_TREE_INTR_AM + q_leaf_identifier;
490
491 for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT; height++ )
492 {
493 parent_node_id = curr_node_id / 2;
494
495 /* Left/right node ordering matters for the hash */
496 if( curr_node_id & 1 )
497 {
498 left_node = ( ( const unsigned char( * )[32] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height];
499 rght_node = Tc_candidate_root_node;
500 }
501 else
502 {
503 left_node = Tc_candidate_root_node;
504 rght_node = ( ( const unsigned char( * )[32] )( sig + MBEDTLS_LMS_SIG_PATH_OFFSET ) )[height];
505 }
506
507 create_merkle_intr_node( ctx, left_node, rght_node, parent_node_id,
508 Tc_candidate_root_node);
509
510 curr_node_id /= 2;
511 }
512
513 if( memcmp( Tc_candidate_root_node, ctx->MBEDTLS_PRIVATE(T_1_pub_key),
514 MBEDTLS_LMOTS_N_HASH_LEN) )
515 {
516 return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
517 }
518
519 return( 0 );
520}
521
522int mbedtls_lms_import_pubkey( mbedtls_lms_context *ctx,
523 const unsigned char *key )
524{
525 mbedtls_lms_algorithm_type_t type;
526 mbedtls_lmots_algorithm_type_t otstype;
527
528 if( ctx == NULL )
529 {
530 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
531 }
532
533 if( key == NULL )
534 {
535 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
536 }
537
538 type = network_bytes_to_val( MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBKEY_TYPE_OFFSET );
539 if( type != MBEDTLS_LMS_SHA256_M32_H10 )
540 {
541 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
542 }
543 ctx->MBEDTLS_PRIVATE(type) = type;
544
545 otstype = network_bytes_to_val( MBEDTLS_LMOTS_TYPE_LEN,
546 key + MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET );
547 if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 )
548 {
549 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
550 }
551 ctx->MBEDTLS_PRIVATE(otstype) = otstype;
552
553 memcpy( ctx->MBEDTLS_PRIVATE(I_key_identifier), key + MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET,
554 MBEDTLS_LMOTS_I_KEY_ID_LEN );
555 memcpy( ctx->MBEDTLS_PRIVATE(T_1_pub_key), key + MBEDTLS_LMS_PUBKEY_ROOT_NODE_OFFSET,
556 MBEDTLS_LMOTS_N_HASH_LEN );
557
558 ctx->MBEDTLS_PRIVATE(have_pubkey) = 1;
559
560 return( 0 );
561}
562
563int mbedtls_lms_export_pubkey( mbedtls_lms_context *ctx,
564 unsigned char *key )
565{
566 if( ctx == NULL )
567 {
568 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
569 }
570
571 if( key == NULL )
572 {
573 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
574 }
575
576 if( ! ctx->MBEDTLS_PRIVATE(have_pubkey) )
577 {
578 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
579 }
580
581 val_to_network_bytes( ctx->MBEDTLS_PRIVATE(type),
582 MBEDTLS_LMS_TYPE_LEN, key + MBEDTLS_LMS_PUBKEY_TYPE_OFFSET );
583 val_to_network_bytes( ctx->MBEDTLS_PRIVATE(otstype),
584 MBEDTLS_LMOTS_TYPE_LEN, key + MBEDTLS_LMS_PUBKEY_OTSTYPE_OFFSET );
585 memcpy( key + MBEDTLS_LMS_PUBKEY_I_KEY_ID_OFFSET,
586 ctx->MBEDTLS_PRIVATE(I_key_identifier),
587 MBEDTLS_LMOTS_I_KEY_ID_LEN );
588 memcpy( key + MBEDTLS_LMS_PUBKEY_ROOT_NODE_OFFSET,
589 ctx->MBEDTLS_PRIVATE(T_1_pub_key),
590 MBEDTLS_LMOTS_N_HASH_LEN );
591
592 return( 0 );
593}
594
595int mbedtls_lms_gen_pubkey( mbedtls_lms_context *ctx )
596{
597 unsigned char tree[MERKLE_TREE_NODE_AM][32];
598 unsigned int idx;
599 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
600
601 if( ctx == NULL )
602 {
603 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
604 }
605
606 if( ! ctx->MBEDTLS_PRIVATE( have_privkey ) )
607 {
608 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
609 }
610
611 if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 )
612 {
613 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
614 }
615
616 if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 )
617 {
618 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
619 }
620
621 for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ )
622 {
623 ret = mbedtls_lmots_gen_pubkey( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx] );
624 if( ret )
625 {
626 return( ret );
627 }
628 }
629
630 ret = generate_merkle_tree( ctx, tree);
631 if( ret )
632 {
633 return( ret );
634 }
635
636 /* Root node is always at position 1, due to 1-based indexing */
637 memcpy( ctx->MBEDTLS_PRIVATE(T_1_pub_key), &tree[1], MBEDTLS_LMOTS_N_HASH_LEN );
638
639 ctx->MBEDTLS_PRIVATE(have_pubkey) = 1;
640
641 return( 0 );
642}
643
644int mbedtls_lms_gen_privkey( mbedtls_lms_context *ctx,
645 int ( *f_rng)(void *, unsigned char *, size_t),
646 void* p_rng, unsigned char *seed,
647 size_t seed_len )
648{
649 unsigned int idx;
650 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
651
652 if( ctx == NULL )
653 {
654 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
655 }
656
657 if( ctx->MBEDTLS_PRIVATE(type) != MBEDTLS_LMS_SHA256_M32_H10 )
658 {
659 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
660 }
661
662 if( ctx->MBEDTLS_PRIVATE(otstype) != MBEDTLS_LMOTS_SHA256_N32_W8 )
663 {
664 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
665 }
666
667 if( ctx->MBEDTLS_PRIVATE(have_privkey) )
668 {
669 return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
670 }
671
672 f_rng( p_rng, ctx->MBEDTLS_PRIVATE(I_key_identifier),
673 sizeof( ctx->MBEDTLS_PRIVATE(I_key_identifier) ) );
674
675 ctx->MBEDTLS_PRIVATE(priv_keys) = mbedtls_calloc( MERKLE_TREE_LEAF_AM,
676 sizeof( mbedtls_lmots_context));
677 if( ctx->MBEDTLS_PRIVATE(priv_keys) == NULL )
678 {
679 ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
680 goto out;
681 }
682
683 for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ )
684 {
685 mbedtls_lmots_init( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx] );
686 ret = mbedtls_lmots_set_algorithm_type( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx],
687 ctx->MBEDTLS_PRIVATE(otstype) );
688 if( ret)
689 {
690 goto out;
691 }
692 }
693
694
695 for( idx = 0; idx < MERKLE_TREE_LEAF_AM; idx++ )
696 {
697 ret = mbedtls_lmots_gen_privkey( &ctx->MBEDTLS_PRIVATE(priv_keys)[idx],
698 ctx->MBEDTLS_PRIVATE(I_key_identifier),
699 idx, seed, seed_len );
700 if( ret)
701 {
702 goto out;
703 }
704 }
705
706 ctx->MBEDTLS_PRIVATE(q_next_usable_key) = 0;
707 ctx->MBEDTLS_PRIVATE(have_privkey) = 1;
708
709out:
710 if( ret )
711 {
712 mbedtls_free( ctx->MBEDTLS_PRIVATE(priv_keys) );
713 return( ret );
714 }
715
716 return( 0 );
717}
718
719#endif /* MBEDTLS_LMS_C */