Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  Public Key abstraction layer
  3.  *
  4.  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
  5.  *  SPDX-License-Identifier: GPL-2.0
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License along
  18.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  19.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  *  This file is part of mbed TLS (https://tls.mbed.org)
  22.  */
  23.  
  24. #if !defined(MBEDTLS_CONFIG_FILE)
  25. #include "mbedtls/config.h"
  26. #else
  27. #include MBEDTLS_CONFIG_FILE
  28. #endif
  29.  
  30. #if defined(MBEDTLS_PK_C)
  31. #include "mbedtls/pk.h"
  32. #include "mbedtls/pk_internal.h"
  33.  
  34. #include "mbedtls/platform_util.h"
  35.  
  36. #if defined(MBEDTLS_RSA_C)
  37. #include "mbedtls/rsa.h"
  38. #endif
  39. #if defined(MBEDTLS_ECP_C)
  40. #include "mbedtls/ecp.h"
  41. #endif
  42. #if defined(MBEDTLS_ECDSA_C)
  43. #include "mbedtls/ecdsa.h"
  44. #endif
  45.  
  46. #include <limits.h>
  47. #include <stdint.h>
  48.  
  49. /* Parameter validation macros based on platform_util.h */
  50. #define PK_VALIDATE_RET( cond )    \
  51.     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
  52. #define PK_VALIDATE( cond )        \
  53.     MBEDTLS_INTERNAL_VALIDATE( cond )
  54.  
  55. /*
  56.  * Initialise a mbedtls_pk_context
  57.  */
  58. void mbedtls_pk_init( mbedtls_pk_context *ctx )
  59. {
  60.     PK_VALIDATE( ctx != NULL );
  61.  
  62.     ctx->pk_info = NULL;
  63.     ctx->pk_ctx = NULL;
  64. }
  65.  
  66. /*
  67.  * Free (the components of) a mbedtls_pk_context
  68.  */
  69. void mbedtls_pk_free( mbedtls_pk_context *ctx )
  70. {
  71.     if( ctx == NULL )
  72.         return;
  73.  
  74.     if ( ctx->pk_info != NULL )
  75.         ctx->pk_info->ctx_free_func( ctx->pk_ctx );
  76.  
  77.     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
  78. }
  79.  
  80. #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
  81. /*
  82.  * Initialize a restart context
  83.  */
  84. void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
  85. {
  86.     PK_VALIDATE( ctx != NULL );
  87.     ctx->pk_info = NULL;
  88.     ctx->rs_ctx = NULL;
  89. }
  90.  
  91. /*
  92.  * Free the components of a restart context
  93.  */
  94. void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
  95. {
  96.     if( ctx == NULL || ctx->pk_info == NULL ||
  97.         ctx->pk_info->rs_free_func == NULL )
  98.     {
  99.         return;
  100.     }
  101.  
  102.     ctx->pk_info->rs_free_func( ctx->rs_ctx );
  103.  
  104.     ctx->pk_info = NULL;
  105.     ctx->rs_ctx = NULL;
  106. }
  107. #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
  108.  
  109. /*
  110.  * Get pk_info structure from type
  111.  */
  112. const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type )
  113. {
  114.     switch( pk_type ) {
  115. #if defined(MBEDTLS_RSA_C)
  116.         case MBEDTLS_PK_RSA:
  117.             return( &mbedtls_rsa_info );
  118. #endif
  119. #if defined(MBEDTLS_ECP_C)
  120.         case MBEDTLS_PK_ECKEY:
  121.             return( &mbedtls_eckey_info );
  122.         case MBEDTLS_PK_ECKEY_DH:
  123.             return( &mbedtls_eckeydh_info );
  124. #endif
  125. #if defined(MBEDTLS_ECDSA_C)
  126.         case MBEDTLS_PK_ECDSA:
  127.             return( &mbedtls_ecdsa_info );
  128. #endif
  129.         /* MBEDTLS_PK_RSA_ALT omitted on purpose */
  130.         default:
  131.             return( NULL );
  132.     }
  133. }
  134.  
  135. /*
  136.  * Initialise context
  137.  */
  138. int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info )
  139. {
  140.     PK_VALIDATE_RET( ctx != NULL );
  141.     if( info == NULL || ctx->pk_info != NULL )
  142.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  143.  
  144.     if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
  145.         return( MBEDTLS_ERR_PK_ALLOC_FAILED );
  146.  
  147.     ctx->pk_info = info;
  148.  
  149.     return( 0 );
  150. }
  151.  
  152. #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
  153. /*
  154.  * Initialize an RSA-alt context
  155.  */
  156. int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key,
  157.                          mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
  158.                          mbedtls_pk_rsa_alt_sign_func sign_func,
  159.                          mbedtls_pk_rsa_alt_key_len_func key_len_func )
  160. {
  161.     mbedtls_rsa_alt_context *rsa_alt;
  162.     const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info;
  163.  
  164.     PK_VALIDATE_RET( ctx != NULL );
  165.     if( ctx->pk_info != NULL )
  166.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  167.  
  168.     if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
  169.         return( MBEDTLS_ERR_PK_ALLOC_FAILED );
  170.  
  171.     ctx->pk_info = info;
  172.  
  173.     rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx;
  174.  
  175.     rsa_alt->key = key;
  176.     rsa_alt->decrypt_func = decrypt_func;
  177.     rsa_alt->sign_func = sign_func;
  178.     rsa_alt->key_len_func = key_len_func;
  179.  
  180.     return( 0 );
  181. }
  182. #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
  183.  
  184. /*
  185.  * Tell if a PK can do the operations of the given type
  186.  */
  187. int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type )
  188. {
  189.     /* A context with null pk_info is not set up yet and can't do anything.
  190.      * For backward compatibility, also accept NULL instead of a context
  191.      * pointer. */
  192.     if( ctx == NULL || ctx->pk_info == NULL )
  193.         return( 0 );
  194.  
  195.     return( ctx->pk_info->can_do( type ) );
  196. }
  197.  
  198. /*
  199.  * Helper for mbedtls_pk_sign and mbedtls_pk_verify
  200.  */
  201. static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len )
  202. {
  203.     const mbedtls_md_info_t *md_info;
  204.  
  205.     if( *hash_len != 0 )
  206.         return( 0 );
  207.  
  208.     if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
  209.         return( -1 );
  210.  
  211.     *hash_len = mbedtls_md_get_size( md_info );
  212.     return( 0 );
  213. }
  214.  
  215. #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
  216. /*
  217.  * Helper to set up a restart context if needed
  218.  */
  219. static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
  220.                              const mbedtls_pk_info_t *info )
  221. {
  222.     /* Don't do anything if already set up or invalid */
  223.     if( ctx == NULL || ctx->pk_info != NULL )
  224.         return( 0 );
  225.  
  226.     /* Should never happen when we're called */
  227.     if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
  228.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  229.  
  230.     if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
  231.         return( MBEDTLS_ERR_PK_ALLOC_FAILED );
  232.  
  233.     ctx->pk_info = info;
  234.  
  235.     return( 0 );
  236. }
  237. #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
  238.  
  239. /*
  240.  * Verify a signature (restartable)
  241.  */
  242. int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
  243.                mbedtls_md_type_t md_alg,
  244.                const unsigned char *hash, size_t hash_len,
  245.                const unsigned char *sig, size_t sig_len,
  246.                mbedtls_pk_restart_ctx *rs_ctx )
  247. {
  248.     PK_VALIDATE_RET( ctx != NULL );
  249.     PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
  250.                      hash != NULL );
  251.     PK_VALIDATE_RET( sig != NULL );
  252.  
  253.     if( ctx->pk_info == NULL ||
  254.         pk_hashlen_helper( md_alg, &hash_len ) != 0 )
  255.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  256.  
  257. #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
  258.     /* optimization: use non-restartable version if restart disabled */
  259.     if( rs_ctx != NULL &&
  260.         mbedtls_ecp_restart_is_enabled() &&
  261.         ctx->pk_info->verify_rs_func != NULL )
  262.     {
  263.         int ret;
  264.  
  265.         if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
  266.             return( ret );
  267.  
  268.         ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
  269.                    md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
  270.  
  271.         if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
  272.             mbedtls_pk_restart_free( rs_ctx );
  273.  
  274.         return( ret );
  275.     }
  276. #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
  277.     (void) rs_ctx;
  278. #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
  279.  
  280.     if( ctx->pk_info->verify_func == NULL )
  281.         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
  282.  
  283.     return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
  284.                                        sig, sig_len ) );
  285. }
  286.  
  287. /*
  288.  * Verify a signature
  289.  */
  290. int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
  291.                const unsigned char *hash, size_t hash_len,
  292.                const unsigned char *sig, size_t sig_len )
  293. {
  294.     return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
  295.                                            sig, sig_len, NULL ) );
  296. }
  297.  
  298. /*
  299.  * Verify a signature with options
  300.  */
  301. int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
  302.                    mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
  303.                    const unsigned char *hash, size_t hash_len,
  304.                    const unsigned char *sig, size_t sig_len )
  305. {
  306.     PK_VALIDATE_RET( ctx != NULL );
  307.     PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
  308.                      hash != NULL );
  309.     PK_VALIDATE_RET( sig != NULL );
  310.  
  311.     if( ctx->pk_info == NULL )
  312.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  313.  
  314.     if( ! mbedtls_pk_can_do( ctx, type ) )
  315.         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
  316.  
  317.     if( type == MBEDTLS_PK_RSASSA_PSS )
  318.     {
  319. #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
  320.         int ret;
  321.         const mbedtls_pk_rsassa_pss_options *pss_opts;
  322.  
  323. #if SIZE_MAX > UINT_MAX
  324.         if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
  325.             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  326. #endif /* SIZE_MAX > UINT_MAX */
  327.  
  328.         if( options == NULL )
  329.             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  330.  
  331.         pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
  332.  
  333.         if( sig_len < mbedtls_pk_get_len( ctx ) )
  334.             return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
  335.  
  336.         ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ),
  337.                 NULL, NULL, MBEDTLS_RSA_PUBLIC,
  338.                 md_alg, (unsigned int) hash_len, hash,
  339.                 pss_opts->mgf1_hash_id,
  340.                 pss_opts->expected_salt_len,
  341.                 sig );
  342.         if( ret != 0 )
  343.             return( ret );
  344.  
  345.         if( sig_len > mbedtls_pk_get_len( ctx ) )
  346.             return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
  347.  
  348.         return( 0 );
  349. #else
  350.         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
  351. #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
  352.     }
  353.  
  354.     /* General case: no options */
  355.     if( options != NULL )
  356.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  357.  
  358.     return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
  359. }
  360.  
  361. /*
  362.  * Make a signature (restartable)
  363.  */
  364. int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
  365.              mbedtls_md_type_t md_alg,
  366.              const unsigned char *hash, size_t hash_len,
  367.              unsigned char *sig, size_t *sig_len,
  368.              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
  369.              mbedtls_pk_restart_ctx *rs_ctx )
  370. {
  371.     PK_VALIDATE_RET( ctx != NULL );
  372.     PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
  373.                      hash != NULL );
  374.     PK_VALIDATE_RET( sig != NULL );
  375.  
  376.     if( ctx->pk_info == NULL ||
  377.         pk_hashlen_helper( md_alg, &hash_len ) != 0 )
  378.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  379.  
  380. #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
  381.     /* optimization: use non-restartable version if restart disabled */
  382.     if( rs_ctx != NULL &&
  383.         mbedtls_ecp_restart_is_enabled() &&
  384.         ctx->pk_info->sign_rs_func != NULL )
  385.     {
  386.         int ret;
  387.  
  388.         if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
  389.             return( ret );
  390.  
  391.         ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
  392.                 hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx );
  393.  
  394.         if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
  395.             mbedtls_pk_restart_free( rs_ctx );
  396.  
  397.         return( ret );
  398.     }
  399. #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
  400.     (void) rs_ctx;
  401. #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
  402.  
  403.     if( ctx->pk_info->sign_func == NULL )
  404.         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
  405.  
  406.     return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
  407.                                      sig, sig_len, f_rng, p_rng ) );
  408. }
  409.  
  410. /*
  411.  * Make a signature
  412.  */
  413. int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
  414.              const unsigned char *hash, size_t hash_len,
  415.              unsigned char *sig, size_t *sig_len,
  416.              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
  417. {
  418.     return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
  419.                                          sig, sig_len, f_rng, p_rng, NULL ) );
  420. }
  421.  
  422. /*
  423.  * Decrypt message
  424.  */
  425. int mbedtls_pk_decrypt( mbedtls_pk_context *ctx,
  426.                 const unsigned char *input, size_t ilen,
  427.                 unsigned char *output, size_t *olen, size_t osize,
  428.                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
  429. {
  430.     PK_VALIDATE_RET( ctx != NULL );
  431.     PK_VALIDATE_RET( input != NULL || ilen == 0 );
  432.     PK_VALIDATE_RET( output != NULL || osize == 0 );
  433.     PK_VALIDATE_RET( olen != NULL );
  434.  
  435.     if( ctx->pk_info == NULL )
  436.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  437.  
  438.     if( ctx->pk_info->decrypt_func == NULL )
  439.         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
  440.  
  441.     return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
  442.                 output, olen, osize, f_rng, p_rng ) );
  443. }
  444.  
  445. /*
  446.  * Encrypt message
  447.  */
  448. int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
  449.                 const unsigned char *input, size_t ilen,
  450.                 unsigned char *output, size_t *olen, size_t osize,
  451.                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
  452. {
  453.     PK_VALIDATE_RET( ctx != NULL );
  454.     PK_VALIDATE_RET( input != NULL || ilen == 0 );
  455.     PK_VALIDATE_RET( output != NULL || osize == 0 );
  456.     PK_VALIDATE_RET( olen != NULL );
  457.  
  458.     if( ctx->pk_info == NULL )
  459.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  460.  
  461.     if( ctx->pk_info->encrypt_func == NULL )
  462.         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
  463.  
  464.     return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen,
  465.                 output, olen, osize, f_rng, p_rng ) );
  466. }
  467.  
  468. /*
  469.  * Check public-private key pair
  470.  */
  471. int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv )
  472. {
  473.     PK_VALIDATE_RET( pub != NULL );
  474.     PK_VALIDATE_RET( prv != NULL );
  475.  
  476.     if( pub->pk_info == NULL ||
  477.         prv->pk_info == NULL ||
  478.         prv->pk_info->check_pair_func == NULL )
  479.     {
  480.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  481.     }
  482.  
  483.     if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT )
  484.     {
  485.         if( pub->pk_info->type != MBEDTLS_PK_RSA )
  486.             return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
  487.     }
  488.     else
  489.     {
  490.         if( pub->pk_info != prv->pk_info )
  491.             return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
  492.     }
  493.  
  494.     return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) );
  495. }
  496.  
  497. /*
  498.  * Get key size in bits
  499.  */
  500. size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx )
  501. {
  502.     /* For backward compatibility, accept NULL or a context that
  503.      * isn't set up yet, and return a fake value that should be safe. */
  504.     if( ctx == NULL || ctx->pk_info == NULL )
  505.         return( 0 );
  506.  
  507.     return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) );
  508. }
  509.  
  510. /*
  511.  * Export debug information
  512.  */
  513. int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items )
  514. {
  515.     PK_VALIDATE_RET( ctx != NULL );
  516.     if( ctx->pk_info == NULL )
  517.         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
  518.  
  519.     if( ctx->pk_info->debug_func == NULL )
  520.         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
  521.  
  522.     ctx->pk_info->debug_func( ctx->pk_ctx, items );
  523.     return( 0 );
  524. }
  525.  
  526. /*
  527.  * Access the PK type name
  528.  */
  529. const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx )
  530. {
  531.     if( ctx == NULL || ctx->pk_info == NULL )
  532.         return( "invalid PK" );
  533.  
  534.     return( ctx->pk_info->name );
  535. }
  536.  
  537. /*
  538.  * Access the PK type
  539.  */
  540. mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx )
  541. {
  542.     if( ctx == NULL || ctx->pk_info == NULL )
  543.         return( MBEDTLS_PK_NONE );
  544.  
  545.     return( ctx->pk_info->type );
  546. }
  547.  
  548. #endif /* MBEDTLS_PK_C */
  549.