int dslink_handshake_generate_key_pair(mbedtls_ecdh_context *ctx) { mbedtls_entropy_context ent; mbedtls_entropy_init(&ent); mbedtls_ecdh_init(ctx); int ret = 0; if ((ret = dslink_handshake_get_group(&ctx->grp)) != 0) { goto exit; } if ((errno = mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d, &ctx->Q, mbedtls_entropy_func, &ent)) != 0) { ret = DSLINK_CRYPT_KEY_PAIR_GEN_ERR; goto exit; } exit: mbedtls_entropy_free(&ent); return ret; }
/* * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair */ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); }
/* * Generate key pair */ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { return( mbedtls_ecp_group_load( &ctx->grp, gid ) || mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); }
/* * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) */ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, key_tries, sign_tries, blind_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); sign_tries = 0; do { /* * Steps 1-3: generate a suitable ephemeral keypair * and set r = xR mod n */ key_tries = 0; do { MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); if( key_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } } while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); /* * Step 5: derive MPI from hashed message */ MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); /* * Generate a random value to blind inv_mod in next step, * avoiding a potential timing leak. */ blind_tries = 0; do { size_t n_size = ( grp->nbits + 7 ) / 8; MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); /* See mbedtls_ecp_gen_keypair() */ if( ++blind_tries > 30 ) return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); } while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); /* * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); if( sign_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } } while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); cleanup: mbedtls_ecp_point_free( &R ); mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); return( ret ); }