int (*ecdh_compute_key)(unsigned char **pout, size_t *poutlen,
const EC_POINT *pub_key, const EC_KEY *ecdh);
/* Inverse modulo order */
- int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r, BIGNUM *x,
- BN_CTX *ctx);
+ int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r,
+ const BIGNUM *x, BN_CTX *);
int (*blind_coordinates)(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
};
void X25519_public_from_private(uint8_t out_public_value[32],
const uint8_t private_key[32]);
-int EC_GROUP_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
- BIGNUM *x, BN_CTX *ctx);
+int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
+ const BIGNUM *x, BN_CTX *ctx);
int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
}
static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
- BIGNUM *x, BN_CTX *ctx)
+ const BIGNUM *x, BN_CTX *ctx)
{
BIGNUM *e = NULL;
BN_CTX *new_ctx = NULL;
int ret = 0;
+ if (group->mont_data == NULL)
+ return 0;
+
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
return 0;
if ((e = BN_CTX_get(ctx)) == NULL)
goto err;
- /* Check if optimized inverse is implemented */
- if (group->mont_data != NULL) {
- /*-
- * We want inverse in constant time, therefore we utilize the fact
- * order must be prime and use Fermats Little Theorem instead.
- */
- if (!BN_set_word(e, 2))
- goto err;
- if (!BN_sub(e, group->order, e))
- goto err;
- /*-
- * Exponent e is public.
- * No need for scatter-gather or BN_FLG_CONSTTIME.
- */
- if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
- goto err;
- /* Inverse of zero doesn't exist. Let the fallback catch it. */
- ret = (BN_is_zero(r)) ? 0 : 1;
- }
+ /*-
+ * We want inverse in constant time, therefore we utilize the fact
+ * order must be prime and use Fermats Little Theorem instead.
+ */
+ if (!BN_set_word(e, 2))
+ goto err;
+ if (!BN_sub(e, group->order, e))
+ goto err;
+ /*-
+ * Exponent e is public.
+ * No need for scatter-gather or BN_FLG_CONSTTIME.
+ */
+ if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
+ goto err;
- /* Fallback to classic inverse */
- if (ret == 0) {
- if (!BN_mod_inverse(r, x, group->order, ctx))
- goto err;
- ret = 1;
- }
+ ret = 1;
err:
if (ctx != NULL)
return ret;
}
-int EC_GROUP_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
- BIGNUM *x, BN_CTX *ctx)
+/*-
+ * Default behavior, if group->meth->field_inverse_mod_ord is NULL:
+ * - When group->order is even, this function returns an error.
+ * - When group->order is otherwise composite, the correctness
+ * of the output is not guaranteed.
+ * - When x is outside the range [1, group->order), the correctness
+ * of the output is not guaranteed.
+ * - Otherwise, this function returns the multiplicative inverse in the
+ * range [1, group->order).
+ *
+ * EC_METHODs must implement their own field_inverse_mod_ord for
+ * other functionality.
+ */
+int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
+ const BIGNUM *x, BN_CTX *ctx)
{
if (group->meth->field_inverse_mod_ord != NULL)
return group->meth->field_inverse_mod_ord(group, res, x, ctx);
while (BN_is_zero(r));
/* compute the inverse of k */
- if (!EC_GROUP_do_inverse_ord(group, k, k, ctx)) {
+ if (!ec_group_do_inverse_ord(group, k, k, ctx)) {
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
goto err;
}
goto err;
}
/* calculate tmp1 = inv(S) mod order */
- if (!EC_GROUP_do_inverse_ord(group, u2, sig->s, ctx)) {
+ if (!ec_group_do_inverse_ord(group, u2, sig->s, ctx)) {
ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
goto err;
}