- {
- int r = 0;
- BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
- BN_CTX *ctx_new = NULL;
-
- /* compare the field types*/
- if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
- EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
- return 1;
- /* compare the curve name (if present in both) */
- if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
- EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
- return 1;
-
- if (!ctx)
- ctx_new = ctx = BN_CTX_new();
- if (!ctx)
- return -1;
-
- BN_CTX_start(ctx);
- a1 = BN_CTX_get(ctx);
- a2 = BN_CTX_get(ctx);
- a3 = BN_CTX_get(ctx);
- b1 = BN_CTX_get(ctx);
- b2 = BN_CTX_get(ctx);
- b3 = BN_CTX_get(ctx);
- if (!b3)
- {
- BN_CTX_end(ctx);
- if (ctx_new)
- BN_CTX_free(ctx);
- return -1;
- }
-
- /* XXX This approach assumes that the external representation
- * of curves over the same field type is the same.
- */
- if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
- !b->meth->group_get_curve(b, b1, b2, b3, ctx))
- r = 1;
-
- if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
- r = 1;
-
- /* XXX EC_POINT_cmp() assumes that the methods are equal */
- if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
- EC_GROUP_get0_generator(b), ctx))
- r = 1;
-
- if (!r)
- {
- /* compare the order and cofactor */
- if (!EC_GROUP_get_order(a, a1, ctx) ||
- !EC_GROUP_get_order(b, b1, ctx) ||
- !EC_GROUP_get_cofactor(a, a2, ctx) ||
- !EC_GROUP_get_cofactor(b, b2, ctx))
- {
- BN_CTX_end(ctx);
- if (ctx_new)
- BN_CTX_free(ctx);
- return -1;
- }
- if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
- r = 1;
- }
-
- BN_CTX_end(ctx);
- if (ctx_new)
- BN_CTX_free(ctx);
-
- return r;
- }
-
-
-/* this has 'package' visibility */
-int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
- void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
- {
- EC_EXTRA_DATA *d;
-
- if (ex_data == NULL)
- return 0;
-
- for (d = *ex_data; d != NULL; d = d->next)
- {
- if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
- {
- ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
- return 0;
- }
- }
-
- if (data == NULL)
- /* no explicit entry needed */
- return 1;
-
- d = OPENSSL_malloc(sizeof *d);
- if (d == NULL)
- return 0;
-
- d->data = data;
- d->dup_func = dup_func;
- d->free_func = free_func;
- d->clear_free_func = clear_free_func;
-
- d->next = *ex_data;
- *ex_data = d;
-
- return 1;
- }
-
-/* this has 'package' visibility */
-void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
- void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
- {
- const EC_EXTRA_DATA *d;
-
- for (d = ex_data; d != NULL; d = d->next)
- {
- if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
- return d->data;
- }
-
- return NULL;
- }
-
-/* this has 'package' visibility */
-void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
- void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
- {
- EC_EXTRA_DATA **p;
-
- if (ex_data == NULL)
- return;
-
- for (p = ex_data; *p != NULL; p = &((*p)->next))
- {
- if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
- {
- EC_EXTRA_DATA *next = (*p)->next;
-
- (*p)->free_func((*p)->data);
- OPENSSL_free(*p);
-
- *p = next;
- return;
- }
- }
- }
-
-/* this has 'package' visibility */
-void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
- void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
- {
- EC_EXTRA_DATA **p;
-
- if (ex_data == NULL)
- return;
-
- for (p = ex_data; *p != NULL; p = &((*p)->next))
- {
- if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
- {
- EC_EXTRA_DATA *next = (*p)->next;
-
- (*p)->clear_free_func((*p)->data);
- OPENSSL_free(*p);
-
- *p = next;
- return;
- }
- }
- }
-
-/* this has 'package' visibility */
-void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
- {
- EC_EXTRA_DATA *d;
-
- if (ex_data == NULL)
- return;
-
- d = *ex_data;
- while (d)
- {
- EC_EXTRA_DATA *next = d->next;
-
- d->free_func(d->data);
- OPENSSL_free(d);
-
- d = next;
- }
- *ex_data = NULL;
- }
-
-/* this has 'package' visibility */
-void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
- {
- EC_EXTRA_DATA *d;
-
- if (ex_data == NULL)
- return;
-
- d = *ex_data;
- while (d)
- {
- EC_EXTRA_DATA *next = d->next;
-
- d->clear_free_func(d->data);
- OPENSSL_free(d);
-
- d = next;
- }
- *ex_data = NULL;
- }
+{
+ int r = 0;
+ BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
+ BN_CTX *ctx_new = NULL;
+
+ /* compare the field types */
+ if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
+ EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
+ return 1;
+ /* compare the curve name (if present in both) */
+ if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
+ EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
+ return 1;
+ if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
+ return 0;
+
+ if (ctx == NULL)
+ ctx_new = ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return -1;
+
+ BN_CTX_start(ctx);
+ a1 = BN_CTX_get(ctx);
+ a2 = BN_CTX_get(ctx);
+ a3 = BN_CTX_get(ctx);
+ b1 = BN_CTX_get(ctx);
+ b2 = BN_CTX_get(ctx);
+ b3 = BN_CTX_get(ctx);
+ if (b3 == NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx_new);
+ return -1;
+ }
+
+ /*
+ * XXX This approach assumes that the external representation of curves
+ * over the same field type is the same.
+ */
+ if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
+ !b->meth->group_get_curve(b, b1, b2, b3, ctx))
+ r = 1;
+
+ if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
+ r = 1;
+
+ /* XXX EC_POINT_cmp() assumes that the methods are equal */
+ if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
+ EC_GROUP_get0_generator(b), ctx))
+ r = 1;
+
+ if (!r) {
+ const BIGNUM *ao, *bo, *ac, *bc;
+ /* compare the order and cofactor */
+ ao = EC_GROUP_get0_order(a);
+ bo = EC_GROUP_get0_order(b);
+ ac = EC_GROUP_get0_cofactor(a);
+ bc = EC_GROUP_get0_cofactor(b);
+ if (ao == NULL || bo == NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx_new);
+ return -1;
+ }
+ if (BN_cmp(ao, bo) || BN_cmp(ac, bc))
+ r = 1;
+ }