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