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
13280304Sjkim *    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)
66280304Sjkim{
67280304Sjkim    int i = 0;
68160814Ssimon
69280304Sjkim    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
70280304Sjkim        NID_X9_62_characteristic_two_field)
71280304Sjkim        /* everything else is currently not supported */
72280304Sjkim        return 0;
73160814Ssimon
74280304Sjkim    while (group->poly[i] != 0)
75280304Sjkim        i++;
76160814Ssimon
77280304Sjkim    if (i == 4)
78280304Sjkim        return NID_X9_62_ppBasis;
79280304Sjkim    else if (i == 2)
80280304Sjkim        return NID_X9_62_tpBasis;
81280304Sjkim    else
82280304Sjkim        /* everything else is currently not supported */
83280304Sjkim        return 0;
84280304Sjkim}
85280304Sjkim
86238405Sjkim#ifndef OPENSSL_NO_EC2M
87160814Ssimonint EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
88280304Sjkim{
89280304Sjkim    if (group == NULL)
90280304Sjkim        return 0;
91160814Ssimon
92280304Sjkim    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
93280304Sjkim        NID_X9_62_characteristic_two_field
94280304Sjkim        || !((group->poly[0] != 0) && (group->poly[1] != 0)
95280304Sjkim             && (group->poly[2] == 0))) {
96280304Sjkim        ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS,
97280304Sjkim              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
98280304Sjkim        return 0;
99280304Sjkim    }
100160814Ssimon
101280304Sjkim    if (k)
102280304Sjkim        *k = group->poly[1];
103160814Ssimon
104280304Sjkim    return 1;
105280304Sjkim}
106280304Sjkim
107160814Ssimonint EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
108280304Sjkim                                   unsigned int *k2, unsigned int *k3)
109280304Sjkim{
110280304Sjkim    if (group == NULL)
111280304Sjkim        return 0;
112160814Ssimon
113280304Sjkim    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
114280304Sjkim        NID_X9_62_characteristic_two_field
115280304Sjkim        || !((group->poly[0] != 0) && (group->poly[1] != 0)
116280304Sjkim             && (group->poly[2] != 0) && (group->poly[3] != 0)
117280304Sjkim             && (group->poly[4] == 0))) {
118280304Sjkim        ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS,
119280304Sjkim              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
120280304Sjkim        return 0;
121280304Sjkim    }
122160814Ssimon
123280304Sjkim    if (k1)
124280304Sjkim        *k1 = group->poly[3];
125280304Sjkim    if (k2)
126280304Sjkim        *k2 = group->poly[2];
127280304Sjkim    if (k3)
128280304Sjkim        *k3 = group->poly[1];
129160814Ssimon
130280304Sjkim    return 1;
131280304Sjkim}
132238405Sjkim#endif
133160814Ssimon
134160814Ssimon/* some structures needed for the asn1 encoding */
135160814Ssimontypedef struct x9_62_pentanomial_st {
136280304Sjkim    long k1;
137280304Sjkim    long k2;
138280304Sjkim    long k3;
139280304Sjkim} X9_62_PENTANOMIAL;
140160814Ssimon
141160814Ssimontypedef struct x9_62_characteristic_two_st {
142280304Sjkim    long m;
143280304Sjkim    ASN1_OBJECT *type;
144280304Sjkim    union {
145280304Sjkim        char *ptr;
146280304Sjkim        /* NID_X9_62_onBasis */
147280304Sjkim        ASN1_NULL *onBasis;
148280304Sjkim        /* NID_X9_62_tpBasis */
149280304Sjkim        ASN1_INTEGER *tpBasis;
150280304Sjkim        /* NID_X9_62_ppBasis */
151280304Sjkim        X9_62_PENTANOMIAL *ppBasis;
152280304Sjkim        /* anything else */
153280304Sjkim        ASN1_TYPE *other;
154280304Sjkim    } p;
155280304Sjkim} X9_62_CHARACTERISTIC_TWO;
156160814Ssimon
157160814Ssimontypedef struct x9_62_fieldid_st {
158280304Sjkim    ASN1_OBJECT *fieldType;
159280304Sjkim    union {
160280304Sjkim        char *ptr;
161280304Sjkim        /* NID_X9_62_prime_field */
162280304Sjkim        ASN1_INTEGER *prime;
163280304Sjkim        /* NID_X9_62_characteristic_two_field */
164280304Sjkim        X9_62_CHARACTERISTIC_TWO *char_two;
165280304Sjkim        /* anything else */
166280304Sjkim        ASN1_TYPE *other;
167280304Sjkim    } p;
168280304Sjkim} X9_62_FIELDID;
169160814Ssimon
170160814Ssimontypedef struct x9_62_curve_st {
171280304Sjkim    ASN1_OCTET_STRING *a;
172280304Sjkim    ASN1_OCTET_STRING *b;
173280304Sjkim    ASN1_BIT_STRING *seed;
174280304Sjkim} X9_62_CURVE;
175160814Ssimon
176160814Ssimontypedef struct ec_parameters_st {
177280304Sjkim    long version;
178280304Sjkim    X9_62_FIELDID *fieldID;
179280304Sjkim    X9_62_CURVE *curve;
180280304Sjkim    ASN1_OCTET_STRING *base;
181280304Sjkim    ASN1_INTEGER *order;
182280304Sjkim    ASN1_INTEGER *cofactor;
183280304Sjkim} ECPARAMETERS;
184160814Ssimon
185160814Ssimonstruct ecpk_parameters_st {
186280304Sjkim    int type;
187280304Sjkim    union {
188280304Sjkim        ASN1_OBJECT *named_curve;
189280304Sjkim        ECPARAMETERS *parameters;
190280304Sjkim        ASN1_NULL *implicitlyCA;
191280304Sjkim    } value;
192280304Sjkim} /* ECPKPARAMETERS */ ;
193160814Ssimon
194160814Ssimon/* SEC1 ECPrivateKey */
195160814Ssimontypedef struct ec_privatekey_st {
196280304Sjkim    long version;
197280304Sjkim    ASN1_OCTET_STRING *privateKey;
198280304Sjkim    ECPKPARAMETERS *parameters;
199280304Sjkim    ASN1_BIT_STRING *publicKey;
200280304Sjkim} EC_PRIVATEKEY;
201160814Ssimon
202160814Ssimon/* the OpenSSL ASN.1 definitions */
203160814SsimonASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
204280304Sjkim        ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG),
205280304Sjkim        ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG),
206280304Sjkim        ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG)
207160814Ssimon} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL)
208160814Ssimon
209160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
210160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
211160814Ssimon
212160814SsimonASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY);
213160814Ssimon
214160814SsimonASN1_ADB(X9_62_CHARACTERISTIC_TWO) = {
215280304Sjkim        ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)),
216280304Sjkim        ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)),
217280304Sjkim        ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL))
218160814Ssimon} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL);
219160814Ssimon
220160814SsimonASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = {
221280304Sjkim        ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG),
222280304Sjkim        ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
223280304Sjkim        ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO)
224160814Ssimon} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO)
225160814Ssimon
226160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
227160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
228160814Ssimon
229160814SsimonASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
230160814Ssimon
231160814SsimonASN1_ADB(X9_62_FIELDID) = {
232280304Sjkim        ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
233280304Sjkim        ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO))
234160814Ssimon} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
235160814Ssimon
236160814SsimonASN1_SEQUENCE(X9_62_FIELDID) = {
237280304Sjkim        ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
238280304Sjkim        ASN1_ADB_OBJECT(X9_62_FIELDID)
239160814Ssimon} ASN1_SEQUENCE_END(X9_62_FIELDID)
240160814Ssimon
241160814SsimonASN1_SEQUENCE(X9_62_CURVE) = {
242280304Sjkim        ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
243280304Sjkim        ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
244280304Sjkim        ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
245160814Ssimon} ASN1_SEQUENCE_END(X9_62_CURVE)
246160814Ssimon
247160814SsimonASN1_SEQUENCE(ECPARAMETERS) = {
248280304Sjkim        ASN1_SIMPLE(ECPARAMETERS, version, LONG),
249280304Sjkim        ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
250280304Sjkim        ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
251280304Sjkim        ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
252280304Sjkim        ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
253280304Sjkim        ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
254160814Ssimon} ASN1_SEQUENCE_END(ECPARAMETERS)
255160814Ssimon
256160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
257160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
258160814Ssimon
259160814SsimonASN1_CHOICE(ECPKPARAMETERS) = {
260280304Sjkim        ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
261280304Sjkim        ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
262280304Sjkim        ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL)
263160814Ssimon} ASN1_CHOICE_END(ECPKPARAMETERS)
264160814Ssimon
265160814SsimonDECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
266160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS)
267160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
268160814Ssimon
269160814SsimonASN1_SEQUENCE(EC_PRIVATEKEY) = {
270280304Sjkim        ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
271280304Sjkim        ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
272280304Sjkim        ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
273280304Sjkim        ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
274160814Ssimon} ASN1_SEQUENCE_END(EC_PRIVATEKEY)
275160814Ssimon
276160814SsimonDECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
277160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY)
278160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
279160814Ssimon
280160814Ssimon/* some declarations of internal function */
281160814Ssimon
282280304Sjkim/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */
283160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
284280304Sjkim/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */
285160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
286280304Sjkim/*
287280304Sjkim * ec_asn1_parameters2group() creates a EC_GROUP object from a ECPARAMETERS
288280304Sjkim * object
289280304Sjkim */
290280304Sjkimstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *);
291280304Sjkim/*
292280304Sjkim * ec_asn1_group2parameters() creates a ECPARAMETERS object from a EC_GROUP
293280304Sjkim * object
294280304Sjkim */
295280304Sjkimstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,
296280304Sjkim                                              ECPARAMETERS *);
297280304Sjkim/*
298280304Sjkim * ec_asn1_pkparameters2group() creates a EC_GROUP object from a
299280304Sjkim * ECPKPARAMETERS object
300280304Sjkim */
301280304Sjkimstatic EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *);
302280304Sjkim/*
303280304Sjkim * ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a
304280304Sjkim * EC_GROUP object
305280304Sjkim */
306280304Sjkimstatic ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *,
307280304Sjkim                                                  ECPKPARAMETERS *);
308160814Ssimon
309160814Ssimon/* the function definitions */
310160814Ssimon
311160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
312280304Sjkim{
313280304Sjkim    int ok = 0, nid;
314280304Sjkim    BIGNUM *tmp = NULL;
315160814Ssimon
316280304Sjkim    if (group == NULL || field == NULL)
317280304Sjkim        return 0;
318160814Ssimon
319280304Sjkim    /* clear the old values (if necessary) */
320280304Sjkim    if (field->fieldType != NULL)
321280304Sjkim        ASN1_OBJECT_free(field->fieldType);
322280304Sjkim    if (field->p.other != NULL)
323280304Sjkim        ASN1_TYPE_free(field->p.other);
324160814Ssimon
325280304Sjkim    nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
326280304Sjkim    /* set OID for the field */
327280304Sjkim    if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) {
328280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
329280304Sjkim        goto err;
330280304Sjkim    }
331280304Sjkim
332280304Sjkim    if (nid == NID_X9_62_prime_field) {
333280304Sjkim        if ((tmp = BN_new()) == NULL) {
334280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
335280304Sjkim            goto err;
336280304Sjkim        }
337280304Sjkim        /* the parameters are specified by the prime number p */
338280304Sjkim        if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL)) {
339280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
340280304Sjkim            goto err;
341280304Sjkim        }
342280304Sjkim        /* set the prime number */
343280304Sjkim        field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL);
344280304Sjkim        if (field->p.prime == NULL) {
345280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
346280304Sjkim            goto err;
347280304Sjkim        }
348280304Sjkim    } else                      /* nid == NID_X9_62_characteristic_two_field */
349238405Sjkim#ifdef OPENSSL_NO_EC2M
350280304Sjkim    {
351280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED);
352280304Sjkim        goto err;
353280304Sjkim    }
354238405Sjkim#else
355280304Sjkim    {
356280304Sjkim        int field_type;
357280304Sjkim        X9_62_CHARACTERISTIC_TWO *char_two;
358160814Ssimon
359280304Sjkim        field->p.char_two = X9_62_CHARACTERISTIC_TWO_new();
360280304Sjkim        char_two = field->p.char_two;
361160814Ssimon
362280304Sjkim        if (char_two == NULL) {
363280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
364280304Sjkim            goto err;
365280304Sjkim        }
366160814Ssimon
367280304Sjkim        char_two->m = (long)EC_GROUP_get_degree(group);
368160814Ssimon
369280304Sjkim        field_type = EC_GROUP_get_basis_type(group);
370160814Ssimon
371280304Sjkim        if (field_type == 0) {
372280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
373280304Sjkim            goto err;
374280304Sjkim        }
375280304Sjkim        /* set base type OID */
376280304Sjkim        if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) {
377280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
378280304Sjkim            goto err;
379280304Sjkim        }
380160814Ssimon
381280304Sjkim        if (field_type == NID_X9_62_tpBasis) {
382280304Sjkim            unsigned int k;
383160814Ssimon
384280304Sjkim            if (!EC_GROUP_get_trinomial_basis(group, &k))
385280304Sjkim                goto err;
386160814Ssimon
387280304Sjkim            char_two->p.tpBasis = ASN1_INTEGER_new();
388280304Sjkim            if (!char_two->p.tpBasis) {
389280304Sjkim                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
390280304Sjkim                goto err;
391280304Sjkim            }
392280304Sjkim            if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) {
393280304Sjkim                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
394280304Sjkim                goto err;
395280304Sjkim            }
396280304Sjkim        } else if (field_type == NID_X9_62_ppBasis) {
397280304Sjkim            unsigned int k1, k2, k3;
398160814Ssimon
399280304Sjkim            if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3))
400280304Sjkim                goto err;
401160814Ssimon
402280304Sjkim            char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
403280304Sjkim            if (!char_two->p.ppBasis) {
404280304Sjkim                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
405280304Sjkim                goto err;
406280304Sjkim            }
407280304Sjkim
408280304Sjkim            /* set k? values */
409280304Sjkim            char_two->p.ppBasis->k1 = (long)k1;
410280304Sjkim            char_two->p.ppBasis->k2 = (long)k2;
411280304Sjkim            char_two->p.ppBasis->k3 = (long)k3;
412280304Sjkim        } else {                /* field_type == NID_X9_62_onBasis */
413280304Sjkim
414280304Sjkim            /* for ONB the parameters are (asn1) NULL */
415280304Sjkim            char_two->p.onBasis = ASN1_NULL_new();
416280304Sjkim            if (!char_two->p.onBasis) {
417280304Sjkim                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
418280304Sjkim                goto err;
419280304Sjkim            }
420280304Sjkim        }
421280304Sjkim    }
422238405Sjkim#endif
423160814Ssimon
424280304Sjkim    ok = 1;
425160814Ssimon
426280304Sjkim err:if (tmp)
427280304Sjkim        BN_free(tmp);
428280304Sjkim    return (ok);
429160814Ssimon}
430160814Ssimon
431160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
432280304Sjkim{
433280304Sjkim    int ok = 0, nid;
434280304Sjkim    BIGNUM *tmp_1 = NULL, *tmp_2 = NULL;
435280304Sjkim    unsigned char *buffer_1 = NULL, *buffer_2 = NULL,
436280304Sjkim        *a_buf = NULL, *b_buf = NULL;
437280304Sjkim    size_t len_1, len_2;
438280304Sjkim    unsigned char char_zero = 0;
439160814Ssimon
440280304Sjkim    if (!group || !curve || !curve->a || !curve->b)
441280304Sjkim        return 0;
442160814Ssimon
443280304Sjkim    if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) {
444280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
445280304Sjkim        goto err;
446280304Sjkim    }
447160814Ssimon
448280304Sjkim    nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
449160814Ssimon
450280304Sjkim    /* get a and b */
451280304Sjkim    if (nid == NID_X9_62_prime_field) {
452280304Sjkim        if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL)) {
453280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
454280304Sjkim            goto err;
455280304Sjkim        }
456280304Sjkim    }
457238405Sjkim#ifndef OPENSSL_NO_EC2M
458280304Sjkim    else {                      /* nid == NID_X9_62_characteristic_two_field */
459280304Sjkim
460280304Sjkim        if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) {
461280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
462280304Sjkim            goto err;
463280304Sjkim        }
464280304Sjkim    }
465238405Sjkim#endif
466280304Sjkim    len_1 = (size_t)BN_num_bytes(tmp_1);
467280304Sjkim    len_2 = (size_t)BN_num_bytes(tmp_2);
468160814Ssimon
469280304Sjkim    if (len_1 == 0) {
470280304Sjkim        /* len_1 == 0 => a == 0 */
471280304Sjkim        a_buf = &char_zero;
472280304Sjkim        len_1 = 1;
473280304Sjkim    } else {
474280304Sjkim        if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) {
475280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
476280304Sjkim            goto err;
477280304Sjkim        }
478280304Sjkim        if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) {
479280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
480280304Sjkim            goto err;
481280304Sjkim        }
482280304Sjkim        a_buf = buffer_1;
483280304Sjkim    }
484160814Ssimon
485280304Sjkim    if (len_2 == 0) {
486280304Sjkim        /* len_2 == 0 => b == 0 */
487280304Sjkim        b_buf = &char_zero;
488280304Sjkim        len_2 = 1;
489280304Sjkim    } else {
490280304Sjkim        if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) {
491280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
492280304Sjkim            goto err;
493280304Sjkim        }
494280304Sjkim        if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) {
495280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
496280304Sjkim            goto err;
497280304Sjkim        }
498280304Sjkim        b_buf = buffer_2;
499280304Sjkim    }
500160814Ssimon
501280304Sjkim    /* set a and b */
502280304Sjkim    if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
503280304Sjkim        !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) {
504280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
505280304Sjkim        goto err;
506280304Sjkim    }
507160814Ssimon
508280304Sjkim    /* set the seed (optional) */
509280304Sjkim    if (group->seed) {
510280304Sjkim        if (!curve->seed)
511280304Sjkim            if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) {
512280304Sjkim                ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
513280304Sjkim                goto err;
514280304Sjkim            }
515280304Sjkim        curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
516280304Sjkim        curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT;
517280304Sjkim        if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
518280304Sjkim                                 (int)group->seed_len)) {
519280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
520280304Sjkim            goto err;
521280304Sjkim        }
522280304Sjkim    } else {
523280304Sjkim        if (curve->seed) {
524280304Sjkim            ASN1_BIT_STRING_free(curve->seed);
525280304Sjkim            curve->seed = NULL;
526280304Sjkim        }
527280304Sjkim    }
528160814Ssimon
529280304Sjkim    ok = 1;
530280304Sjkim
531280304Sjkim err:if (buffer_1)
532280304Sjkim        OPENSSL_free(buffer_1);
533280304Sjkim    if (buffer_2)
534280304Sjkim        OPENSSL_free(buffer_2);
535280304Sjkim    if (tmp_1)
536280304Sjkim        BN_free(tmp_1);
537280304Sjkim    if (tmp_2)
538280304Sjkim        BN_free(tmp_2);
539280304Sjkim    return (ok);
540280304Sjkim}
541280304Sjkim
542160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group,
543160814Ssimon                                              ECPARAMETERS *param)
544280304Sjkim{
545280304Sjkim    int ok = 0;
546280304Sjkim    size_t len = 0;
547280304Sjkim    ECPARAMETERS *ret = NULL;
548280304Sjkim    BIGNUM *tmp = NULL;
549280304Sjkim    unsigned char *buffer = NULL;
550280304Sjkim    const EC_POINT *point = NULL;
551280304Sjkim    point_conversion_form_t form;
552160814Ssimon
553280304Sjkim    if ((tmp = BN_new()) == NULL) {
554280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
555280304Sjkim        goto err;
556280304Sjkim    }
557160814Ssimon
558280304Sjkim    if (param == NULL) {
559280304Sjkim        if ((ret = ECPARAMETERS_new()) == NULL) {
560280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
561280304Sjkim            goto err;
562280304Sjkim        }
563280304Sjkim    } else
564280304Sjkim        ret = param;
565160814Ssimon
566280304Sjkim    /* set the version (always one) */
567280304Sjkim    ret->version = (long)0x1;
568160814Ssimon
569280304Sjkim    /* set the fieldID */
570280304Sjkim    if (!ec_asn1_group2fieldid(group, ret->fieldID)) {
571280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
572280304Sjkim        goto err;
573280304Sjkim    }
574160814Ssimon
575280304Sjkim    /* set the curve */
576280304Sjkim    if (!ec_asn1_group2curve(group, ret->curve)) {
577280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
578280304Sjkim        goto err;
579280304Sjkim    }
580160814Ssimon
581280304Sjkim    /* set the base point */
582280304Sjkim    if ((point = EC_GROUP_get0_generator(group)) == NULL) {
583280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR);
584280304Sjkim        goto err;
585280304Sjkim    }
586160814Ssimon
587280304Sjkim    form = EC_GROUP_get_point_conversion_form(group);
588160814Ssimon
589280304Sjkim    len = EC_POINT_point2oct(group, point, form, NULL, len, NULL);
590280304Sjkim    if (len == 0) {
591280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
592280304Sjkim        goto err;
593280304Sjkim    }
594280304Sjkim    if ((buffer = OPENSSL_malloc(len)) == NULL) {
595280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
596280304Sjkim        goto err;
597280304Sjkim    }
598280304Sjkim    if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) {
599280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
600280304Sjkim        goto err;
601280304Sjkim    }
602280304Sjkim    if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) {
603280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
604280304Sjkim        goto err;
605280304Sjkim    }
606280304Sjkim    if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) {
607280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
608280304Sjkim        goto err;
609280304Sjkim    }
610160814Ssimon
611280304Sjkim    /* set the order */
612280304Sjkim    if (!EC_GROUP_get_order(group, tmp, NULL)) {
613280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
614280304Sjkim        goto err;
615280304Sjkim    }
616280304Sjkim    ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
617280304Sjkim    if (ret->order == NULL) {
618280304Sjkim        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
619280304Sjkim        goto err;
620280304Sjkim    }
621160814Ssimon
622280304Sjkim    /* set the cofactor (optional) */
623280304Sjkim    if (EC_GROUP_get_cofactor(group, tmp, NULL)) {
624280304Sjkim        ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
625280304Sjkim        if (ret->cofactor == NULL) {
626280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
627280304Sjkim            goto err;
628280304Sjkim        }
629280304Sjkim    }
630160814Ssimon
631280304Sjkim    ok = 1;
632160814Ssimon
633280304Sjkim err:if (!ok) {
634280304Sjkim        if (ret && !param)
635280304Sjkim            ECPARAMETERS_free(ret);
636280304Sjkim        ret = NULL;
637280304Sjkim    }
638280304Sjkim    if (tmp)
639280304Sjkim        BN_free(tmp);
640280304Sjkim    if (buffer)
641280304Sjkim        OPENSSL_free(buffer);
642280304Sjkim    return (ret);
643280304Sjkim}
644160814Ssimon
645280304SjkimECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
646160814Ssimon                                           ECPKPARAMETERS *params)
647280304Sjkim{
648280304Sjkim    int ok = 1, tmp;
649280304Sjkim    ECPKPARAMETERS *ret = params;
650160814Ssimon
651280304Sjkim    if (ret == NULL) {
652280304Sjkim        if ((ret = ECPKPARAMETERS_new()) == NULL) {
653280304Sjkim            ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, ERR_R_MALLOC_FAILURE);
654280304Sjkim            return NULL;
655280304Sjkim        }
656280304Sjkim    } else {
657280304Sjkim        if (ret->type == 0 && ret->value.named_curve)
658280304Sjkim            ASN1_OBJECT_free(ret->value.named_curve);
659280304Sjkim        else if (ret->type == 1 && ret->value.parameters)
660280304Sjkim            ECPARAMETERS_free(ret->value.parameters);
661280304Sjkim    }
662160814Ssimon
663280304Sjkim    if (EC_GROUP_get_asn1_flag(group)) {
664280304Sjkim        /*
665280304Sjkim         * use the asn1 OID to describe the the elliptic curve parameters
666280304Sjkim         */
667280304Sjkim        tmp = EC_GROUP_get_curve_name(group);
668280304Sjkim        if (tmp) {
669280304Sjkim            ret->type = 0;
670280304Sjkim            if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL)
671280304Sjkim                ok = 0;
672280304Sjkim        } else
673280304Sjkim            /* we don't kmow the nid => ERROR */
674280304Sjkim            ok = 0;
675280304Sjkim    } else {
676280304Sjkim        /* use the ECPARAMETERS structure */
677280304Sjkim        ret->type = 1;
678280304Sjkim        if ((ret->value.parameters =
679280304Sjkim             ec_asn1_group2parameters(group, NULL)) == NULL)
680280304Sjkim            ok = 0;
681280304Sjkim    }
682160814Ssimon
683280304Sjkim    if (!ok) {
684280304Sjkim        ECPKPARAMETERS_free(ret);
685280304Sjkim        return NULL;
686280304Sjkim    }
687280304Sjkim    return ret;
688280304Sjkim}
689160814Ssimon
690160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
691280304Sjkim{
692280304Sjkim    int ok = 0, tmp;
693280304Sjkim    EC_GROUP *ret = NULL;
694280304Sjkim    BIGNUM *p = NULL, *a = NULL, *b = NULL;
695280304Sjkim    EC_POINT *point = NULL;
696280304Sjkim    long field_bits;
697160814Ssimon
698280304Sjkim    if (!params->fieldID || !params->fieldID->fieldType ||
699280304Sjkim        !params->fieldID->p.ptr) {
700280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
701280304Sjkim        goto err;
702280304Sjkim    }
703160814Ssimon
704280304Sjkim    /* now extract the curve parameters a and b */
705280304Sjkim    if (!params->curve || !params->curve->a ||
706280304Sjkim        !params->curve->a->data || !params->curve->b ||
707280304Sjkim        !params->curve->b->data) {
708280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
709280304Sjkim        goto err;
710280304Sjkim    }
711280304Sjkim    a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
712280304Sjkim    if (a == NULL) {
713280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
714280304Sjkim        goto err;
715280304Sjkim    }
716280304Sjkim    b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
717280304Sjkim    if (b == NULL) {
718280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
719280304Sjkim        goto err;
720280304Sjkim    }
721160814Ssimon
722280304Sjkim    /* get the field parameters */
723280304Sjkim    tmp = OBJ_obj2nid(params->fieldID->fieldType);
724280304Sjkim    if (tmp == NID_X9_62_characteristic_two_field)
725238405Sjkim#ifdef OPENSSL_NO_EC2M
726280304Sjkim    {
727280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED);
728280304Sjkim        goto err;
729280304Sjkim    }
730238405Sjkim#else
731280304Sjkim    {
732280304Sjkim        X9_62_CHARACTERISTIC_TWO *char_two;
733160814Ssimon
734280304Sjkim        char_two = params->fieldID->p.char_two;
735160814Ssimon
736280304Sjkim        field_bits = char_two->m;
737280304Sjkim        if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
738280304Sjkim            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
739280304Sjkim            goto err;
740280304Sjkim        }
741162911Ssimon
742280304Sjkim        if ((p = BN_new()) == NULL) {
743280304Sjkim            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
744280304Sjkim            goto err;
745280304Sjkim        }
746160814Ssimon
747280304Sjkim        /* get the base type */
748280304Sjkim        tmp = OBJ_obj2nid(char_two->type);
749160814Ssimon
750280304Sjkim        if (tmp == NID_X9_62_tpBasis) {
751280304Sjkim            long tmp_long;
752160814Ssimon
753280304Sjkim            if (!char_two->p.tpBasis) {
754280304Sjkim                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
755280304Sjkim                goto err;
756280304Sjkim            }
757160814Ssimon
758280304Sjkim            tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis);
759162911Ssimon
760280304Sjkim            if (!(char_two->m > tmp_long && tmp_long > 0)) {
761280304Sjkim                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP,
762280304Sjkim                      EC_R_INVALID_TRINOMIAL_BASIS);
763280304Sjkim                goto err;
764280304Sjkim            }
765160814Ssimon
766280304Sjkim            /* create the polynomial */
767280304Sjkim            if (!BN_set_bit(p, (int)char_two->m))
768280304Sjkim                goto err;
769280304Sjkim            if (!BN_set_bit(p, (int)tmp_long))
770280304Sjkim                goto err;
771280304Sjkim            if (!BN_set_bit(p, 0))
772280304Sjkim                goto err;
773280304Sjkim        } else if (tmp == NID_X9_62_ppBasis) {
774280304Sjkim            X9_62_PENTANOMIAL *penta;
775162911Ssimon
776280304Sjkim            penta = char_two->p.ppBasis;
777280304Sjkim            if (!penta) {
778280304Sjkim                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
779280304Sjkim                goto err;
780280304Sjkim            }
781160814Ssimon
782280304Sjkim            if (!
783280304Sjkim                (char_two->m > penta->k3 && penta->k3 > penta->k2
784280304Sjkim                 && penta->k2 > penta->k1 && penta->k1 > 0)) {
785280304Sjkim                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP,
786280304Sjkim                      EC_R_INVALID_PENTANOMIAL_BASIS);
787280304Sjkim                goto err;
788280304Sjkim            }
789280304Sjkim
790280304Sjkim            /* create the polynomial */
791280304Sjkim            if (!BN_set_bit(p, (int)char_two->m))
792280304Sjkim                goto err;
793280304Sjkim            if (!BN_set_bit(p, (int)penta->k1))
794280304Sjkim                goto err;
795280304Sjkim            if (!BN_set_bit(p, (int)penta->k2))
796280304Sjkim                goto err;
797280304Sjkim            if (!BN_set_bit(p, (int)penta->k3))
798280304Sjkim                goto err;
799280304Sjkim            if (!BN_set_bit(p, 0))
800280304Sjkim                goto err;
801280304Sjkim        } else if (tmp == NID_X9_62_onBasis) {
802280304Sjkim            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED);
803280304Sjkim            goto err;
804280304Sjkim        } else {                /* error */
805280304Sjkim
806280304Sjkim            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
807280304Sjkim            goto err;
808280304Sjkim        }
809280304Sjkim
810280304Sjkim        /* create the EC_GROUP structure */
811280304Sjkim        ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
812280304Sjkim    }
813238405Sjkim#endif
814280304Sjkim    else if (tmp == NID_X9_62_prime_field) {
815280304Sjkim        /* we have a curve over a prime field */
816280304Sjkim        /* extract the prime number */
817280304Sjkim        if (!params->fieldID->p.prime) {
818280304Sjkim            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
819280304Sjkim            goto err;
820280304Sjkim        }
821280304Sjkim        p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
822280304Sjkim        if (p == NULL) {
823280304Sjkim            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
824280304Sjkim            goto err;
825280304Sjkim        }
826162911Ssimon
827280304Sjkim        if (BN_is_negative(p) || BN_is_zero(p)) {
828280304Sjkim            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
829280304Sjkim            goto err;
830280304Sjkim        }
831162911Ssimon
832280304Sjkim        field_bits = BN_num_bits(p);
833280304Sjkim        if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
834280304Sjkim            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
835280304Sjkim            goto err;
836280304Sjkim        }
837162911Ssimon
838280304Sjkim        /* create the EC_GROUP structure */
839280304Sjkim        ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
840280304Sjkim    } else {
841280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
842280304Sjkim        goto err;
843280304Sjkim    }
844160814Ssimon
845280304Sjkim    if (ret == NULL) {
846280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
847280304Sjkim        goto err;
848280304Sjkim    }
849160814Ssimon
850280304Sjkim    /* extract seed (optional) */
851280304Sjkim    if (params->curve->seed != NULL) {
852280304Sjkim        if (ret->seed != NULL)
853280304Sjkim            OPENSSL_free(ret->seed);
854280304Sjkim        if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) {
855280304Sjkim            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
856280304Sjkim            goto err;
857280304Sjkim        }
858280304Sjkim        memcpy(ret->seed, params->curve->seed->data,
859280304Sjkim               params->curve->seed->length);
860280304Sjkim        ret->seed_len = params->curve->seed->length;
861280304Sjkim    }
862160814Ssimon
863280304Sjkim    if (!params->order || !params->base || !params->base->data) {
864280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
865280304Sjkim        goto err;
866280304Sjkim    }
867160814Ssimon
868280304Sjkim    if ((point = EC_POINT_new(ret)) == NULL)
869280304Sjkim        goto err;
870160814Ssimon
871280304Sjkim    /* set the point conversion form */
872280304Sjkim    EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
873280304Sjkim                                       (params->base->data[0] & ~0x01));
874160814Ssimon
875280304Sjkim    /* extract the ec point */
876280304Sjkim    if (!EC_POINT_oct2point(ret, point, params->base->data,
877280304Sjkim                            params->base->length, NULL)) {
878280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
879280304Sjkim        goto err;
880280304Sjkim    }
881160814Ssimon
882280304Sjkim    /* extract the order */
883280304Sjkim    if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) {
884280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
885280304Sjkim        goto err;
886280304Sjkim    }
887280304Sjkim    if (BN_is_negative(a) || BN_is_zero(a)) {
888280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
889280304Sjkim        goto err;
890280304Sjkim    }
891280304Sjkim    if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */
892280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
893280304Sjkim        goto err;
894280304Sjkim    }
895160814Ssimon
896280304Sjkim    /* extract the cofactor (optional) */
897280304Sjkim    if (params->cofactor == NULL) {
898280304Sjkim        if (b) {
899280304Sjkim            BN_free(b);
900280304Sjkim            b = NULL;
901280304Sjkim        }
902280304Sjkim    } else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) {
903280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
904280304Sjkim        goto err;
905280304Sjkim    }
906280304Sjkim    /* set the generator, order and cofactor (if present) */
907280304Sjkim    if (!EC_GROUP_set_generator(ret, point, a, b)) {
908280304Sjkim        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
909280304Sjkim        goto err;
910280304Sjkim    }
911160814Ssimon
912280304Sjkim    ok = 1;
913160814Ssimon
914280304Sjkim err:if (!ok) {
915280304Sjkim        if (ret)
916280304Sjkim            EC_GROUP_clear_free(ret);
917280304Sjkim        ret = NULL;
918280304Sjkim    }
919280304Sjkim
920280304Sjkim    if (p)
921280304Sjkim        BN_free(p);
922280304Sjkim    if (a)
923280304Sjkim        BN_free(a);
924280304Sjkim    if (b)
925280304Sjkim        BN_free(b);
926280304Sjkim    if (point)
927280304Sjkim        EC_POINT_free(point);
928280304Sjkim    return (ret);
929160814Ssimon}
930160814Ssimon
931160814SsimonEC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
932280304Sjkim{
933280304Sjkim    EC_GROUP *ret = NULL;
934280304Sjkim    int tmp = 0;
935160814Ssimon
936280304Sjkim    if (params == NULL) {
937280304Sjkim        ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_MISSING_PARAMETERS);
938280304Sjkim        return NULL;
939280304Sjkim    }
940160814Ssimon
941280304Sjkim    if (params->type == 0) {    /* the curve is given by an OID */
942280304Sjkim        tmp = OBJ_obj2nid(params->value.named_curve);
943280304Sjkim        if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) {
944280304Sjkim            ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP,
945280304Sjkim                  EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
946280304Sjkim            return NULL;
947280304Sjkim        }
948280304Sjkim        EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
949280304Sjkim    } else if (params->type == 1) { /* the parameters are given by a
950280304Sjkim                                     * ECPARAMETERS structure */
951280304Sjkim        ret = ec_asn1_parameters2group(params->value.parameters);
952280304Sjkim        if (!ret) {
953280304Sjkim            ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB);
954280304Sjkim            return NULL;
955280304Sjkim        }
956280304Sjkim        EC_GROUP_set_asn1_flag(ret, 0x0);
957280304Sjkim    } else if (params->type == 2) { /* implicitlyCA */
958280304Sjkim        return NULL;
959280304Sjkim    } else {
960280304Sjkim        ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR);
961280304Sjkim        return NULL;
962280304Sjkim    }
963160814Ssimon
964280304Sjkim    return ret;
965280304Sjkim}
966160814Ssimon
967160814Ssimon/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */
968160814Ssimon
969160814SsimonEC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
970280304Sjkim{
971280304Sjkim    EC_GROUP *group = NULL;
972280304Sjkim    ECPKPARAMETERS *params = NULL;
973291721Sjkim    const unsigned char *p = *in;
974160814Ssimon
975291721Sjkim    if ((params = d2i_ECPKPARAMETERS(NULL, &p, len)) == NULL) {
976280304Sjkim        ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE);
977280304Sjkim        ECPKPARAMETERS_free(params);
978280304Sjkim        return NULL;
979280304Sjkim    }
980160814Ssimon
981280304Sjkim    if ((group = ec_asn1_pkparameters2group(params)) == NULL) {
982280304Sjkim        ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE);
983280304Sjkim        ECPKPARAMETERS_free(params);
984280304Sjkim        return NULL;
985280304Sjkim    }
986160814Ssimon
987280304Sjkim    if (a && *a)
988280304Sjkim        EC_GROUP_clear_free(*a);
989280304Sjkim    if (a)
990280304Sjkim        *a = group;
991160814Ssimon
992280304Sjkim    ECPKPARAMETERS_free(params);
993291721Sjkim    *in = p;
994280304Sjkim    return (group);
995280304Sjkim}
996280304Sjkim
997160814Ssimonint i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
998280304Sjkim{
999280304Sjkim    int ret = 0;
1000280304Sjkim    ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL);
1001280304Sjkim    if (tmp == NULL) {
1002280304Sjkim        ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE);
1003280304Sjkim        return 0;
1004280304Sjkim    }
1005280304Sjkim    if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) {
1006280304Sjkim        ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE);
1007280304Sjkim        ECPKPARAMETERS_free(tmp);
1008280304Sjkim        return 0;
1009280304Sjkim    }
1010280304Sjkim    ECPKPARAMETERS_free(tmp);
1011280304Sjkim    return (ret);
1012280304Sjkim}
1013160814Ssimon
1014160814Ssimon/* some EC_KEY functions */
1015160814Ssimon
1016160814SsimonEC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
1017280304Sjkim{
1018280304Sjkim    int ok = 0;
1019280304Sjkim    EC_KEY *ret = NULL;
1020280304Sjkim    EC_PRIVATEKEY *priv_key = NULL;
1021291721Sjkim    const unsigned char *p = *in;
1022160814Ssimon
1023291721Sjkim    if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL) {
1024280304Sjkim        ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1025280304Sjkim        return NULL;
1026280304Sjkim    }
1027160814Ssimon
1028280304Sjkim    if (a == NULL || *a == NULL) {
1029280304Sjkim        if ((ret = EC_KEY_new()) == NULL) {
1030280304Sjkim            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1031280304Sjkim            goto err;
1032280304Sjkim        }
1033280304Sjkim    } else
1034280304Sjkim        ret = *a;
1035160814Ssimon
1036280304Sjkim    if (priv_key->parameters) {
1037280304Sjkim        if (ret->group)
1038280304Sjkim            EC_GROUP_clear_free(ret->group);
1039280304Sjkim        ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
1040280304Sjkim    }
1041160814Ssimon
1042280304Sjkim    if (ret->group == NULL) {
1043280304Sjkim        ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1044280304Sjkim        goto err;
1045280304Sjkim    }
1046160814Ssimon
1047280304Sjkim    ret->version = priv_key->version;
1048160814Ssimon
1049280304Sjkim    if (priv_key->privateKey) {
1050280304Sjkim        ret->priv_key = BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey),
1051280304Sjkim                                  M_ASN1_STRING_length(priv_key->privateKey),
1052280304Sjkim                                  ret->priv_key);
1053280304Sjkim        if (ret->priv_key == NULL) {
1054280304Sjkim            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_BN_LIB);
1055280304Sjkim            goto err;
1056280304Sjkim        }
1057280304Sjkim    } else {
1058280304Sjkim        ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_MISSING_PRIVATE_KEY);
1059280304Sjkim        goto err;
1060280304Sjkim    }
1061160814Ssimon
1062280304Sjkim    if (ret->pub_key)
1063280304Sjkim        EC_POINT_clear_free(ret->pub_key);
1064280304Sjkim    ret->pub_key = EC_POINT_new(ret->group);
1065280304Sjkim    if (ret->pub_key == NULL) {
1066280304Sjkim        ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1067280304Sjkim        goto err;
1068280304Sjkim    }
1069160814Ssimon
1070280304Sjkim    if (priv_key->publicKey) {
1071280304Sjkim        const unsigned char *pub_oct;
1072280304Sjkim        int pub_oct_len;
1073273149Sjkim
1074280304Sjkim        pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
1075280304Sjkim        pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
1076280304Sjkim        /*
1077280304Sjkim         * The first byte - point conversion form - must be present.
1078280304Sjkim         */
1079280304Sjkim        if (pub_oct_len <= 0) {
1080280304Sjkim            ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL);
1081280304Sjkim            goto err;
1082280304Sjkim        }
1083280304Sjkim        /* Save the point conversion form. */
1084280304Sjkim        ret->conv_form = (point_conversion_form_t) (pub_oct[0] & ~0x01);
1085280304Sjkim        if (!EC_POINT_oct2point(ret->group, ret->pub_key,
1086280304Sjkim                                pub_oct, (size_t)(pub_oct_len), NULL)) {
1087280304Sjkim            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1088280304Sjkim            goto err;
1089280304Sjkim        }
1090280304Sjkim    } else {
1091280304Sjkim        if (!EC_POINT_mul
1092280304Sjkim            (ret->group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) {
1093280304Sjkim            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1094280304Sjkim            goto err;
1095280304Sjkim        }
1096280304Sjkim        /* Remember the original private-key-only encoding. */
1097280304Sjkim        ret->enc_flag |= EC_PKEY_NO_PUBKEY;
1098280304Sjkim    }
1099160814Ssimon
1100280304Sjkim    if (a)
1101280304Sjkim        *a = ret;
1102291721Sjkim    *in = p;
1103280304Sjkim    ok = 1;
1104280304Sjkim err:
1105280304Sjkim    if (!ok) {
1106280304Sjkim        if (ret && (a == NULL || *a != ret))
1107280304Sjkim            EC_KEY_free(ret);
1108280304Sjkim        ret = NULL;
1109280304Sjkim    }
1110160814Ssimon
1111280304Sjkim    if (priv_key)
1112280304Sjkim        EC_PRIVATEKEY_free(priv_key);
1113160814Ssimon
1114280304Sjkim    return (ret);
1115280304Sjkim}
1116160814Ssimon
1117280304Sjkimint i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
1118280304Sjkim{
1119280304Sjkim    int ret = 0, ok = 0;
1120280304Sjkim    unsigned char *buffer = NULL;
1121284285Sjkim    size_t buf_len = 0, tmp_len, bn_len;
1122280304Sjkim    EC_PRIVATEKEY *priv_key = NULL;
1123160814Ssimon
1124280304Sjkim    if (a == NULL || a->group == NULL || a->priv_key == NULL ||
1125280304Sjkim        (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) {
1126280304Sjkim        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
1127280304Sjkim        goto err;
1128280304Sjkim    }
1129160814Ssimon
1130280304Sjkim    if ((priv_key = EC_PRIVATEKEY_new()) == NULL) {
1131280304Sjkim        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1132280304Sjkim        goto err;
1133280304Sjkim    }
1134160814Ssimon
1135280304Sjkim    priv_key->version = a->version;
1136160814Ssimon
1137284285Sjkim    bn_len = (size_t)BN_num_bytes(a->priv_key);
1138284285Sjkim
1139284285Sjkim    /* Octetstring may need leading zeros if BN is to short */
1140284285Sjkim
1141284285Sjkim    buf_len = (EC_GROUP_get_degree(a->group) + 7) / 8;
1142284285Sjkim
1143284285Sjkim    if (bn_len > buf_len) {
1144284285Sjkim        ECerr(EC_F_I2D_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL);
1145284285Sjkim        goto err;
1146284285Sjkim    }
1147284285Sjkim
1148280304Sjkim    buffer = OPENSSL_malloc(buf_len);
1149280304Sjkim    if (buffer == NULL) {
1150280304Sjkim        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1151280304Sjkim        goto err;
1152280304Sjkim    }
1153160814Ssimon
1154284285Sjkim    if (!BN_bn2bin(a->priv_key, buffer + buf_len - bn_len)) {
1155280304Sjkim        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB);
1156280304Sjkim        goto err;
1157280304Sjkim    }
1158160814Ssimon
1159284285Sjkim    if (buf_len - bn_len > 0) {
1160284285Sjkim        memset(buffer, 0, buf_len - bn_len);
1161284285Sjkim    }
1162284285Sjkim
1163280304Sjkim    if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
1164280304Sjkim        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1165280304Sjkim        goto err;
1166280304Sjkim    }
1167160814Ssimon
1168280304Sjkim    if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) {
1169280304Sjkim        if ((priv_key->parameters =
1170280304Sjkim             ec_asn1_group2pkparameters(a->group,
1171280304Sjkim                                        priv_key->parameters)) == NULL) {
1172280304Sjkim            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1173280304Sjkim            goto err;
1174280304Sjkim        }
1175280304Sjkim    }
1176160814Ssimon
1177280304Sjkim    if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) {
1178280304Sjkim        priv_key->publicKey = M_ASN1_BIT_STRING_new();
1179280304Sjkim        if (priv_key->publicKey == NULL) {
1180280304Sjkim            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1181280304Sjkim            goto err;
1182280304Sjkim        }
1183160814Ssimon
1184280304Sjkim        tmp_len = EC_POINT_point2oct(a->group, a->pub_key,
1185280304Sjkim                                     a->conv_form, NULL, 0, NULL);
1186160814Ssimon
1187280304Sjkim        if (tmp_len > buf_len) {
1188280304Sjkim            unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
1189280304Sjkim            if (!tmp_buffer) {
1190280304Sjkim                ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1191280304Sjkim                goto err;
1192280304Sjkim            }
1193280304Sjkim            buffer = tmp_buffer;
1194280304Sjkim            buf_len = tmp_len;
1195280304Sjkim        }
1196160814Ssimon
1197280304Sjkim        if (!EC_POINT_point2oct(a->group, a->pub_key,
1198280304Sjkim                                a->conv_form, buffer, buf_len, NULL)) {
1199280304Sjkim            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1200280304Sjkim            goto err;
1201280304Sjkim        }
1202160814Ssimon
1203280304Sjkim        priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
1204280304Sjkim        priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
1205280304Sjkim        if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
1206280304Sjkim            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1207280304Sjkim            goto err;
1208280304Sjkim        }
1209280304Sjkim    }
1210160814Ssimon
1211280304Sjkim    if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) {
1212280304Sjkim        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1213280304Sjkim        goto err;
1214280304Sjkim    }
1215280304Sjkim    ok = 1;
1216280304Sjkim err:
1217280304Sjkim    if (buffer)
1218280304Sjkim        OPENSSL_free(buffer);
1219280304Sjkim    if (priv_key)
1220280304Sjkim        EC_PRIVATEKEY_free(priv_key);
1221280304Sjkim    return (ok ? ret : 0);
1222280304Sjkim}
1223160814Ssimon
1224160814Ssimonint i2d_ECParameters(EC_KEY *a, unsigned char **out)
1225280304Sjkim{
1226280304Sjkim    if (a == NULL) {
1227280304Sjkim        ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1228280304Sjkim        return 0;
1229280304Sjkim    }
1230280304Sjkim    return i2d_ECPKParameters(a->group, out);
1231280304Sjkim}
1232160814Ssimon
1233160814SsimonEC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
1234280304Sjkim{
1235280304Sjkim    EC_KEY *ret;
1236160814Ssimon
1237280304Sjkim    if (in == NULL || *in == NULL) {
1238280304Sjkim        ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1239280304Sjkim        return NULL;
1240280304Sjkim    }
1241160814Ssimon
1242280304Sjkim    if (a == NULL || *a == NULL) {
1243280304Sjkim        if ((ret = EC_KEY_new()) == NULL) {
1244280304Sjkim            ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
1245280304Sjkim            return NULL;
1246280304Sjkim        }
1247280304Sjkim    } else
1248280304Sjkim        ret = *a;
1249160814Ssimon
1250280304Sjkim    if (!d2i_ECPKParameters(&ret->group, in, len)) {
1251280304Sjkim        ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB);
1252280304Sjkim        if (a == NULL || *a != ret)
1253280304Sjkim             EC_KEY_free(ret);
1254280304Sjkim        return NULL;
1255280304Sjkim    }
1256160814Ssimon
1257280304Sjkim    if (a)
1258280304Sjkim        *a = ret;
1259160814Ssimon
1260280304Sjkim    return ret;
1261280304Sjkim}
1262280304Sjkim
1263160814SsimonEC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
1264280304Sjkim{
1265280304Sjkim    EC_KEY *ret = NULL;
1266160814Ssimon
1267280304Sjkim    if (a == NULL || (*a) == NULL || (*a)->group == NULL) {
1268280304Sjkim        /*
1269280304Sjkim         * sorry, but a EC_GROUP-structur is necessary to set the public key
1270280304Sjkim         */
1271280304Sjkim        ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1272280304Sjkim        return 0;
1273280304Sjkim    }
1274280304Sjkim    ret = *a;
1275280304Sjkim    if (ret->pub_key == NULL &&
1276280304Sjkim        (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
1277280304Sjkim        ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1278280304Sjkim        return 0;
1279280304Sjkim    }
1280280304Sjkim    if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) {
1281280304Sjkim        ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB);
1282280304Sjkim        return 0;
1283280304Sjkim    }
1284280304Sjkim    /* save the point conversion form */
1285280304Sjkim    ret->conv_form = (point_conversion_form_t) (*in[0] & ~0x01);
1286280304Sjkim    *in += len;
1287280304Sjkim    return ret;
1288280304Sjkim}
1289160814Ssimon
1290160814Ssimonint i2o_ECPublicKey(EC_KEY *a, unsigned char **out)
1291280304Sjkim{
1292280304Sjkim    size_t buf_len = 0;
1293280304Sjkim    int new_buffer = 0;
1294160814Ssimon
1295280304Sjkim    if (a == NULL) {
1296280304Sjkim        ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1297280304Sjkim        return 0;
1298280304Sjkim    }
1299160814Ssimon
1300280304Sjkim    buf_len = EC_POINT_point2oct(a->group, a->pub_key,
1301280304Sjkim                                 a->conv_form, NULL, 0, NULL);
1302160814Ssimon
1303280304Sjkim    if (out == NULL || buf_len == 0)
1304280304Sjkim        /* out == NULL => just return the length of the octet string */
1305280304Sjkim        return buf_len;
1306160814Ssimon
1307280304Sjkim    if (*out == NULL) {
1308280304Sjkim        if ((*out = OPENSSL_malloc(buf_len)) == NULL) {
1309280304Sjkim            ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1310280304Sjkim            return 0;
1311280304Sjkim        }
1312280304Sjkim        new_buffer = 1;
1313280304Sjkim    }
1314280304Sjkim    if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
1315280304Sjkim                            *out, buf_len, NULL)) {
1316280304Sjkim        ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB);
1317280304Sjkim        if (new_buffer) {
1318280304Sjkim            OPENSSL_free(*out);
1319280304Sjkim            *out = NULL;
1320280304Sjkim        }
1321280304Sjkim        return 0;
1322280304Sjkim    }
1323280304Sjkim    if (!new_buffer)
1324280304Sjkim        *out += buf_len;
1325280304Sjkim    return buf_len;
1326280304Sjkim}
1327