#define EC_F_EC_GROUP_CLEAR_FREE 103
#define EC_F_EC_GROUP_COPY 102
#define EC_F_EC_GROUP_FREE 104
+#define EC_F_EC_GROUP_GET_EXTRA_DATA 115
#define EC_F_EC_GROUP_NEW 100
#define EC_F_EC_GROUP_SET_CURVE_GFP 101
+#define EC_F_EC_GROUP_SET_EXTRA_DATA 116
#define EC_F_EC_GROUP_SET_GENERATOR 106
#define EC_F_EC_POINT_ADD 107
#define EC_F_EC_POINT_COPY 108
/* Reason codes. */
#define EC_R_INCOMPATIBLE_OBJECTS 100
+#define EC_R_NO_SUCH_EXTRA_DATA 101
+#define EC_R_SLOT_FULL 102
#ifdef __cplusplus
}
{ERR_PACK(0,EC_F_EC_GROUP_CLEAR_FREE,0), "EC_GROUP_clear_free"},
{ERR_PACK(0,EC_F_EC_GROUP_COPY,0), "EC_GROUP_copy"},
{ERR_PACK(0,EC_F_EC_GROUP_FREE,0), "EC_GROUP_free"},
+{ERR_PACK(0,EC_F_EC_GROUP_GET_EXTRA_DATA,0), "EC_GROUP_GET_EXTRA_DATA"},
{ERR_PACK(0,EC_F_EC_GROUP_NEW,0), "EC_GROUP_new"},
{ERR_PACK(0,EC_F_EC_GROUP_SET_CURVE_GFP,0), "EC_GROUP_set_curve_GFp"},
+{ERR_PACK(0,EC_F_EC_GROUP_SET_EXTRA_DATA,0), "EC_GROUP_SET_EXTRA_DATA"},
{ERR_PACK(0,EC_F_EC_GROUP_SET_GENERATOR,0), "EC_GROUP_set_generator"},
{ERR_PACK(0,EC_F_EC_POINT_ADD,0), "EC_POINT_add"},
{ERR_PACK(0,EC_F_EC_POINT_COPY,0), "EC_POINT_copy"},
static ERR_STRING_DATA EC_str_reasons[]=
{
{EC_R_INCOMPATIBLE_OBJECTS ,"incompatible objects"},
+{EC_R_NO_SUCH_EXTRA_DATA ,"no such extra data"},
+{EC_R_SLOT_FULL ,"slot full"},
{0,NULL}
};
struct ec_group_st {
const EC_METHOD *meth;
- /* All members except 'meth' are handled by the method functions,
- * even if they appear generic */
+ void *extra_data;
+ void *(*extra_data_dup_func)(void *);
+ void (*extra_data_free_func)(void *);
+ void (*extra_data_clear_free_func)(void *);
+
+ /* All members except 'meth' and 'extra_data...' are handled by
+ * the method functions, even if they appear generic */
BIGNUM field; /* Field specification.
* For curves over GF(p), this is the modulus. */
} /* EC_GROUP */;
+/* Basically a 'mixin' for extra data, but available for EC_GROUPs only
+ * (with visibility limited to 'package' level for now).
+ * We use the function pointers as index for retrieval; this obviates
+ * global ex_data-style index tables.
+ * (Currently, we have one slot only, but is is possible to extend this
+ * if necessary.) */
+
+int EC_GROUP_set_extra_data(EC_GROUP *, void *extra_data, void *(*extra_data_dup_func)(void *),
+ void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *));
+void *EC_GROUP_get_extra_data(EC_GROUP *, void *(*extra_data_dup_func)(void *),
+ void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *));
+void EC_GROUP_free_extra_data(EC_GROUP *);
+void EC_GROUP_clear_free_extra_data(EC_GROUP *);
+
+
+
struct ec_point_st {
const EC_METHOD *meth;
}
ret->meth = meth;
+
+ ret->extra_data = NULL;
+ ret->extra_data_dup_func = 0;
+ ret->extra_data_free_func = 0;
+ ret->extra_data_clear_free_func = 0;
if (!meth->group_init(ret))
{
{
if (group->meth->group_finish != 0)
group->meth->group_finish(group);
+
+ EC_GROUP_free_extra_data(group);
+
OPENSSL_free(group);
}
group->meth->group_clear_finish(group);
else if (group->meth != NULL && group->meth->group_finish != 0)
group->meth->group_finish(group);
+
+ EC_GROUP_clear_free_extra_data(group);
+
memset(group, 0, sizeof *group);
OPENSSL_free(group);
}
return 0;
}
+ EC_GROUP_clear_free_extra_data(dest);
+ if (src->extra_data_dup_func)
+ {
+ if (src->extra_data != NULL)
+ {
+ dest->extra_data = src->extra_data_dup_func(src->extra_data);
+ if (dest->extra_data == NULL)
+ return 0;
+ }
+
+ dest->extra_data_dup_func = src->extra_data_dup_func;
+ dest->extra_data_free_func = src->extra_data_free_func;
+ dest->extra_data_clear_free_func = src->extra_data_clear_free_func;
+ }
+
return dest->meth->group_copy(dest, src);
}
/* TODO: 'get' functions for EC_GROUPs */
+/* this has 'package' visibility */
+int EC_GROUP_set_extra_data(EC_GROUP *group, void *extra_data, void *(*extra_data_dup_func)(void *),
+ void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *))
+ {
+ if ((group->extra_data != NULL)
+ || (group->extra_data_dup_func != 0)
+ || (group->extra_data_free_func != 0)
+ || (group->extra_data_clear_free_func != 0))
+ {
+ ECerr(EC_F_EC_GROUP_SET_EXTRA_DATA, EC_R_SLOT_FULL);
+ return 0;
+ }
+
+ group->extra_data = extra_data;
+ group->extra_data_dup_func = extra_data_dup_func;
+ group->extra_data_free_func = extra_data_free_func;
+ group->extra_data_clear_free_func = extra_data_clear_free_func;
+ return 1;
+ }
+
+
+/* this has 'package' visibility */
+void *EC_GROUP_get_extra_data(EC_GROUP *group, void *(*extra_data_dup_func)(void *),
+ void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *))
+ {
+ if ((group->extra_data_dup_func != extra_data_dup_func)
+ || (group->extra_data_free_func != extra_data_free_func)
+ || (group->extra_data_clear_free_func != extra_data_clear_free_func))
+ {
+ ECerr(EC_F_EC_GROUP_GET_EXTRA_DATA, EC_R_NO_SUCH_EXTRA_DATA);
+ return NULL;
+ }
+
+ return group->extra_data;
+ }
+
+
+/* this has 'package' visibility */
+void EC_GROUP_free_extra_data(EC_GROUP *group)
+ {
+ if (group->extra_data_free_func)
+ group->extra_data_free_func(group->extra_data);
+ group->extra_data = NULL;
+ group->extra_data_dup_func = 0;
+ group->extra_data_free_func = 0;
+ group->extra_data_clear_free_func = 0;
+ }
+
+
+/* this has 'package' visibility */
+void EC_GROUP_clear_free_extra_data(EC_GROUP *group)
+ {
+ if (group->extra_data_clear_free_func)
+ group->extra_data_clear_free_func(group->extra_data);
+ else if (group->extra_data_free_func)
+ group->extra_data_free_func(group->extra_data);
+ group->extra_data = NULL;
+ group->extra_data_dup_func = 0;
+ group->extra_data_free_func = 0;
+ group->extra_data_clear_free_func = 0;
+ }
+
+
/* functions for EC_POINT objects */