1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * Elliptic curve DSA 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 5a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6a8e1175bSopenharmony_ci */ 7a8e1175bSopenharmony_ci 8a8e1175bSopenharmony_ci/* 9a8e1175bSopenharmony_ci * References: 10a8e1175bSopenharmony_ci * 11a8e1175bSopenharmony_ci * SEC1 https://www.secg.org/sec1-v2.pdf 12a8e1175bSopenharmony_ci */ 13a8e1175bSopenharmony_ci 14a8e1175bSopenharmony_ci#include "common.h" 15a8e1175bSopenharmony_ci 16a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_C) 17a8e1175bSopenharmony_ci 18a8e1175bSopenharmony_ci#include "mbedtls/ecdsa.h" 19a8e1175bSopenharmony_ci#include "mbedtls/asn1write.h" 20a8e1175bSopenharmony_ci 21a8e1175bSopenharmony_ci#include <string.h> 22a8e1175bSopenharmony_ci 23a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_DETERMINISTIC) 24a8e1175bSopenharmony_ci#include "mbedtls/hmac_drbg.h" 25a8e1175bSopenharmony_ci#endif 26a8e1175bSopenharmony_ci 27a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 28a8e1175bSopenharmony_ci 29a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h" 30a8e1175bSopenharmony_ci#include "mbedtls/error.h" 31a8e1175bSopenharmony_ci 32a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 33a8e1175bSopenharmony_ci 34a8e1175bSopenharmony_ci/* 35a8e1175bSopenharmony_ci * Sub-context for ecdsa_verify() 36a8e1175bSopenharmony_ci */ 37a8e1175bSopenharmony_cistruct mbedtls_ecdsa_restart_ver { 38a8e1175bSopenharmony_ci mbedtls_mpi u1, u2; /* intermediate values */ 39a8e1175bSopenharmony_ci enum { /* what to do next? */ 40a8e1175bSopenharmony_ci ecdsa_ver_init = 0, /* getting started */ 41a8e1175bSopenharmony_ci ecdsa_ver_muladd, /* muladd step */ 42a8e1175bSopenharmony_ci } state; 43a8e1175bSopenharmony_ci}; 44a8e1175bSopenharmony_ci 45a8e1175bSopenharmony_ci/* 46a8e1175bSopenharmony_ci * Init verify restart sub-context 47a8e1175bSopenharmony_ci */ 48a8e1175bSopenharmony_cistatic void ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx *ctx) 49a8e1175bSopenharmony_ci{ 50a8e1175bSopenharmony_ci mbedtls_mpi_init(&ctx->u1); 51a8e1175bSopenharmony_ci mbedtls_mpi_init(&ctx->u2); 52a8e1175bSopenharmony_ci ctx->state = ecdsa_ver_init; 53a8e1175bSopenharmony_ci} 54a8e1175bSopenharmony_ci 55a8e1175bSopenharmony_ci/* 56a8e1175bSopenharmony_ci * Free the components of a verify restart sub-context 57a8e1175bSopenharmony_ci */ 58a8e1175bSopenharmony_cistatic void ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx *ctx) 59a8e1175bSopenharmony_ci{ 60a8e1175bSopenharmony_ci if (ctx == NULL) { 61a8e1175bSopenharmony_ci return; 62a8e1175bSopenharmony_ci } 63a8e1175bSopenharmony_ci 64a8e1175bSopenharmony_ci mbedtls_mpi_free(&ctx->u1); 65a8e1175bSopenharmony_ci mbedtls_mpi_free(&ctx->u2); 66a8e1175bSopenharmony_ci 67a8e1175bSopenharmony_ci ecdsa_restart_ver_init(ctx); 68a8e1175bSopenharmony_ci} 69a8e1175bSopenharmony_ci 70a8e1175bSopenharmony_ci/* 71a8e1175bSopenharmony_ci * Sub-context for ecdsa_sign() 72a8e1175bSopenharmony_ci */ 73a8e1175bSopenharmony_cistruct mbedtls_ecdsa_restart_sig { 74a8e1175bSopenharmony_ci int sign_tries; 75a8e1175bSopenharmony_ci int key_tries; 76a8e1175bSopenharmony_ci mbedtls_mpi k; /* per-signature random */ 77a8e1175bSopenharmony_ci mbedtls_mpi r; /* r value */ 78a8e1175bSopenharmony_ci enum { /* what to do next? */ 79a8e1175bSopenharmony_ci ecdsa_sig_init = 0, /* getting started */ 80a8e1175bSopenharmony_ci ecdsa_sig_mul, /* doing ecp_mul() */ 81a8e1175bSopenharmony_ci ecdsa_sig_modn, /* mod N computations */ 82a8e1175bSopenharmony_ci } state; 83a8e1175bSopenharmony_ci}; 84a8e1175bSopenharmony_ci 85a8e1175bSopenharmony_ci/* 86a8e1175bSopenharmony_ci * Init verify sign sub-context 87a8e1175bSopenharmony_ci */ 88a8e1175bSopenharmony_cistatic void ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx *ctx) 89a8e1175bSopenharmony_ci{ 90a8e1175bSopenharmony_ci ctx->sign_tries = 0; 91a8e1175bSopenharmony_ci ctx->key_tries = 0; 92a8e1175bSopenharmony_ci mbedtls_mpi_init(&ctx->k); 93a8e1175bSopenharmony_ci mbedtls_mpi_init(&ctx->r); 94a8e1175bSopenharmony_ci ctx->state = ecdsa_sig_init; 95a8e1175bSopenharmony_ci} 96a8e1175bSopenharmony_ci 97a8e1175bSopenharmony_ci/* 98a8e1175bSopenharmony_ci * Free the components of a sign restart sub-context 99a8e1175bSopenharmony_ci */ 100a8e1175bSopenharmony_cistatic void ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx *ctx) 101a8e1175bSopenharmony_ci{ 102a8e1175bSopenharmony_ci if (ctx == NULL) { 103a8e1175bSopenharmony_ci return; 104a8e1175bSopenharmony_ci } 105a8e1175bSopenharmony_ci 106a8e1175bSopenharmony_ci mbedtls_mpi_free(&ctx->k); 107a8e1175bSopenharmony_ci mbedtls_mpi_free(&ctx->r); 108a8e1175bSopenharmony_ci} 109a8e1175bSopenharmony_ci 110a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_DETERMINISTIC) 111a8e1175bSopenharmony_ci/* 112a8e1175bSopenharmony_ci * Sub-context for ecdsa_sign_det() 113a8e1175bSopenharmony_ci */ 114a8e1175bSopenharmony_cistruct mbedtls_ecdsa_restart_det { 115a8e1175bSopenharmony_ci mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ 116a8e1175bSopenharmony_ci enum { /* what to do next? */ 117a8e1175bSopenharmony_ci ecdsa_det_init = 0, /* getting started */ 118a8e1175bSopenharmony_ci ecdsa_det_sign, /* make signature */ 119a8e1175bSopenharmony_ci } state; 120a8e1175bSopenharmony_ci}; 121a8e1175bSopenharmony_ci 122a8e1175bSopenharmony_ci/* 123a8e1175bSopenharmony_ci * Init verify sign_det sub-context 124a8e1175bSopenharmony_ci */ 125a8e1175bSopenharmony_cistatic void ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx *ctx) 126a8e1175bSopenharmony_ci{ 127a8e1175bSopenharmony_ci mbedtls_hmac_drbg_init(&ctx->rng_ctx); 128a8e1175bSopenharmony_ci ctx->state = ecdsa_det_init; 129a8e1175bSopenharmony_ci} 130a8e1175bSopenharmony_ci 131a8e1175bSopenharmony_ci/* 132a8e1175bSopenharmony_ci * Free the components of a sign_det restart sub-context 133a8e1175bSopenharmony_ci */ 134a8e1175bSopenharmony_cistatic void ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx *ctx) 135a8e1175bSopenharmony_ci{ 136a8e1175bSopenharmony_ci if (ctx == NULL) { 137a8e1175bSopenharmony_ci return; 138a8e1175bSopenharmony_ci } 139a8e1175bSopenharmony_ci 140a8e1175bSopenharmony_ci mbedtls_hmac_drbg_free(&ctx->rng_ctx); 141a8e1175bSopenharmony_ci 142a8e1175bSopenharmony_ci ecdsa_restart_det_init(ctx); 143a8e1175bSopenharmony_ci} 144a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ 145a8e1175bSopenharmony_ci 146a8e1175bSopenharmony_ci#define ECDSA_RS_ECP (rs_ctx == NULL ? NULL : &rs_ctx->ecp) 147a8e1175bSopenharmony_ci 148a8e1175bSopenharmony_ci/* Utility macro for checking and updating ops budget */ 149a8e1175bSopenharmony_ci#define ECDSA_BUDGET(ops) \ 150a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, ECDSA_RS_ECP, ops)); 151a8e1175bSopenharmony_ci 152a8e1175bSopenharmony_ci/* Call this when entering a function that needs its own sub-context */ 153a8e1175bSopenharmony_ci#define ECDSA_RS_ENTER(SUB) do { \ 154a8e1175bSopenharmony_ci /* reset ops count for this call if top-level */ \ 155a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->ecp.depth++ == 0) \ 156a8e1175bSopenharmony_ci rs_ctx->ecp.ops_done = 0; \ 157a8e1175bSopenharmony_ci \ 158a8e1175bSopenharmony_ci /* set up our own sub-context if needed */ \ 159a8e1175bSopenharmony_ci if (mbedtls_ecp_restart_is_enabled() && \ 160a8e1175bSopenharmony_ci rs_ctx != NULL && rs_ctx->SUB == NULL) \ 161a8e1175bSopenharmony_ci { \ 162a8e1175bSopenharmony_ci rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB)); \ 163a8e1175bSopenharmony_ci if (rs_ctx->SUB == NULL) \ 164a8e1175bSopenharmony_ci return MBEDTLS_ERR_ECP_ALLOC_FAILED; \ 165a8e1175bSopenharmony_ci \ 166a8e1175bSopenharmony_ci ecdsa_restart_## SUB ##_init(rs_ctx->SUB); \ 167a8e1175bSopenharmony_ci } \ 168a8e1175bSopenharmony_ci} while (0) 169a8e1175bSopenharmony_ci 170a8e1175bSopenharmony_ci/* Call this when leaving a function that needs its own sub-context */ 171a8e1175bSopenharmony_ci#define ECDSA_RS_LEAVE(SUB) do { \ 172a8e1175bSopenharmony_ci /* clear our sub-context when not in progress (done or error) */ \ 173a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->SUB != NULL && \ 174a8e1175bSopenharmony_ci ret != MBEDTLS_ERR_ECP_IN_PROGRESS) \ 175a8e1175bSopenharmony_ci { \ 176a8e1175bSopenharmony_ci ecdsa_restart_## SUB ##_free(rs_ctx->SUB); \ 177a8e1175bSopenharmony_ci mbedtls_free(rs_ctx->SUB); \ 178a8e1175bSopenharmony_ci rs_ctx->SUB = NULL; \ 179a8e1175bSopenharmony_ci } \ 180a8e1175bSopenharmony_ci \ 181a8e1175bSopenharmony_ci if (rs_ctx != NULL) \ 182a8e1175bSopenharmony_ci rs_ctx->ecp.depth--; \ 183a8e1175bSopenharmony_ci} while (0) 184a8e1175bSopenharmony_ci 185a8e1175bSopenharmony_ci#else /* MBEDTLS_ECP_RESTARTABLE */ 186a8e1175bSopenharmony_ci 187a8e1175bSopenharmony_ci#define ECDSA_RS_ECP NULL 188a8e1175bSopenharmony_ci 189a8e1175bSopenharmony_ci#define ECDSA_BUDGET(ops) /* no-op; for compatibility */ 190a8e1175bSopenharmony_ci 191a8e1175bSopenharmony_ci#define ECDSA_RS_ENTER(SUB) (void) rs_ctx 192a8e1175bSopenharmony_ci#define ECDSA_RS_LEAVE(SUB) (void) rs_ctx 193a8e1175bSopenharmony_ci 194a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECP_RESTARTABLE */ 195a8e1175bSopenharmony_ci 196a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \ 197a8e1175bSopenharmony_ci !defined(MBEDTLS_ECDSA_SIGN_ALT) || \ 198a8e1175bSopenharmony_ci !defined(MBEDTLS_ECDSA_VERIFY_ALT) 199a8e1175bSopenharmony_ci/* 200a8e1175bSopenharmony_ci * Derive a suitable integer for group grp from a buffer of length len 201a8e1175bSopenharmony_ci * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 202a8e1175bSopenharmony_ci */ 203a8e1175bSopenharmony_cistatic int derive_mpi(const mbedtls_ecp_group *grp, mbedtls_mpi *x, 204a8e1175bSopenharmony_ci const unsigned char *buf, size_t blen) 205a8e1175bSopenharmony_ci{ 206a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 207a8e1175bSopenharmony_ci size_t n_size = (grp->nbits + 7) / 8; 208a8e1175bSopenharmony_ci size_t use_size = blen > n_size ? n_size : blen; 209a8e1175bSopenharmony_ci 210a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(x, buf, use_size)); 211a8e1175bSopenharmony_ci if (use_size * 8 > grp->nbits) { 212a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(x, use_size * 8 - grp->nbits)); 213a8e1175bSopenharmony_ci } 214a8e1175bSopenharmony_ci 215a8e1175bSopenharmony_ci /* While at it, reduce modulo N */ 216a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(x, &grp->N) >= 0) { 217a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(x, x, &grp->N)); 218a8e1175bSopenharmony_ci } 219a8e1175bSopenharmony_ci 220a8e1175bSopenharmony_cicleanup: 221a8e1175bSopenharmony_ci return ret; 222a8e1175bSopenharmony_ci} 223a8e1175bSopenharmony_ci#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */ 224a8e1175bSopenharmony_ci 225a8e1175bSopenharmony_ciint mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid) 226a8e1175bSopenharmony_ci{ 227a8e1175bSopenharmony_ci switch (gid) { 228a8e1175bSopenharmony_ci#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED 229a8e1175bSopenharmony_ci case MBEDTLS_ECP_DP_CURVE25519: return 0; 230a8e1175bSopenharmony_ci#endif 231a8e1175bSopenharmony_ci#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED 232a8e1175bSopenharmony_ci case MBEDTLS_ECP_DP_CURVE448: return 0; 233a8e1175bSopenharmony_ci#endif 234a8e1175bSopenharmony_ci default: return 1; 235a8e1175bSopenharmony_ci } 236a8e1175bSopenharmony_ci} 237a8e1175bSopenharmony_ci 238a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECDSA_SIGN_ALT) 239a8e1175bSopenharmony_ci/* 240a8e1175bSopenharmony_ci * Compute ECDSA signature of a hashed message (SEC1 4.1.3) 241a8e1175bSopenharmony_ci * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) 242a8e1175bSopenharmony_ci */ 243a8e1175bSopenharmony_ciint mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, 244a8e1175bSopenharmony_ci mbedtls_mpi *r, mbedtls_mpi *s, 245a8e1175bSopenharmony_ci const mbedtls_mpi *d, const unsigned char *buf, size_t blen, 246a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, 247a8e1175bSopenharmony_ci int (*f_rng_blind)(void *, unsigned char *, size_t), 248a8e1175bSopenharmony_ci void *p_rng_blind, 249a8e1175bSopenharmony_ci mbedtls_ecdsa_restart_ctx *rs_ctx) 250a8e1175bSopenharmony_ci{ 251a8e1175bSopenharmony_ci int ret, key_tries, sign_tries; 252a8e1175bSopenharmony_ci int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; 253a8e1175bSopenharmony_ci mbedtls_ecp_point R; 254a8e1175bSopenharmony_ci mbedtls_mpi k, e, t; 255a8e1175bSopenharmony_ci mbedtls_mpi *pk = &k, *pr = r; 256a8e1175bSopenharmony_ci 257a8e1175bSopenharmony_ci /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ 258a8e1175bSopenharmony_ci if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) { 259a8e1175bSopenharmony_ci return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 260a8e1175bSopenharmony_ci } 261a8e1175bSopenharmony_ci 262a8e1175bSopenharmony_ci /* Make sure d is in range 1..n-1 */ 263a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) { 264a8e1175bSopenharmony_ci return MBEDTLS_ERR_ECP_INVALID_KEY; 265a8e1175bSopenharmony_ci } 266a8e1175bSopenharmony_ci 267a8e1175bSopenharmony_ci mbedtls_ecp_point_init(&R); 268a8e1175bSopenharmony_ci mbedtls_mpi_init(&k); mbedtls_mpi_init(&e); mbedtls_mpi_init(&t); 269a8e1175bSopenharmony_ci 270a8e1175bSopenharmony_ci ECDSA_RS_ENTER(sig); 271a8e1175bSopenharmony_ci 272a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 273a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->sig != NULL) { 274a8e1175bSopenharmony_ci /* redirect to our context */ 275a8e1175bSopenharmony_ci p_sign_tries = &rs_ctx->sig->sign_tries; 276a8e1175bSopenharmony_ci p_key_tries = &rs_ctx->sig->key_tries; 277a8e1175bSopenharmony_ci pk = &rs_ctx->sig->k; 278a8e1175bSopenharmony_ci pr = &rs_ctx->sig->r; 279a8e1175bSopenharmony_ci 280a8e1175bSopenharmony_ci /* jump to current step */ 281a8e1175bSopenharmony_ci if (rs_ctx->sig->state == ecdsa_sig_mul) { 282a8e1175bSopenharmony_ci goto mul; 283a8e1175bSopenharmony_ci } 284a8e1175bSopenharmony_ci if (rs_ctx->sig->state == ecdsa_sig_modn) { 285a8e1175bSopenharmony_ci goto modn; 286a8e1175bSopenharmony_ci } 287a8e1175bSopenharmony_ci } 288a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECP_RESTARTABLE */ 289a8e1175bSopenharmony_ci 290a8e1175bSopenharmony_ci *p_sign_tries = 0; 291a8e1175bSopenharmony_ci do { 292a8e1175bSopenharmony_ci if ((*p_sign_tries)++ > 10) { 293a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; 294a8e1175bSopenharmony_ci goto cleanup; 295a8e1175bSopenharmony_ci } 296a8e1175bSopenharmony_ci 297a8e1175bSopenharmony_ci /* 298a8e1175bSopenharmony_ci * Steps 1-3: generate a suitable ephemeral keypair 299a8e1175bSopenharmony_ci * and set r = xR mod n 300a8e1175bSopenharmony_ci */ 301a8e1175bSopenharmony_ci *p_key_tries = 0; 302a8e1175bSopenharmony_ci do { 303a8e1175bSopenharmony_ci if ((*p_key_tries)++ > 10) { 304a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; 305a8e1175bSopenharmony_ci goto cleanup; 306a8e1175bSopenharmony_ci } 307a8e1175bSopenharmony_ci 308a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, pk, f_rng, p_rng)); 309a8e1175bSopenharmony_ci 310a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 311a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->sig != NULL) { 312a8e1175bSopenharmony_ci rs_ctx->sig->state = ecdsa_sig_mul; 313a8e1175bSopenharmony_ci } 314a8e1175bSopenharmony_ci 315a8e1175bSopenharmony_cimul: 316a8e1175bSopenharmony_ci#endif 317a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &R, pk, &grp->G, 318a8e1175bSopenharmony_ci f_rng_blind, 319a8e1175bSopenharmony_ci p_rng_blind, 320a8e1175bSopenharmony_ci ECDSA_RS_ECP)); 321a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pr, &R.X, &grp->N)); 322a8e1175bSopenharmony_ci } while (mbedtls_mpi_cmp_int(pr, 0) == 0); 323a8e1175bSopenharmony_ci 324a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 325a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->sig != NULL) { 326a8e1175bSopenharmony_ci rs_ctx->sig->state = ecdsa_sig_modn; 327a8e1175bSopenharmony_ci } 328a8e1175bSopenharmony_ci 329a8e1175bSopenharmony_cimodn: 330a8e1175bSopenharmony_ci#endif 331a8e1175bSopenharmony_ci /* 332a8e1175bSopenharmony_ci * Accounting for everything up to the end of the loop 333a8e1175bSopenharmony_ci * (step 6, but checking now avoids saving e and t) 334a8e1175bSopenharmony_ci */ 335a8e1175bSopenharmony_ci ECDSA_BUDGET(MBEDTLS_ECP_OPS_INV + 4); 336a8e1175bSopenharmony_ci 337a8e1175bSopenharmony_ci /* 338a8e1175bSopenharmony_ci * Step 5: derive MPI from hashed message 339a8e1175bSopenharmony_ci */ 340a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen)); 341a8e1175bSopenharmony_ci 342a8e1175bSopenharmony_ci /* 343a8e1175bSopenharmony_ci * Generate a random value to blind inv_mod in next step, 344a8e1175bSopenharmony_ci * avoiding a potential timing leak. 345a8e1175bSopenharmony_ci */ 346a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, &t, f_rng_blind, 347a8e1175bSopenharmony_ci p_rng_blind)); 348a8e1175bSopenharmony_ci 349a8e1175bSopenharmony_ci /* 350a8e1175bSopenharmony_ci * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n 351a8e1175bSopenharmony_ci */ 352a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, pr, d)); 353a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&e, &e, s)); 354a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&e, &e, &t)); 355a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pk, pk, &t)); 356a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pk, pk, &grp->N)); 357a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(s, pk, &grp->N)); 358a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, s, &e)); 359a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(s, s, &grp->N)); 360a8e1175bSopenharmony_ci } while (mbedtls_mpi_cmp_int(s, 0) == 0); 361a8e1175bSopenharmony_ci 362a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 363a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->sig != NULL) { 364a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr)); 365a8e1175bSopenharmony_ci } 366a8e1175bSopenharmony_ci#endif 367a8e1175bSopenharmony_ci 368a8e1175bSopenharmony_cicleanup: 369a8e1175bSopenharmony_ci mbedtls_ecp_point_free(&R); 370a8e1175bSopenharmony_ci mbedtls_mpi_free(&k); mbedtls_mpi_free(&e); mbedtls_mpi_free(&t); 371a8e1175bSopenharmony_ci 372a8e1175bSopenharmony_ci ECDSA_RS_LEAVE(sig); 373a8e1175bSopenharmony_ci 374a8e1175bSopenharmony_ci return ret; 375a8e1175bSopenharmony_ci} 376a8e1175bSopenharmony_ci 377a8e1175bSopenharmony_ci/* 378a8e1175bSopenharmony_ci * Compute ECDSA signature of a hashed message 379a8e1175bSopenharmony_ci */ 380a8e1175bSopenharmony_ciint mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, 381a8e1175bSopenharmony_ci const mbedtls_mpi *d, const unsigned char *buf, size_t blen, 382a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 383a8e1175bSopenharmony_ci{ 384a8e1175bSopenharmony_ci /* Use the same RNG for both blinding and ephemeral key generation */ 385a8e1175bSopenharmony_ci return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, 386a8e1175bSopenharmony_ci f_rng, p_rng, f_rng, p_rng, NULL); 387a8e1175bSopenharmony_ci} 388a8e1175bSopenharmony_ci#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ 389a8e1175bSopenharmony_ci 390a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_DETERMINISTIC) 391a8e1175bSopenharmony_ci/* 392a8e1175bSopenharmony_ci * Deterministic signature wrapper 393a8e1175bSopenharmony_ci * 394a8e1175bSopenharmony_ci * note: The f_rng_blind parameter must not be NULL. 395a8e1175bSopenharmony_ci * 396a8e1175bSopenharmony_ci */ 397a8e1175bSopenharmony_ciint mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, 398a8e1175bSopenharmony_ci mbedtls_mpi *r, mbedtls_mpi *s, 399a8e1175bSopenharmony_ci const mbedtls_mpi *d, const unsigned char *buf, size_t blen, 400a8e1175bSopenharmony_ci mbedtls_md_type_t md_alg, 401a8e1175bSopenharmony_ci int (*f_rng_blind)(void *, unsigned char *, size_t), 402a8e1175bSopenharmony_ci void *p_rng_blind, 403a8e1175bSopenharmony_ci mbedtls_ecdsa_restart_ctx *rs_ctx) 404a8e1175bSopenharmony_ci{ 405a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 406a8e1175bSopenharmony_ci mbedtls_hmac_drbg_context rng_ctx; 407a8e1175bSopenharmony_ci mbedtls_hmac_drbg_context *p_rng = &rng_ctx; 408a8e1175bSopenharmony_ci unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; 409a8e1175bSopenharmony_ci size_t grp_len = (grp->nbits + 7) / 8; 410a8e1175bSopenharmony_ci const mbedtls_md_info_t *md_info; 411a8e1175bSopenharmony_ci mbedtls_mpi h; 412a8e1175bSopenharmony_ci 413a8e1175bSopenharmony_ci if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) { 414a8e1175bSopenharmony_ci return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 415a8e1175bSopenharmony_ci } 416a8e1175bSopenharmony_ci 417a8e1175bSopenharmony_ci mbedtls_mpi_init(&h); 418a8e1175bSopenharmony_ci mbedtls_hmac_drbg_init(&rng_ctx); 419a8e1175bSopenharmony_ci 420a8e1175bSopenharmony_ci ECDSA_RS_ENTER(det); 421a8e1175bSopenharmony_ci 422a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 423a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->det != NULL) { 424a8e1175bSopenharmony_ci /* redirect to our context */ 425a8e1175bSopenharmony_ci p_rng = &rs_ctx->det->rng_ctx; 426a8e1175bSopenharmony_ci 427a8e1175bSopenharmony_ci /* jump to current step */ 428a8e1175bSopenharmony_ci if (rs_ctx->det->state == ecdsa_det_sign) { 429a8e1175bSopenharmony_ci goto sign; 430a8e1175bSopenharmony_ci } 431a8e1175bSopenharmony_ci } 432a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECP_RESTARTABLE */ 433a8e1175bSopenharmony_ci 434a8e1175bSopenharmony_ci /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ 435a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len)); 436a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen)); 437a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len)); 438a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len)); 439a8e1175bSopenharmony_ci 440a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 441a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->det != NULL) { 442a8e1175bSopenharmony_ci rs_ctx->det->state = ecdsa_det_sign; 443a8e1175bSopenharmony_ci } 444a8e1175bSopenharmony_ci 445a8e1175bSopenharmony_cisign: 446a8e1175bSopenharmony_ci#endif 447a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_SIGN_ALT) 448a8e1175bSopenharmony_ci (void) f_rng_blind; 449a8e1175bSopenharmony_ci (void) p_rng_blind; 450a8e1175bSopenharmony_ci ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, 451a8e1175bSopenharmony_ci mbedtls_hmac_drbg_random, p_rng); 452a8e1175bSopenharmony_ci#else 453a8e1175bSopenharmony_ci ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, 454a8e1175bSopenharmony_ci mbedtls_hmac_drbg_random, p_rng, 455a8e1175bSopenharmony_ci f_rng_blind, p_rng_blind, rs_ctx); 456a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECDSA_SIGN_ALT */ 457a8e1175bSopenharmony_ci 458a8e1175bSopenharmony_cicleanup: 459a8e1175bSopenharmony_ci mbedtls_hmac_drbg_free(&rng_ctx); 460a8e1175bSopenharmony_ci mbedtls_mpi_free(&h); 461a8e1175bSopenharmony_ci 462a8e1175bSopenharmony_ci ECDSA_RS_LEAVE(det); 463a8e1175bSopenharmony_ci 464a8e1175bSopenharmony_ci return ret; 465a8e1175bSopenharmony_ci} 466a8e1175bSopenharmony_ci 467a8e1175bSopenharmony_ci/* 468a8e1175bSopenharmony_ci * Deterministic signature wrapper 469a8e1175bSopenharmony_ci */ 470a8e1175bSopenharmony_ciint mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, 471a8e1175bSopenharmony_ci mbedtls_mpi *s, const mbedtls_mpi *d, 472a8e1175bSopenharmony_ci const unsigned char *buf, size_t blen, 473a8e1175bSopenharmony_ci mbedtls_md_type_t md_alg, 474a8e1175bSopenharmony_ci int (*f_rng_blind)(void *, unsigned char *, 475a8e1175bSopenharmony_ci size_t), 476a8e1175bSopenharmony_ci void *p_rng_blind) 477a8e1175bSopenharmony_ci{ 478a8e1175bSopenharmony_ci return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg, 479a8e1175bSopenharmony_ci f_rng_blind, p_rng_blind, NULL); 480a8e1175bSopenharmony_ci} 481a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ 482a8e1175bSopenharmony_ci 483a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) 484a8e1175bSopenharmony_ci/* 485a8e1175bSopenharmony_ci * Verify ECDSA signature of hashed message (SEC1 4.1.4) 486a8e1175bSopenharmony_ci * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) 487a8e1175bSopenharmony_ci */ 488a8e1175bSopenharmony_ciint mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, 489a8e1175bSopenharmony_ci const unsigned char *buf, size_t blen, 490a8e1175bSopenharmony_ci const mbedtls_ecp_point *Q, 491a8e1175bSopenharmony_ci const mbedtls_mpi *r, 492a8e1175bSopenharmony_ci const mbedtls_mpi *s, 493a8e1175bSopenharmony_ci mbedtls_ecdsa_restart_ctx *rs_ctx) 494a8e1175bSopenharmony_ci{ 495a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 496a8e1175bSopenharmony_ci mbedtls_mpi e, s_inv, u1, u2; 497a8e1175bSopenharmony_ci mbedtls_ecp_point R; 498a8e1175bSopenharmony_ci mbedtls_mpi *pu1 = &u1, *pu2 = &u2; 499a8e1175bSopenharmony_ci 500a8e1175bSopenharmony_ci mbedtls_ecp_point_init(&R); 501a8e1175bSopenharmony_ci mbedtls_mpi_init(&e); mbedtls_mpi_init(&s_inv); 502a8e1175bSopenharmony_ci mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2); 503a8e1175bSopenharmony_ci 504a8e1175bSopenharmony_ci /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ 505a8e1175bSopenharmony_ci if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) { 506a8e1175bSopenharmony_ci return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 507a8e1175bSopenharmony_ci } 508a8e1175bSopenharmony_ci 509a8e1175bSopenharmony_ci ECDSA_RS_ENTER(ver); 510a8e1175bSopenharmony_ci 511a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 512a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->ver != NULL) { 513a8e1175bSopenharmony_ci /* redirect to our context */ 514a8e1175bSopenharmony_ci pu1 = &rs_ctx->ver->u1; 515a8e1175bSopenharmony_ci pu2 = &rs_ctx->ver->u2; 516a8e1175bSopenharmony_ci 517a8e1175bSopenharmony_ci /* jump to current step */ 518a8e1175bSopenharmony_ci if (rs_ctx->ver->state == ecdsa_ver_muladd) { 519a8e1175bSopenharmony_ci goto muladd; 520a8e1175bSopenharmony_ci } 521a8e1175bSopenharmony_ci } 522a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECP_RESTARTABLE */ 523a8e1175bSopenharmony_ci 524a8e1175bSopenharmony_ci /* 525a8e1175bSopenharmony_ci * Step 1: make sure r and s are in range 1..n-1 526a8e1175bSopenharmony_ci */ 527a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 || 528a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0) { 529a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; 530a8e1175bSopenharmony_ci goto cleanup; 531a8e1175bSopenharmony_ci } 532a8e1175bSopenharmony_ci 533a8e1175bSopenharmony_ci /* 534a8e1175bSopenharmony_ci * Step 3: derive MPI from hashed message 535a8e1175bSopenharmony_ci */ 536a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen)); 537a8e1175bSopenharmony_ci 538a8e1175bSopenharmony_ci /* 539a8e1175bSopenharmony_ci * Step 4: u1 = e / s mod n, u2 = r / s mod n 540a8e1175bSopenharmony_ci */ 541a8e1175bSopenharmony_ci ECDSA_BUDGET(MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2); 542a8e1175bSopenharmony_ci 543a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&s_inv, s, &grp->N)); 544a8e1175bSopenharmony_ci 545a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu1, &e, &s_inv)); 546a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu1, pu1, &grp->N)); 547a8e1175bSopenharmony_ci 548a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu2, r, &s_inv)); 549a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu2, pu2, &grp->N)); 550a8e1175bSopenharmony_ci 551a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 552a8e1175bSopenharmony_ci if (rs_ctx != NULL && rs_ctx->ver != NULL) { 553a8e1175bSopenharmony_ci rs_ctx->ver->state = ecdsa_ver_muladd; 554a8e1175bSopenharmony_ci } 555a8e1175bSopenharmony_ci 556a8e1175bSopenharmony_cimuladd: 557a8e1175bSopenharmony_ci#endif 558a8e1175bSopenharmony_ci /* 559a8e1175bSopenharmony_ci * Step 5: R = u1 G + u2 Q 560a8e1175bSopenharmony_ci */ 561a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_ecp_muladd_restartable(grp, 562a8e1175bSopenharmony_ci &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP)); 563a8e1175bSopenharmony_ci 564a8e1175bSopenharmony_ci if (mbedtls_ecp_is_zero(&R)) { 565a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; 566a8e1175bSopenharmony_ci goto cleanup; 567a8e1175bSopenharmony_ci } 568a8e1175bSopenharmony_ci 569a8e1175bSopenharmony_ci /* 570a8e1175bSopenharmony_ci * Step 6: convert xR to an integer (no-op) 571a8e1175bSopenharmony_ci * Step 7: reduce xR mod n (gives v) 572a8e1175bSopenharmony_ci */ 573a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&R.X, &R.X, &grp->N)); 574a8e1175bSopenharmony_ci 575a8e1175bSopenharmony_ci /* 576a8e1175bSopenharmony_ci * Step 8: check if v (that is, R.X) is equal to r 577a8e1175bSopenharmony_ci */ 578a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(&R.X, r) != 0) { 579a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; 580a8e1175bSopenharmony_ci goto cleanup; 581a8e1175bSopenharmony_ci } 582a8e1175bSopenharmony_ci 583a8e1175bSopenharmony_cicleanup: 584a8e1175bSopenharmony_ci mbedtls_ecp_point_free(&R); 585a8e1175bSopenharmony_ci mbedtls_mpi_free(&e); mbedtls_mpi_free(&s_inv); 586a8e1175bSopenharmony_ci mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2); 587a8e1175bSopenharmony_ci 588a8e1175bSopenharmony_ci ECDSA_RS_LEAVE(ver); 589a8e1175bSopenharmony_ci 590a8e1175bSopenharmony_ci return ret; 591a8e1175bSopenharmony_ci} 592a8e1175bSopenharmony_ci 593a8e1175bSopenharmony_ci/* 594a8e1175bSopenharmony_ci * Verify ECDSA signature of hashed message 595a8e1175bSopenharmony_ci */ 596a8e1175bSopenharmony_ciint mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, 597a8e1175bSopenharmony_ci const unsigned char *buf, size_t blen, 598a8e1175bSopenharmony_ci const mbedtls_ecp_point *Q, 599a8e1175bSopenharmony_ci const mbedtls_mpi *r, 600a8e1175bSopenharmony_ci const mbedtls_mpi *s) 601a8e1175bSopenharmony_ci{ 602a8e1175bSopenharmony_ci return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL); 603a8e1175bSopenharmony_ci} 604a8e1175bSopenharmony_ci#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ 605a8e1175bSopenharmony_ci 606a8e1175bSopenharmony_ci/* 607a8e1175bSopenharmony_ci * Convert a signature (given by context) to ASN.1 608a8e1175bSopenharmony_ci */ 609a8e1175bSopenharmony_cistatic int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, 610a8e1175bSopenharmony_ci unsigned char *sig, size_t sig_size, 611a8e1175bSopenharmony_ci size_t *slen) 612a8e1175bSopenharmony_ci{ 613a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 614a8e1175bSopenharmony_ci unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 }; 615a8e1175bSopenharmony_ci unsigned char *p = buf + sizeof(buf); 616a8e1175bSopenharmony_ci size_t len = 0; 617a8e1175bSopenharmony_ci 618a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s)); 619a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r)); 620a8e1175bSopenharmony_ci 621a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); 622a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf, 623a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 624a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 625a8e1175bSopenharmony_ci 626a8e1175bSopenharmony_ci if (len > sig_size) { 627a8e1175bSopenharmony_ci return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; 628a8e1175bSopenharmony_ci } 629a8e1175bSopenharmony_ci 630a8e1175bSopenharmony_ci memcpy(sig, p, len); 631a8e1175bSopenharmony_ci *slen = len; 632a8e1175bSopenharmony_ci 633a8e1175bSopenharmony_ci return 0; 634a8e1175bSopenharmony_ci} 635a8e1175bSopenharmony_ci 636a8e1175bSopenharmony_ci/* 637a8e1175bSopenharmony_ci * Compute and write signature 638a8e1175bSopenharmony_ci */ 639a8e1175bSopenharmony_ciint mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, 640a8e1175bSopenharmony_ci mbedtls_md_type_t md_alg, 641a8e1175bSopenharmony_ci const unsigned char *hash, size_t hlen, 642a8e1175bSopenharmony_ci unsigned char *sig, size_t sig_size, size_t *slen, 643a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 644a8e1175bSopenharmony_ci void *p_rng, 645a8e1175bSopenharmony_ci mbedtls_ecdsa_restart_ctx *rs_ctx) 646a8e1175bSopenharmony_ci{ 647a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 648a8e1175bSopenharmony_ci mbedtls_mpi r, s; 649a8e1175bSopenharmony_ci if (f_rng == NULL) { 650a8e1175bSopenharmony_ci return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 651a8e1175bSopenharmony_ci } 652a8e1175bSopenharmony_ci 653a8e1175bSopenharmony_ci mbedtls_mpi_init(&r); 654a8e1175bSopenharmony_ci mbedtls_mpi_init(&s); 655a8e1175bSopenharmony_ci 656a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_DETERMINISTIC) 657a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d, 658a8e1175bSopenharmony_ci hash, hlen, md_alg, f_rng, 659a8e1175bSopenharmony_ci p_rng, rs_ctx)); 660a8e1175bSopenharmony_ci#else 661a8e1175bSopenharmony_ci (void) md_alg; 662a8e1175bSopenharmony_ci 663a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_SIGN_ALT) 664a8e1175bSopenharmony_ci (void) rs_ctx; 665a8e1175bSopenharmony_ci 666a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d, 667a8e1175bSopenharmony_ci hash, hlen, f_rng, p_rng)); 668a8e1175bSopenharmony_ci#else 669a8e1175bSopenharmony_ci /* Use the same RNG for both blinding and ephemeral key generation */ 670a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d, 671a8e1175bSopenharmony_ci hash, hlen, f_rng, p_rng, f_rng, 672a8e1175bSopenharmony_ci p_rng, rs_ctx)); 673a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECDSA_SIGN_ALT */ 674a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ 675a8e1175bSopenharmony_ci 676a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen)); 677a8e1175bSopenharmony_ci 678a8e1175bSopenharmony_cicleanup: 679a8e1175bSopenharmony_ci mbedtls_mpi_free(&r); 680a8e1175bSopenharmony_ci mbedtls_mpi_free(&s); 681a8e1175bSopenharmony_ci 682a8e1175bSopenharmony_ci return ret; 683a8e1175bSopenharmony_ci} 684a8e1175bSopenharmony_ci 685a8e1175bSopenharmony_ci/* 686a8e1175bSopenharmony_ci * Compute and write signature 687a8e1175bSopenharmony_ci */ 688a8e1175bSopenharmony_ciint mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, 689a8e1175bSopenharmony_ci mbedtls_md_type_t md_alg, 690a8e1175bSopenharmony_ci const unsigned char *hash, size_t hlen, 691a8e1175bSopenharmony_ci unsigned char *sig, size_t sig_size, size_t *slen, 692a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 693a8e1175bSopenharmony_ci void *p_rng) 694a8e1175bSopenharmony_ci{ 695a8e1175bSopenharmony_ci return mbedtls_ecdsa_write_signature_restartable( 696a8e1175bSopenharmony_ci ctx, md_alg, hash, hlen, sig, sig_size, slen, 697a8e1175bSopenharmony_ci f_rng, p_rng, NULL); 698a8e1175bSopenharmony_ci} 699a8e1175bSopenharmony_ci 700a8e1175bSopenharmony_ci/* 701a8e1175bSopenharmony_ci * Read and check signature 702a8e1175bSopenharmony_ci */ 703a8e1175bSopenharmony_ciint mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, 704a8e1175bSopenharmony_ci const unsigned char *hash, size_t hlen, 705a8e1175bSopenharmony_ci const unsigned char *sig, size_t slen) 706a8e1175bSopenharmony_ci{ 707a8e1175bSopenharmony_ci return mbedtls_ecdsa_read_signature_restartable( 708a8e1175bSopenharmony_ci ctx, hash, hlen, sig, slen, NULL); 709a8e1175bSopenharmony_ci} 710a8e1175bSopenharmony_ci 711a8e1175bSopenharmony_ci/* 712a8e1175bSopenharmony_ci * Restartable read and check signature 713a8e1175bSopenharmony_ci */ 714a8e1175bSopenharmony_ciint mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, 715a8e1175bSopenharmony_ci const unsigned char *hash, size_t hlen, 716a8e1175bSopenharmony_ci const unsigned char *sig, size_t slen, 717a8e1175bSopenharmony_ci mbedtls_ecdsa_restart_ctx *rs_ctx) 718a8e1175bSopenharmony_ci{ 719a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 720a8e1175bSopenharmony_ci unsigned char *p = (unsigned char *) sig; 721a8e1175bSopenharmony_ci const unsigned char *end = sig + slen; 722a8e1175bSopenharmony_ci size_t len; 723a8e1175bSopenharmony_ci mbedtls_mpi r, s; 724a8e1175bSopenharmony_ci mbedtls_mpi_init(&r); 725a8e1175bSopenharmony_ci mbedtls_mpi_init(&s); 726a8e1175bSopenharmony_ci 727a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 728a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 729a8e1175bSopenharmony_ci ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 730a8e1175bSopenharmony_ci goto cleanup; 731a8e1175bSopenharmony_ci } 732a8e1175bSopenharmony_ci 733a8e1175bSopenharmony_ci if (p + len != end) { 734a8e1175bSopenharmony_ci ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA, 735a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 736a8e1175bSopenharmony_ci goto cleanup; 737a8e1175bSopenharmony_ci } 738a8e1175bSopenharmony_ci 739a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 || 740a8e1175bSopenharmony_ci (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) { 741a8e1175bSopenharmony_ci ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 742a8e1175bSopenharmony_ci goto cleanup; 743a8e1175bSopenharmony_ci } 744a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_VERIFY_ALT) 745a8e1175bSopenharmony_ci (void) rs_ctx; 746a8e1175bSopenharmony_ci 747a8e1175bSopenharmony_ci if ((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen, 748a8e1175bSopenharmony_ci &ctx->Q, &r, &s)) != 0) { 749a8e1175bSopenharmony_ci goto cleanup; 750a8e1175bSopenharmony_ci } 751a8e1175bSopenharmony_ci#else 752a8e1175bSopenharmony_ci if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen, 753a8e1175bSopenharmony_ci &ctx->Q, &r, &s, rs_ctx)) != 0) { 754a8e1175bSopenharmony_ci goto cleanup; 755a8e1175bSopenharmony_ci } 756a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ 757a8e1175bSopenharmony_ci 758a8e1175bSopenharmony_ci /* At this point we know that the buffer starts with a valid signature. 759a8e1175bSopenharmony_ci * Return 0 if the buffer just contains the signature, and a specific 760a8e1175bSopenharmony_ci * error code if the valid signature is followed by more data. */ 761a8e1175bSopenharmony_ci if (p != end) { 762a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; 763a8e1175bSopenharmony_ci } 764a8e1175bSopenharmony_ci 765a8e1175bSopenharmony_cicleanup: 766a8e1175bSopenharmony_ci mbedtls_mpi_free(&r); 767a8e1175bSopenharmony_ci mbedtls_mpi_free(&s); 768a8e1175bSopenharmony_ci 769a8e1175bSopenharmony_ci return ret; 770a8e1175bSopenharmony_ci} 771a8e1175bSopenharmony_ci 772a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) 773a8e1175bSopenharmony_ci/* 774a8e1175bSopenharmony_ci * Generate key pair 775a8e1175bSopenharmony_ci */ 776a8e1175bSopenharmony_ciint mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, 777a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 778a8e1175bSopenharmony_ci{ 779a8e1175bSopenharmony_ci int ret = 0; 780a8e1175bSopenharmony_ci ret = mbedtls_ecp_group_load(&ctx->grp, gid); 781a8e1175bSopenharmony_ci if (ret != 0) { 782a8e1175bSopenharmony_ci return ret; 783a8e1175bSopenharmony_ci } 784a8e1175bSopenharmony_ci 785a8e1175bSopenharmony_ci return mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d, 786a8e1175bSopenharmony_ci &ctx->Q, f_rng, p_rng); 787a8e1175bSopenharmony_ci} 788a8e1175bSopenharmony_ci#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ 789a8e1175bSopenharmony_ci 790a8e1175bSopenharmony_ci/* 791a8e1175bSopenharmony_ci * Set context from an mbedtls_ecp_keypair 792a8e1175bSopenharmony_ci */ 793a8e1175bSopenharmony_ciint mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key) 794a8e1175bSopenharmony_ci{ 795a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 796a8e1175bSopenharmony_ci if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 || 797a8e1175bSopenharmony_ci (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 || 798a8e1175bSopenharmony_ci (ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) { 799a8e1175bSopenharmony_ci mbedtls_ecdsa_free(ctx); 800a8e1175bSopenharmony_ci } 801a8e1175bSopenharmony_ci 802a8e1175bSopenharmony_ci return ret; 803a8e1175bSopenharmony_ci} 804a8e1175bSopenharmony_ci 805a8e1175bSopenharmony_ci/* 806a8e1175bSopenharmony_ci * Initialize context 807a8e1175bSopenharmony_ci */ 808a8e1175bSopenharmony_civoid mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx) 809a8e1175bSopenharmony_ci{ 810a8e1175bSopenharmony_ci mbedtls_ecp_keypair_init(ctx); 811a8e1175bSopenharmony_ci} 812a8e1175bSopenharmony_ci 813a8e1175bSopenharmony_ci/* 814a8e1175bSopenharmony_ci * Free context 815a8e1175bSopenharmony_ci */ 816a8e1175bSopenharmony_civoid mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx) 817a8e1175bSopenharmony_ci{ 818a8e1175bSopenharmony_ci if (ctx == NULL) { 819a8e1175bSopenharmony_ci return; 820a8e1175bSopenharmony_ci } 821a8e1175bSopenharmony_ci 822a8e1175bSopenharmony_ci mbedtls_ecp_keypair_free(ctx); 823a8e1175bSopenharmony_ci} 824a8e1175bSopenharmony_ci 825a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE) 826a8e1175bSopenharmony_ci/* 827a8e1175bSopenharmony_ci * Initialize a restart context 828a8e1175bSopenharmony_ci */ 829a8e1175bSopenharmony_civoid mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx) 830a8e1175bSopenharmony_ci{ 831a8e1175bSopenharmony_ci mbedtls_ecp_restart_init(&ctx->ecp); 832a8e1175bSopenharmony_ci 833a8e1175bSopenharmony_ci ctx->ver = NULL; 834a8e1175bSopenharmony_ci ctx->sig = NULL; 835a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_DETERMINISTIC) 836a8e1175bSopenharmony_ci ctx->det = NULL; 837a8e1175bSopenharmony_ci#endif 838a8e1175bSopenharmony_ci} 839a8e1175bSopenharmony_ci 840a8e1175bSopenharmony_ci/* 841a8e1175bSopenharmony_ci * Free the components of a restart context 842a8e1175bSopenharmony_ci */ 843a8e1175bSopenharmony_civoid mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx) 844a8e1175bSopenharmony_ci{ 845a8e1175bSopenharmony_ci if (ctx == NULL) { 846a8e1175bSopenharmony_ci return; 847a8e1175bSopenharmony_ci } 848a8e1175bSopenharmony_ci 849a8e1175bSopenharmony_ci mbedtls_ecp_restart_free(&ctx->ecp); 850a8e1175bSopenharmony_ci 851a8e1175bSopenharmony_ci ecdsa_restart_ver_free(ctx->ver); 852a8e1175bSopenharmony_ci mbedtls_free(ctx->ver); 853a8e1175bSopenharmony_ci ctx->ver = NULL; 854a8e1175bSopenharmony_ci 855a8e1175bSopenharmony_ci ecdsa_restart_sig_free(ctx->sig); 856a8e1175bSopenharmony_ci mbedtls_free(ctx->sig); 857a8e1175bSopenharmony_ci ctx->sig = NULL; 858a8e1175bSopenharmony_ci 859a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_DETERMINISTIC) 860a8e1175bSopenharmony_ci ecdsa_restart_det_free(ctx->det); 861a8e1175bSopenharmony_ci mbedtls_free(ctx->det); 862a8e1175bSopenharmony_ci ctx->det = NULL; 863a8e1175bSopenharmony_ci#endif 864a8e1175bSopenharmony_ci} 865a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECP_RESTARTABLE */ 866a8e1175bSopenharmony_ci 867a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECDSA_C */ 868