EC2M Lopez-Dahab ladder implementation
[openssl.git] / crypto / ec / ec_lib.c
index 883284b304a08fe50f37e00bf3478cf25c370e1e..6a2d1b5800fecc85cb130f34c8b7d6bc35fe515b 100644 (file)
@@ -1018,12 +1018,15 @@ int ec_group_simple_order_bits(const EC_GROUP *group)
 }
 
 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;
 
@@ -1031,32 +1034,22 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
     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)
@@ -1065,8 +1058,21 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
     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);