LCOV - code coverage report
Current view: top level - os_stub/mbedtlslib/mbedtls/library - pk_ecc.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 66.7 % 21 14
Test Date: 2025-06-29 08:09:00 Functions: 75.0 % 4 3

            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        11650 : 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        11650 :     mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);
      36              : 
      37              :     /* grp may already be initialized; if so, make sure IDs match */
      38        11650 :     if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&
      39            0 :         mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {
      40            0 :         return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
      41              :     }
      42              : 
      43              :     /* set group */
      44        11650 :     return mbedtls_ecp_group_load(&(ecp->grp), grp_id);
      45              : #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
      46              : }
      47              : 
      48          145 : 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          145 :     mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);
      76          145 :     int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);
      77          145 :     if (ret != 0) {
      78            0 :         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
      79              :     }
      80          145 :     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              :     (void) prv;
     137              :     (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        11650 : 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              :     int ret;
     245        11650 :     mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;
     246        11650 :     ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len);
     247        11650 :     if (ret != 0) {
     248            0 :         return ret;
     249              :     }
     250        11650 :     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