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	}
86238405Sjkim#ifndef OPENSSL_NO_EC2M
87160814Ssimonint EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
88160814Ssimon	{
89160814Ssimon	if (group == NULL)
90160814Ssimon		return 0;
91160814Ssimon
92279264Sdelphij	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
93279264Sdelphij	    NID_X9_62_characteristic_two_field
94160814Ssimon	    || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] == 0)))
95160814Ssimon		{
96160814Ssimon		ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
97160814Ssimon		return 0;
98160814Ssimon		}
99160814Ssimon
100160814Ssimon	if (k)
101160814Ssimon		*k = group->poly[1];
102160814Ssimon
103160814Ssimon	return 1;
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
111279264Sdelphij	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
112279264Sdelphij	    NID_X9_62_characteristic_two_field
113160814Ssimon	    || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] != 0) && (group->poly[3] != 0) && (group->poly[4] == 0)))
114160814Ssimon		{
115160814Ssimon		ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
116160814Ssimon		return 0;
117160814Ssimon		}
118160814Ssimon
119160814Ssimon	if (k1)
120160814Ssimon		*k1 = group->poly[3];
121160814Ssimon	if (k2)
122160814Ssimon		*k2 = group->poly[2];
123160814Ssimon	if (k3)
124160814Ssimon		*k3 = group->poly[1];
125160814Ssimon
126160814Ssimon	return 1;
127160814Ssimon	}
128238405Sjkim#endif
129160814Ssimon
130160814Ssimon
131160814Ssimon/* some structures needed for the asn1 encoding */
132160814Ssimontypedef struct x9_62_pentanomial_st {
133160814Ssimon	long k1;
134160814Ssimon	long k2;
135160814Ssimon	long k3;
136160814Ssimon	} X9_62_PENTANOMIAL;
137160814Ssimon
138160814Ssimontypedef struct x9_62_characteristic_two_st {
139160814Ssimon	long m;
140160814Ssimon	ASN1_OBJECT  *type;
141160814Ssimon	union	{
142160814Ssimon		char *ptr;
143160814Ssimon		/* NID_X9_62_onBasis */
144160814Ssimon		ASN1_NULL    *onBasis;
145160814Ssimon		/* NID_X9_62_tpBasis */
146160814Ssimon		ASN1_INTEGER *tpBasis;
147160814Ssimon		/* NID_X9_62_ppBasis */
148160814Ssimon		X9_62_PENTANOMIAL *ppBasis;
149160814Ssimon		/* anything else */
150160814Ssimon		ASN1_TYPE *other;
151160814Ssimon		} p;
152160814Ssimon	} X9_62_CHARACTERISTIC_TWO;
153160814Ssimon
154160814Ssimontypedef struct x9_62_fieldid_st {
155160814Ssimon        ASN1_OBJECT *fieldType;
156160814Ssimon	union	{
157160814Ssimon		char *ptr;
158160814Ssimon		/* NID_X9_62_prime_field */
159160814Ssimon		ASN1_INTEGER *prime;
160160814Ssimon		/* NID_X9_62_characteristic_two_field */
161160814Ssimon		X9_62_CHARACTERISTIC_TWO *char_two;
162160814Ssimon		/* anything else */
163160814Ssimon		ASN1_TYPE *other;
164160814Ssimon		} p;
165160814Ssimon	} X9_62_FIELDID;
166160814Ssimon
167160814Ssimontypedef struct x9_62_curve_st {
168160814Ssimon        ASN1_OCTET_STRING *a;
169160814Ssimon        ASN1_OCTET_STRING *b;
170160814Ssimon        ASN1_BIT_STRING   *seed;
171160814Ssimon        } X9_62_CURVE;
172160814Ssimon
173160814Ssimontypedef struct ec_parameters_st {
174160814Ssimon        long              version;
175160814Ssimon        X9_62_FIELDID     *fieldID;
176160814Ssimon        X9_62_CURVE       *curve;
177160814Ssimon        ASN1_OCTET_STRING *base;
178160814Ssimon        ASN1_INTEGER      *order;
179160814Ssimon        ASN1_INTEGER      *cofactor;
180160814Ssimon        } ECPARAMETERS;
181160814Ssimon
182160814Ssimonstruct ecpk_parameters_st {
183160814Ssimon	int	type;
184160814Ssimon	union {
185160814Ssimon		ASN1_OBJECT  *named_curve;
186160814Ssimon		ECPARAMETERS *parameters;
187160814Ssimon		ASN1_NULL    *implicitlyCA;
188160814Ssimon	} value;
189160814Ssimon	}/* ECPKPARAMETERS */;
190160814Ssimon
191160814Ssimon/* SEC1 ECPrivateKey */
192160814Ssimontypedef struct ec_privatekey_st {
193160814Ssimon	long              version;
194160814Ssimon	ASN1_OCTET_STRING *privateKey;
195160814Ssimon        ECPKPARAMETERS    *parameters;
196160814Ssimon	ASN1_BIT_STRING   *publicKey;
197160814Ssimon	} EC_PRIVATEKEY;
198160814Ssimon
199160814Ssimon/* the OpenSSL ASN.1 definitions */
200160814SsimonASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
201160814Ssimon	ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG),
202160814Ssimon	ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG),
203160814Ssimon	ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG)
204160814Ssimon} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL)
205160814Ssimon
206160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
207160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
208160814Ssimon
209160814SsimonASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY);
210160814Ssimon
211160814SsimonASN1_ADB(X9_62_CHARACTERISTIC_TWO) = {
212160814Ssimon	ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)),
213160814Ssimon	ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)),
214160814Ssimon	ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL))
215160814Ssimon} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL);
216160814Ssimon
217160814SsimonASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = {
218160814Ssimon	ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG),
219160814Ssimon	ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
220160814Ssimon	ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO)
221160814Ssimon} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO)
222160814Ssimon
223160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
224160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
225160814Ssimon
226160814SsimonASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
227160814Ssimon
228160814SsimonASN1_ADB(X9_62_FIELDID) = {
229160814Ssimon	ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
230160814Ssimon	ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO))
231160814Ssimon} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
232160814Ssimon
233160814SsimonASN1_SEQUENCE(X9_62_FIELDID) = {
234160814Ssimon	ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
235160814Ssimon	ASN1_ADB_OBJECT(X9_62_FIELDID)
236160814Ssimon} ASN1_SEQUENCE_END(X9_62_FIELDID)
237160814Ssimon
238160814SsimonASN1_SEQUENCE(X9_62_CURVE) = {
239160814Ssimon	ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
240160814Ssimon	ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
241160814Ssimon	ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
242160814Ssimon} ASN1_SEQUENCE_END(X9_62_CURVE)
243160814Ssimon
244160814SsimonASN1_SEQUENCE(ECPARAMETERS) = {
245160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, version, LONG),
246160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
247160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
248160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
249160814Ssimon	ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
250160814Ssimon	ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
251160814Ssimon} ASN1_SEQUENCE_END(ECPARAMETERS)
252160814Ssimon
253160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
254160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
255160814Ssimon
256160814SsimonASN1_CHOICE(ECPKPARAMETERS) = {
257160814Ssimon	ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
258160814Ssimon	ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
259160814Ssimon	ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL)
260160814Ssimon} ASN1_CHOICE_END(ECPKPARAMETERS)
261160814Ssimon
262160814SsimonDECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
263160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS)
264160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
265160814Ssimon
266160814SsimonASN1_SEQUENCE(EC_PRIVATEKEY) = {
267160814Ssimon	ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
268160814Ssimon	ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
269160814Ssimon	ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
270160814Ssimon	ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
271160814Ssimon} ASN1_SEQUENCE_END(EC_PRIVATEKEY)
272160814Ssimon
273160814SsimonDECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
274160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY)
275160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
276160814Ssimon
277160814Ssimon/* some declarations of internal function */
278160814Ssimon
279160814Ssimon/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */
280160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
281160814Ssimon/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */
282160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
283160814Ssimon/* ec_asn1_parameters2group() creates a EC_GROUP object from a
284160814Ssimon * ECPARAMETERS object */
285160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *);
286160814Ssimon/* ec_asn1_group2parameters() creates a ECPARAMETERS object from a
287160814Ssimon * EC_GROUP object */
288160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,ECPARAMETERS *);
289160814Ssimon/* ec_asn1_pkparameters2group() creates a EC_GROUP object from a
290160814Ssimon * ECPKPARAMETERS object */
291160814Ssimonstatic EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *);
292160814Ssimon/* ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a
293160814Ssimon * EC_GROUP object */
294160814Ssimonstatic ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *,
295160814Ssimon	ECPKPARAMETERS *);
296160814Ssimon
297160814Ssimon
298160814Ssimon/* the function definitions */
299160814Ssimon
300160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
301160814Ssimon	{
302160814Ssimon	int			ok=0, nid;
303160814Ssimon	BIGNUM			*tmp = NULL;
304160814Ssimon
305160814Ssimon	if (group == NULL || field == NULL)
306160814Ssimon		return 0;
307160814Ssimon
308160814Ssimon	/* clear the old values (if necessary) */
309160814Ssimon	if (field->fieldType != NULL)
310160814Ssimon		ASN1_OBJECT_free(field->fieldType);
311160814Ssimon	if (field->p.other != NULL)
312160814Ssimon		ASN1_TYPE_free(field->p.other);
313160814Ssimon
314160814Ssimon	nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
315160814Ssimon	/* set OID for the field */
316160814Ssimon	if ((field->fieldType = OBJ_nid2obj(nid)) == NULL)
317160814Ssimon		{
318160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
319160814Ssimon		goto err;
320160814Ssimon		}
321160814Ssimon
322160814Ssimon	if (nid == NID_X9_62_prime_field)
323160814Ssimon		{
324160814Ssimon		if ((tmp = BN_new()) == NULL)
325160814Ssimon			{
326160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
327160814Ssimon			goto err;
328160814Ssimon			}
329160814Ssimon		/* the parameters are specified by the prime number p */
330160814Ssimon		if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL))
331160814Ssimon			{
332160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
333160814Ssimon			goto err;
334160814Ssimon			}
335160814Ssimon		/* set the prime number */
336160814Ssimon		field->p.prime = BN_to_ASN1_INTEGER(tmp,NULL);
337160814Ssimon		if (field->p.prime == NULL)
338160814Ssimon			{
339160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
340160814Ssimon			goto err;
341160814Ssimon			}
342160814Ssimon		}
343160814Ssimon	else	/* nid == NID_X9_62_characteristic_two_field */
344238405Sjkim#ifdef OPENSSL_NO_EC2M
345160814Ssimon		{
346238405Sjkim		ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED);
347238405Sjkim		goto err;
348238405Sjkim		}
349238405Sjkim#else
350238405Sjkim		{
351160814Ssimon		int		field_type;
352160814Ssimon		X9_62_CHARACTERISTIC_TWO *char_two;
353160814Ssimon
354160814Ssimon		field->p.char_two = X9_62_CHARACTERISTIC_TWO_new();
355160814Ssimon		char_two = field->p.char_two;
356160814Ssimon
357160814Ssimon		if (char_two == NULL)
358160814Ssimon			{
359160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
360160814Ssimon			goto err;
361160814Ssimon			}
362160814Ssimon
363160814Ssimon		char_two->m = (long)EC_GROUP_get_degree(group);
364160814Ssimon
365160814Ssimon		field_type = EC_GROUP_get_basis_type(group);
366160814Ssimon
367160814Ssimon		if (field_type == 0)
368160814Ssimon			{
369160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
370160814Ssimon			goto err;
371160814Ssimon			}
372160814Ssimon		/* set base type OID */
373160814Ssimon		if ((char_two->type = OBJ_nid2obj(field_type)) == NULL)
374160814Ssimon			{
375160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
376160814Ssimon			goto err;
377160814Ssimon			}
378160814Ssimon
379160814Ssimon		if (field_type == NID_X9_62_tpBasis)
380160814Ssimon			{
381160814Ssimon			unsigned int k;
382160814Ssimon
383160814Ssimon			if (!EC_GROUP_get_trinomial_basis(group, &k))
384160814Ssimon				goto err;
385160814Ssimon
386160814Ssimon			char_two->p.tpBasis = ASN1_INTEGER_new();
387160814Ssimon			if (!char_two->p.tpBasis)
388160814Ssimon				{
389160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
390160814Ssimon				goto err;
391160814Ssimon				}
392160814Ssimon			if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k))
393160814Ssimon				{
394160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2FIELDID,
395160814Ssimon					ERR_R_ASN1_LIB);
396160814Ssimon				goto err;
397160814Ssimon				}
398160814Ssimon			}
399160814Ssimon		else if (field_type == NID_X9_62_ppBasis)
400160814Ssimon			{
401160814Ssimon			unsigned int k1, k2, k3;
402160814Ssimon
403160814Ssimon			if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3))
404160814Ssimon				goto err;
405160814Ssimon
406160814Ssimon			char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
407160814Ssimon			if (!char_two->p.ppBasis)
408160814Ssimon				{
409160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
410160814Ssimon				goto err;
411160814Ssimon				}
412160814Ssimon
413160814Ssimon			/* set k? values */
414160814Ssimon			char_two->p.ppBasis->k1 = (long)k1;
415160814Ssimon			char_two->p.ppBasis->k2 = (long)k2;
416160814Ssimon			char_two->p.ppBasis->k3 = (long)k3;
417160814Ssimon			}
418160814Ssimon		else /* field_type == NID_X9_62_onBasis */
419160814Ssimon			{
420160814Ssimon			/* for ONB the parameters are (asn1) NULL */
421160814Ssimon			char_two->p.onBasis = ASN1_NULL_new();
422160814Ssimon			if (!char_two->p.onBasis)
423160814Ssimon				{
424160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
425160814Ssimon				goto err;
426160814Ssimon				}
427160814Ssimon			}
428160814Ssimon		}
429238405Sjkim#endif
430160814Ssimon
431160814Ssimon	ok = 1;
432160814Ssimon
433160814Ssimonerr :	if (tmp)
434160814Ssimon		BN_free(tmp);
435160814Ssimon	return(ok);
436160814Ssimon}
437160814Ssimon
438160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
439160814Ssimon	{
440160814Ssimon	int           ok=0, nid;
441160814Ssimon	BIGNUM        *tmp_1=NULL, *tmp_2=NULL;
442160814Ssimon	unsigned char *buffer_1=NULL, *buffer_2=NULL,
443160814Ssimon	              *a_buf=NULL, *b_buf=NULL;
444160814Ssimon	size_t        len_1, len_2;
445160814Ssimon	unsigned char char_zero = 0;
446160814Ssimon
447160814Ssimon	if (!group || !curve || !curve->a || !curve->b)
448160814Ssimon		return 0;
449160814Ssimon
450160814Ssimon	if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL)
451160814Ssimon		{
452160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
453160814Ssimon		goto err;
454160814Ssimon		}
455160814Ssimon
456160814Ssimon	nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
457160814Ssimon
458160814Ssimon	/* get a and b */
459160814Ssimon	if (nid == NID_X9_62_prime_field)
460160814Ssimon		{
461160814Ssimon		if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL))
462160814Ssimon			{
463160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
464160814Ssimon			goto err;
465160814Ssimon			}
466160814Ssimon		}
467238405Sjkim#ifndef OPENSSL_NO_EC2M
468160814Ssimon	else	/* nid == NID_X9_62_characteristic_two_field */
469160814Ssimon		{
470160814Ssimon		if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL))
471160814Ssimon			{
472160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
473160814Ssimon			goto err;
474160814Ssimon			}
475160814Ssimon		}
476238405Sjkim#endif
477160814Ssimon	len_1 = (size_t)BN_num_bytes(tmp_1);
478160814Ssimon	len_2 = (size_t)BN_num_bytes(tmp_2);
479160814Ssimon
480160814Ssimon	if (len_1 == 0)
481160814Ssimon		{
482160814Ssimon		/* len_1 == 0 => a == 0 */
483160814Ssimon		a_buf = &char_zero;
484160814Ssimon		len_1 = 1;
485160814Ssimon		}
486160814Ssimon	else
487160814Ssimon		{
488160814Ssimon		if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL)
489160814Ssimon			{
490160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE,
491160814Ssimon			      ERR_R_MALLOC_FAILURE);
492160814Ssimon			goto err;
493160814Ssimon			}
494160814Ssimon		if ( (len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0)
495160814Ssimon			{
496160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
497160814Ssimon			goto err;
498160814Ssimon			}
499160814Ssimon		a_buf = buffer_1;
500160814Ssimon		}
501160814Ssimon
502160814Ssimon	if (len_2 == 0)
503160814Ssimon		{
504160814Ssimon		/* len_2 == 0 => b == 0 */
505160814Ssimon		b_buf = &char_zero;
506160814Ssimon		len_2 = 1;
507160814Ssimon		}
508160814Ssimon	else
509160814Ssimon		{
510160814Ssimon		if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL)
511160814Ssimon			{
512160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE,
513160814Ssimon			      ERR_R_MALLOC_FAILURE);
514160814Ssimon			goto err;
515160814Ssimon			}
516160814Ssimon		if ( (len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0)
517160814Ssimon			{
518160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
519160814Ssimon			goto err;
520160814Ssimon			}
521160814Ssimon		b_buf = buffer_2;
522160814Ssimon		}
523160814Ssimon
524160814Ssimon	/* set a and b */
525160814Ssimon	if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
526160814Ssimon	    !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2))
527160814Ssimon		{
528160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
529160814Ssimon		goto err;
530160814Ssimon		}
531160814Ssimon
532160814Ssimon	/* set the seed (optional) */
533160814Ssimon	if (group->seed)
534160814Ssimon		{
535160814Ssimon		if (!curve->seed)
536160814Ssimon			if ((curve->seed = ASN1_BIT_STRING_new()) == NULL)
537160814Ssimon				{
538160814Ssimon				ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
539160814Ssimon				goto err;
540160814Ssimon				}
541167612Ssimon		curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
542167612Ssimon		curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT;
543160814Ssimon		if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
544160814Ssimon		                         (int)group->seed_len))
545160814Ssimon			{
546160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
547160814Ssimon			goto err;
548160814Ssimon			}
549160814Ssimon		}
550160814Ssimon	else
551160814Ssimon		{
552160814Ssimon		if (curve->seed)
553160814Ssimon			{
554160814Ssimon			ASN1_BIT_STRING_free(curve->seed);
555160814Ssimon			curve->seed = NULL;
556160814Ssimon			}
557160814Ssimon		}
558160814Ssimon
559160814Ssimon	ok = 1;
560160814Ssimon
561160814Ssimonerr:	if (buffer_1)
562160814Ssimon		OPENSSL_free(buffer_1);
563160814Ssimon	if (buffer_2)
564160814Ssimon		OPENSSL_free(buffer_2);
565160814Ssimon	if (tmp_1)
566160814Ssimon		BN_free(tmp_1);
567160814Ssimon	if (tmp_2)
568160814Ssimon		BN_free(tmp_2);
569160814Ssimon	return(ok);
570160814Ssimon	}
571160814Ssimon
572160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group,
573160814Ssimon                                              ECPARAMETERS *param)
574160814Ssimon	{
575160814Ssimon	int	ok=0;
576160814Ssimon	size_t  len=0;
577160814Ssimon	ECPARAMETERS   *ret=NULL;
578160814Ssimon	BIGNUM	       *tmp=NULL;
579160814Ssimon	unsigned char  *buffer=NULL;
580160814Ssimon	const EC_POINT *point=NULL;
581160814Ssimon	point_conversion_form_t form;
582160814Ssimon
583160814Ssimon	if ((tmp = BN_new()) == NULL)
584160814Ssimon		{
585160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
586160814Ssimon		goto err;
587160814Ssimon		}
588160814Ssimon
589160814Ssimon	if (param == NULL)
590160814Ssimon	{
591160814Ssimon		if ((ret = ECPARAMETERS_new()) == NULL)
592160814Ssimon			{
593160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS,
594160814Ssimon			      ERR_R_MALLOC_FAILURE);
595160814Ssimon			goto err;
596160814Ssimon			}
597160814Ssimon	}
598160814Ssimon	else
599160814Ssimon		ret = param;
600160814Ssimon
601160814Ssimon	/* set the version (always one) */
602160814Ssimon	ret->version = (long)0x1;
603160814Ssimon
604160814Ssimon	/* set the fieldID */
605160814Ssimon	if (!ec_asn1_group2fieldid(group, ret->fieldID))
606160814Ssimon		{
607160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
608160814Ssimon		goto err;
609160814Ssimon		}
610160814Ssimon
611160814Ssimon	/* set the curve */
612160814Ssimon	if (!ec_asn1_group2curve(group, ret->curve))
613160814Ssimon		{
614160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
615160814Ssimon		goto err;
616160814Ssimon		}
617160814Ssimon
618160814Ssimon	/* set the base point */
619160814Ssimon	if ((point = EC_GROUP_get0_generator(group)) == NULL)
620160814Ssimon		{
621160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR);
622160814Ssimon		goto err;
623160814Ssimon		}
624160814Ssimon
625160814Ssimon	form = EC_GROUP_get_point_conversion_form(group);
626160814Ssimon
627160814Ssimon	len = EC_POINT_point2oct(group, point, form, NULL, len, NULL);
628160814Ssimon	if (len == 0)
629160814Ssimon		{
630160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
631160814Ssimon		goto err;
632160814Ssimon		}
633160814Ssimon	if ((buffer = OPENSSL_malloc(len)) == NULL)
634160814Ssimon		{
635160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
636160814Ssimon		goto err;
637160814Ssimon		}
638160814Ssimon	if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL))
639160814Ssimon		{
640160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
641160814Ssimon		goto err;
642160814Ssimon		}
643160814Ssimon	if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL)
644160814Ssimon		{
645160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
646160814Ssimon		goto err;
647160814Ssimon		}
648160814Ssimon	if (!ASN1_OCTET_STRING_set(ret->base, buffer, len))
649160814Ssimon		{
650160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
651160814Ssimon		goto err;
652160814Ssimon		}
653160814Ssimon
654160814Ssimon	/* set the order */
655160814Ssimon	if (!EC_GROUP_get_order(group, tmp, NULL))
656160814Ssimon		{
657160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
658160814Ssimon		goto err;
659160814Ssimon		}
660160814Ssimon	ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
661160814Ssimon	if (ret->order == NULL)
662160814Ssimon		{
663160814Ssimon		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
664160814Ssimon		goto err;
665160814Ssimon		}
666160814Ssimon
667160814Ssimon	/* set the cofactor (optional) */
668160814Ssimon	if (EC_GROUP_get_cofactor(group, tmp, NULL))
669160814Ssimon		{
670160814Ssimon		ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
671160814Ssimon		if (ret->cofactor == NULL)
672160814Ssimon			{
673160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
674160814Ssimon			goto err;
675160814Ssimon			}
676160814Ssimon		}
677160814Ssimon
678160814Ssimon	ok = 1;
679160814Ssimon
680160814Ssimonerr :	if(!ok)
681160814Ssimon		{
682160814Ssimon		if (ret && !param)
683160814Ssimon			ECPARAMETERS_free(ret);
684160814Ssimon		ret = NULL;
685160814Ssimon		}
686160814Ssimon	if (tmp)
687160814Ssimon		BN_free(tmp);
688160814Ssimon	if (buffer)
689160814Ssimon		OPENSSL_free(buffer);
690160814Ssimon	return(ret);
691160814Ssimon	}
692160814Ssimon
693160814SsimonECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
694160814Ssimon                                           ECPKPARAMETERS *params)
695160814Ssimon	{
696160814Ssimon	int            ok = 1, tmp;
697160814Ssimon	ECPKPARAMETERS *ret = params;
698160814Ssimon
699160814Ssimon	if (ret == NULL)
700160814Ssimon		{
701160814Ssimon		if ((ret = ECPKPARAMETERS_new()) == NULL)
702160814Ssimon			{
703160814Ssimon			ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS,
704160814Ssimon			      ERR_R_MALLOC_FAILURE);
705160814Ssimon			return NULL;
706160814Ssimon			}
707160814Ssimon		}
708160814Ssimon	else
709160814Ssimon		{
710160814Ssimon		if (ret->type == 0 && ret->value.named_curve)
711160814Ssimon			ASN1_OBJECT_free(ret->value.named_curve);
712160814Ssimon		else if (ret->type == 1 && ret->value.parameters)
713160814Ssimon			ECPARAMETERS_free(ret->value.parameters);
714160814Ssimon		}
715160814Ssimon
716160814Ssimon	if (EC_GROUP_get_asn1_flag(group))
717160814Ssimon		{
718160814Ssimon		/* use the asn1 OID to describe the
719160814Ssimon		 * the elliptic curve parameters
720160814Ssimon		 */
721160814Ssimon		tmp = EC_GROUP_get_curve_name(group);
722160814Ssimon		if (tmp)
723160814Ssimon			{
724160814Ssimon			ret->type = 0;
725160814Ssimon			if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL)
726160814Ssimon				ok = 0;
727160814Ssimon			}
728160814Ssimon		else
729160814Ssimon			/* we don't kmow the nid => ERROR */
730160814Ssimon			ok = 0;
731160814Ssimon		}
732160814Ssimon	else
733160814Ssimon		{
734160814Ssimon		/* use the ECPARAMETERS structure */
735160814Ssimon		ret->type = 1;
736160814Ssimon		if ((ret->value.parameters = ec_asn1_group2parameters(
737160814Ssimon		     group, NULL)) == NULL)
738160814Ssimon			ok = 0;
739160814Ssimon		}
740160814Ssimon
741160814Ssimon	if (!ok)
742160814Ssimon		{
743160814Ssimon		ECPKPARAMETERS_free(ret);
744160814Ssimon		return NULL;
745160814Ssimon		}
746160814Ssimon	return ret;
747160814Ssimon	}
748160814Ssimon
749160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
750160814Ssimon	{
751160814Ssimon	int			ok = 0, tmp;
752160814Ssimon	EC_GROUP		*ret = NULL;
753160814Ssimon	BIGNUM			*p = NULL, *a = NULL, *b = NULL;
754160814Ssimon	EC_POINT		*point=NULL;
755162911Ssimon	long    		field_bits;
756160814Ssimon
757160814Ssimon	if (!params->fieldID || !params->fieldID->fieldType ||
758160814Ssimon	    !params->fieldID->p.ptr)
759160814Ssimon		{
760160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
761160814Ssimon		goto err;
762160814Ssimon		}
763160814Ssimon
764160814Ssimon	/* now extract the curve parameters a and b */
765160814Ssimon	if (!params->curve || !params->curve->a ||
766160814Ssimon	    !params->curve->a->data || !params->curve->b ||
767160814Ssimon	    !params->curve->b->data)
768160814Ssimon		{
769160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
770160814Ssimon		goto err;
771160814Ssimon		}
772160814Ssimon	a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
773160814Ssimon	if (a == NULL)
774160814Ssimon		{
775160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
776160814Ssimon		goto err;
777160814Ssimon		}
778160814Ssimon	b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
779160814Ssimon	if (b == NULL)
780160814Ssimon		{
781160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
782160814Ssimon		goto err;
783160814Ssimon		}
784160814Ssimon
785160814Ssimon	/* get the field parameters */
786160814Ssimon	tmp = OBJ_obj2nid(params->fieldID->fieldType);
787160814Ssimon	if (tmp == NID_X9_62_characteristic_two_field)
788238405Sjkim#ifdef OPENSSL_NO_EC2M
789160814Ssimon		{
790238405Sjkim		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED);
791238405Sjkim		goto err;
792238405Sjkim		}
793238405Sjkim#else
794238405Sjkim		{
795160814Ssimon		X9_62_CHARACTERISTIC_TWO *char_two;
796160814Ssimon
797160814Ssimon		char_two = params->fieldID->p.char_two;
798160814Ssimon
799162911Ssimon		field_bits = char_two->m;
800162911Ssimon		if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS)
801162911Ssimon			{
802162911Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
803162911Ssimon			goto err;
804162911Ssimon			}
805162911Ssimon
806160814Ssimon		if ((p = BN_new()) == NULL)
807160814Ssimon			{
808160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
809160814Ssimon			goto err;
810160814Ssimon			}
811160814Ssimon
812160814Ssimon		/* get the base type */
813160814Ssimon		tmp = OBJ_obj2nid(char_two->type);
814160814Ssimon
815160814Ssimon		if (tmp ==  NID_X9_62_tpBasis)
816160814Ssimon			{
817160814Ssimon			long tmp_long;
818160814Ssimon
819160814Ssimon			if (!char_two->p.tpBasis)
820160814Ssimon				{
821160814Ssimon				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
822160814Ssimon				goto err;
823160814Ssimon				}
824160814Ssimon
825160814Ssimon			tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis);
826162911Ssimon
827162911Ssimon			if (!(char_two->m > tmp_long && tmp_long > 0))
828162911Ssimon				{
829162911Ssimon				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_TRINOMIAL_BASIS);
830162911Ssimon				goto err;
831162911Ssimon				}
832162911Ssimon
833160814Ssimon			/* create the polynomial */
834160814Ssimon			if (!BN_set_bit(p, (int)char_two->m))
835160814Ssimon				goto err;
836160814Ssimon			if (!BN_set_bit(p, (int)tmp_long))
837160814Ssimon				goto err;
838160814Ssimon			if (!BN_set_bit(p, 0))
839160814Ssimon				goto err;
840160814Ssimon			}
841160814Ssimon		else if (tmp == NID_X9_62_ppBasis)
842160814Ssimon			{
843160814Ssimon			X9_62_PENTANOMIAL *penta;
844160814Ssimon
845160814Ssimon			penta = char_two->p.ppBasis;
846160814Ssimon			if (!penta)
847160814Ssimon				{
848160814Ssimon				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
849160814Ssimon				goto err;
850160814Ssimon				}
851162911Ssimon
852162911Ssimon			if (!(char_two->m > penta->k3 && penta->k3 > penta->k2 && penta->k2 > penta->k1 && penta->k1 > 0))
853162911Ssimon				{
854162911Ssimon				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_PENTANOMIAL_BASIS);
855162911Ssimon				goto err;
856162911Ssimon				}
857162911Ssimon
858160814Ssimon			/* create the polynomial */
859160814Ssimon			if (!BN_set_bit(p, (int)char_two->m)) goto err;
860160814Ssimon			if (!BN_set_bit(p, (int)penta->k1)) goto err;
861160814Ssimon			if (!BN_set_bit(p, (int)penta->k2)) goto err;
862160814Ssimon			if (!BN_set_bit(p, (int)penta->k3)) goto err;
863160814Ssimon			if (!BN_set_bit(p, 0)) goto err;
864160814Ssimon			}
865160814Ssimon		else if (tmp == NID_X9_62_onBasis)
866160814Ssimon			{
867160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED);
868160814Ssimon			goto err;
869160814Ssimon			}
870160814Ssimon		else /* error */
871160814Ssimon			{
872160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
873160814Ssimon			goto err;
874160814Ssimon			}
875160814Ssimon
876160814Ssimon		/* create the EC_GROUP structure */
877160814Ssimon		ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
878160814Ssimon		}
879238405Sjkim#endif
880160814Ssimon	else if (tmp == NID_X9_62_prime_field)
881160814Ssimon		{
882160814Ssimon		/* we have a curve over a prime field */
883160814Ssimon		/* extract the prime number */
884160814Ssimon		if (!params->fieldID->p.prime)
885160814Ssimon			{
886160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
887160814Ssimon			goto err;
888160814Ssimon			}
889160814Ssimon		p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
890160814Ssimon		if (p == NULL)
891160814Ssimon			{
892160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
893160814Ssimon			goto err;
894160814Ssimon			}
895162911Ssimon
896162911Ssimon		if (BN_is_negative(p) || BN_is_zero(p))
897162911Ssimon			{
898162911Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
899162911Ssimon			goto err;
900162911Ssimon			}
901162911Ssimon
902162911Ssimon		field_bits = BN_num_bits(p);
903162911Ssimon		if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS)
904162911Ssimon			{
905162911Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
906162911Ssimon			goto err;
907162911Ssimon			}
908162911Ssimon
909160814Ssimon		/* create the EC_GROUP structure */
910160814Ssimon		ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
911160814Ssimon		}
912160814Ssimon	else
913160814Ssimon		{
914160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
915160814Ssimon		goto err;
916160814Ssimon		}
917160814Ssimon
918160814Ssimon	if (ret == NULL)
919160814Ssimon		{
920160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
921160814Ssimon		goto err;
922160814Ssimon		}
923160814Ssimon
924160814Ssimon	/* extract seed (optional) */
925160814Ssimon	if (params->curve->seed != NULL)
926160814Ssimon		{
927160814Ssimon		if (ret->seed != NULL)
928160814Ssimon			OPENSSL_free(ret->seed);
929160814Ssimon		if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length)))
930160814Ssimon			{
931160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP,
932160814Ssimon			      ERR_R_MALLOC_FAILURE);
933160814Ssimon			goto err;
934160814Ssimon			}
935160814Ssimon		memcpy(ret->seed, params->curve->seed->data,
936160814Ssimon		       params->curve->seed->length);
937160814Ssimon		ret->seed_len = params->curve->seed->length;
938160814Ssimon		}
939160814Ssimon
940160814Ssimon	if (!params->order || !params->base || !params->base->data)
941160814Ssimon		{
942160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
943160814Ssimon		goto err;
944160814Ssimon		}
945160814Ssimon
946160814Ssimon	if ((point = EC_POINT_new(ret)) == NULL) goto err;
947160814Ssimon
948160814Ssimon	/* set the point conversion form */
949160814Ssimon	EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
950160814Ssimon				(params->base->data[0] & ~0x01));
951160814Ssimon
952160814Ssimon	/* extract the ec point */
953160814Ssimon	if (!EC_POINT_oct2point(ret, point, params->base->data,
954160814Ssimon		                params->base->length, NULL))
955160814Ssimon		{
956160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
957160814Ssimon		goto err;
958160814Ssimon		}
959160814Ssimon
960160814Ssimon	/* extract the order */
961160814Ssimon	if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL)
962160814Ssimon		{
963160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
964160814Ssimon		goto err;
965160814Ssimon		}
966162911Ssimon	if (BN_is_negative(a) || BN_is_zero(a))
967162911Ssimon		{
968162911Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
969162911Ssimon		goto err;
970162911Ssimon		}
971162911Ssimon	if (BN_num_bits(a) > (int)field_bits + 1) /* Hasse bound */
972162911Ssimon		{
973162911Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
974162911Ssimon		goto err;
975162911Ssimon		}
976160814Ssimon
977160814Ssimon	/* extract the cofactor (optional) */
978160814Ssimon	if (params->cofactor == NULL)
979160814Ssimon		{
980160814Ssimon		if (b)
981160814Ssimon			{
982160814Ssimon			BN_free(b);
983160814Ssimon			b = NULL;
984160814Ssimon			}
985160814Ssimon		}
986160814Ssimon	else
987160814Ssimon		if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL)
988160814Ssimon			{
989160814Ssimon			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
990160814Ssimon			goto err;
991160814Ssimon			}
992160814Ssimon	/* set the generator, order and cofactor (if present) */
993160814Ssimon	if (!EC_GROUP_set_generator(ret, point, a, b))
994160814Ssimon		{
995160814Ssimon		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
996160814Ssimon		goto err;
997160814Ssimon		}
998160814Ssimon
999160814Ssimon	ok = 1;
1000160814Ssimon
1001160814Ssimonerr:	if (!ok)
1002160814Ssimon		{
1003160814Ssimon		if (ret)
1004160814Ssimon			EC_GROUP_clear_free(ret);
1005160814Ssimon		ret = NULL;
1006160814Ssimon		}
1007160814Ssimon
1008160814Ssimon	if (p)
1009160814Ssimon		BN_free(p);
1010160814Ssimon	if (a)
1011160814Ssimon		BN_free(a);
1012160814Ssimon	if (b)
1013160814Ssimon		BN_free(b);
1014160814Ssimon	if (point)
1015160814Ssimon		EC_POINT_free(point);
1016160814Ssimon	return(ret);
1017160814Ssimon}
1018160814Ssimon
1019160814SsimonEC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
1020160814Ssimon	{
1021160814Ssimon	EC_GROUP *ret=NULL;
1022160814Ssimon	int      tmp=0;
1023160814Ssimon
1024160814Ssimon	if (params == NULL)
1025160814Ssimon		{
1026160814Ssimon		ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP,
1027160814Ssimon		      EC_R_MISSING_PARAMETERS);
1028160814Ssimon		return NULL;
1029160814Ssimon		}
1030160814Ssimon
1031160814Ssimon	if (params->type == 0)
1032160814Ssimon		{ /* the curve is given by an OID */
1033160814Ssimon		tmp = OBJ_obj2nid(params->value.named_curve);
1034160814Ssimon		if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL)
1035160814Ssimon			{
1036160814Ssimon			ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP,
1037160814Ssimon			      EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
1038160814Ssimon			return NULL;
1039160814Ssimon			}
1040160814Ssimon		EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
1041160814Ssimon		}
1042160814Ssimon	else if (params->type == 1)
1043160814Ssimon		{ /* the parameters are given by a ECPARAMETERS
1044160814Ssimon		   * structure */
1045160814Ssimon		ret = ec_asn1_parameters2group(params->value.parameters);
1046160814Ssimon		if (!ret)
1047160814Ssimon			{
1048160814Ssimon			ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB);
1049160814Ssimon			return NULL;
1050160814Ssimon			}
1051160814Ssimon		EC_GROUP_set_asn1_flag(ret, 0x0);
1052160814Ssimon		}
1053160814Ssimon	else if (params->type == 2)
1054160814Ssimon		{ /* implicitlyCA */
1055160814Ssimon		return NULL;
1056160814Ssimon		}
1057160814Ssimon	else
1058160814Ssimon		{
1059160814Ssimon		ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR);
1060160814Ssimon		return NULL;
1061160814Ssimon		}
1062160814Ssimon
1063160814Ssimon	return ret;
1064160814Ssimon	}
1065160814Ssimon
1066160814Ssimon/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */
1067160814Ssimon
1068160814SsimonEC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
1069160814Ssimon	{
1070160814Ssimon	EC_GROUP	*group  = NULL;
1071160814Ssimon	ECPKPARAMETERS	*params = NULL;
1072160814Ssimon
1073160814Ssimon	if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL)
1074160814Ssimon		{
1075160814Ssimon		ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE);
1076160814Ssimon		ECPKPARAMETERS_free(params);
1077160814Ssimon		return NULL;
1078160814Ssimon		}
1079160814Ssimon
1080160814Ssimon	if ((group = ec_asn1_pkparameters2group(params)) == NULL)
1081160814Ssimon		{
1082160814Ssimon		ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE);
1083238405Sjkim		ECPKPARAMETERS_free(params);
1084160814Ssimon		return NULL;
1085160814Ssimon		}
1086160814Ssimon
1087160814Ssimon
1088160814Ssimon	if (a && *a)
1089160814Ssimon		EC_GROUP_clear_free(*a);
1090160814Ssimon	if (a)
1091160814Ssimon		*a = group;
1092160814Ssimon
1093160814Ssimon	ECPKPARAMETERS_free(params);
1094160814Ssimon	return(group);
1095160814Ssimon	}
1096160814Ssimon
1097160814Ssimonint i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
1098160814Ssimon	{
1099160814Ssimon	int		ret=0;
1100160814Ssimon	ECPKPARAMETERS	*tmp = ec_asn1_group2pkparameters(a, NULL);
1101160814Ssimon	if (tmp == NULL)
1102160814Ssimon		{
1103160814Ssimon		ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE);
1104160814Ssimon		return 0;
1105160814Ssimon		}
1106160814Ssimon	if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0)
1107160814Ssimon		{
1108160814Ssimon		ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE);
1109160814Ssimon		ECPKPARAMETERS_free(tmp);
1110160814Ssimon		return 0;
1111160814Ssimon		}
1112160814Ssimon	ECPKPARAMETERS_free(tmp);
1113160814Ssimon	return(ret);
1114160814Ssimon	}
1115160814Ssimon
1116160814Ssimon/* some EC_KEY functions */
1117160814Ssimon
1118160814SsimonEC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
1119160814Ssimon	{
1120160814Ssimon	int             ok=0;
1121160814Ssimon	EC_KEY          *ret=NULL;
1122160814Ssimon	EC_PRIVATEKEY   *priv_key=NULL;
1123160814Ssimon
1124160814Ssimon	if ((priv_key = EC_PRIVATEKEY_new()) == NULL)
1125160814Ssimon		{
1126160814Ssimon		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1127160814Ssimon		return NULL;
1128160814Ssimon		}
1129160814Ssimon
1130160814Ssimon	if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL)
1131160814Ssimon		{
1132160814Ssimon		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1133160814Ssimon		EC_PRIVATEKEY_free(priv_key);
1134160814Ssimon		return NULL;
1135160814Ssimon		}
1136160814Ssimon
1137160814Ssimon	if (a == NULL || *a == NULL)
1138160814Ssimon		{
1139160814Ssimon		if ((ret = EC_KEY_new()) == NULL)
1140160814Ssimon			{
1141160814Ssimon			ECerr(EC_F_D2I_ECPRIVATEKEY,
1142160814Ssimon                                 ERR_R_MALLOC_FAILURE);
1143160814Ssimon			goto err;
1144160814Ssimon			}
1145160814Ssimon		if (a)
1146160814Ssimon			*a = ret;
1147160814Ssimon		}
1148160814Ssimon	else
1149160814Ssimon		ret = *a;
1150160814Ssimon
1151160814Ssimon	if (priv_key->parameters)
1152160814Ssimon		{
1153160814Ssimon		if (ret->group)
1154160814Ssimon			EC_GROUP_clear_free(ret->group);
1155160814Ssimon		ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
1156160814Ssimon		}
1157160814Ssimon
1158160814Ssimon	if (ret->group == NULL)
1159160814Ssimon		{
1160160814Ssimon		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1161160814Ssimon		goto err;
1162160814Ssimon		}
1163160814Ssimon
1164160814Ssimon	ret->version = priv_key->version;
1165160814Ssimon
1166160814Ssimon	if (priv_key->privateKey)
1167160814Ssimon		{
1168160814Ssimon		ret->priv_key = BN_bin2bn(
1169160814Ssimon			M_ASN1_STRING_data(priv_key->privateKey),
1170160814Ssimon			M_ASN1_STRING_length(priv_key->privateKey),
1171160814Ssimon			ret->priv_key);
1172160814Ssimon		if (ret->priv_key == NULL)
1173160814Ssimon			{
1174160814Ssimon			ECerr(EC_F_D2I_ECPRIVATEKEY,
1175160814Ssimon                              ERR_R_BN_LIB);
1176160814Ssimon			goto err;
1177160814Ssimon			}
1178160814Ssimon		}
1179160814Ssimon	else
1180160814Ssimon		{
1181160814Ssimon		ECerr(EC_F_D2I_ECPRIVATEKEY,
1182160814Ssimon                      EC_R_MISSING_PRIVATE_KEY);
1183160814Ssimon		goto err;
1184160814Ssimon		}
1185160814Ssimon
1186279264Sdelphij	if (ret->pub_key)
1187279264Sdelphij		EC_POINT_clear_free(ret->pub_key);
1188279264Sdelphij	ret->pub_key = EC_POINT_new(ret->group);
1189279264Sdelphij	if (ret->pub_key == NULL)
1190279264Sdelphij		{
1191279264Sdelphij		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1192279264Sdelphij		goto err;
1193279264Sdelphij		}
1194279264Sdelphij
1195160814Ssimon	if (priv_key->publicKey)
1196160814Ssimon		{
1197160814Ssimon		const unsigned char *pub_oct;
1198279264Sdelphij		int pub_oct_len;
1199160814Ssimon
1200279264Sdelphij		pub_oct     = M_ASN1_STRING_data(priv_key->publicKey);
1201279264Sdelphij		pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
1202279264Sdelphij		/* The first byte - point conversion form - must be present. */
1203279264Sdelphij                if (pub_oct_len <= 0)
1204160814Ssimon			{
1205279264Sdelphij			ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL);
1206160814Ssimon			goto err;
1207160814Ssimon			}
1208279264Sdelphij		/* Save the point conversion form. */
1209160814Ssimon		ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01);
1210160814Ssimon		if (!EC_POINT_oct2point(ret->group, ret->pub_key,
1211279264Sdelphij					pub_oct, (size_t)(pub_oct_len), NULL))
1212160814Ssimon			{
1213160814Ssimon			ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1214160814Ssimon			goto err;
1215160814Ssimon			}
1216160814Ssimon		}
1217279264Sdelphij	else
1218279264Sdelphij		{
1219279264Sdelphij		if (!EC_POINT_mul(ret->group, ret->pub_key, ret->priv_key, NULL, NULL, NULL))
1220279264Sdelphij			{
1221279264Sdelphij			ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1222279264Sdelphij			goto err;
1223279264Sdelphij			}
1224279264Sdelphij		/* Remember the original private-key-only encoding. */
1225279264Sdelphij		ret->enc_flag |= EC_PKEY_NO_PUBKEY;
1226279264Sdelphij		}
1227160814Ssimon
1228160814Ssimon	ok = 1;
1229160814Ssimonerr:
1230160814Ssimon	if (!ok)
1231160814Ssimon		{
1232160814Ssimon		if (ret)
1233160814Ssimon			EC_KEY_free(ret);
1234160814Ssimon		ret = NULL;
1235160814Ssimon		}
1236160814Ssimon
1237160814Ssimon	if (priv_key)
1238160814Ssimon		EC_PRIVATEKEY_free(priv_key);
1239160814Ssimon
1240160814Ssimon	return(ret);
1241160814Ssimon	}
1242160814Ssimon
1243160814Ssimonint	i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
1244160814Ssimon	{
1245160814Ssimon	int             ret=0, ok=0;
1246160814Ssimon	unsigned char   *buffer=NULL;
1247160814Ssimon	size_t          buf_len=0, tmp_len;
1248160814Ssimon	EC_PRIVATEKEY   *priv_key=NULL;
1249160814Ssimon
1250279264Sdelphij	if (a == NULL || a->group == NULL || a->priv_key == NULL ||
1251279264Sdelphij	    (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL))
1252160814Ssimon		{
1253160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY,
1254160814Ssimon                      ERR_R_PASSED_NULL_PARAMETER);
1255160814Ssimon		goto err;
1256160814Ssimon		}
1257160814Ssimon
1258160814Ssimon	if ((priv_key = EC_PRIVATEKEY_new()) == NULL)
1259160814Ssimon		{
1260160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY,
1261160814Ssimon                      ERR_R_MALLOC_FAILURE);
1262160814Ssimon		goto err;
1263160814Ssimon		}
1264160814Ssimon
1265160814Ssimon	priv_key->version = a->version;
1266160814Ssimon
1267160814Ssimon	buf_len = (size_t)BN_num_bytes(a->priv_key);
1268160814Ssimon	buffer = OPENSSL_malloc(buf_len);
1269160814Ssimon	if (buffer == NULL)
1270160814Ssimon		{
1271160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY,
1272160814Ssimon                      ERR_R_MALLOC_FAILURE);
1273160814Ssimon		goto err;
1274160814Ssimon		}
1275160814Ssimon
1276160814Ssimon	if (!BN_bn2bin(a->priv_key, buffer))
1277160814Ssimon		{
1278160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB);
1279160814Ssimon		goto err;
1280160814Ssimon		}
1281160814Ssimon
1282160814Ssimon	if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len))
1283160814Ssimon		{
1284160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1285160814Ssimon		goto err;
1286160814Ssimon		}
1287160814Ssimon
1288160814Ssimon	if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS))
1289160814Ssimon		{
1290160814Ssimon		if ((priv_key->parameters = ec_asn1_group2pkparameters(
1291160814Ssimon			a->group, priv_key->parameters)) == NULL)
1292160814Ssimon			{
1293160814Ssimon			ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1294160814Ssimon			goto err;
1295160814Ssimon			}
1296160814Ssimon		}
1297160814Ssimon
1298160814Ssimon	if (!(a->enc_flag & EC_PKEY_NO_PUBKEY))
1299160814Ssimon		{
1300160814Ssimon		priv_key->publicKey = M_ASN1_BIT_STRING_new();
1301160814Ssimon		if (priv_key->publicKey == NULL)
1302160814Ssimon			{
1303160814Ssimon			ECerr(EC_F_I2D_ECPRIVATEKEY,
1304160814Ssimon				ERR_R_MALLOC_FAILURE);
1305160814Ssimon			goto err;
1306160814Ssimon			}
1307160814Ssimon
1308160814Ssimon		tmp_len = EC_POINT_point2oct(a->group, a->pub_key,
1309160814Ssimon				a->conv_form, NULL, 0, NULL);
1310160814Ssimon
1311160814Ssimon		if (tmp_len > buf_len)
1312160814Ssimon			{
1313160814Ssimon			unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
1314160814Ssimon			if (!tmp_buffer)
1315160814Ssimon				{
1316160814Ssimon				ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1317160814Ssimon				goto err;
1318160814Ssimon				}
1319160814Ssimon			buffer = tmp_buffer;
1320160814Ssimon			buf_len = tmp_len;
1321160814Ssimon			}
1322160814Ssimon
1323160814Ssimon		if (!EC_POINT_point2oct(a->group, a->pub_key,
1324160814Ssimon			a->conv_form, buffer, buf_len, NULL))
1325160814Ssimon			{
1326160814Ssimon			ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1327160814Ssimon			goto err;
1328160814Ssimon			}
1329160814Ssimon
1330167612Ssimon		priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
1331167612Ssimon		priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
1332160814Ssimon		if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer,
1333160814Ssimon				buf_len))
1334160814Ssimon			{
1335160814Ssimon			ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1336160814Ssimon			goto err;
1337160814Ssimon			}
1338160814Ssimon		}
1339160814Ssimon
1340160814Ssimon	if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0)
1341160814Ssimon		{
1342160814Ssimon		ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1343160814Ssimon		goto err;
1344160814Ssimon		}
1345160814Ssimon	ok=1;
1346160814Ssimonerr:
1347160814Ssimon	if (buffer)
1348160814Ssimon		OPENSSL_free(buffer);
1349160814Ssimon	if (priv_key)
1350160814Ssimon		EC_PRIVATEKEY_free(priv_key);
1351160814Ssimon	return(ok?ret:0);
1352160814Ssimon	}
1353160814Ssimon
1354160814Ssimonint i2d_ECParameters(EC_KEY *a, unsigned char **out)
1355160814Ssimon	{
1356160814Ssimon	if (a == NULL)
1357160814Ssimon		{
1358160814Ssimon		ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1359160814Ssimon		return 0;
1360160814Ssimon		}
1361160814Ssimon	return i2d_ECPKParameters(a->group, out);
1362160814Ssimon	}
1363160814Ssimon
1364160814SsimonEC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
1365160814Ssimon	{
1366160814Ssimon	EC_KEY   *ret;
1367160814Ssimon
1368160814Ssimon	if (in == NULL || *in == NULL)
1369160814Ssimon		{
1370160814Ssimon		ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1371160814Ssimon		return NULL;
1372160814Ssimon		}
1373160814Ssimon
1374160814Ssimon	if (a == NULL || *a == NULL)
1375160814Ssimon		{
1376160814Ssimon		if ((ret = EC_KEY_new()) == NULL)
1377160814Ssimon			{
1378160814Ssimon			ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
1379160814Ssimon			return NULL;
1380160814Ssimon			}
1381160814Ssimon		if (a)
1382160814Ssimon			*a = ret;
1383160814Ssimon		}
1384160814Ssimon	else
1385160814Ssimon		ret = *a;
1386160814Ssimon
1387160814Ssimon	if (!d2i_ECPKParameters(&ret->group, in, len))
1388160814Ssimon		{
1389160814Ssimon		ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB);
1390160814Ssimon		return NULL;
1391160814Ssimon		}
1392160814Ssimon
1393160814Ssimon	return ret;
1394160814Ssimon	}
1395160814Ssimon
1396160814SsimonEC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
1397160814Ssimon	{
1398160814Ssimon	EC_KEY *ret=NULL;
1399160814Ssimon
1400160814Ssimon	if (a == NULL || (*a) == NULL || (*a)->group == NULL)
1401160814Ssimon		{
1402160814Ssimon		/* sorry, but a EC_GROUP-structur is necessary
1403160814Ssimon                 * to set the public key */
1404160814Ssimon		ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1405160814Ssimon		return 0;
1406160814Ssimon		}
1407160814Ssimon	ret = *a;
1408160814Ssimon	if (ret->pub_key == NULL &&
1409160814Ssimon		(ret->pub_key = EC_POINT_new(ret->group)) == NULL)
1410160814Ssimon		{
1411160814Ssimon		ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1412160814Ssimon		return 0;
1413160814Ssimon		}
1414160814Ssimon	if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL))
1415160814Ssimon		{
1416160814Ssimon		ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB);
1417160814Ssimon		return 0;
1418160814Ssimon		}
1419160814Ssimon	/* save the point conversion form */
1420160814Ssimon	ret->conv_form = (point_conversion_form_t)(*in[0] & ~0x01);
1421160814Ssimon	*in += len;
1422160814Ssimon	return ret;
1423160814Ssimon	}
1424160814Ssimon
1425160814Ssimonint i2o_ECPublicKey(EC_KEY *a, unsigned char **out)
1426160814Ssimon	{
1427160814Ssimon        size_t buf_len=0;
1428160814Ssimon	int new_buffer = 0;
1429160814Ssimon
1430160814Ssimon        if (a == NULL)
1431160814Ssimon		{
1432160814Ssimon		ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1433160814Ssimon		return 0;
1434160814Ssimon		}
1435160814Ssimon
1436160814Ssimon        buf_len = EC_POINT_point2oct(a->group, a->pub_key,
1437160814Ssimon                              a->conv_form, NULL, 0, NULL);
1438160814Ssimon
1439160814Ssimon	if (out == NULL || buf_len == 0)
1440160814Ssimon	/* out == NULL => just return the length of the octet string */
1441160814Ssimon		return buf_len;
1442160814Ssimon
1443160814Ssimon	if (*out == NULL)
1444160814Ssimon		{
1445160814Ssimon		if ((*out = OPENSSL_malloc(buf_len)) == NULL)
1446160814Ssimon			{
1447160814Ssimon			ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1448160814Ssimon			return 0;
1449160814Ssimon			}
1450160814Ssimon		new_buffer = 1;
1451160814Ssimon		}
1452160814Ssimon        if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
1453160814Ssimon				*out, buf_len, NULL))
1454160814Ssimon		{
1455160814Ssimon		ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB);
1456279264Sdelphij		if (new_buffer)
1457279264Sdelphij			{
1458279264Sdelphij			OPENSSL_free(*out);
1459279264Sdelphij			*out = NULL;
1460279264Sdelphij			}
1461160814Ssimon		return 0;
1462160814Ssimon		}
1463160814Ssimon	if (!new_buffer)
1464160814Ssimon		*out += buf_len;
1465160814Ssimon	return buf_len;
1466160814Ssimon	}
1467