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