ec_asn1.c revision 160814
1160814Ssimon/* crypto/ec/ec_asn1.c */
2160814Ssimon/*
3160814Ssimon * Written by Nils Larsch for the OpenSSL project.
4160814Ssimon */
5160814Ssimon/* ====================================================================
6160814Ssimon * Copyright (c) 2000-2003 The OpenSSL Project.  All rights reserved.
7160814Ssimon *
8160814Ssimon * Redistribution and use in source and binary forms, with or without
9160814Ssimon * modification, are permitted provided that the following conditions
10160814Ssimon * are met:
11160814Ssimon *
12160814Ssimon * 1. Redistributions of source code must retain the above copyright
13160814Ssimon *    notice, this list of conditions and the following disclaimer.
14160814Ssimon *
15160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
16160814Ssimon *    notice, this list of conditions and the following disclaimer in
17160814Ssimon *    the documentation and/or other materials provided with the
18160814Ssimon *    distribution.
19160814Ssimon *
20160814Ssimon * 3. All advertising materials mentioning features or use of this
21160814Ssimon *    software must display the following acknowledgment:
22160814Ssimon *    "This product includes software developed by the OpenSSL Project
23160814Ssimon *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24160814Ssimon *
25160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26160814Ssimon *    endorse or promote products derived from this software without
27160814Ssimon *    prior written permission. For written permission, please contact
28160814Ssimon *    licensing@OpenSSL.org.
29160814Ssimon *
30160814Ssimon * 5. Products derived from this software may not be called "OpenSSL"
31160814Ssimon *    nor may "OpenSSL" appear in their names without prior written
32160814Ssimon *    permission of the OpenSSL Project.
33160814Ssimon *
34160814Ssimon * 6. Redistributions of any form whatsoever must retain the following
35160814Ssimon *    acknowledgment:
36160814Ssimon *    "This product includes software developed by the OpenSSL Project
37160814Ssimon *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38160814Ssimon *
39160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42160814Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
51160814Ssimon * ====================================================================
52160814Ssimon *
53160814Ssimon * This product includes cryptographic software written by Eric Young
54160814Ssimon * (eay@cryptsoft.com).  This product includes software written by Tim
55160814Ssimon * Hudson (tjh@cryptsoft.com).
56160814Ssimon *
57160814Ssimon */
58160814Ssimon
59160814Ssimon#include <string.h>
60160814Ssimon#include "ec_lcl.h"
61160814Ssimon#include <openssl/err.h>
62160814Ssimon#include <openssl/asn1t.h>
63160814Ssimon#include <openssl/objects.h>
64160814Ssimon
65160814Ssimon
66160814Ssimonint EC_GROUP_get_basis_type(const EC_GROUP *group)
67160814Ssimon	{
68160814Ssimon	int i=0;
69160814Ssimon
70160814Ssimon	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
71160814Ssimon		NID_X9_62_characteristic_two_field)
72160814Ssimon		/* everything else is currently not supported */
73160814Ssimon		return 0;
74160814Ssimon
75160814Ssimon	while (group->poly[i] != 0)
76160814Ssimon		i++;
77160814Ssimon
78160814Ssimon	if (i == 4)
79160814Ssimon		return NID_X9_62_ppBasis;
80160814Ssimon	else if (i == 2)
81160814Ssimon		return NID_X9_62_tpBasis;
82160814Ssimon	else
83160814Ssimon		/* everything else is currently not supported */
84160814Ssimon		return 0;
85160814Ssimon	}
86160814Ssimon
87160814Ssimonint EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
88160814Ssimon	{
89160814Ssimon	if (group == NULL)
90160814Ssimon		return 0;
91160814Ssimon
92160814Ssimon	if (EC_GROUP_method_of(group)->group_set_curve != ec_GF2m_simple_group_set_curve
93160814Ssimon	    || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] == 0)))
94160814Ssimon		{
95160814Ssimon		ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
96160814Ssimon		return 0;
97160814Ssimon		}
98160814Ssimon
99160814Ssimon	if (k)
100160814Ssimon		*k = group->poly[1];
101160814Ssimon
102160814Ssimon	return 1;
103160814Ssimon	}
104160814Ssimon
105160814Ssimonint EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
106160814Ssimon	unsigned int *k2, unsigned int *k3)
107160814Ssimon	{
108160814Ssimon	if (group == NULL)
109160814Ssimon		return 0;
110160814Ssimon
111160814Ssimon	if (EC_GROUP_method_of(group)->group_set_curve != ec_GF2m_simple_group_set_curve
112160814Ssimon	    || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] != 0) && (group->poly[3] != 0) && (group->poly[4] == 0)))
113160814Ssimon		{
114160814Ssimon		ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
115160814Ssimon		return 0;
116160814Ssimon		}
117160814Ssimon
118160814Ssimon	if (k1)
119160814Ssimon		*k1 = group->poly[3];
120160814Ssimon	if (k2)
121160814Ssimon		*k2 = group->poly[2];
122160814Ssimon	if (k3)
123160814Ssimon		*k3 = group->poly[1];
124160814Ssimon
125160814Ssimon	return 1;
126160814Ssimon	}
127160814Ssimon
128160814Ssimon
129160814Ssimon
130160814Ssimon/* some structures needed for the asn1 encoding */
131160814Ssimontypedef struct x9_62_pentanomial_st {
132160814Ssimon	long k1;
133160814Ssimon	long k2;
134160814Ssimon	long k3;
135160814Ssimon	} X9_62_PENTANOMIAL;
136160814Ssimon
137160814Ssimontypedef struct x9_62_characteristic_two_st {
138160814Ssimon	long m;
139160814Ssimon	ASN1_OBJECT  *type;
140160814Ssimon	union	{
141160814Ssimon		char *ptr;
142160814Ssimon		/* NID_X9_62_onBasis */
143160814Ssimon		ASN1_NULL    *onBasis;
144160814Ssimon		/* NID_X9_62_tpBasis */
145160814Ssimon		ASN1_INTEGER *tpBasis;
146160814Ssimon		/* NID_X9_62_ppBasis */
147160814Ssimon		X9_62_PENTANOMIAL *ppBasis;
148160814Ssimon		/* anything else */
149160814Ssimon		ASN1_TYPE *other;
150160814Ssimon		} p;
151160814Ssimon	} X9_62_CHARACTERISTIC_TWO;
152160814Ssimon
153160814Ssimontypedef struct x9_62_fieldid_st {
154160814Ssimon        ASN1_OBJECT *fieldType;
155160814Ssimon	union	{
156160814Ssimon		char *ptr;
157160814Ssimon		/* NID_X9_62_prime_field */
158160814Ssimon		ASN1_INTEGER *prime;
159160814Ssimon		/* NID_X9_62_characteristic_two_field */
160160814Ssimon		X9_62_CHARACTERISTIC_TWO *char_two;
161160814Ssimon		/* anything else */
162160814Ssimon		ASN1_TYPE *other;
163160814Ssimon		} p;
164160814Ssimon	} X9_62_FIELDID;
165160814Ssimon
166160814Ssimontypedef struct x9_62_curve_st {
167160814Ssimon        ASN1_OCTET_STRING *a;
168160814Ssimon        ASN1_OCTET_STRING *b;
169160814Ssimon        ASN1_BIT_STRING   *seed;
170160814Ssimon        } X9_62_CURVE;
171160814Ssimon
172160814Ssimontypedef struct ec_parameters_st {
173160814Ssimon        long              version;
174160814Ssimon        X9_62_FIELDID     *fieldID;
175160814Ssimon        X9_62_CURVE       *curve;
176160814Ssimon        ASN1_OCTET_STRING *base;
177160814Ssimon        ASN1_INTEGER      *order;
178160814Ssimon        ASN1_INTEGER      *cofactor;
179160814Ssimon        } ECPARAMETERS;
180160814Ssimon
181160814Ssimonstruct ecpk_parameters_st {
182160814Ssimon	int	type;
183160814Ssimon	union {
184160814Ssimon		ASN1_OBJECT  *named_curve;
185160814Ssimon		ECPARAMETERS *parameters;
186160814Ssimon		ASN1_NULL    *implicitlyCA;
187160814Ssimon	} value;
188160814Ssimon	}/* ECPKPARAMETERS */;
189160814Ssimon
190160814Ssimon/* SEC1 ECPrivateKey */
191160814Ssimontypedef struct ec_privatekey_st {
192160814Ssimon	long              version;
193160814Ssimon	ASN1_OCTET_STRING *privateKey;
194160814Ssimon        ECPKPARAMETERS    *parameters;
195160814Ssimon	ASN1_BIT_STRING   *publicKey;
196160814Ssimon	} EC_PRIVATEKEY;
197160814Ssimon
198160814Ssimon/* the OpenSSL ASN.1 definitions */
199160814SsimonASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
200160814Ssimon	ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG),
201160814Ssimon	ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG),
202160814Ssimon	ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG)
203160814Ssimon} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL)
204160814Ssimon
205160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
206160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
207160814Ssimon
208160814SsimonASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY);
209160814Ssimon
210160814SsimonASN1_ADB(X9_62_CHARACTERISTIC_TWO) = {
211160814Ssimon	ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)),
212160814Ssimon	ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)),
213160814Ssimon	ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL))
214160814Ssimon} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL);
215160814Ssimon
216160814SsimonASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = {
217160814Ssimon	ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG),
218160814Ssimon	ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
219160814Ssimon	ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO)
220160814Ssimon} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO)
221160814Ssimon
222160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
223160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
224160814Ssimon
225160814SsimonASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
226160814Ssimon
227160814SsimonASN1_ADB(X9_62_FIELDID) = {
228160814Ssimon	ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
229160814Ssimon	ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO))
230160814Ssimon} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
231160814Ssimon
232160814SsimonASN1_SEQUENCE(X9_62_FIELDID) = {
233160814Ssimon	ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
234160814Ssimon	ASN1_ADB_OBJECT(X9_62_FIELDID)
235160814Ssimon} ASN1_SEQUENCE_END(X9_62_FIELDID)
236160814Ssimon
237160814SsimonASN1_SEQUENCE(X9_62_CURVE) = {
238160814Ssimon	ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
239160814Ssimon	ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
240160814Ssimon	ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
241160814Ssimon} ASN1_SEQUENCE_END(X9_62_CURVE)
242160814Ssimon
243160814SsimonASN1_SEQUENCE(ECPARAMETERS) = {
244160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, version, LONG),
245160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
246160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
247160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
248160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
249160814Ssimon	ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
250160814Ssimon} ASN1_SEQUENCE_END(ECPARAMETERS)
251160814Ssimon
252160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
253160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
254160814Ssimon
255160814SsimonASN1_CHOICE(ECPKPARAMETERS) = {
256160814Ssimon	ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
257160814Ssimon	ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
258160814Ssimon	ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL)
259160814Ssimon} ASN1_CHOICE_END(ECPKPARAMETERS)
260160814Ssimon
261160814SsimonDECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
262160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS)
263160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
264160814Ssimon
265160814SsimonASN1_SEQUENCE(EC_PRIVATEKEY) = {
266160814Ssimon	ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
267160814Ssimon	ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
268160814Ssimon	ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
269160814Ssimon	ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
270160814Ssimon} ASN1_SEQUENCE_END(EC_PRIVATEKEY)
271160814Ssimon
272160814SsimonDECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
273160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY)
274160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
275160814Ssimon
276160814Ssimon/* some declarations of internal function */
277160814Ssimon
278160814Ssimon/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */
279160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
280160814Ssimon/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */
281160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
282160814Ssimon/* ec_asn1_parameters2group() creates a EC_GROUP object from a
283160814Ssimon * ECPARAMETERS object */
284160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *);
285160814Ssimon/* ec_asn1_group2parameters() creates a ECPARAMETERS object from a
286160814Ssimon * EC_GROUP object */
287160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,ECPARAMETERS *);
288160814Ssimon/* ec_asn1_pkparameters2group() creates a EC_GROUP object from a
289160814Ssimon * ECPKPARAMETERS object */
290160814Ssimonstatic EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *);
291160814Ssimon/* ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a
292160814Ssimon * EC_GROUP object */
293160814Ssimonstatic ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *,
294160814Ssimon	ECPKPARAMETERS *);
295160814Ssimon
296160814Ssimon
297160814Ssimon/* the function definitions */
298160814Ssimon
299160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
300160814Ssimon	{
301160814Ssimon	int			ok=0, nid;
302160814Ssimon	BIGNUM			*tmp = NULL;
303160814Ssimon
304160814Ssimon	if (group == NULL || field == NULL)
305160814Ssimon		return 0;
306160814Ssimon
307160814Ssimon	/* clear the old values (if necessary) */
308160814Ssimon	if (field->fieldType != NULL)
309160814Ssimon		ASN1_OBJECT_free(field->fieldType);
310160814Ssimon	if (field->p.other != NULL)
311160814Ssimon		ASN1_TYPE_free(field->p.other);
312160814Ssimon
313160814Ssimon	nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
314160814Ssimon	/* set OID for the field */
315160814Ssimon	if ((field->fieldType = OBJ_nid2obj(nid)) == NULL)
316160814Ssimon		{
317160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
318160814Ssimon		goto err;
319160814Ssimon		}
320160814Ssimon
321160814Ssimon	if (nid == NID_X9_62_prime_field)
322160814Ssimon		{
323160814Ssimon		if ((tmp = BN_new()) == NULL)
324160814Ssimon			{
325160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
326160814Ssimon			goto err;
327160814Ssimon			}
328160814Ssimon		/* the parameters are specified by the prime number p */
329160814Ssimon		if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL))
330160814Ssimon			{
331160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
332160814Ssimon			goto err;
333160814Ssimon			}
334160814Ssimon		/* set the prime number */
335160814Ssimon		field->p.prime = BN_to_ASN1_INTEGER(tmp,NULL);
336160814Ssimon		if (field->p.prime == NULL)
337160814Ssimon			{
338160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
339160814Ssimon			goto err;
340160814Ssimon			}
341160814Ssimon		}
342160814Ssimon	else	/* nid == NID_X9_62_characteristic_two_field */
343160814Ssimon		{
344160814Ssimon		int		field_type;
345160814Ssimon		X9_62_CHARACTERISTIC_TWO *char_two;
346160814Ssimon
347160814Ssimon		field->p.char_two = X9_62_CHARACTERISTIC_TWO_new();
348160814Ssimon		char_two = field->p.char_two;
349160814Ssimon
350160814Ssimon		if (char_two == NULL)
351160814Ssimon			{
352160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
353160814Ssimon			goto err;
354160814Ssimon			}
355160814Ssimon
356160814Ssimon		char_two->m = (long)EC_GROUP_get_degree(group);
357160814Ssimon
358160814Ssimon		field_type = EC_GROUP_get_basis_type(group);
359160814Ssimon
360160814Ssimon		if (field_type == 0)
361160814Ssimon			{
362160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
363160814Ssimon			goto err;
364160814Ssimon			}
365160814Ssimon		/* set base type OID */
366160814Ssimon		if ((char_two->type = OBJ_nid2obj(field_type)) == NULL)
367160814Ssimon			{
368160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
369160814Ssimon			goto err;
370160814Ssimon			}
371160814Ssimon
372160814Ssimon		if (field_type == NID_X9_62_tpBasis)
373160814Ssimon			{
374160814Ssimon			unsigned int k;
375160814Ssimon
376160814Ssimon			if (!EC_GROUP_get_trinomial_basis(group, &k))
377160814Ssimon				goto err;
378160814Ssimon
379160814Ssimon			char_two->p.tpBasis = ASN1_INTEGER_new();
380160814Ssimon			if (!char_two->p.tpBasis)
381160814Ssimon				{
382160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
383160814Ssimon				goto err;
384160814Ssimon				}
385160814Ssimon			if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k))
386160814Ssimon				{
387160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2FIELDID,
388160814Ssimon					ERR_R_ASN1_LIB);
389160814Ssimon				goto err;
390160814Ssimon				}
391160814Ssimon			}
392160814Ssimon		else if (field_type == NID_X9_62_ppBasis)
393160814Ssimon			{
394160814Ssimon			unsigned int k1, k2, k3;
395160814Ssimon
396160814Ssimon			if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3))
397160814Ssimon				goto err;
398160814Ssimon
399160814Ssimon			char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
400160814Ssimon			if (!char_two->p.ppBasis)
401160814Ssimon				{
402160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
403160814Ssimon				goto err;
404160814Ssimon				}
405160814Ssimon
406160814Ssimon			/* set k? values */
407160814Ssimon			char_two->p.ppBasis->k1 = (long)k1;
408160814Ssimon			char_two->p.ppBasis->k2 = (long)k2;
409160814Ssimon			char_two->p.ppBasis->k3 = (long)k3;
410160814Ssimon			}
411160814Ssimon		else /* field_type == NID_X9_62_onBasis */
412160814Ssimon			{
413160814Ssimon			/* for ONB the parameters are (asn1) NULL */
414160814Ssimon			char_two->p.onBasis = ASN1_NULL_new();
415160814Ssimon			if (!char_two->p.onBasis)
416160814Ssimon				{
417160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
418160814Ssimon				goto err;
419160814Ssimon				}
420160814Ssimon			}
421160814Ssimon		}
422160814Ssimon
423160814Ssimon	ok = 1;
424160814Ssimon
425160814Ssimonerr :	if (tmp)
426160814Ssimon		BN_free(tmp);
427160814Ssimon	return(ok);
428160814Ssimon}
429160814Ssimon
430160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
431160814Ssimon	{
432160814Ssimon	int           ok=0, nid;
433160814Ssimon	BIGNUM        *tmp_1=NULL, *tmp_2=NULL;
434160814Ssimon	unsigned char *buffer_1=NULL, *buffer_2=NULL,
435160814Ssimon	              *a_buf=NULL, *b_buf=NULL;
436160814Ssimon	size_t        len_1, len_2;
437160814Ssimon	unsigned char char_zero = 0;
438160814Ssimon
439160814Ssimon	if (!group || !curve || !curve->a || !curve->b)
440160814Ssimon		return 0;
441160814Ssimon
442160814Ssimon	if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL)
443160814Ssimon		{
444160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
445160814Ssimon		goto err;
446160814Ssimon		}
447160814Ssimon
448160814Ssimon	nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
449160814Ssimon
450160814Ssimon	/* get a and b */
451160814Ssimon	if (nid == NID_X9_62_prime_field)
452160814Ssimon		{
453160814Ssimon		if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL))
454160814Ssimon			{
455160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
456160814Ssimon			goto err;
457160814Ssimon			}
458160814Ssimon		}
459160814Ssimon	else	/* nid == NID_X9_62_characteristic_two_field */
460160814Ssimon		{
461160814Ssimon		if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL))
462160814Ssimon			{
463160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
464160814Ssimon			goto err;
465160814Ssimon			}
466160814Ssimon		}
467160814Ssimon
468160814Ssimon	len_1 = (size_t)BN_num_bytes(tmp_1);
469160814Ssimon	len_2 = (size_t)BN_num_bytes(tmp_2);
470160814Ssimon
471160814Ssimon	if (len_1 == 0)
472160814Ssimon		{
473160814Ssimon		/* len_1 == 0 => a == 0 */
474160814Ssimon		a_buf = &char_zero;
475160814Ssimon		len_1 = 1;
476160814Ssimon		}
477160814Ssimon	else
478160814Ssimon		{
479160814Ssimon		if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL)
480160814Ssimon			{
481160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE,
482160814Ssimon			      ERR_R_MALLOC_FAILURE);
483160814Ssimon			goto err;
484160814Ssimon			}
485160814Ssimon		if ( (len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0)
486160814Ssimon			{
487160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
488160814Ssimon			goto err;
489160814Ssimon			}
490160814Ssimon		a_buf = buffer_1;
491160814Ssimon		}
492160814Ssimon
493160814Ssimon	if (len_2 == 0)
494160814Ssimon		{
495160814Ssimon		/* len_2 == 0 => b == 0 */
496160814Ssimon		b_buf = &char_zero;
497160814Ssimon		len_2 = 1;
498160814Ssimon		}
499160814Ssimon	else
500160814Ssimon		{
501160814Ssimon		if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL)
502160814Ssimon			{
503160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE,
504160814Ssimon			      ERR_R_MALLOC_FAILURE);
505160814Ssimon			goto err;
506160814Ssimon			}
507160814Ssimon		if ( (len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0)
508160814Ssimon			{
509160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
510160814Ssimon			goto err;
511160814Ssimon			}
512160814Ssimon		b_buf = buffer_2;
513160814Ssimon		}
514160814Ssimon
515160814Ssimon	/* set a and b */
516160814Ssimon	if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
517160814Ssimon	    !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2))
518160814Ssimon		{
519160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
520160814Ssimon		goto err;
521160814Ssimon		}
522160814Ssimon
523160814Ssimon	/* set the seed (optional) */
524160814Ssimon	if (group->seed)
525160814Ssimon		{
526160814Ssimon		if (!curve->seed)
527160814Ssimon			if ((curve->seed = ASN1_BIT_STRING_new()) == NULL)
528160814Ssimon				{
529160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
530160814Ssimon				goto err;
531160814Ssimon				}
532160814Ssimon		if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
533160814Ssimon		                         (int)group->seed_len))
534160814Ssimon			{
535160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
536160814Ssimon			goto err;
537160814Ssimon			}
538160814Ssimon		}
539160814Ssimon	else
540160814Ssimon		{
541160814Ssimon		if (curve->seed)
542160814Ssimon			{
543160814Ssimon			ASN1_BIT_STRING_free(curve->seed);
544160814Ssimon			curve->seed = NULL;
545160814Ssimon			}
546160814Ssimon		}
547160814Ssimon
548160814Ssimon	ok = 1;
549160814Ssimon
550160814Ssimonerr:	if (buffer_1)
551160814Ssimon		OPENSSL_free(buffer_1);
552160814Ssimon	if (buffer_2)
553160814Ssimon		OPENSSL_free(buffer_2);
554160814Ssimon	if (tmp_1)
555160814Ssimon		BN_free(tmp_1);
556160814Ssimon	if (tmp_2)
557160814Ssimon		BN_free(tmp_2);
558160814Ssimon	return(ok);
559160814Ssimon	}
560160814Ssimon
561160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group,
562160814Ssimon                                              ECPARAMETERS *param)
563160814Ssimon	{
564160814Ssimon	int	ok=0;
565160814Ssimon	size_t  len=0;
566160814Ssimon	ECPARAMETERS   *ret=NULL;
567160814Ssimon	BIGNUM	       *tmp=NULL;
568160814Ssimon	unsigned char  *buffer=NULL;
569160814Ssimon	const EC_POINT *point=NULL;
570160814Ssimon	point_conversion_form_t form;
571160814Ssimon
572160814Ssimon	if ((tmp = BN_new()) == NULL)
573160814Ssimon		{
574160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
575160814Ssimon		goto err;
576160814Ssimon		}
577160814Ssimon
578160814Ssimon	if (param == NULL)
579160814Ssimon	{
580160814Ssimon		if ((ret = ECPARAMETERS_new()) == NULL)
581160814Ssimon			{
582160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS,
583160814Ssimon			      ERR_R_MALLOC_FAILURE);
584160814Ssimon			goto err;
585160814Ssimon			}
586160814Ssimon	}
587160814Ssimon	else
588160814Ssimon		ret = param;
589160814Ssimon
590160814Ssimon	/* set the version (always one) */
591160814Ssimon	ret->version = (long)0x1;
592160814Ssimon
593160814Ssimon	/* set the fieldID */
594160814Ssimon	if (!ec_asn1_group2fieldid(group, ret->fieldID))
595160814Ssimon		{
596160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
597160814Ssimon		goto err;
598160814Ssimon		}
599160814Ssimon
600160814Ssimon	/* set the curve */
601160814Ssimon	if (!ec_asn1_group2curve(group, ret->curve))
602160814Ssimon		{
603160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
604160814Ssimon		goto err;
605160814Ssimon		}
606160814Ssimon
607160814Ssimon	/* set the base point */
608160814Ssimon	if ((point = EC_GROUP_get0_generator(group)) == NULL)
609160814Ssimon		{
610160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR);
611160814Ssimon		goto err;
612160814Ssimon		}
613160814Ssimon
614160814Ssimon	form = EC_GROUP_get_point_conversion_form(group);
615160814Ssimon
616160814Ssimon	len = EC_POINT_point2oct(group, point, form, NULL, len, NULL);
617160814Ssimon	if (len == 0)
618160814Ssimon		{
619160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
620160814Ssimon		goto err;
621160814Ssimon		}
622160814Ssimon	if ((buffer = OPENSSL_malloc(len)) == NULL)
623160814Ssimon		{
624160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
625160814Ssimon		goto err;
626160814Ssimon		}
627160814Ssimon	if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL))
628160814Ssimon		{
629160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
630160814Ssimon		goto err;
631160814Ssimon		}
632160814Ssimon	if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL)
633160814Ssimon		{
634160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
635160814Ssimon		goto err;
636160814Ssimon		}
637160814Ssimon	if (!ASN1_OCTET_STRING_set(ret->base, buffer, len))
638160814Ssimon		{
639160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
640160814Ssimon		goto err;
641160814Ssimon		}
642160814Ssimon
643160814Ssimon	/* set the order */
644160814Ssimon	if (!EC_GROUP_get_order(group, tmp, NULL))
645160814Ssimon		{
646160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
647160814Ssimon		goto err;
648160814Ssimon		}
649160814Ssimon	ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
650160814Ssimon	if (ret->order == NULL)
651160814Ssimon		{
652160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
653160814Ssimon		goto err;
654160814Ssimon		}
655160814Ssimon
656160814Ssimon	/* set the cofactor (optional) */
657160814Ssimon	if (EC_GROUP_get_cofactor(group, tmp, NULL))
658160814Ssimon		{
659160814Ssimon		ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
660160814Ssimon		if (ret->cofactor == NULL)
661160814Ssimon			{
662160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
663160814Ssimon			goto err;
664160814Ssimon			}
665160814Ssimon		}
666160814Ssimon
667160814Ssimon	ok = 1;
668160814Ssimon
669160814Ssimonerr :	if(!ok)
670160814Ssimon		{
671160814Ssimon		if (ret && !param)
672160814Ssimon			ECPARAMETERS_free(ret);
673160814Ssimon		ret = NULL;
674160814Ssimon		}
675160814Ssimon	if (tmp)
676160814Ssimon		BN_free(tmp);
677160814Ssimon	if (buffer)
678160814Ssimon		OPENSSL_free(buffer);
679160814Ssimon	return(ret);
680160814Ssimon	}
681160814Ssimon
682160814SsimonECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
683160814Ssimon                                           ECPKPARAMETERS *params)
684160814Ssimon	{
685160814Ssimon	int            ok = 1, tmp;
686160814Ssimon	ECPKPARAMETERS *ret = params;
687160814Ssimon
688160814Ssimon	if (ret == NULL)
689160814Ssimon		{
690160814Ssimon		if ((ret = ECPKPARAMETERS_new()) == NULL)
691160814Ssimon			{
692160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS,
693160814Ssimon			      ERR_R_MALLOC_FAILURE);
694160814Ssimon			return NULL;
695160814Ssimon			}
696160814Ssimon		}
697160814Ssimon	else
698160814Ssimon		{
699160814Ssimon		if (ret->type == 0 && ret->value.named_curve)
700160814Ssimon			ASN1_OBJECT_free(ret->value.named_curve);
701160814Ssimon		else if (ret->type == 1 && ret->value.parameters)
702160814Ssimon			ECPARAMETERS_free(ret->value.parameters);
703160814Ssimon		}
704160814Ssimon
705160814Ssimon	if (EC_GROUP_get_asn1_flag(group))
706160814Ssimon		{
707160814Ssimon		/* use the asn1 OID to describe the
708160814Ssimon		 * the elliptic curve parameters
709160814Ssimon		 */
710160814Ssimon		tmp = EC_GROUP_get_curve_name(group);
711160814Ssimon		if (tmp)
712160814Ssimon			{
713160814Ssimon			ret->type = 0;
714160814Ssimon			if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL)
715160814Ssimon				ok = 0;
716160814Ssimon			}
717160814Ssimon		else
718160814Ssimon			/* we don't kmow the nid => ERROR */
719160814Ssimon			ok = 0;
720160814Ssimon		}
721160814Ssimon	else
722160814Ssimon		{
723160814Ssimon		/* use the ECPARAMETERS structure */
724160814Ssimon		ret->type = 1;
725160814Ssimon		if ((ret->value.parameters = ec_asn1_group2parameters(
726160814Ssimon		     group, NULL)) == NULL)
727160814Ssimon			ok = 0;
728160814Ssimon		}
729160814Ssimon
730160814Ssimon	if (!ok)
731160814Ssimon		{
732160814Ssimon		ECPKPARAMETERS_free(ret);
733160814Ssimon		return NULL;
734160814Ssimon		}
735160814Ssimon	return ret;
736160814Ssimon	}
737160814Ssimon
738160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
739160814Ssimon	{
740160814Ssimon	int			ok = 0, tmp;
741160814Ssimon	EC_GROUP		*ret = NULL;
742160814Ssimon	BIGNUM			*p = NULL, *a = NULL, *b = NULL;
743160814Ssimon	EC_POINT		*point=NULL;
744160814Ssimon
745160814Ssimon	if (!params->fieldID || !params->fieldID->fieldType ||
746160814Ssimon	    !params->fieldID->p.ptr)
747160814Ssimon		{
748160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
749160814Ssimon		goto err;
750160814Ssimon		}
751160814Ssimon
752160814Ssimon	/* now extract the curve parameters a and b */
753160814Ssimon	if (!params->curve || !params->curve->a ||
754160814Ssimon	    !params->curve->a->data || !params->curve->b ||
755160814Ssimon	    !params->curve->b->data)
756160814Ssimon		{
757160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
758160814Ssimon		goto err;
759160814Ssimon		}
760160814Ssimon	a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
761160814Ssimon	if (a == NULL)
762160814Ssimon		{
763160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
764160814Ssimon		goto err;
765160814Ssimon		}
766160814Ssimon	b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
767160814Ssimon	if (b == NULL)
768160814Ssimon		{
769160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
770160814Ssimon		goto err;
771160814Ssimon		}
772160814Ssimon
773160814Ssimon	/* get the field parameters */
774160814Ssimon	tmp = OBJ_obj2nid(params->fieldID->fieldType);
775160814Ssimon
776160814Ssimon	if (tmp == NID_X9_62_characteristic_two_field)
777160814Ssimon		{
778160814Ssimon		X9_62_CHARACTERISTIC_TWO *char_two;
779160814Ssimon
780160814Ssimon		char_two = params->fieldID->p.char_two;
781160814Ssimon
782160814Ssimon		if ((p = BN_new()) == NULL)
783160814Ssimon			{
784160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
785160814Ssimon			goto err;
786160814Ssimon			}
787160814Ssimon
788160814Ssimon		/* get the base type */
789160814Ssimon		tmp = OBJ_obj2nid(char_two->type);
790160814Ssimon
791160814Ssimon		if (tmp ==  NID_X9_62_tpBasis)
792160814Ssimon			{
793160814Ssimon			long tmp_long;
794160814Ssimon
795160814Ssimon			if (!char_two->p.tpBasis)
796160814Ssimon				{
797160814Ssimon				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
798160814Ssimon				goto err;
799160814Ssimon				}
800160814Ssimon
801160814Ssimon			tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis);
802160814Ssimon			/* create the polynomial */
803160814Ssimon			if (!BN_set_bit(p, (int)char_two->m))
804160814Ssimon				goto err;
805160814Ssimon			if (!BN_set_bit(p, (int)tmp_long))
806160814Ssimon				goto err;
807160814Ssimon			if (!BN_set_bit(p, 0))
808160814Ssimon				goto err;
809160814Ssimon			}
810160814Ssimon		else if (tmp == NID_X9_62_ppBasis)
811160814Ssimon			{
812160814Ssimon			X9_62_PENTANOMIAL *penta;
813160814Ssimon
814160814Ssimon			penta = char_two->p.ppBasis;
815160814Ssimon			if (!penta)
816160814Ssimon				{
817160814Ssimon				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
818160814Ssimon				goto err;
819160814Ssimon				}
820160814Ssimon			/* create the polynomial */
821160814Ssimon			if (!BN_set_bit(p, (int)char_two->m)) goto err;
822160814Ssimon			if (!BN_set_bit(p, (int)penta->k1)) goto err;
823160814Ssimon			if (!BN_set_bit(p, (int)penta->k2)) goto err;
824160814Ssimon			if (!BN_set_bit(p, (int)penta->k3)) goto err;
825160814Ssimon			if (!BN_set_bit(p, 0)) goto err;
826160814Ssimon			}
827160814Ssimon		else if (tmp == NID_X9_62_onBasis)
828160814Ssimon			{
829160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED);
830160814Ssimon			goto err;
831160814Ssimon			}
832160814Ssimon		else /* error */
833160814Ssimon			{
834160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
835160814Ssimon			goto err;
836160814Ssimon			}
837160814Ssimon
838160814Ssimon		/* create the EC_GROUP structure */
839160814Ssimon		ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
840160814Ssimon		}
841160814Ssimon	else if (tmp == NID_X9_62_prime_field)
842160814Ssimon		{
843160814Ssimon		/* we have a curve over a prime field */
844160814Ssimon		/* extract the prime number */
845160814Ssimon		if (!params->fieldID->p.prime)
846160814Ssimon			{
847160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
848160814Ssimon			goto err;
849160814Ssimon			}
850160814Ssimon		p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
851160814Ssimon		if (p == NULL)
852160814Ssimon			{
853160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
854160814Ssimon			goto err;
855160814Ssimon			}
856160814Ssimon		/* create the EC_GROUP structure */
857160814Ssimon		ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
858160814Ssimon		}
859160814Ssimon	else
860160814Ssimon		{
861160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
862160814Ssimon		goto err;
863160814Ssimon		}
864160814Ssimon
865160814Ssimon	if (ret == NULL)
866160814Ssimon		{
867160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
868160814Ssimon		goto err;
869160814Ssimon		}
870160814Ssimon
871160814Ssimon	/* extract seed (optional) */
872160814Ssimon	if (params->curve->seed != NULL)
873160814Ssimon		{
874160814Ssimon		if (ret->seed != NULL)
875160814Ssimon			OPENSSL_free(ret->seed);
876160814Ssimon		if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length)))
877160814Ssimon			{
878160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP,
879160814Ssimon			      ERR_R_MALLOC_FAILURE);
880160814Ssimon			goto err;
881160814Ssimon			}
882160814Ssimon		memcpy(ret->seed, params->curve->seed->data,
883160814Ssimon		       params->curve->seed->length);
884160814Ssimon		ret->seed_len = params->curve->seed->length;
885160814Ssimon		}
886160814Ssimon
887160814Ssimon	if (!params->order || !params->base || !params->base->data)
888160814Ssimon		{
889160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
890160814Ssimon		goto err;
891160814Ssimon		}
892160814Ssimon
893160814Ssimon	if ((point = EC_POINT_new(ret)) == NULL) goto err;
894160814Ssimon
895160814Ssimon	/* set the point conversion form */
896160814Ssimon	EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
897160814Ssimon				(params->base->data[0] & ~0x01));
898160814Ssimon
899160814Ssimon	/* extract the ec point */
900160814Ssimon	if (!EC_POINT_oct2point(ret, point, params->base->data,
901160814Ssimon		                params->base->length, NULL))
902160814Ssimon		{
903160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
904160814Ssimon		goto err;
905160814Ssimon		}
906160814Ssimon
907160814Ssimon	/* extract the order */
908160814Ssimon	if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL)
909160814Ssimon		{
910160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
911160814Ssimon		goto err;
912160814Ssimon		}
913160814Ssimon
914160814Ssimon	/* extract the cofactor (optional) */
915160814Ssimon	if (params->cofactor == NULL)
916160814Ssimon		{
917160814Ssimon		if (b)
918160814Ssimon			{
919160814Ssimon			BN_free(b);
920160814Ssimon			b = NULL;
921160814Ssimon			}
922160814Ssimon		}
923160814Ssimon	else
924160814Ssimon		if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL)
925160814Ssimon			{
926160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
927160814Ssimon			goto err;
928160814Ssimon			}
929160814Ssimon	/* set the generator, order and cofactor (if present) */
930160814Ssimon	if (!EC_GROUP_set_generator(ret, point, a, b))
931160814Ssimon		{
932160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
933160814Ssimon		goto err;
934160814Ssimon		}
935160814Ssimon
936160814Ssimon	ok = 1;
937160814Ssimon
938160814Ssimonerr:	if (!ok)
939160814Ssimon		{
940160814Ssimon		if (ret)
941160814Ssimon			EC_GROUP_clear_free(ret);
942160814Ssimon		ret = NULL;
943160814Ssimon		}
944160814Ssimon
945160814Ssimon	if (p)
946160814Ssimon		BN_free(p);
947160814Ssimon	if (a)
948160814Ssimon		BN_free(a);
949160814Ssimon	if (b)
950160814Ssimon		BN_free(b);
951160814Ssimon	if (point)
952160814Ssimon		EC_POINT_free(point);
953160814Ssimon	return(ret);
954160814Ssimon}
955160814Ssimon
956160814SsimonEC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
957160814Ssimon	{
958160814Ssimon	EC_GROUP *ret=NULL;
959160814Ssimon	int      tmp=0;
960160814Ssimon
961160814Ssimon	if (params == NULL)
962160814Ssimon		{
963160814Ssimon		ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP,
964160814Ssimon		      EC_R_MISSING_PARAMETERS);
965160814Ssimon		return NULL;
966160814Ssimon		}
967160814Ssimon
968160814Ssimon	if (params->type == 0)
969160814Ssimon		{ /* the curve is given by an OID */
970160814Ssimon		tmp = OBJ_obj2nid(params->value.named_curve);
971160814Ssimon		if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL)
972160814Ssimon			{
973160814Ssimon			ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP,
974160814Ssimon			      EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
975160814Ssimon			return NULL;
976160814Ssimon			}
977160814Ssimon		EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
978160814Ssimon		}
979160814Ssimon	else if (params->type == 1)
980160814Ssimon		{ /* the parameters are given by a ECPARAMETERS
981160814Ssimon		   * structure */
982160814Ssimon		ret = ec_asn1_parameters2group(params->value.parameters);
983160814Ssimon		if (!ret)
984160814Ssimon			{
985160814Ssimon			ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB);
986160814Ssimon			return NULL;
987160814Ssimon			}
988160814Ssimon		EC_GROUP_set_asn1_flag(ret, 0x0);
989160814Ssimon		}
990160814Ssimon	else if (params->type == 2)
991160814Ssimon		{ /* implicitlyCA */
992160814Ssimon		return NULL;
993160814Ssimon		}
994160814Ssimon	else
995160814Ssimon		{
996160814Ssimon		ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR);
997160814Ssimon		return NULL;
998160814Ssimon		}
999160814Ssimon
1000160814Ssimon	return ret;
1001160814Ssimon	}
1002160814Ssimon
1003160814Ssimon/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */
1004160814Ssimon
1005160814SsimonEC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
1006160814Ssimon	{
1007160814Ssimon	EC_GROUP	*group  = NULL;
1008160814Ssimon	ECPKPARAMETERS	*params = NULL;
1009160814Ssimon
1010160814Ssimon	if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL)
1011160814Ssimon		{
1012160814Ssimon		ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE);
1013160814Ssimon		ECPKPARAMETERS_free(params);
1014160814Ssimon		return NULL;
1015160814Ssimon		}
1016160814Ssimon
1017160814Ssimon	if ((group = ec_asn1_pkparameters2group(params)) == NULL)
1018160814Ssimon		{
1019160814Ssimon		ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE);
1020160814Ssimon		return NULL;
1021160814Ssimon		}
1022160814Ssimon
1023160814Ssimon
1024160814Ssimon	if (a && *a)
1025160814Ssimon		EC_GROUP_clear_free(*a);
1026160814Ssimon	if (a)
1027160814Ssimon		*a = group;
1028160814Ssimon
1029160814Ssimon	ECPKPARAMETERS_free(params);
1030160814Ssimon	return(group);
1031160814Ssimon	}
1032160814Ssimon
1033160814Ssimonint i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
1034160814Ssimon	{
1035160814Ssimon	int		ret=0;
1036160814Ssimon	ECPKPARAMETERS	*tmp = ec_asn1_group2pkparameters(a, NULL);
1037160814Ssimon	if (tmp == NULL)
1038160814Ssimon		{
1039160814Ssimon		ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE);
1040160814Ssimon		return 0;
1041160814Ssimon		}
1042160814Ssimon	if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0)
1043160814Ssimon		{
1044160814Ssimon		ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE);
1045160814Ssimon		ECPKPARAMETERS_free(tmp);
1046160814Ssimon		return 0;
1047160814Ssimon		}
1048160814Ssimon	ECPKPARAMETERS_free(tmp);
1049160814Ssimon	return(ret);
1050160814Ssimon	}
1051160814Ssimon
1052160814Ssimon/* some EC_KEY functions */
1053160814Ssimon
1054160814SsimonEC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
1055160814Ssimon	{
1056160814Ssimon	int             ok=0;
1057160814Ssimon	EC_KEY          *ret=NULL;
1058160814Ssimon	EC_PRIVATEKEY   *priv_key=NULL;
1059160814Ssimon
1060160814Ssimon	if ((priv_key = EC_PRIVATEKEY_new()) == NULL)
1061160814Ssimon		{
1062160814Ssimon		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1063160814Ssimon		return NULL;
1064160814Ssimon		}
1065160814Ssimon
1066160814Ssimon	if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL)
1067160814Ssimon		{
1068160814Ssimon		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1069160814Ssimon		EC_PRIVATEKEY_free(priv_key);
1070160814Ssimon		return NULL;
1071160814Ssimon		}
1072160814Ssimon
1073160814Ssimon	if (a == NULL || *a == NULL)
1074160814Ssimon		{
1075160814Ssimon		if ((ret = EC_KEY_new()) == NULL)
1076160814Ssimon			{
1077160814Ssimon			ECerr(EC_F_D2I_ECPRIVATEKEY,
1078160814Ssimon                                 ERR_R_MALLOC_FAILURE);
1079160814Ssimon			goto err;
1080160814Ssimon			}
1081160814Ssimon		if (a)
1082160814Ssimon			*a = ret;
1083160814Ssimon		}
1084160814Ssimon	else
1085160814Ssimon		ret = *a;
1086160814Ssimon
1087160814Ssimon	if (priv_key->parameters)
1088160814Ssimon		{
1089160814Ssimon		if (ret->group)
1090160814Ssimon			EC_GROUP_clear_free(ret->group);
1091160814Ssimon		ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
1092160814Ssimon		}
1093160814Ssimon
1094160814Ssimon	if (ret->group == NULL)
1095160814Ssimon		{
1096160814Ssimon		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1097160814Ssimon		goto err;
1098160814Ssimon		}
1099160814Ssimon
1100160814Ssimon	ret->version = priv_key->version;
1101160814Ssimon
1102160814Ssimon	if (priv_key->privateKey)
1103160814Ssimon		{
1104160814Ssimon		ret->priv_key = BN_bin2bn(
1105160814Ssimon			M_ASN1_STRING_data(priv_key->privateKey),
1106160814Ssimon			M_ASN1_STRING_length(priv_key->privateKey),
1107160814Ssimon			ret->priv_key);
1108160814Ssimon		if (ret->priv_key == NULL)
1109160814Ssimon			{
1110160814Ssimon			ECerr(EC_F_D2I_ECPRIVATEKEY,
1111160814Ssimon                              ERR_R_BN_LIB);
1112160814Ssimon			goto err;
1113160814Ssimon			}
1114160814Ssimon		}
1115160814Ssimon	else
1116160814Ssimon		{
1117160814Ssimon		ECerr(EC_F_D2I_ECPRIVATEKEY,
1118160814Ssimon                      EC_R_MISSING_PRIVATE_KEY);
1119160814Ssimon		goto err;
1120160814Ssimon		}
1121160814Ssimon
1122160814Ssimon	if (priv_key->publicKey)
1123160814Ssimon		{
1124160814Ssimon		const unsigned char *pub_oct;
1125160814Ssimon		size_t pub_oct_len;
1126160814Ssimon
1127160814Ssimon		if (ret->pub_key)
1128160814Ssimon			EC_POINT_clear_free(ret->pub_key);
1129160814Ssimon		ret->pub_key = EC_POINT_new(ret->group);
1130160814Ssimon		if (ret->pub_key == NULL)
1131160814Ssimon			{
1132160814Ssimon			ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1133160814Ssimon			goto err;
1134160814Ssimon			}
1135160814Ssimon		pub_oct     = M_ASN1_STRING_data(priv_key->publicKey);
1136160814Ssimon		pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
1137160814Ssimon		/* save the point conversion form */
1138160814Ssimon		ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01);
1139160814Ssimon		if (!EC_POINT_oct2point(ret->group, ret->pub_key,
1140160814Ssimon			pub_oct, pub_oct_len, NULL))
1141160814Ssimon			{
1142160814Ssimon			ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1143160814Ssimon			goto err;
1144160814Ssimon			}
1145160814Ssimon		}
1146160814Ssimon
1147160814Ssimon	ok = 1;
1148160814Ssimonerr:
1149160814Ssimon	if (!ok)
1150160814Ssimon		{
1151160814Ssimon		if (ret)
1152160814Ssimon			EC_KEY_free(ret);
1153160814Ssimon		ret = NULL;
1154160814Ssimon		}
1155160814Ssimon
1156160814Ssimon	if (priv_key)
1157160814Ssimon		EC_PRIVATEKEY_free(priv_key);
1158160814Ssimon
1159160814Ssimon	return(ret);
1160160814Ssimon	}
1161160814Ssimon
1162160814Ssimonint	i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
1163160814Ssimon	{
1164160814Ssimon	int             ret=0, ok=0;
1165160814Ssimon	unsigned char   *buffer=NULL;
1166160814Ssimon	size_t          buf_len=0, tmp_len;
1167160814Ssimon	EC_PRIVATEKEY   *priv_key=NULL;
1168160814Ssimon
1169160814Ssimon	if (a == NULL || a->group == NULL || a->priv_key == NULL)
1170160814Ssimon		{
1171160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY,
1172160814Ssimon                      ERR_R_PASSED_NULL_PARAMETER);
1173160814Ssimon		goto err;
1174160814Ssimon		}
1175160814Ssimon
1176160814Ssimon	if ((priv_key = EC_PRIVATEKEY_new()) == NULL)
1177160814Ssimon		{
1178160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY,
1179160814Ssimon                      ERR_R_MALLOC_FAILURE);
1180160814Ssimon		goto err;
1181160814Ssimon		}
1182160814Ssimon
1183160814Ssimon	priv_key->version = a->version;
1184160814Ssimon
1185160814Ssimon	buf_len = (size_t)BN_num_bytes(a->priv_key);
1186160814Ssimon	buffer = OPENSSL_malloc(buf_len);
1187160814Ssimon	if (buffer == NULL)
1188160814Ssimon		{
1189160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY,
1190160814Ssimon                      ERR_R_MALLOC_FAILURE);
1191160814Ssimon		goto err;
1192160814Ssimon		}
1193160814Ssimon
1194160814Ssimon	if (!BN_bn2bin(a->priv_key, buffer))
1195160814Ssimon		{
1196160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB);
1197160814Ssimon		goto err;
1198160814Ssimon		}
1199160814Ssimon
1200160814Ssimon	if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len))
1201160814Ssimon		{
1202160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1203160814Ssimon		goto err;
1204160814Ssimon		}
1205160814Ssimon
1206160814Ssimon	if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS))
1207160814Ssimon		{
1208160814Ssimon		if ((priv_key->parameters = ec_asn1_group2pkparameters(
1209160814Ssimon			a->group, priv_key->parameters)) == NULL)
1210160814Ssimon			{
1211160814Ssimon			ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1212160814Ssimon			goto err;
1213160814Ssimon			}
1214160814Ssimon		}
1215160814Ssimon
1216160814Ssimon	if (!(a->enc_flag & EC_PKEY_NO_PUBKEY))
1217160814Ssimon		{
1218160814Ssimon		priv_key->publicKey = M_ASN1_BIT_STRING_new();
1219160814Ssimon		if (priv_key->publicKey == NULL)
1220160814Ssimon			{
1221160814Ssimon			ECerr(EC_F_I2D_ECPRIVATEKEY,
1222160814Ssimon				ERR_R_MALLOC_FAILURE);
1223160814Ssimon			goto err;
1224160814Ssimon			}
1225160814Ssimon
1226160814Ssimon		tmp_len = EC_POINT_point2oct(a->group, a->pub_key,
1227160814Ssimon				a->conv_form, NULL, 0, NULL);
1228160814Ssimon
1229160814Ssimon		if (tmp_len > buf_len)
1230160814Ssimon			{
1231160814Ssimon			unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
1232160814Ssimon			if (!tmp_buffer)
1233160814Ssimon				{
1234160814Ssimon				ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1235160814Ssimon				goto err;
1236160814Ssimon				}
1237160814Ssimon			buffer = tmp_buffer;
1238160814Ssimon			buf_len = tmp_len;
1239160814Ssimon			}
1240160814Ssimon
1241160814Ssimon		if (!EC_POINT_point2oct(a->group, a->pub_key,
1242160814Ssimon			a->conv_form, buffer, buf_len, NULL))
1243160814Ssimon			{
1244160814Ssimon			ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1245160814Ssimon			goto err;
1246160814Ssimon			}
1247160814Ssimon
1248160814Ssimon		if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer,
1249160814Ssimon				buf_len))
1250160814Ssimon			{
1251160814Ssimon			ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1252160814Ssimon			goto err;
1253160814Ssimon			}
1254160814Ssimon		}
1255160814Ssimon
1256160814Ssimon	if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0)
1257160814Ssimon		{
1258160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1259160814Ssimon		goto err;
1260160814Ssimon		}
1261160814Ssimon	ok=1;
1262160814Ssimonerr:
1263160814Ssimon	if (buffer)
1264160814Ssimon		OPENSSL_free(buffer);
1265160814Ssimon	if (priv_key)
1266160814Ssimon		EC_PRIVATEKEY_free(priv_key);
1267160814Ssimon	return(ok?ret:0);
1268160814Ssimon	}
1269160814Ssimon
1270160814Ssimonint i2d_ECParameters(EC_KEY *a, unsigned char **out)
1271160814Ssimon	{
1272160814Ssimon	if (a == NULL)
1273160814Ssimon		{
1274160814Ssimon		ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1275160814Ssimon		return 0;
1276160814Ssimon		}
1277160814Ssimon	return i2d_ECPKParameters(a->group, out);
1278160814Ssimon	}
1279160814Ssimon
1280160814SsimonEC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
1281160814Ssimon	{
1282160814Ssimon	EC_KEY   *ret;
1283160814Ssimon
1284160814Ssimon	if (in == NULL || *in == NULL)
1285160814Ssimon		{
1286160814Ssimon		ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1287160814Ssimon		return NULL;
1288160814Ssimon		}
1289160814Ssimon
1290160814Ssimon	if (a == NULL || *a == NULL)
1291160814Ssimon		{
1292160814Ssimon		if ((ret = EC_KEY_new()) == NULL)
1293160814Ssimon			{
1294160814Ssimon			ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
1295160814Ssimon			return NULL;
1296160814Ssimon			}
1297160814Ssimon		if (a)
1298160814Ssimon			*a = ret;
1299160814Ssimon		}
1300160814Ssimon	else
1301160814Ssimon		ret = *a;
1302160814Ssimon
1303160814Ssimon	if (!d2i_ECPKParameters(&ret->group, in, len))
1304160814Ssimon		{
1305160814Ssimon		ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB);
1306160814Ssimon		return NULL;
1307160814Ssimon		}
1308160814Ssimon
1309160814Ssimon	return ret;
1310160814Ssimon	}
1311160814Ssimon
1312160814SsimonEC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
1313160814Ssimon	{
1314160814Ssimon	EC_KEY *ret=NULL;
1315160814Ssimon
1316160814Ssimon	if (a == NULL || (*a) == NULL || (*a)->group == NULL)
1317160814Ssimon		{
1318160814Ssimon		/* sorry, but a EC_GROUP-structur is necessary
1319160814Ssimon                 * to set the public key */
1320160814Ssimon		ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1321160814Ssimon		return 0;
1322160814Ssimon		}
1323160814Ssimon	ret = *a;
1324160814Ssimon	if (ret->pub_key == NULL &&
1325160814Ssimon		(ret->pub_key = EC_POINT_new(ret->group)) == NULL)
1326160814Ssimon		{
1327160814Ssimon		ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1328160814Ssimon		return 0;
1329160814Ssimon		}
1330160814Ssimon	if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL))
1331160814Ssimon		{
1332160814Ssimon		ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB);
1333160814Ssimon		return 0;
1334160814Ssimon		}
1335160814Ssimon	/* save the point conversion form */
1336160814Ssimon	ret->conv_form = (point_conversion_form_t)(*in[0] & ~0x01);
1337160814Ssimon	*in += len;
1338160814Ssimon	return ret;
1339160814Ssimon	}
1340160814Ssimon
1341160814Ssimonint i2o_ECPublicKey(EC_KEY *a, unsigned char **out)
1342160814Ssimon	{
1343160814Ssimon        size_t buf_len=0;
1344160814Ssimon	int new_buffer = 0;
1345160814Ssimon
1346160814Ssimon        if (a == NULL)
1347160814Ssimon		{
1348160814Ssimon		ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1349160814Ssimon		return 0;
1350160814Ssimon		}
1351160814Ssimon
1352160814Ssimon        buf_len = EC_POINT_point2oct(a->group, a->pub_key,
1353160814Ssimon                              a->conv_form, NULL, 0, NULL);
1354160814Ssimon
1355160814Ssimon	if (out == NULL || buf_len == 0)
1356160814Ssimon	/* out == NULL => just return the length of the octet string */
1357160814Ssimon		return buf_len;
1358160814Ssimon
1359160814Ssimon	if (*out == NULL)
1360160814Ssimon		{
1361160814Ssimon		if ((*out = OPENSSL_malloc(buf_len)) == NULL)
1362160814Ssimon			{
1363160814Ssimon			ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1364160814Ssimon			return 0;
1365160814Ssimon			}
1366160814Ssimon		new_buffer = 1;
1367160814Ssimon		}
1368160814Ssimon        if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
1369160814Ssimon				*out, buf_len, NULL))
1370160814Ssimon		{
1371160814Ssimon		ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB);
1372160814Ssimon		OPENSSL_free(*out);
1373160814Ssimon		*out = NULL;
1374160814Ssimon		return 0;
1375160814Ssimon		}
1376160814Ssimon	if (!new_buffer)
1377160814Ssimon		*out += buf_len;
1378160814Ssimon	return buf_len;
1379160814Ssimon	}
1380