quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ecdh.c (21644B)


      1 /*
      2  *  Elliptic curve Diffie-Hellman
      3  *
      4  *  Copyright The Mbed TLS Contributors
      5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      6  */
      7 
      8 /*
      9  * References:
     10  *
     11  * SEC1 https://www.secg.org/sec1-v2.pdf
     12  * RFC 4492
     13  */
     14 
     15 #include "common.h"
     16 
     17 #if defined(MBEDTLS_ECDH_C)
     18 
     19 #include "mbedtls/ecdh.h"
     20 #include "mbedtls/platform_util.h"
     21 #include "mbedtls/error.h"
     22 
     23 #include <string.h>
     24 
     25 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
     26 typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
     27 #endif
     28 
     29 static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
     30     const mbedtls_ecdh_context *ctx)
     31 {
     32 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
     33     return ctx->grp.id;
     34 #else
     35     return ctx->grp_id;
     36 #endif
     37 }
     38 
     39 int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
     40 {
     41     /* At this time, all groups support ECDH. */
     42     (void) gid;
     43     return 1;
     44 }
     45 
     46 #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
     47 /*
     48  * Generate public key (restartable version)
     49  *
     50  * Note: this internal function relies on its caller preserving the value of
     51  * the output parameter 'd' across continuation calls. This would not be
     52  * acceptable for a public function but is OK here as we control call sites.
     53  */
     54 static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
     55                                        mbedtls_mpi *d, mbedtls_ecp_point *Q,
     56                                        int (*f_rng)(void *, unsigned char *, size_t),
     57                                        void *p_rng,
     58                                        mbedtls_ecp_restart_ctx *rs_ctx)
     59 {
     60     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     61 
     62     int restarting = 0;
     63 #if defined(MBEDTLS_ECP_RESTARTABLE)
     64     restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
     65 #endif
     66     /* If multiplication is in progress, we already generated a privkey */
     67     if (!restarting) {
     68         MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
     69     }
     70 
     71     MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
     72                                                 f_rng, p_rng, rs_ctx));
     73 
     74 cleanup:
     75     return ret;
     76 }
     77 
     78 /*
     79  * Generate public key
     80  */
     81 int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
     82                             int (*f_rng)(void *, unsigned char *, size_t),
     83                             void *p_rng)
     84 {
     85     return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
     86 }
     87 #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
     88 
     89 #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
     90 /*
     91  * Compute shared secret (SEC1 3.3.1)
     92  */
     93 static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
     94                                            mbedtls_mpi *z,
     95                                            const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
     96                                            int (*f_rng)(void *, unsigned char *, size_t),
     97                                            void *p_rng,
     98                                            mbedtls_ecp_restart_ctx *rs_ctx)
     99 {
    100     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    101     mbedtls_ecp_point P;
    102 
    103     mbedtls_ecp_point_init(&P);
    104 
    105     MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
    106                                                 f_rng, p_rng, rs_ctx));
    107 
    108     if (mbedtls_ecp_is_zero(&P)) {
    109         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    110         goto cleanup;
    111     }
    112 
    113     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
    114 
    115 cleanup:
    116     mbedtls_ecp_point_free(&P);
    117 
    118     return ret;
    119 }
    120 
    121 /*
    122  * Compute shared secret (SEC1 3.3.1)
    123  */
    124 int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
    125                                 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
    126                                 int (*f_rng)(void *, unsigned char *, size_t),
    127                                 void *p_rng)
    128 {
    129     return ecdh_compute_shared_restartable(grp, z, Q, d,
    130                                            f_rng, p_rng, NULL);
    131 }
    132 #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
    133 
    134 static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
    135 {
    136     mbedtls_ecp_group_init(&ctx->grp);
    137     mbedtls_mpi_init(&ctx->d);
    138     mbedtls_ecp_point_init(&ctx->Q);
    139     mbedtls_ecp_point_init(&ctx->Qp);
    140     mbedtls_mpi_init(&ctx->z);
    141 
    142 #if defined(MBEDTLS_ECP_RESTARTABLE)
    143     mbedtls_ecp_restart_init(&ctx->rs);
    144 #endif
    145 }
    146 
    147 mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
    148 {
    149 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    150     return ctx->MBEDTLS_PRIVATE(grp).id;
    151 #else
    152     return ctx->MBEDTLS_PRIVATE(grp_id);
    153 #endif
    154 }
    155 
    156 /*
    157  * Initialize context
    158  */
    159 void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
    160 {
    161 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    162     ecdh_init_internal(ctx);
    163     mbedtls_ecp_point_init(&ctx->Vi);
    164     mbedtls_ecp_point_init(&ctx->Vf);
    165     mbedtls_mpi_init(&ctx->_d);
    166 #else
    167     memset(ctx, 0, sizeof(mbedtls_ecdh_context));
    168 
    169     ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
    170 #endif
    171     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
    172 #if defined(MBEDTLS_ECP_RESTARTABLE)
    173     ctx->restart_enabled = 0;
    174 #endif
    175 }
    176 
    177 static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
    178                                mbedtls_ecp_group_id grp_id)
    179 {
    180     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    181 
    182     ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
    183     if (ret != 0) {
    184         return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
    185     }
    186 
    187     return 0;
    188 }
    189 
    190 /*
    191  * Setup context
    192  */
    193 int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
    194 {
    195 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    196     return ecdh_setup_internal(ctx, grp_id);
    197 #else
    198     switch (grp_id) {
    199 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
    200         case MBEDTLS_ECP_DP_CURVE25519:
    201             ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
    202             ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
    203             ctx->grp_id = grp_id;
    204             return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
    205 #endif
    206         default:
    207             ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
    208             ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
    209             ctx->grp_id = grp_id;
    210             ecdh_init_internal(&ctx->ctx.mbed_ecdh);
    211             return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
    212     }
    213 #endif
    214 }
    215 
    216 static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
    217 {
    218     mbedtls_ecp_group_free(&ctx->grp);
    219     mbedtls_mpi_free(&ctx->d);
    220     mbedtls_ecp_point_free(&ctx->Q);
    221     mbedtls_ecp_point_free(&ctx->Qp);
    222     mbedtls_mpi_free(&ctx->z);
    223 
    224 #if defined(MBEDTLS_ECP_RESTARTABLE)
    225     mbedtls_ecp_restart_free(&ctx->rs);
    226 #endif
    227 }
    228 
    229 #if defined(MBEDTLS_ECP_RESTARTABLE)
    230 /*
    231  * Enable restartable operations for context
    232  */
    233 void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
    234 {
    235     ctx->restart_enabled = 1;
    236 }
    237 #endif
    238 
    239 /*
    240  * Free context
    241  */
    242 void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
    243 {
    244     if (ctx == NULL) {
    245         return;
    246     }
    247 
    248 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    249     mbedtls_ecp_point_free(&ctx->Vi);
    250     mbedtls_ecp_point_free(&ctx->Vf);
    251     mbedtls_mpi_free(&ctx->_d);
    252     ecdh_free_internal(ctx);
    253 #else
    254     switch (ctx->var) {
    255 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
    256         case MBEDTLS_ECDH_VARIANT_EVEREST:
    257             mbedtls_everest_free(&ctx->ctx.everest_ecdh);
    258             break;
    259 #endif
    260         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
    261             ecdh_free_internal(&ctx->ctx.mbed_ecdh);
    262             break;
    263         default:
    264             break;
    265     }
    266 
    267     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
    268     ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
    269     ctx->grp_id = MBEDTLS_ECP_DP_NONE;
    270 #endif
    271 }
    272 
    273 static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
    274                                      size_t *olen, int point_format,
    275                                      unsigned char *buf, size_t blen,
    276                                      int (*f_rng)(void *,
    277                                                   unsigned char *,
    278                                                   size_t),
    279                                      void *p_rng,
    280                                      int restart_enabled)
    281 {
    282     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    283     size_t grp_len, pt_len;
    284 #if defined(MBEDTLS_ECP_RESTARTABLE)
    285     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
    286 #endif
    287 
    288     if (ctx->grp.pbits == 0) {
    289         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    290     }
    291 
    292 #if defined(MBEDTLS_ECP_RESTARTABLE)
    293     if (restart_enabled) {
    294         rs_ctx = &ctx->rs;
    295     }
    296 #else
    297     (void) restart_enabled;
    298 #endif
    299 
    300 
    301 #if defined(MBEDTLS_ECP_RESTARTABLE)
    302     if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
    303                                            f_rng, p_rng, rs_ctx)) != 0) {
    304         return ret;
    305     }
    306 #else
    307     if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
    308                                        f_rng, p_rng)) != 0) {
    309         return ret;
    310     }
    311 #endif /* MBEDTLS_ECP_RESTARTABLE */
    312 
    313     if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
    314                                            blen)) != 0) {
    315         return ret;
    316     }
    317 
    318     buf += grp_len;
    319     blen -= grp_len;
    320 
    321     if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
    322                                            &pt_len, buf, blen)) != 0) {
    323         return ret;
    324     }
    325 
    326     *olen = grp_len + pt_len;
    327     return 0;
    328 }
    329 
    330 /*
    331  * Setup and write the ServerKeyExchange parameters (RFC 4492)
    332  *      struct {
    333  *          ECParameters    curve_params;
    334  *          ECPoint         public;
    335  *      } ServerECDHParams;
    336  */
    337 int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
    338                              unsigned char *buf, size_t blen,
    339                              int (*f_rng)(void *, unsigned char *, size_t),
    340                              void *p_rng)
    341 {
    342     int restart_enabled = 0;
    343 #if defined(MBEDTLS_ECP_RESTARTABLE)
    344     restart_enabled = ctx->restart_enabled;
    345 #else
    346     (void) restart_enabled;
    347 #endif
    348 
    349 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    350     return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
    351                                      f_rng, p_rng, restart_enabled);
    352 #else
    353     switch (ctx->var) {
    354 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
    355         case MBEDTLS_ECDH_VARIANT_EVEREST:
    356             return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
    357                                                buf, blen, f_rng, p_rng);
    358 #endif
    359         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
    360             return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
    361                                              ctx->point_format, buf, blen,
    362                                              f_rng, p_rng,
    363                                              restart_enabled);
    364         default:
    365             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    366     }
    367 #endif
    368 }
    369 
    370 static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
    371                                      const unsigned char **buf,
    372                                      const unsigned char *end)
    373 {
    374     return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
    375                                       (size_t) (end - *buf));
    376 }
    377 
    378 /*
    379  * Read the ServerKeyExchange parameters (RFC 4492)
    380  *      struct {
    381  *          ECParameters    curve_params;
    382  *          ECPoint         public;
    383  *      } ServerECDHParams;
    384  */
    385 int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
    386                              const unsigned char **buf,
    387                              const unsigned char *end)
    388 {
    389     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    390     mbedtls_ecp_group_id grp_id;
    391     if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
    392         != 0) {
    393         return ret;
    394     }
    395 
    396     if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
    397         return ret;
    398     }
    399 
    400 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    401     return ecdh_read_params_internal(ctx, buf, end);
    402 #else
    403     switch (ctx->var) {
    404 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
    405         case MBEDTLS_ECDH_VARIANT_EVEREST:
    406             return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
    407                                                buf, end);
    408 #endif
    409         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
    410             return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
    411                                              buf, end);
    412         default:
    413             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    414     }
    415 #endif
    416 }
    417 
    418 static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
    419                                     const mbedtls_ecp_keypair *key,
    420                                     mbedtls_ecdh_side side)
    421 {
    422     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    423 
    424     /* If it's not our key, just import the public part as Qp */
    425     if (side == MBEDTLS_ECDH_THEIRS) {
    426         return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
    427     }
    428 
    429     /* Our key: import public (as Q) and private parts */
    430     if (side != MBEDTLS_ECDH_OURS) {
    431         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    432     }
    433 
    434     if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
    435         (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
    436         return ret;
    437     }
    438 
    439     return 0;
    440 }
    441 
    442 /*
    443  * Get parameters from a keypair
    444  */
    445 int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
    446                             const mbedtls_ecp_keypair *key,
    447                             mbedtls_ecdh_side side)
    448 {
    449     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    450     if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
    451         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    452     }
    453 
    454     if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
    455         /* This is the first call to get_params(). Set up the context
    456          * for use with the group. */
    457         if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
    458             return ret;
    459         }
    460     } else {
    461         /* This is not the first call to get_params(). Check that the
    462          * current key's group is the same as the context's, which was set
    463          * from the first key's group. */
    464         if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
    465             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    466         }
    467     }
    468 
    469 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    470     return ecdh_get_params_internal(ctx, key, side);
    471 #else
    472     switch (ctx->var) {
    473 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
    474         case MBEDTLS_ECDH_VARIANT_EVEREST:
    475         {
    476             mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
    477                                           MBEDTLS_EVEREST_ECDH_OURS :
    478                                           MBEDTLS_EVEREST_ECDH_THEIRS;
    479             return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
    480                                               key, s);
    481         }
    482 #endif
    483         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
    484             return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
    485                                             key, side);
    486         default:
    487             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    488     }
    489 #endif
    490 }
    491 
    492 static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
    493                                      size_t *olen, int point_format,
    494                                      unsigned char *buf, size_t blen,
    495                                      int (*f_rng)(void *,
    496                                                   unsigned char *,
    497                                                   size_t),
    498                                      void *p_rng,
    499                                      int restart_enabled)
    500 {
    501     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    502 #if defined(MBEDTLS_ECP_RESTARTABLE)
    503     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
    504 #endif
    505 
    506     if (ctx->grp.pbits == 0) {
    507         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    508     }
    509 
    510 #if defined(MBEDTLS_ECP_RESTARTABLE)
    511     if (restart_enabled) {
    512         rs_ctx = &ctx->rs;
    513     }
    514 #else
    515     (void) restart_enabled;
    516 #endif
    517 
    518 #if defined(MBEDTLS_ECP_RESTARTABLE)
    519     if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
    520                                            f_rng, p_rng, rs_ctx)) != 0) {
    521         return ret;
    522     }
    523 #else
    524     if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
    525                                        f_rng, p_rng)) != 0) {
    526         return ret;
    527     }
    528 #endif /* MBEDTLS_ECP_RESTARTABLE */
    529 
    530     return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
    531                                        buf, blen);
    532 }
    533 
    534 /*
    535  * Setup and export the client public value
    536  */
    537 int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
    538                              unsigned char *buf, size_t blen,
    539                              int (*f_rng)(void *, unsigned char *, size_t),
    540                              void *p_rng)
    541 {
    542     int restart_enabled = 0;
    543 #if defined(MBEDTLS_ECP_RESTARTABLE)
    544     restart_enabled = ctx->restart_enabled;
    545 #endif
    546 
    547 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    548     return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
    549                                      f_rng, p_rng, restart_enabled);
    550 #else
    551     switch (ctx->var) {
    552 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
    553         case MBEDTLS_ECDH_VARIANT_EVEREST:
    554             return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
    555                                                buf, blen, f_rng, p_rng);
    556 #endif
    557         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
    558             return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
    559                                              ctx->point_format, buf, blen,
    560                                              f_rng, p_rng,
    561                                              restart_enabled);
    562         default:
    563             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    564     }
    565 #endif
    566 }
    567 
    568 static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
    569                                      const unsigned char *buf, size_t blen)
    570 {
    571     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    572     const unsigned char *p = buf;
    573 
    574     if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
    575                                           blen)) != 0) {
    576         return ret;
    577     }
    578 
    579     if ((size_t) (p - buf) != blen) {
    580         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    581     }
    582 
    583     return 0;
    584 }
    585 
    586 /*
    587  * Parse and import the client's public value
    588  */
    589 int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
    590                              const unsigned char *buf, size_t blen)
    591 {
    592 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    593     return ecdh_read_public_internal(ctx, buf, blen);
    594 #else
    595     switch (ctx->var) {
    596 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
    597         case MBEDTLS_ECDH_VARIANT_EVEREST:
    598             return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
    599                                                buf, blen);
    600 #endif
    601         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
    602             return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
    603                                              buf, blen);
    604         default:
    605             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    606     }
    607 #endif
    608 }
    609 
    610 static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
    611                                      size_t *olen, unsigned char *buf,
    612                                      size_t blen,
    613                                      int (*f_rng)(void *,
    614                                                   unsigned char *,
    615                                                   size_t),
    616                                      void *p_rng,
    617                                      int restart_enabled)
    618 {
    619     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    620 #if defined(MBEDTLS_ECP_RESTARTABLE)
    621     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
    622 #endif
    623 
    624     if (ctx == NULL || ctx->grp.pbits == 0) {
    625         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    626     }
    627 
    628 #if defined(MBEDTLS_ECP_RESTARTABLE)
    629     if (restart_enabled) {
    630         rs_ctx = &ctx->rs;
    631     }
    632 #else
    633     (void) restart_enabled;
    634 #endif
    635 
    636 #if defined(MBEDTLS_ECP_RESTARTABLE)
    637     if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
    638                                                &ctx->d, f_rng, p_rng,
    639                                                rs_ctx)) != 0) {
    640         return ret;
    641     }
    642 #else
    643     if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
    644                                            &ctx->d, f_rng, p_rng)) != 0) {
    645         return ret;
    646     }
    647 #endif /* MBEDTLS_ECP_RESTARTABLE */
    648 
    649     if (mbedtls_mpi_size(&ctx->z) > blen) {
    650         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    651     }
    652 
    653     *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
    654 
    655     if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
    656         return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
    657     }
    658 
    659     return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
    660 }
    661 
    662 /*
    663  * Derive and export the shared secret
    664  */
    665 int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
    666                              unsigned char *buf, size_t blen,
    667                              int (*f_rng)(void *, unsigned char *, size_t),
    668                              void *p_rng)
    669 {
    670     int restart_enabled = 0;
    671 #if defined(MBEDTLS_ECP_RESTARTABLE)
    672     restart_enabled = ctx->restart_enabled;
    673 #endif
    674 
    675 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
    676     return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
    677                                      restart_enabled);
    678 #else
    679     switch (ctx->var) {
    680 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
    681         case MBEDTLS_ECDH_VARIANT_EVEREST:
    682             return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
    683                                                buf, blen, f_rng, p_rng);
    684 #endif
    685         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
    686             return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
    687                                              blen, f_rng, p_rng,
    688                                              restart_enabled);
    689         default:
    690             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    691     }
    692 #endif
    693 }
    694 #endif /* MBEDTLS_ECDH_C */