LCOV - code coverage report
Current view: top level - externals/mbedtls/library - pk_ecc.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 47.6 % 21 10
Test Date: 2026-01-29 09:48:10 Functions: 50.0 % 4 2
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 25.0 % 8 2

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  *  ECC setters for PK.
       3                 :             :  *
       4                 :             :  *  Copyright The Mbed TLS Contributors
       5                 :             :  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       6                 :             :  */
       7                 :             : 
       8                 :             : #include "common.h"
       9                 :             : 
      10                 :             : #include "mbedtls/pk.h"
      11                 :             : #include "mbedtls/error.h"
      12                 :             : #include "mbedtls/ecp.h"
      13                 :             : #include "pk_internal.h"
      14                 :             : 
      15                 :             : #if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS)
      16                 :             : 
      17                 :           4 : int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
      18                 :             : {
      19                 :             : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
      20                 :             :     size_t ec_bits;
      21                 :             :     psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits);
      22                 :             : 
      23                 :             :     /* group may already be initialized; if so, make sure IDs match */
      24                 :             :     if ((pk->ec_family != 0 && pk->ec_family != ec_family) ||
      25                 :             :         (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) {
      26                 :             :         return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
      27                 :             :     }
      28                 :             : 
      29                 :             :     /* set group */
      30                 :             :     pk->ec_family = ec_family;
      31                 :             :     pk->ec_bits = ec_bits;
      32                 :             : 
      33                 :             :     return 0;
      34                 :             : #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
      35                 :           4 :     mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);
      36                 :             : 
      37                 :             :     /* grp may already be initialized; if so, make sure IDs match */
      38         [ -  + ]:           4 :     if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&
      39         [ #  # ]:           0 :         mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {
      40                 :             :         return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
      41                 :             :     }
      42                 :             : 
      43                 :             :     /* set group */
      44                 :           4 :     return mbedtls_ecp_group_load(&(ecp->grp), grp_id);
      45                 :             : #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
      46                 :             : }
      47                 :             : 
      48                 :           0 : int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len)
      49                 :             : {
      50                 :             : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
      51                 :             :     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
      52                 :             :     psa_key_usage_t flags;
      53                 :             :     psa_status_t status;
      54                 :             : 
      55                 :             :     psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family));
      56                 :             :     if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) {
      57                 :             :         /* Do not set algorithm here because Montgomery keys cannot do ECDSA and
      58                 :             :          * the PK module cannot do ECDH. When the key will be used in TLS for
      59                 :             :          * ECDH, it will be exported and then re-imported with proper flags
      60                 :             :          * and algorithm. */
      61                 :             :         flags = PSA_KEY_USAGE_EXPORT;
      62                 :             :     } else {
      63                 :             :         psa_set_key_algorithm(&attributes,
      64                 :             :                               MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH));
      65                 :             :         flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE |
      66                 :             :                 PSA_KEY_USAGE_EXPORT;
      67                 :             :     }
      68                 :             :     psa_set_key_usage_flags(&attributes, flags);
      69                 :             : 
      70                 :             :     status = psa_import_key(&attributes, key, key_len, &pk->priv_id);
      71                 :             :     return psa_pk_status_to_mbedtls(status);
      72                 :             : 
      73                 :             : #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
      74                 :             : 
      75                 :           0 :     mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);
      76                 :           0 :     int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);
      77         [ #  # ]:           0 :     if (ret != 0) {
      78                 :           0 :         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
      79                 :             :     }
      80                 :             :     return 0;
      81                 :             : #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
      82                 :             : }
      83                 :             : 
      84                 :           0 : int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
      85                 :             :                                        const unsigned char *prv, size_t prv_len,
      86                 :             :                                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
      87                 :             : {
      88                 :             : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
      89                 :             : 
      90                 :             :     (void) f_rng;
      91                 :             :     (void) p_rng;
      92                 :             :     (void) prv;
      93                 :             :     (void) prv_len;
      94                 :             :     psa_status_t status;
      95                 :             : 
      96                 :             :     status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
      97                 :             :                                    &pk->pub_raw_len);
      98                 :             :     return psa_pk_status_to_mbedtls(status);
      99                 :             : 
     100                 :             : #elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */
     101                 :             : 
     102                 :             :     (void) f_rng;
     103                 :             :     (void) p_rng;
     104                 :             :     psa_status_t status;
     105                 :             : 
     106                 :             :     mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
     107                 :             :     size_t curve_bits;
     108                 :             :     psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);
     109                 :             : 
     110                 :             :     /* Import private key into PSA, from serialized input */
     111                 :             :     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     112                 :             :     psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
     113                 :             :     psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
     114                 :             :     psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
     115                 :             :     status = psa_import_key(&key_attr, prv, prv_len, &key_id);
     116                 :             :     if (status != PSA_SUCCESS) {
     117                 :             :         return psa_pk_status_to_mbedtls(status);
     118                 :             :     }
     119                 :             : 
     120                 :             :     /* Export public key from PSA */
     121                 :             :     unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
     122                 :             :     size_t pub_len;
     123                 :             :     status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len);
     124                 :             :     psa_status_t destruction_status = psa_destroy_key(key_id);
     125                 :             :     if (status != PSA_SUCCESS) {
     126                 :             :         return psa_pk_status_to_mbedtls(status);
     127                 :             :     } else if (destruction_status != PSA_SUCCESS) {
     128                 :             :         return psa_pk_status_to_mbedtls(destruction_status);
     129                 :             :     }
     130                 :             : 
     131                 :             :     /* Load serialized public key into ecp_keypair structure */
     132                 :             :     return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len);
     133                 :             : 
     134                 :             : #else /* MBEDTLS_USE_PSA_CRYPTO */
     135                 :             : 
     136                 :           0 :     (void) prv;
     137                 :           0 :     (void) prv_len;
     138                 :             : 
     139                 :           0 :     mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
     140                 :           0 :     return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);
     141                 :             : 
     142                 :             : #endif /* MBEDTLS_USE_PSA_CRYPTO */
     143                 :             : }
     144                 :             : 
     145                 :             : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
     146                 :             : /*
     147                 :             :  * Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case.
     148                 :             :  *
     149                 :             :  * Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA
     150                 :             :  * functions to handle keys. However, currently psa_import_key() does not
     151                 :             :  * support compressed points. In case that support was explicitly requested,
     152                 :             :  * this fallback uses ECP functions to get the job done. This is the reason
     153                 :             :  * why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT.
     154                 :             :  *
     155                 :             :  * [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group().
     156                 :             :  *              out: will have the public key set.
     157                 :             :  * [in] pub, pub_len: the public key as an ECPoint,
     158                 :             :  *                    in any format supported by ECP.
     159                 :             :  *
     160                 :             :  * Return:
     161                 :             :  * - 0 on success;
     162                 :             :  * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
     163                 :             :  *   but not supported;
     164                 :             :  * - another error code otherwise.
     165                 :             :  */
     166                 :             : static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk,
     167                 :             :                                               const unsigned char *pub,
     168                 :             :                                               size_t pub_len)
     169                 :             : {
     170                 :             : #if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)
     171                 :             :     (void) pk;
     172                 :             :     (void) pub;
     173                 :             :     (void) pub_len;
     174                 :             :     return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
     175                 :             : #else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
     176                 :             :     mbedtls_ecp_keypair ecp_key;
     177                 :             :     mbedtls_ecp_group_id ecp_group_id;
     178                 :             :     int ret;
     179                 :             : 
     180                 :             :     ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);
     181                 :             : 
     182                 :             :     mbedtls_ecp_keypair_init(&ecp_key);
     183                 :             :     ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id);
     184                 :             :     if (ret != 0) {
     185                 :             :         goto exit;
     186                 :             :     }
     187                 :             :     ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q,
     188                 :             :                                         pub, pub_len);
     189                 :             :     if (ret != 0) {
     190                 :             :         goto exit;
     191                 :             :     }
     192                 :             :     ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q,
     193                 :             :                                          MBEDTLS_ECP_PF_UNCOMPRESSED,
     194                 :             :                                          &pk->pub_raw_len, pk->pub_raw,
     195                 :             :                                          sizeof(pk->pub_raw));
     196                 :             : 
     197                 :             : exit:
     198                 :             :     mbedtls_ecp_keypair_free(&ecp_key);
     199                 :             :     return ret;
     200                 :             : #endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
     201                 :             : }
     202                 :             : #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
     203                 :             : 
     204                 :           4 : int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len)
     205                 :             : {
     206                 :             : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
     207                 :             : 
     208                 :             :     /* Load the key */
     209                 :             :     if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) {
     210                 :             :         /* Format directly supported by PSA:
     211                 :             :          * - non-Weierstrass curves that only have one format;
     212                 :             :          * - uncompressed format for Weierstrass curves. */
     213                 :             :         if (pub_len > sizeof(pk->pub_raw)) {
     214                 :             :             return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
     215                 :             :         }
     216                 :             :         memcpy(pk->pub_raw, pub, pub_len);
     217                 :             :         pk->pub_raw_len = pub_len;
     218                 :             :     } else {
     219                 :             :         /* Other format, try the fallback */
     220                 :             :         int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len);
     221                 :             :         if (ret != 0) {
     222                 :             :             return ret;
     223                 :             :         }
     224                 :             :     }
     225                 :             : 
     226                 :             :     /* Validate the key by trying to import it */
     227                 :             :     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     228                 :             :     psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
     229                 :             : 
     230                 :             :     psa_set_key_usage_flags(&key_attrs, 0);
     231                 :             :     psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family));
     232                 :             :     psa_set_key_bits(&key_attrs, pk->ec_bits);
     233                 :             : 
     234                 :             :     if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len,
     235                 :             :                         &key_id) != PSA_SUCCESS) ||
     236                 :             :         (psa_destroy_key(key_id) != PSA_SUCCESS)) {
     237                 :             :         return MBEDTLS_ERR_PK_INVALID_PUBKEY;
     238                 :             :     }
     239                 :             : 
     240                 :             :     return 0;
     241                 :             : 
     242                 :             : #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
     243                 :             : 
     244                 :           4 :     int ret;
     245                 :           4 :     mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;
     246                 :           4 :     ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len);
     247         [ +  - ]:           4 :     if (ret != 0) {
     248                 :             :         return ret;
     249                 :             :     }
     250                 :           4 :     return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q);
     251                 :             : 
     252                 :             : #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
     253                 :             : }
     254                 :             : 
     255                 :             : #endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */
        

Generated by: LCOV version 2.0-1