-/* some internal functions */
-
-static X9_62_FIELDID *ec_asn1_group2field(const EC_GROUP *, X9_62_FIELDID *);
-static X9_62_CURVE *ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
-static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *);
-static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,
- ECPARAMETERS *);
-EC_GROUP *EC_ASN1_pkparameters2group(const ECPKPARAMETERS *);
-ECPKPARAMETERS *EC_ASN1_group2pkparameters(const EC_GROUP *, ECPKPARAMETERS *);
-
-static X9_62_FIELDID *ec_asn1_group2field(const EC_GROUP *group,
- X9_62_FIELDID *field)
- {
- int ok=0, nid;
- X9_62_FIELDID *ret=NULL;
- BIGNUM *tmp=NULL;
-
- if (field == NULL)
- {
- if ((ret = X9_62_FIELDID_new()) == NULL)
- {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- }
- else
- {
- ret = field;
- if (ret->fieldType != NULL)
- ASN1_OBJECT_free(ret->fieldType);
- if (ret->parameters != NULL)
- ASN1_TYPE_free(ret->parameters);
- }
-
- nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
-
- if ((ret->fieldType = OBJ_nid2obj(nid)) == NULL)
- {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
- goto err;
- }
-
- if (nid == NID_X9_62_prime_field)
- {
- if ((tmp = BN_new()) == NULL)
- {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if ((ret->parameters = ASN1_TYPE_new()) == NULL)
- {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- ret->parameters->type = V_ASN1_INTEGER;
- if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL))
- {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
- goto err;
- }
- ret->parameters->value.integer = BN_to_ASN1_INTEGER(tmp, NULL);
- if (ret->parameters->value.integer == NULL)
- {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
- goto err;
- }
- }
- else
- goto err;
-
- ok = 1;
-
-err : if (!ok)
- {
- if (ret && !field)
- X9_62_FIELDID_free(ret);
- ret = NULL;
- }
- if (tmp)
- BN_free(tmp);
- return(ret);
+/* some declarations of internal function */
+
+/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */
+static int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
+/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */
+static int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
+
+/* the function definitions */
+
+static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
+{
+ int ok = 0, nid;
+ BIGNUM *tmp = NULL;
+
+ if (group == NULL || field == NULL)
+ return 0;
+
+ /* clear the old values (if necessary) */
+ ASN1_OBJECT_free(field->fieldType);
+ ASN1_TYPE_free(field->p.other);
+
+ nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
+ /* set OID for the field */
+ if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
+ goto err;
+ }
+
+ if (nid == NID_X9_62_prime_field) {
+ if ((tmp = BN_new()) == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ /* the parameters are specified by the prime number p */
+ if (!EC_GROUP_get_curve(group, tmp, NULL, NULL, NULL)) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
+ goto err;
+ }
+ /* set the prime number */
+ field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL);
+ if (field->p.prime == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ } else if (nid == NID_X9_62_characteristic_two_field)
+#ifdef OPENSSL_NO_EC2M
+ {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED);
+ goto err;
+ }
+#else
+ {
+ int field_type;
+ X9_62_CHARACTERISTIC_TWO *char_two;
+
+ field->p.char_two = X9_62_CHARACTERISTIC_TWO_new();
+ char_two = field->p.char_two;
+
+ if (char_two == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ char_two->m = (long)EC_GROUP_get_degree(group);
+
+ field_type = EC_GROUP_get_basis_type(group);
+
+ if (field_type == 0) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
+ goto err;
+ }
+ /* set base type OID */
+ if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
+ goto err;
+ }
+
+ if (field_type == NID_X9_62_tpBasis) {
+ unsigned int k;
+
+ if (!EC_GROUP_get_trinomial_basis(group, &k))
+ goto err;
+
+ char_two->p.tpBasis = ASN1_INTEGER_new();
+ if (char_two->p.tpBasis == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ } else if (field_type == NID_X9_62_ppBasis) {
+ unsigned int k1, k2, k3;
+
+ if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3))
+ goto err;
+
+ char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
+ if (char_two->p.ppBasis == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* set k? values */
+ char_two->p.ppBasis->k1 = (long)k1;
+ char_two->p.ppBasis->k2 = (long)k2;
+ char_two->p.ppBasis->k3 = (long)k3;
+ } else { /* field_type == NID_X9_62_onBasis */
+
+ /* for ONB the parameters are (asn1) NULL */
+ char_two->p.onBasis = ASN1_NULL_new();
+ if (char_two->p.onBasis == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ }
+#endif
+ else {
+ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_UNSUPPORTED_FIELD);
+ goto err;
+ }
+
+ ok = 1;
+
+ err:
+ BN_free(tmp);
+ return ok;
+}
+
+static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
+{
+ int ok = 0;
+ BIGNUM *tmp_1 = NULL, *tmp_2 = NULL;
+ unsigned char *a_buf = NULL, *b_buf = NULL;
+ size_t len;
+
+ if (!group || !curve || !curve->a || !curve->b)
+ return 0;
+
+ if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* get a and b */
+ if (!EC_GROUP_get_curve(group, NULL, tmp_1, tmp_2, NULL)) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /*
+ * Per SEC 1, the curve coefficients must be padded up to size. See C.2's
+ * definition of Curve, C.1's definition of FieldElement, and 2.3.5's
+ * definition of how to encode the field elements.
+ */
+ len = ((size_t)EC_GROUP_get_degree(group) + 7) / 8;
+ if ((a_buf = OPENSSL_malloc(len)) == NULL
+ || (b_buf = OPENSSL_malloc(len)) == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (BN_bn2binpad(tmp_1, a_buf, len) < 0
+ || BN_bn2binpad(tmp_2, b_buf, len) < 0) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ /* set a and b */
+ if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len)
+ || !ASN1_OCTET_STRING_set(curve->b, b_buf, len)) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ /* set the seed (optional) */
+ if (group->seed) {
+ if (!curve->seed)
+ if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
+ (int)group->seed_len)) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ } else {
+ ASN1_BIT_STRING_free(curve->seed);
+ curve->seed = NULL;
+ }
+
+ ok = 1;
+
+ err:
+ OPENSSL_free(a_buf);
+ OPENSSL_free(b_buf);
+ BN_free(tmp_1);
+ BN_free(tmp_2);
+ return ok;
+}
+
+ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
+ ECPARAMETERS *params)
+{
+ size_t len = 0;
+ ECPARAMETERS *ret = NULL;
+ const BIGNUM *tmp;
+ unsigned char *buffer = NULL;
+ const EC_POINT *point = NULL;
+ point_conversion_form_t form;
+
+ if (params == NULL) {
+ if ((ret = ECPARAMETERS_new()) == NULL) {
+ ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ } else
+ ret = params;
+
+ /* set the version (always one) */
+ ret->version = (long)0x1;
+
+ /* set the fieldID */
+ if (!ec_asn1_group2fieldid(group, ret->fieldID)) {
+ ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /* set the curve */
+ if (!ec_asn1_group2curve(group, ret->curve)) {
+ ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /* set the base point */
+ if ((point = EC_GROUP_get0_generator(group)) == NULL) {
+ ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, EC_R_UNDEFINED_GENERATOR);
+ goto err;
+ }
+
+ form = EC_GROUP_get_point_conversion_form(group);
+
+ len = EC_POINT_point2buf(group, point, form, &buffer, NULL);
+ if (len == 0) {
+ ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) {
+ OPENSSL_free(buffer);
+ ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ASN1_STRING_set0(ret->base, buffer, len);
+
+ /* set the order */
+ tmp = EC_GROUP_get0_order(group);
+ if (tmp == NULL) {
+ ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB);
+ goto err;
+ }
+ ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
+ if (ret->order == NULL) {
+ ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ /* set the cofactor (optional) */
+ tmp = EC_GROUP_get0_cofactor(group);
+ if (tmp != NULL) {
+ ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
+ if (ret->cofactor == NULL) {
+ ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ }
+
+ return ret;
+
+ err:
+ if (params == NULL)
+ ECPARAMETERS_free(ret);
+ return NULL;