Path: blob/master/thirdparty/mbedtls/library/ecdsa.c
21648 views
/*1* Elliptic curve DSA2*3* Copyright The Mbed TLS Contributors4* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later5*/67/*8* References:9*10* SEC1 https://www.secg.org/sec1-v2.pdf11*/1213#include "common.h"1415#if defined(MBEDTLS_ECDSA_C)1617#include "mbedtls/ecdsa.h"18#include "mbedtls/asn1write.h"19#include "bignum_internal.h"2021#include <string.h>2223#if defined(MBEDTLS_ECDSA_DETERMINISTIC)24#include "mbedtls/hmac_drbg.h"25#endif2627#include "mbedtls/platform.h"2829#include "mbedtls/platform_util.h"30#include "mbedtls/error.h"3132#if defined(MBEDTLS_ECP_RESTARTABLE)3334/*35* Sub-context for ecdsa_verify()36*/37struct mbedtls_ecdsa_restart_ver {38mbedtls_mpi u1, u2; /* intermediate values */39enum { /* what to do next? */40ecdsa_ver_init = 0, /* getting started */41ecdsa_ver_muladd, /* muladd step */42} state;43};4445/*46* Init verify restart sub-context47*/48static void ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx *ctx)49{50mbedtls_mpi_init(&ctx->u1);51mbedtls_mpi_init(&ctx->u2);52ctx->state = ecdsa_ver_init;53}5455/*56* Free the components of a verify restart sub-context57*/58static void ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx *ctx)59{60if (ctx == NULL) {61return;62}6364mbedtls_mpi_free(&ctx->u1);65mbedtls_mpi_free(&ctx->u2);6667ecdsa_restart_ver_init(ctx);68}6970/*71* Sub-context for ecdsa_sign()72*/73struct mbedtls_ecdsa_restart_sig {74int sign_tries;75int key_tries;76mbedtls_mpi k; /* per-signature random */77mbedtls_mpi r; /* r value */78enum { /* what to do next? */79ecdsa_sig_init = 0, /* getting started */80ecdsa_sig_mul, /* doing ecp_mul() */81ecdsa_sig_modn, /* mod N computations */82} state;83};8485/*86* Init verify sign sub-context87*/88static void ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx *ctx)89{90ctx->sign_tries = 0;91ctx->key_tries = 0;92mbedtls_mpi_init(&ctx->k);93mbedtls_mpi_init(&ctx->r);94ctx->state = ecdsa_sig_init;95}9697/*98* Free the components of a sign restart sub-context99*/100static void ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx *ctx)101{102if (ctx == NULL) {103return;104}105106mbedtls_mpi_free(&ctx->k);107mbedtls_mpi_free(&ctx->r);108}109110#if defined(MBEDTLS_ECDSA_DETERMINISTIC)111/*112* Sub-context for ecdsa_sign_det()113*/114struct mbedtls_ecdsa_restart_det {115mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */116enum { /* what to do next? */117ecdsa_det_init = 0, /* getting started */118ecdsa_det_sign, /* make signature */119} state;120};121122/*123* Init verify sign_det sub-context124*/125static void ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx *ctx)126{127mbedtls_hmac_drbg_init(&ctx->rng_ctx);128ctx->state = ecdsa_det_init;129}130131/*132* Free the components of a sign_det restart sub-context133*/134static void ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx *ctx)135{136if (ctx == NULL) {137return;138}139140mbedtls_hmac_drbg_free(&ctx->rng_ctx);141142ecdsa_restart_det_init(ctx);143}144#endif /* MBEDTLS_ECDSA_DETERMINISTIC */145146#define ECDSA_RS_ECP (rs_ctx == NULL ? NULL : &rs_ctx->ecp)147148/* Utility macro for checking and updating ops budget */149#define ECDSA_BUDGET(ops) \150MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, ECDSA_RS_ECP, ops));151152/* Call this when entering a function that needs its own sub-context */153#define ECDSA_RS_ENTER(SUB) do { \154/* reset ops count for this call if top-level */ \155if (rs_ctx != NULL && rs_ctx->ecp.depth++ == 0) \156rs_ctx->ecp.ops_done = 0; \157\158/* set up our own sub-context if needed */ \159if (mbedtls_ecp_restart_is_enabled() && \160rs_ctx != NULL && rs_ctx->SUB == NULL) \161{ \162rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB)); \163if (rs_ctx->SUB == NULL) \164return MBEDTLS_ERR_ECP_ALLOC_FAILED; \165\166ecdsa_restart_## SUB ##_init(rs_ctx->SUB); \167} \168} while (0)169170/* Call this when leaving a function that needs its own sub-context */171#define ECDSA_RS_LEAVE(SUB) do { \172/* clear our sub-context when not in progress (done or error) */ \173if (rs_ctx != NULL && rs_ctx->SUB != NULL && \174ret != MBEDTLS_ERR_ECP_IN_PROGRESS) \175{ \176ecdsa_restart_## SUB ##_free(rs_ctx->SUB); \177mbedtls_free(rs_ctx->SUB); \178rs_ctx->SUB = NULL; \179} \180\181if (rs_ctx != NULL) \182rs_ctx->ecp.depth--; \183} while (0)184185#else /* MBEDTLS_ECP_RESTARTABLE */186187#define ECDSA_RS_ECP NULL188189#define ECDSA_BUDGET(ops) /* no-op; for compatibility */190191#define ECDSA_RS_ENTER(SUB) (void) rs_ctx192#define ECDSA_RS_LEAVE(SUB) (void) rs_ctx193194#endif /* MBEDTLS_ECP_RESTARTABLE */195196#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \197!defined(MBEDTLS_ECDSA_SIGN_ALT) || \198!defined(MBEDTLS_ECDSA_VERIFY_ALT)199/*200* Derive a suitable integer for group grp from a buffer of length len201* SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3202*/203static int derive_mpi(const mbedtls_ecp_group *grp, mbedtls_mpi *x,204const unsigned char *buf, size_t blen)205{206int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;207size_t n_size = (grp->nbits + 7) / 8;208size_t use_size = blen > n_size ? n_size : blen;209210MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(x, buf, use_size));211if (use_size * 8 > grp->nbits) {212MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(x, use_size * 8 - grp->nbits));213}214215/* While at it, reduce modulo N */216if (mbedtls_mpi_cmp_mpi(x, &grp->N) >= 0) {217MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(x, x, &grp->N));218}219220cleanup:221return ret;222}223#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */224225int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid)226{227switch (gid) {228#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED229case MBEDTLS_ECP_DP_CURVE25519: return 0;230#endif231#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED232case MBEDTLS_ECP_DP_CURVE448: return 0;233#endif234default: return 1;235}236}237238#if !defined(MBEDTLS_ECDSA_SIGN_ALT)239/*240* Compute ECDSA signature of a hashed message (SEC1 4.1.3)241* Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)242*/243int mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp,244mbedtls_mpi *r, mbedtls_mpi *s,245const mbedtls_mpi *d, const unsigned char *buf, size_t blen,246int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,247int (*f_rng_blind)(void *, unsigned char *, size_t),248void *p_rng_blind,249mbedtls_ecdsa_restart_ctx *rs_ctx)250{251int ret, key_tries, sign_tries;252int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;253mbedtls_ecp_point R;254mbedtls_mpi k, e;255mbedtls_mpi *pk = &k, *pr = r;256257/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */258if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {259return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;260}261262/* Make sure d is in range 1..n-1 */263if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) {264return MBEDTLS_ERR_ECP_INVALID_KEY;265}266267mbedtls_ecp_point_init(&R);268mbedtls_mpi_init(&k); mbedtls_mpi_init(&e);269270ECDSA_RS_ENTER(sig);271272#if defined(MBEDTLS_ECP_RESTARTABLE)273if (rs_ctx != NULL && rs_ctx->sig != NULL) {274/* redirect to our context */275p_sign_tries = &rs_ctx->sig->sign_tries;276p_key_tries = &rs_ctx->sig->key_tries;277pk = &rs_ctx->sig->k;278pr = &rs_ctx->sig->r;279280/* jump to current step */281if (rs_ctx->sig->state == ecdsa_sig_mul) {282goto mul;283}284if (rs_ctx->sig->state == ecdsa_sig_modn) {285goto modn;286}287}288#endif /* MBEDTLS_ECP_RESTARTABLE */289290*p_sign_tries = 0;291do {292if ((*p_sign_tries)++ > 10) {293ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;294goto cleanup;295}296297/*298* Steps 1-3: generate a suitable ephemeral keypair299* and set r = xR mod n300*/301*p_key_tries = 0;302do {303if ((*p_key_tries)++ > 10) {304ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;305goto cleanup;306}307308MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, pk, f_rng, p_rng));309310#if defined(MBEDTLS_ECP_RESTARTABLE)311if (rs_ctx != NULL && rs_ctx->sig != NULL) {312rs_ctx->sig->state = ecdsa_sig_mul;313}314315mul:316#endif317MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &R, pk, &grp->G,318f_rng_blind,319p_rng_blind,320ECDSA_RS_ECP));321MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pr, &R.X, &grp->N));322} while (mbedtls_mpi_cmp_int(pr, 0) == 0);323324#if defined(MBEDTLS_ECP_RESTARTABLE)325if (rs_ctx != NULL && rs_ctx->sig != NULL) {326rs_ctx->sig->state = ecdsa_sig_modn;327}328329modn:330#endif331/*332* Accounting for everything up to the end of the loop333* (step 6, but checking now avoids saving e and t)334*/335ECDSA_BUDGET(MBEDTLS_ECP_OPS_INV + 4);336337/*338* Step 5: derive MPI from hashed message339*/340MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));341342/*343* Step 6: compute s = (e + r * d) / k344*/345MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, pr, d));346MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&e, &e, s));347MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(NULL, s, pk, &grp->N));348MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, s, &e));349MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(s, s, &grp->N));350} while (mbedtls_mpi_cmp_int(s, 0) == 0);351352#if defined(MBEDTLS_ECP_RESTARTABLE)353if (rs_ctx != NULL && rs_ctx->sig != NULL) {354MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr));355}356#endif357358cleanup:359mbedtls_ecp_point_free(&R);360mbedtls_mpi_free(&k); mbedtls_mpi_free(&e);361362ECDSA_RS_LEAVE(sig);363364return ret;365}366367/*368* Compute ECDSA signature of a hashed message369*/370int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,371const mbedtls_mpi *d, const unsigned char *buf, size_t blen,372int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)373{374/* Use the same RNG for both blinding and ephemeral key generation */375return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,376f_rng, p_rng, f_rng, p_rng, NULL);377}378#endif /* !MBEDTLS_ECDSA_SIGN_ALT */379380#if defined(MBEDTLS_ECDSA_DETERMINISTIC)381/*382* Deterministic signature wrapper383*384* note: The f_rng_blind parameter must not be NULL.385*386*/387int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp,388mbedtls_mpi *r, mbedtls_mpi *s,389const mbedtls_mpi *d, const unsigned char *buf, size_t blen,390mbedtls_md_type_t md_alg,391int (*f_rng_blind)(void *, unsigned char *, size_t),392void *p_rng_blind,393mbedtls_ecdsa_restart_ctx *rs_ctx)394{395int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;396mbedtls_hmac_drbg_context rng_ctx;397mbedtls_hmac_drbg_context *p_rng = &rng_ctx;398unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];399size_t grp_len = (grp->nbits + 7) / 8;400const mbedtls_md_info_t *md_info;401mbedtls_mpi h;402403if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) {404return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;405}406407mbedtls_mpi_init(&h);408mbedtls_hmac_drbg_init(&rng_ctx);409410ECDSA_RS_ENTER(det);411412#if defined(MBEDTLS_ECP_RESTARTABLE)413if (rs_ctx != NULL && rs_ctx->det != NULL) {414/* redirect to our context */415p_rng = &rs_ctx->det->rng_ctx;416417/* jump to current step */418if (rs_ctx->det->state == ecdsa_det_sign) {419goto sign;420}421}422#endif /* MBEDTLS_ECP_RESTARTABLE */423424/* Use private key and message hash (reduced) to initialize HMAC_DRBG */425MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len));426MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen));427MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len));428MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len));429430#if defined(MBEDTLS_ECP_RESTARTABLE)431if (rs_ctx != NULL && rs_ctx->det != NULL) {432rs_ctx->det->state = ecdsa_det_sign;433}434435sign:436#endif437#if defined(MBEDTLS_ECDSA_SIGN_ALT)438(void) f_rng_blind;439(void) p_rng_blind;440ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen,441mbedtls_hmac_drbg_random, p_rng);442#else443ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,444mbedtls_hmac_drbg_random, p_rng,445f_rng_blind, p_rng_blind, rs_ctx);446#endif /* MBEDTLS_ECDSA_SIGN_ALT */447448cleanup:449mbedtls_hmac_drbg_free(&rng_ctx);450mbedtls_mpi_free(&h);451452ECDSA_RS_LEAVE(det);453454return ret;455}456457/*458* Deterministic signature wrapper459*/460int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r,461mbedtls_mpi *s, const mbedtls_mpi *d,462const unsigned char *buf, size_t blen,463mbedtls_md_type_t md_alg,464int (*f_rng_blind)(void *, unsigned char *,465size_t),466void *p_rng_blind)467{468return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg,469f_rng_blind, p_rng_blind, NULL);470}471#endif /* MBEDTLS_ECDSA_DETERMINISTIC */472473#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)474/*475* Verify ECDSA signature of hashed message (SEC1 4.1.4)476* Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)477*/478int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,479const unsigned char *buf, size_t blen,480const mbedtls_ecp_point *Q,481const mbedtls_mpi *r,482const mbedtls_mpi *s,483mbedtls_ecdsa_restart_ctx *rs_ctx)484{485int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;486mbedtls_mpi e, s_inv, u1, u2;487mbedtls_ecp_point R;488mbedtls_mpi *pu1 = &u1, *pu2 = &u2;489490mbedtls_ecp_point_init(&R);491mbedtls_mpi_init(&e); mbedtls_mpi_init(&s_inv);492mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2);493494/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */495if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {496return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;497}498499ECDSA_RS_ENTER(ver);500501#if defined(MBEDTLS_ECP_RESTARTABLE)502if (rs_ctx != NULL && rs_ctx->ver != NULL) {503/* redirect to our context */504pu1 = &rs_ctx->ver->u1;505pu2 = &rs_ctx->ver->u2;506507/* jump to current step */508if (rs_ctx->ver->state == ecdsa_ver_muladd) {509goto muladd;510}511}512#endif /* MBEDTLS_ECP_RESTARTABLE */513514/*515* Step 1: make sure r and s are in range 1..n-1516*/517if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 ||518mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0) {519ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;520goto cleanup;521}522523/*524* Step 3: derive MPI from hashed message525*/526MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));527528/*529* Step 4: u1 = e / s mod n, u2 = r / s mod n530*/531ECDSA_BUDGET(MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2);532533MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(NULL, &s_inv, s, &grp->N));534535MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu1, &e, &s_inv));536MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu1, pu1, &grp->N));537538MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu2, r, &s_inv));539MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu2, pu2, &grp->N));540541#if defined(MBEDTLS_ECP_RESTARTABLE)542if (rs_ctx != NULL && rs_ctx->ver != NULL) {543rs_ctx->ver->state = ecdsa_ver_muladd;544}545546muladd:547#endif548/*549* Step 5: R = u1 G + u2 Q550*/551MBEDTLS_MPI_CHK(mbedtls_ecp_muladd_restartable(grp,552&R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP));553554if (mbedtls_ecp_is_zero(&R)) {555ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;556goto cleanup;557}558559/*560* Step 6: convert xR to an integer (no-op)561* Step 7: reduce xR mod n (gives v)562*/563MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&R.X, &R.X, &grp->N));564565/*566* Step 8: check if v (that is, R.X) is equal to r567*/568if (mbedtls_mpi_cmp_mpi(&R.X, r) != 0) {569ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;570goto cleanup;571}572573cleanup:574mbedtls_ecp_point_free(&R);575mbedtls_mpi_free(&e); mbedtls_mpi_free(&s_inv);576mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2);577578ECDSA_RS_LEAVE(ver);579580return ret;581}582583/*584* Verify ECDSA signature of hashed message585*/586int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,587const unsigned char *buf, size_t blen,588const mbedtls_ecp_point *Q,589const mbedtls_mpi *r,590const mbedtls_mpi *s)591{592return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL);593}594#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */595596/*597* Convert a signature (given by context) to ASN.1598*/599static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s,600unsigned char *sig, size_t sig_size,601size_t *slen)602{603int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;604unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };605unsigned char *p = buf + sizeof(buf);606size_t len = 0;607608MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s));609MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r));610611MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len));612MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf,613MBEDTLS_ASN1_CONSTRUCTED |614MBEDTLS_ASN1_SEQUENCE));615616if (len > sig_size) {617return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;618}619620memcpy(sig, p, len);621*slen = len;622623return 0;624}625626/*627* Compute and write signature628*/629int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,630mbedtls_md_type_t md_alg,631const unsigned char *hash, size_t hlen,632unsigned char *sig, size_t sig_size, size_t *slen,633int (*f_rng)(void *, unsigned char *, size_t),634void *p_rng,635mbedtls_ecdsa_restart_ctx *rs_ctx)636{637int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;638mbedtls_mpi r, s;639if (f_rng == NULL) {640return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;641}642643mbedtls_mpi_init(&r);644mbedtls_mpi_init(&s);645646#if defined(MBEDTLS_ECDSA_DETERMINISTIC)647MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d,648hash, hlen, md_alg, f_rng,649p_rng, rs_ctx));650#else651(void) md_alg;652653#if defined(MBEDTLS_ECDSA_SIGN_ALT)654(void) rs_ctx;655656MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d,657hash, hlen, f_rng, p_rng));658#else659/* Use the same RNG for both blinding and ephemeral key generation */660MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d,661hash, hlen, f_rng, p_rng, f_rng,662p_rng, rs_ctx));663#endif /* MBEDTLS_ECDSA_SIGN_ALT */664#endif /* MBEDTLS_ECDSA_DETERMINISTIC */665666MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen));667668cleanup:669mbedtls_mpi_free(&r);670mbedtls_mpi_free(&s);671672return ret;673}674675/*676* Compute and write signature677*/678int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,679mbedtls_md_type_t md_alg,680const unsigned char *hash, size_t hlen,681unsigned char *sig, size_t sig_size, size_t *slen,682int (*f_rng)(void *, unsigned char *, size_t),683void *p_rng)684{685return mbedtls_ecdsa_write_signature_restartable(686ctx, md_alg, hash, hlen, sig, sig_size, slen,687f_rng, p_rng, NULL);688}689690/*691* Read and check signature692*/693int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,694const unsigned char *hash, size_t hlen,695const unsigned char *sig, size_t slen)696{697return mbedtls_ecdsa_read_signature_restartable(698ctx, hash, hlen, sig, slen, NULL);699}700701/*702* Restartable read and check signature703*/704int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx,705const unsigned char *hash, size_t hlen,706const unsigned char *sig, size_t slen,707mbedtls_ecdsa_restart_ctx *rs_ctx)708{709int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;710unsigned char *p = (unsigned char *) sig;711const unsigned char *end = sig + slen;712size_t len;713mbedtls_mpi r, s;714mbedtls_mpi_init(&r);715mbedtls_mpi_init(&s);716717if ((ret = mbedtls_asn1_get_tag(&p, end, &len,718MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {719ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;720goto cleanup;721}722723if (p + len != end) {724ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA,725MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);726goto cleanup;727}728729if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 ||730(ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) {731ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;732goto cleanup;733}734#if defined(MBEDTLS_ECDSA_VERIFY_ALT)735(void) rs_ctx;736737if ((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen,738&ctx->Q, &r, &s)) != 0) {739goto cleanup;740}741#else742if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen,743&ctx->Q, &r, &s, rs_ctx)) != 0) {744goto cleanup;745}746#endif /* MBEDTLS_ECDSA_VERIFY_ALT */747748/* At this point we know that the buffer starts with a valid signature.749* Return 0 if the buffer just contains the signature, and a specific750* error code if the valid signature is followed by more data. */751if (p != end) {752ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;753}754755cleanup:756mbedtls_mpi_free(&r);757mbedtls_mpi_free(&s);758759return ret;760}761762#if !defined(MBEDTLS_ECDSA_GENKEY_ALT)763/*764* Generate key pair765*/766int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,767int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)768{769int ret = 0;770ret = mbedtls_ecp_group_load(&ctx->grp, gid);771if (ret != 0) {772return ret;773}774775return mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d,776&ctx->Q, f_rng, p_rng);777}778#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */779780/*781* Set context from an mbedtls_ecp_keypair782*/783int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key)784{785int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;786if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 ||787(ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 ||788(ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) {789mbedtls_ecdsa_free(ctx);790}791792return ret;793}794795/*796* Initialize context797*/798void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx)799{800mbedtls_ecp_keypair_init(ctx);801}802803/*804* Free context805*/806void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx)807{808if (ctx == NULL) {809return;810}811812mbedtls_ecp_keypair_free(ctx);813}814815#if defined(MBEDTLS_ECP_RESTARTABLE)816/*817* Initialize a restart context818*/819void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx)820{821mbedtls_ecp_restart_init(&ctx->ecp);822823ctx->ver = NULL;824ctx->sig = NULL;825#if defined(MBEDTLS_ECDSA_DETERMINISTIC)826ctx->det = NULL;827#endif828}829830/*831* Free the components of a restart context832*/833void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx)834{835if (ctx == NULL) {836return;837}838839mbedtls_ecp_restart_free(&ctx->ecp);840841ecdsa_restart_ver_free(ctx->ver);842mbedtls_free(ctx->ver);843ctx->ver = NULL;844845ecdsa_restart_sig_free(ctx->sig);846mbedtls_free(ctx->sig);847ctx->sig = NULL;848849#if defined(MBEDTLS_ECDSA_DETERMINISTIC)850ecdsa_restart_det_free(ctx->det);851mbedtls_free(ctx->det);852ctx->det = NULL;853#endif854}855#endif /* MBEDTLS_ECP_RESTARTABLE */856857#endif /* MBEDTLS_ECDSA_C */858859860