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
13296465Sdelphij *    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
65160814Ssimonint EC_GROUP_get_basis_type(const EC_GROUP *group)
66296465Sdelphij{
67296465Sdelphij    int i = 0;
68160814Ssimon
69296465Sdelphij    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
70296465Sdelphij        NID_X9_62_characteristic_two_field)
71296465Sdelphij        /* everything else is currently not supported */
72296465Sdelphij        return 0;
73160814Ssimon
74296465Sdelphij    while (group->poly[i] != 0)
75296465Sdelphij        i++;
76160814Ssimon
77296465Sdelphij    if (i == 4)
78296465Sdelphij        return NID_X9_62_ppBasis;
79296465Sdelphij    else if (i == 2)
80296465Sdelphij        return NID_X9_62_tpBasis;
81296465Sdelphij    else
82296465Sdelphij        /* everything else is currently not supported */
83296465Sdelphij        return 0;
84296465Sdelphij}
85160814Ssimon
86160814Ssimonint EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
87296465Sdelphij{
88296465Sdelphij    if (group == NULL)
89296465Sdelphij        return 0;
90160814Ssimon
91296465Sdelphij    if (EC_GROUP_method_of(group)->group_set_curve !=
92296465Sdelphij        ec_GF2m_simple_group_set_curve || !((group->poly[0] != 0)
93296465Sdelphij                                            && (group->poly[1] != 0)
94296465Sdelphij                                            && (group->poly[2] == 0))) {
95296465Sdelphij        ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS,
96296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
97296465Sdelphij        return 0;
98296465Sdelphij    }
99160814Ssimon
100296465Sdelphij    if (k)
101296465Sdelphij        *k = group->poly[1];
102160814Ssimon
103296465Sdelphij    return 1;
104296465Sdelphij}
105160814Ssimon
106160814Ssimonint EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
107296465Sdelphij                                   unsigned int *k2, unsigned int *k3)
108296465Sdelphij{
109296465Sdelphij    if (group == NULL)
110296465Sdelphij        return 0;
111160814Ssimon
112296465Sdelphij    if (EC_GROUP_method_of(group)->group_set_curve !=
113296465Sdelphij        ec_GF2m_simple_group_set_curve || !((group->poly[0] != 0)
114296465Sdelphij                                            && (group->poly[1] != 0)
115296465Sdelphij                                            && (group->poly[2] != 0)
116296465Sdelphij                                            && (group->poly[3] != 0)
117296465Sdelphij                                            && (group->poly[4] == 0))) {
118296465Sdelphij        ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS,
119296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
120296465Sdelphij        return 0;
121296465Sdelphij    }
122160814Ssimon
123296465Sdelphij    if (k1)
124296465Sdelphij        *k1 = group->poly[3];
125296465Sdelphij    if (k2)
126296465Sdelphij        *k2 = group->poly[2];
127296465Sdelphij    if (k3)
128296465Sdelphij        *k3 = group->poly[1];
129160814Ssimon
130296465Sdelphij    return 1;
131296465Sdelphij}
132160814Ssimon
133160814Ssimon/* some structures needed for the asn1 encoding */
134160814Ssimontypedef struct x9_62_pentanomial_st {
135296465Sdelphij    long k1;
136296465Sdelphij    long k2;
137296465Sdelphij    long k3;
138296465Sdelphij} X9_62_PENTANOMIAL;
139160814Ssimon
140160814Ssimontypedef struct x9_62_characteristic_two_st {
141296465Sdelphij    long m;
142296465Sdelphij    ASN1_OBJECT *type;
143296465Sdelphij    union {
144296465Sdelphij        char *ptr;
145296465Sdelphij        /* NID_X9_62_onBasis */
146296465Sdelphij        ASN1_NULL *onBasis;
147296465Sdelphij        /* NID_X9_62_tpBasis */
148296465Sdelphij        ASN1_INTEGER *tpBasis;
149296465Sdelphij        /* NID_X9_62_ppBasis */
150296465Sdelphij        X9_62_PENTANOMIAL *ppBasis;
151296465Sdelphij        /* anything else */
152296465Sdelphij        ASN1_TYPE *other;
153296465Sdelphij    } p;
154296465Sdelphij} X9_62_CHARACTERISTIC_TWO;
155160814Ssimon
156160814Ssimontypedef struct x9_62_fieldid_st {
157296465Sdelphij    ASN1_OBJECT *fieldType;
158296465Sdelphij    union {
159296465Sdelphij        char *ptr;
160296465Sdelphij        /* NID_X9_62_prime_field */
161296465Sdelphij        ASN1_INTEGER *prime;
162296465Sdelphij        /* NID_X9_62_characteristic_two_field */
163296465Sdelphij        X9_62_CHARACTERISTIC_TWO *char_two;
164296465Sdelphij        /* anything else */
165296465Sdelphij        ASN1_TYPE *other;
166296465Sdelphij    } p;
167296465Sdelphij} X9_62_FIELDID;
168160814Ssimon
169160814Ssimontypedef struct x9_62_curve_st {
170296465Sdelphij    ASN1_OCTET_STRING *a;
171296465Sdelphij    ASN1_OCTET_STRING *b;
172296465Sdelphij    ASN1_BIT_STRING *seed;
173296465Sdelphij} X9_62_CURVE;
174160814Ssimon
175160814Ssimontypedef struct ec_parameters_st {
176296465Sdelphij    long version;
177296465Sdelphij    X9_62_FIELDID *fieldID;
178296465Sdelphij    X9_62_CURVE *curve;
179296465Sdelphij    ASN1_OCTET_STRING *base;
180296465Sdelphij    ASN1_INTEGER *order;
181296465Sdelphij    ASN1_INTEGER *cofactor;
182296465Sdelphij} ECPARAMETERS;
183160814Ssimon
184160814Ssimonstruct ecpk_parameters_st {
185296465Sdelphij    int type;
186296465Sdelphij    union {
187296465Sdelphij        ASN1_OBJECT *named_curve;
188296465Sdelphij        ECPARAMETERS *parameters;
189296465Sdelphij        ASN1_NULL *implicitlyCA;
190296465Sdelphij    } value;
191296465Sdelphij} /* ECPKPARAMETERS */ ;
192160814Ssimon
193160814Ssimon/* SEC1 ECPrivateKey */
194160814Ssimontypedef struct ec_privatekey_st {
195296465Sdelphij    long version;
196296465Sdelphij    ASN1_OCTET_STRING *privateKey;
197296465Sdelphij    ECPKPARAMETERS *parameters;
198296465Sdelphij    ASN1_BIT_STRING *publicKey;
199296465Sdelphij} EC_PRIVATEKEY;
200160814Ssimon
201160814Ssimon/* the OpenSSL ASN.1 definitions */
202160814SsimonASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
203296465Sdelphij        ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG),
204296465Sdelphij        ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG),
205296465Sdelphij        ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG)
206160814Ssimon} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL)
207160814Ssimon
208160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
209160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
210160814Ssimon
211160814SsimonASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY);
212160814Ssimon
213160814SsimonASN1_ADB(X9_62_CHARACTERISTIC_TWO) = {
214296465Sdelphij        ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)),
215296465Sdelphij        ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)),
216296465Sdelphij        ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL))
217160814Ssimon} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL);
218160814Ssimon
219160814SsimonASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = {
220296465Sdelphij        ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG),
221296465Sdelphij        ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
222296465Sdelphij        ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO)
223160814Ssimon} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO)
224160814Ssimon
225160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
226160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
227160814Ssimon
228160814SsimonASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
229160814Ssimon
230160814SsimonASN1_ADB(X9_62_FIELDID) = {
231296465Sdelphij        ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
232296465Sdelphij        ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO))
233160814Ssimon} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
234160814Ssimon
235160814SsimonASN1_SEQUENCE(X9_62_FIELDID) = {
236296465Sdelphij        ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
237296465Sdelphij        ASN1_ADB_OBJECT(X9_62_FIELDID)
238160814Ssimon} ASN1_SEQUENCE_END(X9_62_FIELDID)
239160814Ssimon
240160814SsimonASN1_SEQUENCE(X9_62_CURVE) = {
241296465Sdelphij        ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
242296465Sdelphij        ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
243296465Sdelphij        ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
244160814Ssimon} ASN1_SEQUENCE_END(X9_62_CURVE)
245160814Ssimon
246160814SsimonASN1_SEQUENCE(ECPARAMETERS) = {
247296465Sdelphij        ASN1_SIMPLE(ECPARAMETERS, version, LONG),
248296465Sdelphij        ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
249296465Sdelphij        ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
250296465Sdelphij        ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
251296465Sdelphij        ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
252296465Sdelphij        ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
253160814Ssimon} ASN1_SEQUENCE_END(ECPARAMETERS)
254160814Ssimon
255160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
256160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
257160814Ssimon
258160814SsimonASN1_CHOICE(ECPKPARAMETERS) = {
259296465Sdelphij        ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
260296465Sdelphij        ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
261296465Sdelphij        ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL)
262160814Ssimon} ASN1_CHOICE_END(ECPKPARAMETERS)
263160814Ssimon
264160814SsimonDECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
265160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS)
266160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
267160814Ssimon
268160814SsimonASN1_SEQUENCE(EC_PRIVATEKEY) = {
269296465Sdelphij        ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
270296465Sdelphij        ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
271296465Sdelphij        ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
272296465Sdelphij        ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
273160814Ssimon} ASN1_SEQUENCE_END(EC_PRIVATEKEY)
274160814Ssimon
275160814SsimonDECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
276160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY)
277160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
278160814Ssimon
279160814Ssimon/* some declarations of internal function */
280160814Ssimon
281296465Sdelphij/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */
282160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
283296465Sdelphij/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */
284160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
285296465Sdelphij/*
286296465Sdelphij * ec_asn1_parameters2group() creates a EC_GROUP object from a ECPARAMETERS
287296465Sdelphij * object
288296465Sdelphij */
289296465Sdelphijstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *);
290296465Sdelphij/*
291296465Sdelphij * ec_asn1_group2parameters() creates a ECPARAMETERS object from a EC_GROUP
292296465Sdelphij * object
293296465Sdelphij */
294296465Sdelphijstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,
295296465Sdelphij                                              ECPARAMETERS *);
296296465Sdelphij/*
297296465Sdelphij * ec_asn1_pkparameters2group() creates a EC_GROUP object from a
298296465Sdelphij * ECPKPARAMETERS object
299296465Sdelphij */
300296465Sdelphijstatic EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *);
301296465Sdelphij/*
302296465Sdelphij * ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a
303296465Sdelphij * EC_GROUP object
304296465Sdelphij */
305296465Sdelphijstatic ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *,
306296465Sdelphij                                                  ECPKPARAMETERS *);
307160814Ssimon
308160814Ssimon/* the function definitions */
309160814Ssimon
310160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
311296465Sdelphij{
312296465Sdelphij    int ok = 0, nid;
313296465Sdelphij    BIGNUM *tmp = NULL;
314160814Ssimon
315296465Sdelphij    if (group == NULL || field == NULL)
316296465Sdelphij        return 0;
317160814Ssimon
318296465Sdelphij    /* clear the old values (if necessary) */
319296465Sdelphij    if (field->fieldType != NULL)
320296465Sdelphij        ASN1_OBJECT_free(field->fieldType);
321296465Sdelphij    if (field->p.other != NULL)
322296465Sdelphij        ASN1_TYPE_free(field->p.other);
323160814Ssimon
324296465Sdelphij    nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
325296465Sdelphij    /* set OID for the field */
326296465Sdelphij    if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) {
327296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
328296465Sdelphij        goto err;
329296465Sdelphij    }
330160814Ssimon
331296465Sdelphij    if (nid == NID_X9_62_prime_field) {
332296465Sdelphij        if ((tmp = BN_new()) == NULL) {
333296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
334296465Sdelphij            goto err;
335296465Sdelphij        }
336296465Sdelphij        /* the parameters are specified by the prime number p */
337296465Sdelphij        if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL)) {
338296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
339296465Sdelphij            goto err;
340296465Sdelphij        }
341296465Sdelphij        /* set the prime number */
342296465Sdelphij        field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL);
343296465Sdelphij        if (field->p.prime == NULL) {
344296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
345296465Sdelphij            goto err;
346296465Sdelphij        }
347296465Sdelphij    } else {                    /* nid == NID_X9_62_characteristic_two_field */
348160814Ssimon
349296465Sdelphij        int field_type;
350296465Sdelphij        X9_62_CHARACTERISTIC_TWO *char_two;
351160814Ssimon
352296465Sdelphij        field->p.char_two = X9_62_CHARACTERISTIC_TWO_new();
353296465Sdelphij        char_two = field->p.char_two;
354160814Ssimon
355296465Sdelphij        if (char_two == NULL) {
356296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
357296465Sdelphij            goto err;
358296465Sdelphij        }
359160814Ssimon
360296465Sdelphij        char_two->m = (long)EC_GROUP_get_degree(group);
361160814Ssimon
362296465Sdelphij        field_type = EC_GROUP_get_basis_type(group);
363160814Ssimon
364296465Sdelphij        if (field_type == 0) {
365296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
366296465Sdelphij            goto err;
367296465Sdelphij        }
368296465Sdelphij        /* set base type OID */
369296465Sdelphij        if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) {
370296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
371296465Sdelphij            goto err;
372296465Sdelphij        }
373160814Ssimon
374296465Sdelphij        if (field_type == NID_X9_62_tpBasis) {
375296465Sdelphij            unsigned int k;
376160814Ssimon
377296465Sdelphij            if (!EC_GROUP_get_trinomial_basis(group, &k))
378296465Sdelphij                goto err;
379160814Ssimon
380296465Sdelphij            char_two->p.tpBasis = ASN1_INTEGER_new();
381296465Sdelphij            if (!char_two->p.tpBasis) {
382296465Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
383296465Sdelphij                goto err;
384296465Sdelphij            }
385296465Sdelphij            if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) {
386296465Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
387296465Sdelphij                goto err;
388296465Sdelphij            }
389296465Sdelphij        } else if (field_type == NID_X9_62_ppBasis) {
390296465Sdelphij            unsigned int k1, k2, k3;
391160814Ssimon
392296465Sdelphij            if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3))
393296465Sdelphij                goto err;
394160814Ssimon
395296465Sdelphij            char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
396296465Sdelphij            if (!char_two->p.ppBasis) {
397296465Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
398296465Sdelphij                goto err;
399296465Sdelphij            }
400296465Sdelphij
401296465Sdelphij            /* set k? values */
402296465Sdelphij            char_two->p.ppBasis->k1 = (long)k1;
403296465Sdelphij            char_two->p.ppBasis->k2 = (long)k2;
404296465Sdelphij            char_two->p.ppBasis->k3 = (long)k3;
405296465Sdelphij        } else {                /* field_type == NID_X9_62_onBasis */
406296465Sdelphij
407296465Sdelphij            /* for ONB the parameters are (asn1) NULL */
408296465Sdelphij            char_two->p.onBasis = ASN1_NULL_new();
409296465Sdelphij            if (!char_two->p.onBasis) {
410296465Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
411296465Sdelphij                goto err;
412296465Sdelphij            }
413296465Sdelphij        }
414296465Sdelphij    }
415296465Sdelphij
416296465Sdelphij    ok = 1;
417296465Sdelphij
418296465Sdelphij err:if (tmp)
419296465Sdelphij        BN_free(tmp);
420296465Sdelphij    return (ok);
421160814Ssimon}
422160814Ssimon
423160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
424296465Sdelphij{
425296465Sdelphij    int ok = 0, nid;
426296465Sdelphij    BIGNUM *tmp_1 = NULL, *tmp_2 = NULL;
427296465Sdelphij    unsigned char *buffer_1 = NULL, *buffer_2 = NULL,
428296465Sdelphij        *a_buf = NULL, *b_buf = NULL;
429296465Sdelphij    size_t len_1, len_2;
430296465Sdelphij    unsigned char char_zero = 0;
431160814Ssimon
432296465Sdelphij    if (!group || !curve || !curve->a || !curve->b)
433296465Sdelphij        return 0;
434160814Ssimon
435296465Sdelphij    if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) {
436296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
437296465Sdelphij        goto err;
438296465Sdelphij    }
439160814Ssimon
440296465Sdelphij    nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
441160814Ssimon
442296465Sdelphij    /* get a and b */
443296465Sdelphij    if (nid == NID_X9_62_prime_field) {
444296465Sdelphij        if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL)) {
445296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
446296465Sdelphij            goto err;
447296465Sdelphij        }
448296465Sdelphij    } else {                    /* nid == NID_X9_62_characteristic_two_field */
449160814Ssimon
450296465Sdelphij        if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) {
451296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
452296465Sdelphij            goto err;
453296465Sdelphij        }
454296465Sdelphij    }
455160814Ssimon
456296465Sdelphij    len_1 = (size_t)BN_num_bytes(tmp_1);
457296465Sdelphij    len_2 = (size_t)BN_num_bytes(tmp_2);
458160814Ssimon
459296465Sdelphij    if (len_1 == 0) {
460296465Sdelphij        /* len_1 == 0 => a == 0 */
461296465Sdelphij        a_buf = &char_zero;
462296465Sdelphij        len_1 = 1;
463296465Sdelphij    } else {
464296465Sdelphij        if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) {
465296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
466296465Sdelphij            goto err;
467296465Sdelphij        }
468296465Sdelphij        if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) {
469296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
470296465Sdelphij            goto err;
471296465Sdelphij        }
472296465Sdelphij        a_buf = buffer_1;
473296465Sdelphij    }
474160814Ssimon
475296465Sdelphij    if (len_2 == 0) {
476296465Sdelphij        /* len_2 == 0 => b == 0 */
477296465Sdelphij        b_buf = &char_zero;
478296465Sdelphij        len_2 = 1;
479296465Sdelphij    } else {
480296465Sdelphij        if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) {
481296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
482296465Sdelphij            goto err;
483296465Sdelphij        }
484296465Sdelphij        if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) {
485296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
486296465Sdelphij            goto err;
487296465Sdelphij        }
488296465Sdelphij        b_buf = buffer_2;
489296465Sdelphij    }
490160814Ssimon
491296465Sdelphij    /* set a and b */
492296465Sdelphij    if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
493296465Sdelphij        !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) {
494296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
495296465Sdelphij        goto err;
496296465Sdelphij    }
497160814Ssimon
498296465Sdelphij    /* set the seed (optional) */
499296465Sdelphij    if (group->seed) {
500296465Sdelphij        if (!curve->seed)
501296465Sdelphij            if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) {
502296465Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
503296465Sdelphij                goto err;
504296465Sdelphij            }
505296465Sdelphij        curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
506296465Sdelphij        curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT;
507296465Sdelphij        if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
508296465Sdelphij                                 (int)group->seed_len)) {
509296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
510296465Sdelphij            goto err;
511296465Sdelphij        }
512296465Sdelphij    } else {
513296465Sdelphij        if (curve->seed) {
514296465Sdelphij            ASN1_BIT_STRING_free(curve->seed);
515296465Sdelphij            curve->seed = NULL;
516296465Sdelphij        }
517296465Sdelphij    }
518296465Sdelphij
519296465Sdelphij    ok = 1;
520296465Sdelphij
521296465Sdelphij err:if (buffer_1)
522296465Sdelphij        OPENSSL_free(buffer_1);
523296465Sdelphij    if (buffer_2)
524296465Sdelphij        OPENSSL_free(buffer_2);
525296465Sdelphij    if (tmp_1)
526296465Sdelphij        BN_free(tmp_1);
527296465Sdelphij    if (tmp_2)
528296465Sdelphij        BN_free(tmp_2);
529296465Sdelphij    return (ok);
530296465Sdelphij}
531296465Sdelphij
532160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group,
533160814Ssimon                                              ECPARAMETERS *param)
534296465Sdelphij{
535296465Sdelphij    int ok = 0;
536296465Sdelphij    size_t len = 0;
537296465Sdelphij    ECPARAMETERS *ret = NULL;
538296465Sdelphij    BIGNUM *tmp = NULL;
539296465Sdelphij    unsigned char *buffer = NULL;
540296465Sdelphij    const EC_POINT *point = NULL;
541296465Sdelphij    point_conversion_form_t form;
542160814Ssimon
543296465Sdelphij    if ((tmp = BN_new()) == NULL) {
544296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
545296465Sdelphij        goto err;
546296465Sdelphij    }
547160814Ssimon
548296465Sdelphij    if (param == NULL) {
549296465Sdelphij        if ((ret = ECPARAMETERS_new()) == NULL) {
550296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
551296465Sdelphij            goto err;
552296465Sdelphij        }
553296465Sdelphij    } else
554296465Sdelphij        ret = param;
555160814Ssimon
556296465Sdelphij    /* set the version (always one) */
557296465Sdelphij    ret->version = (long)0x1;
558160814Ssimon
559296465Sdelphij    /* set the fieldID */
560296465Sdelphij    if (!ec_asn1_group2fieldid(group, ret->fieldID)) {
561296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
562296465Sdelphij        goto err;
563296465Sdelphij    }
564160814Ssimon
565296465Sdelphij    /* set the curve */
566296465Sdelphij    if (!ec_asn1_group2curve(group, ret->curve)) {
567296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
568296465Sdelphij        goto err;
569296465Sdelphij    }
570160814Ssimon
571296465Sdelphij    /* set the base point */
572296465Sdelphij    if ((point = EC_GROUP_get0_generator(group)) == NULL) {
573296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR);
574296465Sdelphij        goto err;
575296465Sdelphij    }
576160814Ssimon
577296465Sdelphij    form = EC_GROUP_get_point_conversion_form(group);
578160814Ssimon
579296465Sdelphij    len = EC_POINT_point2oct(group, point, form, NULL, len, NULL);
580296465Sdelphij    if (len == 0) {
581296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
582296465Sdelphij        goto err;
583296465Sdelphij    }
584296465Sdelphij    if ((buffer = OPENSSL_malloc(len)) == NULL) {
585296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
586296465Sdelphij        goto err;
587296465Sdelphij    }
588296465Sdelphij    if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) {
589296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
590296465Sdelphij        goto err;
591296465Sdelphij    }
592296465Sdelphij    if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) {
593296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
594296465Sdelphij        goto err;
595296465Sdelphij    }
596296465Sdelphij    if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) {
597296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
598296465Sdelphij        goto err;
599296465Sdelphij    }
600160814Ssimon
601296465Sdelphij    /* set the order */
602296465Sdelphij    if (!EC_GROUP_get_order(group, tmp, NULL)) {
603296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
604296465Sdelphij        goto err;
605296465Sdelphij    }
606296465Sdelphij    ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
607296465Sdelphij    if (ret->order == NULL) {
608296465Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
609296465Sdelphij        goto err;
610296465Sdelphij    }
611160814Ssimon
612296465Sdelphij    /* set the cofactor (optional) */
613296465Sdelphij    if (EC_GROUP_get_cofactor(group, tmp, NULL)) {
614296465Sdelphij        ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
615296465Sdelphij        if (ret->cofactor == NULL) {
616296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
617296465Sdelphij            goto err;
618296465Sdelphij        }
619296465Sdelphij    }
620160814Ssimon
621296465Sdelphij    ok = 1;
622160814Ssimon
623296465Sdelphij err:if (!ok) {
624296465Sdelphij        if (ret && !param)
625296465Sdelphij            ECPARAMETERS_free(ret);
626296465Sdelphij        ret = NULL;
627296465Sdelphij    }
628296465Sdelphij    if (tmp)
629296465Sdelphij        BN_free(tmp);
630296465Sdelphij    if (buffer)
631296465Sdelphij        OPENSSL_free(buffer);
632296465Sdelphij    return (ret);
633296465Sdelphij}
634160814Ssimon
635296465SdelphijECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
636160814Ssimon                                           ECPKPARAMETERS *params)
637296465Sdelphij{
638296465Sdelphij    int ok = 1, tmp;
639296465Sdelphij    ECPKPARAMETERS *ret = params;
640160814Ssimon
641296465Sdelphij    if (ret == NULL) {
642296465Sdelphij        if ((ret = ECPKPARAMETERS_new()) == NULL) {
643296465Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, ERR_R_MALLOC_FAILURE);
644296465Sdelphij            return NULL;
645296465Sdelphij        }
646296465Sdelphij    } else {
647296465Sdelphij        if (ret->type == 0 && ret->value.named_curve)
648296465Sdelphij            ASN1_OBJECT_free(ret->value.named_curve);
649296465Sdelphij        else if (ret->type == 1 && ret->value.parameters)
650296465Sdelphij            ECPARAMETERS_free(ret->value.parameters);
651296465Sdelphij    }
652160814Ssimon
653296465Sdelphij    if (EC_GROUP_get_asn1_flag(group)) {
654296465Sdelphij        /*
655296465Sdelphij         * use the asn1 OID to describe the the elliptic curve parameters
656296465Sdelphij         */
657296465Sdelphij        tmp = EC_GROUP_get_curve_name(group);
658296465Sdelphij        if (tmp) {
659296465Sdelphij            ret->type = 0;
660296465Sdelphij            if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL)
661296465Sdelphij                ok = 0;
662296465Sdelphij        } else
663296465Sdelphij            /* we don't kmow the nid => ERROR */
664296465Sdelphij            ok = 0;
665296465Sdelphij    } else {
666296465Sdelphij        /* use the ECPARAMETERS structure */
667296465Sdelphij        ret->type = 1;
668296465Sdelphij        if ((ret->value.parameters =
669296465Sdelphij             ec_asn1_group2parameters(group, NULL)) == NULL)
670296465Sdelphij            ok = 0;
671296465Sdelphij    }
672160814Ssimon
673296465Sdelphij    if (!ok) {
674296465Sdelphij        ECPKPARAMETERS_free(ret);
675296465Sdelphij        return NULL;
676296465Sdelphij    }
677296465Sdelphij    return ret;
678296465Sdelphij}
679160814Ssimon
680160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
681296465Sdelphij{
682296465Sdelphij    int ok = 0, tmp;
683296465Sdelphij    EC_GROUP *ret = NULL;
684296465Sdelphij    BIGNUM *p = NULL, *a = NULL, *b = NULL;
685296465Sdelphij    EC_POINT *point = NULL;
686296465Sdelphij    long field_bits;
687160814Ssimon
688296465Sdelphij    if (!params->fieldID || !params->fieldID->fieldType ||
689296465Sdelphij        !params->fieldID->p.ptr) {
690296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
691296465Sdelphij        goto err;
692296465Sdelphij    }
693160814Ssimon
694296465Sdelphij    /* now extract the curve parameters a and b */
695296465Sdelphij    if (!params->curve || !params->curve->a ||
696296465Sdelphij        !params->curve->a->data || !params->curve->b ||
697296465Sdelphij        !params->curve->b->data) {
698296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
699296465Sdelphij        goto err;
700296465Sdelphij    }
701296465Sdelphij    a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
702296465Sdelphij    if (a == NULL) {
703296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
704296465Sdelphij        goto err;
705296465Sdelphij    }
706296465Sdelphij    b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
707296465Sdelphij    if (b == NULL) {
708296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
709296465Sdelphij        goto err;
710296465Sdelphij    }
711160814Ssimon
712296465Sdelphij    /* get the field parameters */
713296465Sdelphij    tmp = OBJ_obj2nid(params->fieldID->fieldType);
714160814Ssimon
715296465Sdelphij    if (tmp == NID_X9_62_characteristic_two_field) {
716296465Sdelphij        X9_62_CHARACTERISTIC_TWO *char_two;
717160814Ssimon
718296465Sdelphij        char_two = params->fieldID->p.char_two;
719160814Ssimon
720296465Sdelphij        field_bits = char_two->m;
721296465Sdelphij        if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
722296465Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
723296465Sdelphij            goto err;
724296465Sdelphij        }
725162911Ssimon
726296465Sdelphij        if ((p = BN_new()) == NULL) {
727296465Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
728296465Sdelphij            goto err;
729296465Sdelphij        }
730160814Ssimon
731296465Sdelphij        /* get the base type */
732296465Sdelphij        tmp = OBJ_obj2nid(char_two->type);
733160814Ssimon
734296465Sdelphij        if (tmp == NID_X9_62_tpBasis) {
735296465Sdelphij            long tmp_long;
736160814Ssimon
737296465Sdelphij            if (!char_two->p.tpBasis) {
738296465Sdelphij                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
739296465Sdelphij                goto err;
740296465Sdelphij            }
741160814Ssimon
742296465Sdelphij            tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis);
743162911Ssimon
744296465Sdelphij            if (!(char_two->m > tmp_long && tmp_long > 0)) {
745296465Sdelphij                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP,
746296465Sdelphij                      EC_R_INVALID_TRINOMIAL_BASIS);
747296465Sdelphij                goto err;
748296465Sdelphij            }
749160814Ssimon
750296465Sdelphij            /* create the polynomial */
751296465Sdelphij            if (!BN_set_bit(p, (int)char_two->m))
752296465Sdelphij                goto err;
753296465Sdelphij            if (!BN_set_bit(p, (int)tmp_long))
754296465Sdelphij                goto err;
755296465Sdelphij            if (!BN_set_bit(p, 0))
756296465Sdelphij                goto err;
757296465Sdelphij        } else if (tmp == NID_X9_62_ppBasis) {
758296465Sdelphij            X9_62_PENTANOMIAL *penta;
759162911Ssimon
760296465Sdelphij            penta = char_two->p.ppBasis;
761296465Sdelphij            if (!penta) {
762296465Sdelphij                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
763296465Sdelphij                goto err;
764296465Sdelphij            }
765160814Ssimon
766296465Sdelphij            if (!
767296465Sdelphij                (char_two->m > penta->k3 && penta->k3 > penta->k2
768296465Sdelphij                 && penta->k2 > penta->k1 && penta->k1 > 0)) {
769296465Sdelphij                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP,
770296465Sdelphij                      EC_R_INVALID_PENTANOMIAL_BASIS);
771296465Sdelphij                goto err;
772296465Sdelphij            }
773162911Ssimon
774296465Sdelphij            /* create the polynomial */
775296465Sdelphij            if (!BN_set_bit(p, (int)char_two->m))
776296465Sdelphij                goto err;
777296465Sdelphij            if (!BN_set_bit(p, (int)penta->k1))
778296465Sdelphij                goto err;
779296465Sdelphij            if (!BN_set_bit(p, (int)penta->k2))
780296465Sdelphij                goto err;
781296465Sdelphij            if (!BN_set_bit(p, (int)penta->k3))
782296465Sdelphij                goto err;
783296465Sdelphij            if (!BN_set_bit(p, 0))
784296465Sdelphij                goto err;
785296465Sdelphij        } else if (tmp == NID_X9_62_onBasis) {
786296465Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED);
787296465Sdelphij            goto err;
788296465Sdelphij        } else {                /* error */
789162911Ssimon
790296465Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
791296465Sdelphij            goto err;
792296465Sdelphij        }
793162911Ssimon
794296465Sdelphij        /* create the EC_GROUP structure */
795296465Sdelphij        ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
796296465Sdelphij    } else if (tmp == NID_X9_62_prime_field) {
797296465Sdelphij        /* we have a curve over a prime field */
798296465Sdelphij        /* extract the prime number */
799296465Sdelphij        if (!params->fieldID->p.prime) {
800296465Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
801296465Sdelphij            goto err;
802296465Sdelphij        }
803296465Sdelphij        p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
804296465Sdelphij        if (p == NULL) {
805296465Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
806296465Sdelphij            goto err;
807296465Sdelphij        }
808160814Ssimon
809296465Sdelphij        if (BN_is_negative(p) || BN_is_zero(p)) {
810296465Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
811296465Sdelphij            goto err;
812296465Sdelphij        }
813160814Ssimon
814296465Sdelphij        field_bits = BN_num_bits(p);
815296465Sdelphij        if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
816296465Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
817296465Sdelphij            goto err;
818296465Sdelphij        }
819160814Ssimon
820296465Sdelphij        /* create the EC_GROUP structure */
821296465Sdelphij        ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
822296465Sdelphij    } else {
823296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
824296465Sdelphij        goto err;
825296465Sdelphij    }
826160814Ssimon
827296465Sdelphij    if (ret == NULL) {
828296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
829296465Sdelphij        goto err;
830296465Sdelphij    }
831160814Ssimon
832296465Sdelphij    /* extract seed (optional) */
833296465Sdelphij    if (params->curve->seed != NULL) {
834296465Sdelphij        if (ret->seed != NULL)
835296465Sdelphij            OPENSSL_free(ret->seed);
836296465Sdelphij        if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) {
837296465Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
838296465Sdelphij            goto err;
839296465Sdelphij        }
840296465Sdelphij        memcpy(ret->seed, params->curve->seed->data,
841296465Sdelphij               params->curve->seed->length);
842296465Sdelphij        ret->seed_len = params->curve->seed->length;
843296465Sdelphij    }
844160814Ssimon
845296465Sdelphij    if (!params->order || !params->base || !params->base->data) {
846296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
847296465Sdelphij        goto err;
848296465Sdelphij    }
849160814Ssimon
850296465Sdelphij    if ((point = EC_POINT_new(ret)) == NULL)
851296465Sdelphij        goto err;
852160814Ssimon
853296465Sdelphij    /* set the point conversion form */
854296465Sdelphij    EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
855296465Sdelphij                                       (params->base->data[0] & ~0x01));
856160814Ssimon
857296465Sdelphij    /* extract the ec point */
858296465Sdelphij    if (!EC_POINT_oct2point(ret, point, params->base->data,
859296465Sdelphij                            params->base->length, NULL)) {
860296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
861296465Sdelphij        goto err;
862296465Sdelphij    }
863160814Ssimon
864296465Sdelphij    /* extract the order */
865296465Sdelphij    if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) {
866296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
867296465Sdelphij        goto err;
868296465Sdelphij    }
869296465Sdelphij    if (BN_is_negative(a) || BN_is_zero(a)) {
870296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
871296465Sdelphij        goto err;
872296465Sdelphij    }
873296465Sdelphij    if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */
874296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
875296465Sdelphij        goto err;
876296465Sdelphij    }
877296465Sdelphij
878296465Sdelphij    /* extract the cofactor (optional) */
879296465Sdelphij    if (params->cofactor == NULL) {
880296465Sdelphij        if (b) {
881296465Sdelphij            BN_free(b);
882296465Sdelphij            b = NULL;
883296465Sdelphij        }
884296465Sdelphij    } else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) {
885296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
886296465Sdelphij        goto err;
887296465Sdelphij    }
888296465Sdelphij    /* set the generator, order and cofactor (if present) */
889296465Sdelphij    if (!EC_GROUP_set_generator(ret, point, a, b)) {
890296465Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
891296465Sdelphij        goto err;
892296465Sdelphij    }
893296465Sdelphij
894296465Sdelphij    ok = 1;
895296465Sdelphij
896296465Sdelphij err:if (!ok) {
897296465Sdelphij        if (ret)
898296465Sdelphij            EC_GROUP_clear_free(ret);
899296465Sdelphij        ret = NULL;
900296465Sdelphij    }
901296465Sdelphij
902296465Sdelphij    if (p)
903296465Sdelphij        BN_free(p);
904296465Sdelphij    if (a)
905296465Sdelphij        BN_free(a);
906296465Sdelphij    if (b)
907296465Sdelphij        BN_free(b);
908296465Sdelphij    if (point)
909296465Sdelphij        EC_POINT_free(point);
910296465Sdelphij    return (ret);
911160814Ssimon}
912160814Ssimon
913160814SsimonEC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
914296465Sdelphij{
915296465Sdelphij    EC_GROUP *ret = NULL;
916296465Sdelphij    int tmp = 0;
917160814Ssimon
918296465Sdelphij    if (params == NULL) {
919296465Sdelphij        ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_MISSING_PARAMETERS);
920296465Sdelphij        return NULL;
921296465Sdelphij    }
922160814Ssimon
923296465Sdelphij    if (params->type == 0) {    /* the curve is given by an OID */
924296465Sdelphij        tmp = OBJ_obj2nid(params->value.named_curve);
925296465Sdelphij        if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) {
926296465Sdelphij            ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP,
927296465Sdelphij                  EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
928296465Sdelphij            return NULL;
929296465Sdelphij        }
930296465Sdelphij        EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
931296465Sdelphij    } else if (params->type == 1) { /* the parameters are given by a
932296465Sdelphij                                     * ECPARAMETERS structure */
933296465Sdelphij        ret = ec_asn1_parameters2group(params->value.parameters);
934296465Sdelphij        if (!ret) {
935296465Sdelphij            ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB);
936296465Sdelphij            return NULL;
937296465Sdelphij        }
938296465Sdelphij        EC_GROUP_set_asn1_flag(ret, 0x0);
939296465Sdelphij    } else if (params->type == 2) { /* implicitlyCA */
940296465Sdelphij        return NULL;
941296465Sdelphij    } else {
942296465Sdelphij        ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR);
943296465Sdelphij        return NULL;
944296465Sdelphij    }
945160814Ssimon
946296465Sdelphij    return ret;
947296465Sdelphij}
948160814Ssimon
949160814Ssimon/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */
950160814Ssimon
951160814SsimonEC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
952296465Sdelphij{
953296465Sdelphij    EC_GROUP *group = NULL;
954296465Sdelphij    ECPKPARAMETERS *params = NULL;
955160814Ssimon
956296465Sdelphij    if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) {
957296465Sdelphij        ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE);
958296465Sdelphij        ECPKPARAMETERS_free(params);
959296465Sdelphij        return NULL;
960296465Sdelphij    }
961160814Ssimon
962296465Sdelphij    if ((group = ec_asn1_pkparameters2group(params)) == NULL) {
963296465Sdelphij        ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE);
964296465Sdelphij        return NULL;
965296465Sdelphij    }
966160814Ssimon
967296465Sdelphij    if (a && *a)
968296465Sdelphij        EC_GROUP_clear_free(*a);
969296465Sdelphij    if (a)
970296465Sdelphij        *a = group;
971160814Ssimon
972296465Sdelphij    ECPKPARAMETERS_free(params);
973296465Sdelphij    return (group);
974296465Sdelphij}
975296465Sdelphij
976160814Ssimonint i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
977296465Sdelphij{
978296465Sdelphij    int ret = 0;
979296465Sdelphij    ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL);
980296465Sdelphij    if (tmp == NULL) {
981296465Sdelphij        ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE);
982296465Sdelphij        return 0;
983296465Sdelphij    }
984296465Sdelphij    if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) {
985296465Sdelphij        ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE);
986296465Sdelphij        ECPKPARAMETERS_free(tmp);
987296465Sdelphij        return 0;
988296465Sdelphij    }
989296465Sdelphij    ECPKPARAMETERS_free(tmp);
990296465Sdelphij    return (ret);
991296465Sdelphij}
992160814Ssimon
993160814Ssimon/* some EC_KEY functions */
994160814Ssimon
995160814SsimonEC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
996296465Sdelphij{
997296465Sdelphij    int ok = 0;
998296465Sdelphij    EC_KEY *ret = NULL;
999296465Sdelphij    EC_PRIVATEKEY *priv_key = NULL;
1000160814Ssimon
1001296465Sdelphij    if ((priv_key = EC_PRIVATEKEY_new()) == NULL) {
1002296465Sdelphij        ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1003296465Sdelphij        return NULL;
1004296465Sdelphij    }
1005160814Ssimon
1006296465Sdelphij    if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL) {
1007296465Sdelphij        ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1008296465Sdelphij        EC_PRIVATEKEY_free(priv_key);
1009296465Sdelphij        return NULL;
1010296465Sdelphij    }
1011160814Ssimon
1012296465Sdelphij    if (a == NULL || *a == NULL) {
1013296465Sdelphij        if ((ret = EC_KEY_new()) == NULL) {
1014296465Sdelphij            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1015296465Sdelphij            goto err;
1016296465Sdelphij        }
1017296465Sdelphij    } else
1018296465Sdelphij        ret = *a;
1019160814Ssimon
1020296465Sdelphij    if (priv_key->parameters) {
1021296465Sdelphij        if (ret->group)
1022296465Sdelphij            EC_GROUP_clear_free(ret->group);
1023296465Sdelphij        ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
1024296465Sdelphij    }
1025160814Ssimon
1026296465Sdelphij    if (ret->group == NULL) {
1027296465Sdelphij        ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1028296465Sdelphij        goto err;
1029296465Sdelphij    }
1030160814Ssimon
1031296465Sdelphij    ret->version = priv_key->version;
1032160814Ssimon
1033296465Sdelphij    if (priv_key->privateKey) {
1034296465Sdelphij        ret->priv_key = BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey),
1035296465Sdelphij                                  M_ASN1_STRING_length(priv_key->privateKey),
1036296465Sdelphij                                  ret->priv_key);
1037296465Sdelphij        if (ret->priv_key == NULL) {
1038296465Sdelphij            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_BN_LIB);
1039296465Sdelphij            goto err;
1040296465Sdelphij        }
1041296465Sdelphij    } else {
1042296465Sdelphij        ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_MISSING_PRIVATE_KEY);
1043296465Sdelphij        goto err;
1044296465Sdelphij    }
1045160814Ssimon
1046296465Sdelphij    if (priv_key->publicKey) {
1047296465Sdelphij        const unsigned char *pub_oct;
1048296465Sdelphij        size_t pub_oct_len;
1049160814Ssimon
1050296465Sdelphij        if (ret->pub_key)
1051296465Sdelphij            EC_POINT_clear_free(ret->pub_key);
1052296465Sdelphij        ret->pub_key = EC_POINT_new(ret->group);
1053296465Sdelphij        if (ret->pub_key == NULL) {
1054296465Sdelphij            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1055296465Sdelphij            goto err;
1056296465Sdelphij        }
1057296465Sdelphij        pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
1058296465Sdelphij        pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
1059296465Sdelphij        /* save the point conversion form */
1060296465Sdelphij        ret->conv_form = (point_conversion_form_t) (pub_oct[0] & ~0x01);
1061296465Sdelphij        if (!EC_POINT_oct2point(ret->group, ret->pub_key,
1062296465Sdelphij                                pub_oct, pub_oct_len, NULL)) {
1063296465Sdelphij            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1064296465Sdelphij            goto err;
1065296465Sdelphij        }
1066296465Sdelphij    }
1067160814Ssimon
1068296465Sdelphij    if (a)
1069296465Sdelphij        *a = ret;
1070296465Sdelphij    ok = 1;
1071296465Sdelphij err:
1072296465Sdelphij    if (!ok) {
1073296465Sdelphij        if (ret && (a == NULL || *a != ret))
1074296465Sdelphij            EC_KEY_free(ret);
1075296465Sdelphij        ret = NULL;
1076296465Sdelphij    }
1077160814Ssimon
1078296465Sdelphij    if (priv_key)
1079296465Sdelphij        EC_PRIVATEKEY_free(priv_key);
1080160814Ssimon
1081296465Sdelphij    return (ret);
1082296465Sdelphij}
1083160814Ssimon
1084296465Sdelphijint i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
1085296465Sdelphij{
1086296465Sdelphij    int ret = 0, ok = 0;
1087296465Sdelphij    unsigned char *buffer = NULL;
1088296465Sdelphij    size_t buf_len = 0, tmp_len;
1089296465Sdelphij    EC_PRIVATEKEY *priv_key = NULL;
1090160814Ssimon
1091296465Sdelphij    if (a == NULL || a->group == NULL || a->priv_key == NULL) {
1092296465Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
1093296465Sdelphij        goto err;
1094296465Sdelphij    }
1095160814Ssimon
1096296465Sdelphij    if ((priv_key = EC_PRIVATEKEY_new()) == NULL) {
1097296465Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1098296465Sdelphij        goto err;
1099296465Sdelphij    }
1100160814Ssimon
1101296465Sdelphij    priv_key->version = a->version;
1102160814Ssimon
1103296465Sdelphij    buf_len = (size_t)BN_num_bytes(a->priv_key);
1104296465Sdelphij    buffer = OPENSSL_malloc(buf_len);
1105296465Sdelphij    if (buffer == NULL) {
1106296465Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1107296465Sdelphij        goto err;
1108296465Sdelphij    }
1109160814Ssimon
1110296465Sdelphij    if (!BN_bn2bin(a->priv_key, buffer)) {
1111296465Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB);
1112296465Sdelphij        goto err;
1113296465Sdelphij    }
1114160814Ssimon
1115296465Sdelphij    if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
1116296465Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1117296465Sdelphij        goto err;
1118296465Sdelphij    }
1119160814Ssimon
1120296465Sdelphij    if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) {
1121296465Sdelphij        if ((priv_key->parameters =
1122296465Sdelphij             ec_asn1_group2pkparameters(a->group,
1123296465Sdelphij                                        priv_key->parameters)) == NULL) {
1124296465Sdelphij            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1125296465Sdelphij            goto err;
1126296465Sdelphij        }
1127296465Sdelphij    }
1128160814Ssimon
1129296465Sdelphij    if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) {
1130296465Sdelphij        priv_key->publicKey = M_ASN1_BIT_STRING_new();
1131296465Sdelphij        if (priv_key->publicKey == NULL) {
1132296465Sdelphij            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1133296465Sdelphij            goto err;
1134296465Sdelphij        }
1135160814Ssimon
1136296465Sdelphij        tmp_len = EC_POINT_point2oct(a->group, a->pub_key,
1137296465Sdelphij                                     a->conv_form, NULL, 0, NULL);
1138160814Ssimon
1139296465Sdelphij        if (tmp_len > buf_len) {
1140296465Sdelphij            unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
1141296465Sdelphij            if (!tmp_buffer) {
1142296465Sdelphij                ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1143296465Sdelphij                goto err;
1144296465Sdelphij            }
1145296465Sdelphij            buffer = tmp_buffer;
1146296465Sdelphij            buf_len = tmp_len;
1147296465Sdelphij        }
1148160814Ssimon
1149296465Sdelphij        if (!EC_POINT_point2oct(a->group, a->pub_key,
1150296465Sdelphij                                a->conv_form, buffer, buf_len, NULL)) {
1151296465Sdelphij            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1152296465Sdelphij            goto err;
1153296465Sdelphij        }
1154160814Ssimon
1155296465Sdelphij        priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
1156296465Sdelphij        priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
1157296465Sdelphij        if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
1158296465Sdelphij            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1159296465Sdelphij            goto err;
1160296465Sdelphij        }
1161296465Sdelphij    }
1162160814Ssimon
1163296465Sdelphij    if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) {
1164296465Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1165296465Sdelphij        goto err;
1166296465Sdelphij    }
1167296465Sdelphij    ok = 1;
1168296465Sdelphij err:
1169296465Sdelphij    if (buffer)
1170296465Sdelphij        OPENSSL_free(buffer);
1171296465Sdelphij    if (priv_key)
1172296465Sdelphij        EC_PRIVATEKEY_free(priv_key);
1173296465Sdelphij    return (ok ? ret : 0);
1174296465Sdelphij}
1175296465Sdelphij
1176160814Ssimonint i2d_ECParameters(EC_KEY *a, unsigned char **out)
1177296465Sdelphij{
1178296465Sdelphij    if (a == NULL) {
1179296465Sdelphij        ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1180296465Sdelphij        return 0;
1181296465Sdelphij    }
1182296465Sdelphij    return i2d_ECPKParameters(a->group, out);
1183296465Sdelphij}
1184160814Ssimon
1185160814SsimonEC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
1186296465Sdelphij{
1187296465Sdelphij    EC_KEY *ret;
1188160814Ssimon
1189296465Sdelphij    if (in == NULL || *in == NULL) {
1190296465Sdelphij        ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1191296465Sdelphij        return NULL;
1192296465Sdelphij    }
1193160814Ssimon
1194296465Sdelphij    if (a == NULL || *a == NULL) {
1195296465Sdelphij        if ((ret = EC_KEY_new()) == NULL) {
1196296465Sdelphij            ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
1197296465Sdelphij            return NULL;
1198296465Sdelphij        }
1199296465Sdelphij    } else
1200296465Sdelphij        ret = *a;
1201160814Ssimon
1202296465Sdelphij    if (!d2i_ECPKParameters(&ret->group, in, len)) {
1203296465Sdelphij        ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB);
1204296465Sdelphij        if (a == NULL || *a != ret)
1205296465Sdelphij             EC_KEY_free(ret);
1206296465Sdelphij        return NULL;
1207296465Sdelphij    }
1208160814Ssimon
1209296465Sdelphij    if (a)
1210296465Sdelphij        *a = ret;
1211160814Ssimon
1212296465Sdelphij    return ret;
1213296465Sdelphij}
1214296465Sdelphij
1215160814SsimonEC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
1216296465Sdelphij{
1217296465Sdelphij    EC_KEY *ret = NULL;
1218160814Ssimon
1219296465Sdelphij    if (a == NULL || (*a) == NULL || (*a)->group == NULL) {
1220296465Sdelphij        /*
1221296465Sdelphij         * sorry, but a EC_GROUP-structur is necessary to set the public key
1222296465Sdelphij         */
1223296465Sdelphij        ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1224296465Sdelphij        return 0;
1225296465Sdelphij    }
1226296465Sdelphij    ret = *a;
1227296465Sdelphij    if (ret->pub_key == NULL &&
1228296465Sdelphij        (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
1229296465Sdelphij        ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1230296465Sdelphij        return 0;
1231296465Sdelphij    }
1232296465Sdelphij    if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) {
1233296465Sdelphij        ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB);
1234296465Sdelphij        return 0;
1235296465Sdelphij    }
1236296465Sdelphij    /* save the point conversion form */
1237296465Sdelphij    ret->conv_form = (point_conversion_form_t) (*in[0] & ~0x01);
1238296465Sdelphij    *in += len;
1239296465Sdelphij    return ret;
1240296465Sdelphij}
1241160814Ssimon
1242160814Ssimonint i2o_ECPublicKey(EC_KEY *a, unsigned char **out)
1243296465Sdelphij{
1244296465Sdelphij    size_t buf_len = 0;
1245296465Sdelphij    int new_buffer = 0;
1246160814Ssimon
1247296465Sdelphij    if (a == NULL) {
1248296465Sdelphij        ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1249296465Sdelphij        return 0;
1250296465Sdelphij    }
1251160814Ssimon
1252296465Sdelphij    buf_len = EC_POINT_point2oct(a->group, a->pub_key,
1253296465Sdelphij                                 a->conv_form, NULL, 0, NULL);
1254160814Ssimon
1255296465Sdelphij    if (out == NULL || buf_len == 0)
1256296465Sdelphij        /* out == NULL => just return the length of the octet string */
1257296465Sdelphij        return buf_len;
1258160814Ssimon
1259296465Sdelphij    if (*out == NULL) {
1260296465Sdelphij        if ((*out = OPENSSL_malloc(buf_len)) == NULL) {
1261296465Sdelphij            ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1262296465Sdelphij            return 0;
1263296465Sdelphij        }
1264296465Sdelphij        new_buffer = 1;
1265296465Sdelphij    }
1266296465Sdelphij    if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
1267296465Sdelphij                            *out, buf_len, NULL)) {
1268296465Sdelphij        ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB);
1269296465Sdelphij        OPENSSL_free(*out);
1270296465Sdelphij        *out = NULL;
1271296465Sdelphij        return 0;
1272296465Sdelphij    }
1273296465Sdelphij    if (!new_buffer)
1274296465Sdelphij        *out += buf_len;
1275296465Sdelphij    return buf_len;
1276296465Sdelphij}
1277