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
13296341Sdelphij *    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)
66296341Sdelphij{
67296341Sdelphij    int i = 0;
68160814Ssimon
69296341Sdelphij    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
70296341Sdelphij        NID_X9_62_characteristic_two_field)
71296341Sdelphij        /* everything else is currently not supported */
72296341Sdelphij        return 0;
73160814Ssimon
74296341Sdelphij    while (group->poly[i] != 0)
75296341Sdelphij        i++;
76160814Ssimon
77296341Sdelphij    if (i == 4)
78296341Sdelphij        return NID_X9_62_ppBasis;
79296341Sdelphij    else if (i == 2)
80296341Sdelphij        return NID_X9_62_tpBasis;
81296341Sdelphij    else
82296341Sdelphij        /* everything else is currently not supported */
83296341Sdelphij        return 0;
84296341Sdelphij}
85296341Sdelphij
86238405Sjkim#ifndef OPENSSL_NO_EC2M
87160814Ssimonint EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
88296341Sdelphij{
89296341Sdelphij    if (group == NULL)
90296341Sdelphij        return 0;
91160814Ssimon
92296341Sdelphij    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
93296341Sdelphij        NID_X9_62_characteristic_two_field
94296341Sdelphij        || !((group->poly[0] != 0) && (group->poly[1] != 0)
95296341Sdelphij             && (group->poly[2] == 0))) {
96296341Sdelphij        ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS,
97296341Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
98296341Sdelphij        return 0;
99296341Sdelphij    }
100160814Ssimon
101296341Sdelphij    if (k)
102296341Sdelphij        *k = group->poly[1];
103160814Ssimon
104296341Sdelphij    return 1;
105296341Sdelphij}
106296341Sdelphij
107160814Ssimonint EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
108296341Sdelphij                                   unsigned int *k2, unsigned int *k3)
109296341Sdelphij{
110296341Sdelphij    if (group == NULL)
111296341Sdelphij        return 0;
112160814Ssimon
113296341Sdelphij    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
114296341Sdelphij        NID_X9_62_characteristic_two_field
115296341Sdelphij        || !((group->poly[0] != 0) && (group->poly[1] != 0)
116296341Sdelphij             && (group->poly[2] != 0) && (group->poly[3] != 0)
117296341Sdelphij             && (group->poly[4] == 0))) {
118296341Sdelphij        ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS,
119296341Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
120296341Sdelphij        return 0;
121296341Sdelphij    }
122160814Ssimon
123296341Sdelphij    if (k1)
124296341Sdelphij        *k1 = group->poly[3];
125296341Sdelphij    if (k2)
126296341Sdelphij        *k2 = group->poly[2];
127296341Sdelphij    if (k3)
128296341Sdelphij        *k3 = group->poly[1];
129160814Ssimon
130296341Sdelphij    return 1;
131296341Sdelphij}
132238405Sjkim#endif
133160814Ssimon
134160814Ssimon/* some structures needed for the asn1 encoding */
135160814Ssimontypedef struct x9_62_pentanomial_st {
136296341Sdelphij    long k1;
137296341Sdelphij    long k2;
138296341Sdelphij    long k3;
139296341Sdelphij} X9_62_PENTANOMIAL;
140160814Ssimon
141160814Ssimontypedef struct x9_62_characteristic_two_st {
142296341Sdelphij    long m;
143296341Sdelphij    ASN1_OBJECT *type;
144296341Sdelphij    union {
145296341Sdelphij        char *ptr;
146296341Sdelphij        /* NID_X9_62_onBasis */
147296341Sdelphij        ASN1_NULL *onBasis;
148296341Sdelphij        /* NID_X9_62_tpBasis */
149296341Sdelphij        ASN1_INTEGER *tpBasis;
150296341Sdelphij        /* NID_X9_62_ppBasis */
151296341Sdelphij        X9_62_PENTANOMIAL *ppBasis;
152296341Sdelphij        /* anything else */
153296341Sdelphij        ASN1_TYPE *other;
154296341Sdelphij    } p;
155296341Sdelphij} X9_62_CHARACTERISTIC_TWO;
156160814Ssimon
157160814Ssimontypedef struct x9_62_fieldid_st {
158296341Sdelphij    ASN1_OBJECT *fieldType;
159296341Sdelphij    union {
160296341Sdelphij        char *ptr;
161296341Sdelphij        /* NID_X9_62_prime_field */
162296341Sdelphij        ASN1_INTEGER *prime;
163296341Sdelphij        /* NID_X9_62_characteristic_two_field */
164296341Sdelphij        X9_62_CHARACTERISTIC_TWO *char_two;
165296341Sdelphij        /* anything else */
166296341Sdelphij        ASN1_TYPE *other;
167296341Sdelphij    } p;
168296341Sdelphij} X9_62_FIELDID;
169160814Ssimon
170160814Ssimontypedef struct x9_62_curve_st {
171296341Sdelphij    ASN1_OCTET_STRING *a;
172296341Sdelphij    ASN1_OCTET_STRING *b;
173296341Sdelphij    ASN1_BIT_STRING *seed;
174296341Sdelphij} X9_62_CURVE;
175160814Ssimon
176160814Ssimontypedef struct ec_parameters_st {
177296341Sdelphij    long version;
178296341Sdelphij    X9_62_FIELDID *fieldID;
179296341Sdelphij    X9_62_CURVE *curve;
180296341Sdelphij    ASN1_OCTET_STRING *base;
181296341Sdelphij    ASN1_INTEGER *order;
182296341Sdelphij    ASN1_INTEGER *cofactor;
183296341Sdelphij} ECPARAMETERS;
184160814Ssimon
185160814Ssimonstruct ecpk_parameters_st {
186296341Sdelphij    int type;
187296341Sdelphij    union {
188296341Sdelphij        ASN1_OBJECT *named_curve;
189296341Sdelphij        ECPARAMETERS *parameters;
190296341Sdelphij        ASN1_NULL *implicitlyCA;
191296341Sdelphij    } value;
192296341Sdelphij} /* ECPKPARAMETERS */ ;
193160814Ssimon
194160814Ssimon/* SEC1 ECPrivateKey */
195160814Ssimontypedef struct ec_privatekey_st {
196296341Sdelphij    long version;
197296341Sdelphij    ASN1_OCTET_STRING *privateKey;
198296341Sdelphij    ECPKPARAMETERS *parameters;
199296341Sdelphij    ASN1_BIT_STRING *publicKey;
200296341Sdelphij} EC_PRIVATEKEY;
201160814Ssimon
202160814Ssimon/* the OpenSSL ASN.1 definitions */
203160814SsimonASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
204296341Sdelphij        ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG),
205296341Sdelphij        ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG),
206296341Sdelphij        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) = {
215296341Sdelphij        ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)),
216296341Sdelphij        ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)),
217296341Sdelphij        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) = {
221296341Sdelphij        ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG),
222296341Sdelphij        ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
223296341Sdelphij        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) = {
232296341Sdelphij        ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
233296341Sdelphij        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) = {
237296341Sdelphij        ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
238296341Sdelphij        ASN1_ADB_OBJECT(X9_62_FIELDID)
239160814Ssimon} ASN1_SEQUENCE_END(X9_62_FIELDID)
240160814Ssimon
241160814SsimonASN1_SEQUENCE(X9_62_CURVE) = {
242296341Sdelphij        ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
243296341Sdelphij        ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
244296341Sdelphij        ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
245160814Ssimon} ASN1_SEQUENCE_END(X9_62_CURVE)
246160814Ssimon
247160814SsimonASN1_SEQUENCE(ECPARAMETERS) = {
248296341Sdelphij        ASN1_SIMPLE(ECPARAMETERS, version, LONG),
249296341Sdelphij        ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
250296341Sdelphij        ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
251296341Sdelphij        ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
252296341Sdelphij        ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
253296341Sdelphij        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) = {
260296341Sdelphij        ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
261296341Sdelphij        ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
262296341Sdelphij        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) = {
270296341Sdelphij        ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
271296341Sdelphij        ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
272296341Sdelphij        ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
273296341Sdelphij        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
282296341Sdelphij/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */
283160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
284296341Sdelphij/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */
285160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
286296341Sdelphij/*
287296341Sdelphij * ec_asn1_parameters2group() creates a EC_GROUP object from a ECPARAMETERS
288296341Sdelphij * object
289296341Sdelphij */
290296341Sdelphijstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *);
291296341Sdelphij/*
292296341Sdelphij * ec_asn1_group2parameters() creates a ECPARAMETERS object from a EC_GROUP
293296341Sdelphij * object
294296341Sdelphij */
295296341Sdelphijstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,
296296341Sdelphij                                              ECPARAMETERS *);
297296341Sdelphij/*
298296341Sdelphij * ec_asn1_pkparameters2group() creates a EC_GROUP object from a
299296341Sdelphij * ECPKPARAMETERS object
300296341Sdelphij */
301296341Sdelphijstatic EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *);
302296341Sdelphij/*
303296341Sdelphij * ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a
304296341Sdelphij * EC_GROUP object
305296341Sdelphij */
306296341Sdelphijstatic ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *,
307296341Sdelphij                                                  ECPKPARAMETERS *);
308160814Ssimon
309160814Ssimon/* the function definitions */
310160814Ssimon
311160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
312296341Sdelphij{
313296341Sdelphij    int ok = 0, nid;
314296341Sdelphij    BIGNUM *tmp = NULL;
315160814Ssimon
316296341Sdelphij    if (group == NULL || field == NULL)
317296341Sdelphij        return 0;
318160814Ssimon
319296341Sdelphij    /* clear the old values (if necessary) */
320296341Sdelphij    if (field->fieldType != NULL)
321296341Sdelphij        ASN1_OBJECT_free(field->fieldType);
322296341Sdelphij    if (field->p.other != NULL)
323296341Sdelphij        ASN1_TYPE_free(field->p.other);
324160814Ssimon
325296341Sdelphij    nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
326296341Sdelphij    /* set OID for the field */
327296341Sdelphij    if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) {
328296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
329296341Sdelphij        goto err;
330296341Sdelphij    }
331296341Sdelphij
332296341Sdelphij    if (nid == NID_X9_62_prime_field) {
333296341Sdelphij        if ((tmp = BN_new()) == NULL) {
334296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
335296341Sdelphij            goto err;
336296341Sdelphij        }
337296341Sdelphij        /* the parameters are specified by the prime number p */
338296341Sdelphij        if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL)) {
339296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
340296341Sdelphij            goto err;
341296341Sdelphij        }
342296341Sdelphij        /* set the prime number */
343296341Sdelphij        field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL);
344296341Sdelphij        if (field->p.prime == NULL) {
345296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
346296341Sdelphij            goto err;
347296341Sdelphij        }
348296341Sdelphij    } else                      /* nid == NID_X9_62_characteristic_two_field */
349238405Sjkim#ifdef OPENSSL_NO_EC2M
350296341Sdelphij    {
351296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED);
352296341Sdelphij        goto err;
353296341Sdelphij    }
354238405Sjkim#else
355296341Sdelphij    {
356296341Sdelphij        int field_type;
357296341Sdelphij        X9_62_CHARACTERISTIC_TWO *char_two;
358160814Ssimon
359296341Sdelphij        field->p.char_two = X9_62_CHARACTERISTIC_TWO_new();
360296341Sdelphij        char_two = field->p.char_two;
361160814Ssimon
362296341Sdelphij        if (char_two == NULL) {
363296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
364296341Sdelphij            goto err;
365296341Sdelphij        }
366160814Ssimon
367296341Sdelphij        char_two->m = (long)EC_GROUP_get_degree(group);
368160814Ssimon
369296341Sdelphij        field_type = EC_GROUP_get_basis_type(group);
370160814Ssimon
371296341Sdelphij        if (field_type == 0) {
372296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
373296341Sdelphij            goto err;
374296341Sdelphij        }
375296341Sdelphij        /* set base type OID */
376296341Sdelphij        if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) {
377296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
378296341Sdelphij            goto err;
379296341Sdelphij        }
380160814Ssimon
381296341Sdelphij        if (field_type == NID_X9_62_tpBasis) {
382296341Sdelphij            unsigned int k;
383160814Ssimon
384296341Sdelphij            if (!EC_GROUP_get_trinomial_basis(group, &k))
385296341Sdelphij                goto err;
386160814Ssimon
387296341Sdelphij            char_two->p.tpBasis = ASN1_INTEGER_new();
388296341Sdelphij            if (!char_two->p.tpBasis) {
389296341Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
390296341Sdelphij                goto err;
391296341Sdelphij            }
392296341Sdelphij            if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) {
393296341Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
394296341Sdelphij                goto err;
395296341Sdelphij            }
396296341Sdelphij        } else if (field_type == NID_X9_62_ppBasis) {
397296341Sdelphij            unsigned int k1, k2, k3;
398160814Ssimon
399296341Sdelphij            if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3))
400296341Sdelphij                goto err;
401160814Ssimon
402296341Sdelphij            char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
403296341Sdelphij            if (!char_two->p.ppBasis) {
404296341Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
405296341Sdelphij                goto err;
406296341Sdelphij            }
407296341Sdelphij
408296341Sdelphij            /* set k? values */
409296341Sdelphij            char_two->p.ppBasis->k1 = (long)k1;
410296341Sdelphij            char_two->p.ppBasis->k2 = (long)k2;
411296341Sdelphij            char_two->p.ppBasis->k3 = (long)k3;
412296341Sdelphij        } else {                /* field_type == NID_X9_62_onBasis */
413296341Sdelphij
414296341Sdelphij            /* for ONB the parameters are (asn1) NULL */
415296341Sdelphij            char_two->p.onBasis = ASN1_NULL_new();
416296341Sdelphij            if (!char_two->p.onBasis) {
417296341Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
418296341Sdelphij                goto err;
419296341Sdelphij            }
420296341Sdelphij        }
421296341Sdelphij    }
422238405Sjkim#endif
423160814Ssimon
424296341Sdelphij    ok = 1;
425160814Ssimon
426296341Sdelphij err:if (tmp)
427296341Sdelphij        BN_free(tmp);
428296341Sdelphij    return (ok);
429160814Ssimon}
430160814Ssimon
431160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
432296341Sdelphij{
433296341Sdelphij    int ok = 0, nid;
434296341Sdelphij    BIGNUM *tmp_1 = NULL, *tmp_2 = NULL;
435296341Sdelphij    unsigned char *buffer_1 = NULL, *buffer_2 = NULL,
436296341Sdelphij        *a_buf = NULL, *b_buf = NULL;
437296341Sdelphij    size_t len_1, len_2;
438296341Sdelphij    unsigned char char_zero = 0;
439160814Ssimon
440296341Sdelphij    if (!group || !curve || !curve->a || !curve->b)
441296341Sdelphij        return 0;
442160814Ssimon
443296341Sdelphij    if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) {
444296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
445296341Sdelphij        goto err;
446296341Sdelphij    }
447160814Ssimon
448296341Sdelphij    nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
449160814Ssimon
450296341Sdelphij    /* get a and b */
451296341Sdelphij    if (nid == NID_X9_62_prime_field) {
452296341Sdelphij        if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL)) {
453296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
454296341Sdelphij            goto err;
455296341Sdelphij        }
456296341Sdelphij    }
457238405Sjkim#ifndef OPENSSL_NO_EC2M
458296341Sdelphij    else {                      /* nid == NID_X9_62_characteristic_two_field */
459296341Sdelphij
460296341Sdelphij        if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) {
461296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
462296341Sdelphij            goto err;
463296341Sdelphij        }
464296341Sdelphij    }
465238405Sjkim#endif
466296341Sdelphij    len_1 = (size_t)BN_num_bytes(tmp_1);
467296341Sdelphij    len_2 = (size_t)BN_num_bytes(tmp_2);
468160814Ssimon
469296341Sdelphij    if (len_1 == 0) {
470296341Sdelphij        /* len_1 == 0 => a == 0 */
471296341Sdelphij        a_buf = &char_zero;
472296341Sdelphij        len_1 = 1;
473296341Sdelphij    } else {
474296341Sdelphij        if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) {
475296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
476296341Sdelphij            goto err;
477296341Sdelphij        }
478296341Sdelphij        if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) {
479296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
480296341Sdelphij            goto err;
481296341Sdelphij        }
482296341Sdelphij        a_buf = buffer_1;
483296341Sdelphij    }
484160814Ssimon
485296341Sdelphij    if (len_2 == 0) {
486296341Sdelphij        /* len_2 == 0 => b == 0 */
487296341Sdelphij        b_buf = &char_zero;
488296341Sdelphij        len_2 = 1;
489296341Sdelphij    } else {
490296341Sdelphij        if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) {
491296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
492296341Sdelphij            goto err;
493296341Sdelphij        }
494296341Sdelphij        if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) {
495296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
496296341Sdelphij            goto err;
497296341Sdelphij        }
498296341Sdelphij        b_buf = buffer_2;
499296341Sdelphij    }
500160814Ssimon
501296341Sdelphij    /* set a and b */
502296341Sdelphij    if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
503296341Sdelphij        !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) {
504296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
505296341Sdelphij        goto err;
506296341Sdelphij    }
507160814Ssimon
508296341Sdelphij    /* set the seed (optional) */
509296341Sdelphij    if (group->seed) {
510296341Sdelphij        if (!curve->seed)
511296341Sdelphij            if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) {
512296341Sdelphij                ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
513296341Sdelphij                goto err;
514296341Sdelphij            }
515296341Sdelphij        curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
516296341Sdelphij        curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT;
517296341Sdelphij        if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
518296341Sdelphij                                 (int)group->seed_len)) {
519296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
520296341Sdelphij            goto err;
521296341Sdelphij        }
522296341Sdelphij    } else {
523296341Sdelphij        if (curve->seed) {
524296341Sdelphij            ASN1_BIT_STRING_free(curve->seed);
525296341Sdelphij            curve->seed = NULL;
526296341Sdelphij        }
527296341Sdelphij    }
528160814Ssimon
529296341Sdelphij    ok = 1;
530296341Sdelphij
531296341Sdelphij err:if (buffer_1)
532296341Sdelphij        OPENSSL_free(buffer_1);
533296341Sdelphij    if (buffer_2)
534296341Sdelphij        OPENSSL_free(buffer_2);
535296341Sdelphij    if (tmp_1)
536296341Sdelphij        BN_free(tmp_1);
537296341Sdelphij    if (tmp_2)
538296341Sdelphij        BN_free(tmp_2);
539296341Sdelphij    return (ok);
540296341Sdelphij}
541296341Sdelphij
542160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group,
543160814Ssimon                                              ECPARAMETERS *param)
544296341Sdelphij{
545296341Sdelphij    int ok = 0;
546296341Sdelphij    size_t len = 0;
547296341Sdelphij    ECPARAMETERS *ret = NULL;
548296341Sdelphij    BIGNUM *tmp = NULL;
549296341Sdelphij    unsigned char *buffer = NULL;
550296341Sdelphij    const EC_POINT *point = NULL;
551296341Sdelphij    point_conversion_form_t form;
552160814Ssimon
553296341Sdelphij    if ((tmp = BN_new()) == NULL) {
554296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
555296341Sdelphij        goto err;
556296341Sdelphij    }
557160814Ssimon
558296341Sdelphij    if (param == NULL) {
559296341Sdelphij        if ((ret = ECPARAMETERS_new()) == NULL) {
560296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
561296341Sdelphij            goto err;
562296341Sdelphij        }
563296341Sdelphij    } else
564296341Sdelphij        ret = param;
565160814Ssimon
566296341Sdelphij    /* set the version (always one) */
567296341Sdelphij    ret->version = (long)0x1;
568160814Ssimon
569296341Sdelphij    /* set the fieldID */
570296341Sdelphij    if (!ec_asn1_group2fieldid(group, ret->fieldID)) {
571296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
572296341Sdelphij        goto err;
573296341Sdelphij    }
574160814Ssimon
575296341Sdelphij    /* set the curve */
576296341Sdelphij    if (!ec_asn1_group2curve(group, ret->curve)) {
577296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
578296341Sdelphij        goto err;
579296341Sdelphij    }
580160814Ssimon
581296341Sdelphij    /* set the base point */
582296341Sdelphij    if ((point = EC_GROUP_get0_generator(group)) == NULL) {
583296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR);
584296341Sdelphij        goto err;
585296341Sdelphij    }
586160814Ssimon
587296341Sdelphij    form = EC_GROUP_get_point_conversion_form(group);
588160814Ssimon
589296341Sdelphij    len = EC_POINT_point2oct(group, point, form, NULL, len, NULL);
590296341Sdelphij    if (len == 0) {
591296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
592296341Sdelphij        goto err;
593296341Sdelphij    }
594296341Sdelphij    if ((buffer = OPENSSL_malloc(len)) == NULL) {
595296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
596296341Sdelphij        goto err;
597296341Sdelphij    }
598296341Sdelphij    if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) {
599296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
600296341Sdelphij        goto err;
601296341Sdelphij    }
602296341Sdelphij    if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) {
603296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
604296341Sdelphij        goto err;
605296341Sdelphij    }
606296341Sdelphij    if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) {
607296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
608296341Sdelphij        goto err;
609296341Sdelphij    }
610160814Ssimon
611296341Sdelphij    /* set the order */
612296341Sdelphij    if (!EC_GROUP_get_order(group, tmp, NULL)) {
613296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
614296341Sdelphij        goto err;
615296341Sdelphij    }
616296341Sdelphij    ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
617296341Sdelphij    if (ret->order == NULL) {
618296341Sdelphij        ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
619296341Sdelphij        goto err;
620296341Sdelphij    }
621160814Ssimon
622296341Sdelphij    /* set the cofactor (optional) */
623296341Sdelphij    if (EC_GROUP_get_cofactor(group, tmp, NULL)) {
624296341Sdelphij        ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
625296341Sdelphij        if (ret->cofactor == NULL) {
626296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
627296341Sdelphij            goto err;
628296341Sdelphij        }
629296341Sdelphij    }
630160814Ssimon
631296341Sdelphij    ok = 1;
632160814Ssimon
633296341Sdelphij err:if (!ok) {
634296341Sdelphij        if (ret && !param)
635296341Sdelphij            ECPARAMETERS_free(ret);
636296341Sdelphij        ret = NULL;
637296341Sdelphij    }
638296341Sdelphij    if (tmp)
639296341Sdelphij        BN_free(tmp);
640296341Sdelphij    if (buffer)
641296341Sdelphij        OPENSSL_free(buffer);
642296341Sdelphij    return (ret);
643296341Sdelphij}
644160814Ssimon
645296341SdelphijECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
646160814Ssimon                                           ECPKPARAMETERS *params)
647296341Sdelphij{
648296341Sdelphij    int ok = 1, tmp;
649296341Sdelphij    ECPKPARAMETERS *ret = params;
650160814Ssimon
651296341Sdelphij    if (ret == NULL) {
652296341Sdelphij        if ((ret = ECPKPARAMETERS_new()) == NULL) {
653296341Sdelphij            ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, ERR_R_MALLOC_FAILURE);
654296341Sdelphij            return NULL;
655296341Sdelphij        }
656296341Sdelphij    } else {
657296341Sdelphij        if (ret->type == 0 && ret->value.named_curve)
658296341Sdelphij            ASN1_OBJECT_free(ret->value.named_curve);
659296341Sdelphij        else if (ret->type == 1 && ret->value.parameters)
660296341Sdelphij            ECPARAMETERS_free(ret->value.parameters);
661296341Sdelphij    }
662160814Ssimon
663296341Sdelphij    if (EC_GROUP_get_asn1_flag(group)) {
664296341Sdelphij        /*
665296341Sdelphij         * use the asn1 OID to describe the the elliptic curve parameters
666296341Sdelphij         */
667296341Sdelphij        tmp = EC_GROUP_get_curve_name(group);
668296341Sdelphij        if (tmp) {
669296341Sdelphij            ret->type = 0;
670296341Sdelphij            if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL)
671296341Sdelphij                ok = 0;
672296341Sdelphij        } else
673296341Sdelphij            /* we don't kmow the nid => ERROR */
674296341Sdelphij            ok = 0;
675296341Sdelphij    } else {
676296341Sdelphij        /* use the ECPARAMETERS structure */
677296341Sdelphij        ret->type = 1;
678296341Sdelphij        if ((ret->value.parameters =
679296341Sdelphij             ec_asn1_group2parameters(group, NULL)) == NULL)
680296341Sdelphij            ok = 0;
681296341Sdelphij    }
682160814Ssimon
683296341Sdelphij    if (!ok) {
684296341Sdelphij        ECPKPARAMETERS_free(ret);
685296341Sdelphij        return NULL;
686296341Sdelphij    }
687296341Sdelphij    return ret;
688296341Sdelphij}
689160814Ssimon
690160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
691296341Sdelphij{
692296341Sdelphij    int ok = 0, tmp;
693296341Sdelphij    EC_GROUP *ret = NULL;
694296341Sdelphij    BIGNUM *p = NULL, *a = NULL, *b = NULL;
695296341Sdelphij    EC_POINT *point = NULL;
696296341Sdelphij    long field_bits;
697160814Ssimon
698296341Sdelphij    if (!params->fieldID || !params->fieldID->fieldType ||
699296341Sdelphij        !params->fieldID->p.ptr) {
700296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
701296341Sdelphij        goto err;
702296341Sdelphij    }
703160814Ssimon
704296341Sdelphij    /* now extract the curve parameters a and b */
705296341Sdelphij    if (!params->curve || !params->curve->a ||
706296341Sdelphij        !params->curve->a->data || !params->curve->b ||
707296341Sdelphij        !params->curve->b->data) {
708296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
709296341Sdelphij        goto err;
710296341Sdelphij    }
711296341Sdelphij    a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
712296341Sdelphij    if (a == NULL) {
713296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
714296341Sdelphij        goto err;
715296341Sdelphij    }
716296341Sdelphij    b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
717296341Sdelphij    if (b == NULL) {
718296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
719296341Sdelphij        goto err;
720296341Sdelphij    }
721160814Ssimon
722296341Sdelphij    /* get the field parameters */
723296341Sdelphij    tmp = OBJ_obj2nid(params->fieldID->fieldType);
724296341Sdelphij    if (tmp == NID_X9_62_characteristic_two_field)
725238405Sjkim#ifdef OPENSSL_NO_EC2M
726296341Sdelphij    {
727296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED);
728296341Sdelphij        goto err;
729296341Sdelphij    }
730238405Sjkim#else
731296341Sdelphij    {
732296341Sdelphij        X9_62_CHARACTERISTIC_TWO *char_two;
733160814Ssimon
734296341Sdelphij        char_two = params->fieldID->p.char_two;
735160814Ssimon
736296341Sdelphij        field_bits = char_two->m;
737296341Sdelphij        if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
738296341Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
739296341Sdelphij            goto err;
740296341Sdelphij        }
741162911Ssimon
742296341Sdelphij        if ((p = BN_new()) == NULL) {
743296341Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
744296341Sdelphij            goto err;
745296341Sdelphij        }
746160814Ssimon
747296341Sdelphij        /* get the base type */
748296341Sdelphij        tmp = OBJ_obj2nid(char_two->type);
749160814Ssimon
750296341Sdelphij        if (tmp == NID_X9_62_tpBasis) {
751296341Sdelphij            long tmp_long;
752160814Ssimon
753296341Sdelphij            if (!char_two->p.tpBasis) {
754296341Sdelphij                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
755296341Sdelphij                goto err;
756296341Sdelphij            }
757160814Ssimon
758296341Sdelphij            tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis);
759162911Ssimon
760296341Sdelphij            if (!(char_two->m > tmp_long && tmp_long > 0)) {
761296341Sdelphij                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP,
762296341Sdelphij                      EC_R_INVALID_TRINOMIAL_BASIS);
763296341Sdelphij                goto err;
764296341Sdelphij            }
765160814Ssimon
766296341Sdelphij            /* create the polynomial */
767296341Sdelphij            if (!BN_set_bit(p, (int)char_two->m))
768296341Sdelphij                goto err;
769296341Sdelphij            if (!BN_set_bit(p, (int)tmp_long))
770296341Sdelphij                goto err;
771296341Sdelphij            if (!BN_set_bit(p, 0))
772296341Sdelphij                goto err;
773296341Sdelphij        } else if (tmp == NID_X9_62_ppBasis) {
774296341Sdelphij            X9_62_PENTANOMIAL *penta;
775162911Ssimon
776296341Sdelphij            penta = char_two->p.ppBasis;
777296341Sdelphij            if (!penta) {
778296341Sdelphij                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
779296341Sdelphij                goto err;
780296341Sdelphij            }
781160814Ssimon
782296341Sdelphij            if (!
783296341Sdelphij                (char_two->m > penta->k3 && penta->k3 > penta->k2
784296341Sdelphij                 && penta->k2 > penta->k1 && penta->k1 > 0)) {
785296341Sdelphij                ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP,
786296341Sdelphij                      EC_R_INVALID_PENTANOMIAL_BASIS);
787296341Sdelphij                goto err;
788296341Sdelphij            }
789296341Sdelphij
790296341Sdelphij            /* create the polynomial */
791296341Sdelphij            if (!BN_set_bit(p, (int)char_two->m))
792296341Sdelphij                goto err;
793296341Sdelphij            if (!BN_set_bit(p, (int)penta->k1))
794296341Sdelphij                goto err;
795296341Sdelphij            if (!BN_set_bit(p, (int)penta->k2))
796296341Sdelphij                goto err;
797296341Sdelphij            if (!BN_set_bit(p, (int)penta->k3))
798296341Sdelphij                goto err;
799296341Sdelphij            if (!BN_set_bit(p, 0))
800296341Sdelphij                goto err;
801296341Sdelphij        } else if (tmp == NID_X9_62_onBasis) {
802296341Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED);
803296341Sdelphij            goto err;
804296341Sdelphij        } else {                /* error */
805296341Sdelphij
806296341Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
807296341Sdelphij            goto err;
808296341Sdelphij        }
809296341Sdelphij
810296341Sdelphij        /* create the EC_GROUP structure */
811296341Sdelphij        ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
812296341Sdelphij    }
813238405Sjkim#endif
814296341Sdelphij    else if (tmp == NID_X9_62_prime_field) {
815296341Sdelphij        /* we have a curve over a prime field */
816296341Sdelphij        /* extract the prime number */
817296341Sdelphij        if (!params->fieldID->p.prime) {
818296341Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
819296341Sdelphij            goto err;
820296341Sdelphij        }
821296341Sdelphij        p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
822296341Sdelphij        if (p == NULL) {
823296341Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
824296341Sdelphij            goto err;
825296341Sdelphij        }
826162911Ssimon
827296341Sdelphij        if (BN_is_negative(p) || BN_is_zero(p)) {
828296341Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
829296341Sdelphij            goto err;
830296341Sdelphij        }
831162911Ssimon
832296341Sdelphij        field_bits = BN_num_bits(p);
833296341Sdelphij        if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
834296341Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
835296341Sdelphij            goto err;
836296341Sdelphij        }
837162911Ssimon
838296341Sdelphij        /* create the EC_GROUP structure */
839296341Sdelphij        ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
840296341Sdelphij    } else {
841296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
842296341Sdelphij        goto err;
843296341Sdelphij    }
844160814Ssimon
845296341Sdelphij    if (ret == NULL) {
846296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
847296341Sdelphij        goto err;
848296341Sdelphij    }
849160814Ssimon
850296341Sdelphij    /* extract seed (optional) */
851296341Sdelphij    if (params->curve->seed != NULL) {
852296341Sdelphij        if (ret->seed != NULL)
853296341Sdelphij            OPENSSL_free(ret->seed);
854296341Sdelphij        if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) {
855296341Sdelphij            ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
856296341Sdelphij            goto err;
857296341Sdelphij        }
858296341Sdelphij        memcpy(ret->seed, params->curve->seed->data,
859296341Sdelphij               params->curve->seed->length);
860296341Sdelphij        ret->seed_len = params->curve->seed->length;
861296341Sdelphij    }
862160814Ssimon
863296341Sdelphij    if (!params->order || !params->base || !params->base->data) {
864296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
865296341Sdelphij        goto err;
866296341Sdelphij    }
867160814Ssimon
868296341Sdelphij    if ((point = EC_POINT_new(ret)) == NULL)
869296341Sdelphij        goto err;
870160814Ssimon
871296341Sdelphij    /* set the point conversion form */
872296341Sdelphij    EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
873296341Sdelphij                                       (params->base->data[0] & ~0x01));
874160814Ssimon
875296341Sdelphij    /* extract the ec point */
876296341Sdelphij    if (!EC_POINT_oct2point(ret, point, params->base->data,
877296341Sdelphij                            params->base->length, NULL)) {
878296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
879296341Sdelphij        goto err;
880296341Sdelphij    }
881160814Ssimon
882296341Sdelphij    /* extract the order */
883296341Sdelphij    if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) {
884296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
885296341Sdelphij        goto err;
886296341Sdelphij    }
887296341Sdelphij    if (BN_is_negative(a) || BN_is_zero(a)) {
888296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
889296341Sdelphij        goto err;
890296341Sdelphij    }
891296341Sdelphij    if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */
892296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
893296341Sdelphij        goto err;
894296341Sdelphij    }
895160814Ssimon
896296341Sdelphij    /* extract the cofactor (optional) */
897296341Sdelphij    if (params->cofactor == NULL) {
898296341Sdelphij        if (b) {
899296341Sdelphij            BN_free(b);
900296341Sdelphij            b = NULL;
901296341Sdelphij        }
902296341Sdelphij    } else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) {
903296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
904296341Sdelphij        goto err;
905296341Sdelphij    }
906296341Sdelphij    /* set the generator, order and cofactor (if present) */
907296341Sdelphij    if (!EC_GROUP_set_generator(ret, point, a, b)) {
908296341Sdelphij        ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
909296341Sdelphij        goto err;
910296341Sdelphij    }
911160814Ssimon
912296341Sdelphij    ok = 1;
913160814Ssimon
914296341Sdelphij err:if (!ok) {
915296341Sdelphij        if (ret)
916296341Sdelphij            EC_GROUP_clear_free(ret);
917296341Sdelphij        ret = NULL;
918296341Sdelphij    }
919296341Sdelphij
920296341Sdelphij    if (p)
921296341Sdelphij        BN_free(p);
922296341Sdelphij    if (a)
923296341Sdelphij        BN_free(a);
924296341Sdelphij    if (b)
925296341Sdelphij        BN_free(b);
926296341Sdelphij    if (point)
927296341Sdelphij        EC_POINT_free(point);
928296341Sdelphij    return (ret);
929160814Ssimon}
930160814Ssimon
931160814SsimonEC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
932296341Sdelphij{
933296341Sdelphij    EC_GROUP *ret = NULL;
934296341Sdelphij    int tmp = 0;
935160814Ssimon
936296341Sdelphij    if (params == NULL) {
937296341Sdelphij        ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_MISSING_PARAMETERS);
938296341Sdelphij        return NULL;
939296341Sdelphij    }
940160814Ssimon
941296341Sdelphij    if (params->type == 0) {    /* the curve is given by an OID */
942296341Sdelphij        tmp = OBJ_obj2nid(params->value.named_curve);
943296341Sdelphij        if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) {
944296341Sdelphij            ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP,
945296341Sdelphij                  EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
946296341Sdelphij            return NULL;
947296341Sdelphij        }
948296341Sdelphij        EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
949296341Sdelphij    } else if (params->type == 1) { /* the parameters are given by a
950296341Sdelphij                                     * ECPARAMETERS structure */
951296341Sdelphij        ret = ec_asn1_parameters2group(params->value.parameters);
952296341Sdelphij        if (!ret) {
953296341Sdelphij            ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB);
954296341Sdelphij            return NULL;
955296341Sdelphij        }
956296341Sdelphij        EC_GROUP_set_asn1_flag(ret, 0x0);
957296341Sdelphij    } else if (params->type == 2) { /* implicitlyCA */
958296341Sdelphij        return NULL;
959296341Sdelphij    } else {
960296341Sdelphij        ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR);
961296341Sdelphij        return NULL;
962296341Sdelphij    }
963160814Ssimon
964296341Sdelphij    return ret;
965296341Sdelphij}
966160814Ssimon
967160814Ssimon/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */
968160814Ssimon
969160814SsimonEC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
970296341Sdelphij{
971296341Sdelphij    EC_GROUP *group = NULL;
972296341Sdelphij    ECPKPARAMETERS *params = NULL;
973160814Ssimon
974296341Sdelphij    if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) {
975296341Sdelphij        ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE);
976296341Sdelphij        ECPKPARAMETERS_free(params);
977296341Sdelphij        return NULL;
978296341Sdelphij    }
979160814Ssimon
980296341Sdelphij    if ((group = ec_asn1_pkparameters2group(params)) == NULL) {
981296341Sdelphij        ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE);
982296341Sdelphij        ECPKPARAMETERS_free(params);
983296341Sdelphij        return NULL;
984296341Sdelphij    }
985160814Ssimon
986296341Sdelphij    if (a && *a)
987296341Sdelphij        EC_GROUP_clear_free(*a);
988296341Sdelphij    if (a)
989296341Sdelphij        *a = group;
990160814Ssimon
991296341Sdelphij    ECPKPARAMETERS_free(params);
992296341Sdelphij    return (group);
993296341Sdelphij}
994296341Sdelphij
995160814Ssimonint i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
996296341Sdelphij{
997296341Sdelphij    int ret = 0;
998296341Sdelphij    ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL);
999296341Sdelphij    if (tmp == NULL) {
1000296341Sdelphij        ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE);
1001296341Sdelphij        return 0;
1002296341Sdelphij    }
1003296341Sdelphij    if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) {
1004296341Sdelphij        ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE);
1005296341Sdelphij        ECPKPARAMETERS_free(tmp);
1006296341Sdelphij        return 0;
1007296341Sdelphij    }
1008296341Sdelphij    ECPKPARAMETERS_free(tmp);
1009296341Sdelphij    return (ret);
1010296341Sdelphij}
1011160814Ssimon
1012160814Ssimon/* some EC_KEY functions */
1013160814Ssimon
1014160814SsimonEC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
1015296341Sdelphij{
1016296341Sdelphij    int ok = 0;
1017296341Sdelphij    EC_KEY *ret = NULL;
1018296341Sdelphij    EC_PRIVATEKEY *priv_key = NULL;
1019160814Ssimon
1020296341Sdelphij    if ((priv_key = d2i_EC_PRIVATEKEY(NULL, in, len)) == NULL) {
1021296341Sdelphij        ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1022296341Sdelphij        return NULL;
1023296341Sdelphij    }
1024160814Ssimon
1025296341Sdelphij    if (a == NULL || *a == NULL) {
1026296341Sdelphij        if ((ret = EC_KEY_new()) == NULL) {
1027296341Sdelphij            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1028296341Sdelphij            goto err;
1029296341Sdelphij        }
1030296341Sdelphij    } else
1031296341Sdelphij        ret = *a;
1032160814Ssimon
1033296341Sdelphij    if (priv_key->parameters) {
1034296341Sdelphij        if (ret->group)
1035296341Sdelphij            EC_GROUP_clear_free(ret->group);
1036296341Sdelphij        ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
1037296341Sdelphij    }
1038160814Ssimon
1039296341Sdelphij    if (ret->group == NULL) {
1040296341Sdelphij        ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1041296341Sdelphij        goto err;
1042296341Sdelphij    }
1043160814Ssimon
1044296341Sdelphij    ret->version = priv_key->version;
1045160814Ssimon
1046296341Sdelphij    if (priv_key->privateKey) {
1047296341Sdelphij        ret->priv_key = BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey),
1048296341Sdelphij                                  M_ASN1_STRING_length(priv_key->privateKey),
1049296341Sdelphij                                  ret->priv_key);
1050296341Sdelphij        if (ret->priv_key == NULL) {
1051296341Sdelphij            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_BN_LIB);
1052296341Sdelphij            goto err;
1053296341Sdelphij        }
1054296341Sdelphij    } else {
1055296341Sdelphij        ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_MISSING_PRIVATE_KEY);
1056296341Sdelphij        goto err;
1057296341Sdelphij    }
1058160814Ssimon
1059296341Sdelphij    if (ret->pub_key)
1060296341Sdelphij        EC_POINT_clear_free(ret->pub_key);
1061296341Sdelphij    ret->pub_key = EC_POINT_new(ret->group);
1062296341Sdelphij    if (ret->pub_key == NULL) {
1063296341Sdelphij        ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1064296341Sdelphij        goto err;
1065296341Sdelphij    }
1066160814Ssimon
1067296341Sdelphij    if (priv_key->publicKey) {
1068296341Sdelphij        const unsigned char *pub_oct;
1069296341Sdelphij        int pub_oct_len;
1070273399Sdelphij
1071296341Sdelphij        pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
1072296341Sdelphij        pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
1073296341Sdelphij        /*
1074296341Sdelphij         * The first byte - point conversion form - must be present.
1075296341Sdelphij         */
1076296341Sdelphij        if (pub_oct_len <= 0) {
1077296341Sdelphij            ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL);
1078296341Sdelphij            goto err;
1079296341Sdelphij        }
1080296341Sdelphij        /* Save the point conversion form. */
1081296341Sdelphij        ret->conv_form = (point_conversion_form_t) (pub_oct[0] & ~0x01);
1082296341Sdelphij        if (!EC_POINT_oct2point(ret->group, ret->pub_key,
1083296341Sdelphij                                pub_oct, (size_t)(pub_oct_len), NULL)) {
1084296341Sdelphij            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1085296341Sdelphij            goto err;
1086296341Sdelphij        }
1087296341Sdelphij    } else {
1088296341Sdelphij        if (!EC_POINT_mul
1089296341Sdelphij            (ret->group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) {
1090296341Sdelphij            ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1091296341Sdelphij            goto err;
1092296341Sdelphij        }
1093296341Sdelphij        /* Remember the original private-key-only encoding. */
1094296341Sdelphij        ret->enc_flag |= EC_PKEY_NO_PUBKEY;
1095296341Sdelphij    }
1096160814Ssimon
1097296341Sdelphij    if (a)
1098296341Sdelphij        *a = ret;
1099296341Sdelphij    ok = 1;
1100296341Sdelphij err:
1101296341Sdelphij    if (!ok) {
1102296341Sdelphij        if (ret && (a == NULL || *a != ret))
1103296341Sdelphij            EC_KEY_free(ret);
1104296341Sdelphij        ret = NULL;
1105296341Sdelphij    }
1106160814Ssimon
1107296341Sdelphij    if (priv_key)
1108296341Sdelphij        EC_PRIVATEKEY_free(priv_key);
1109160814Ssimon
1110296341Sdelphij    return (ret);
1111296341Sdelphij}
1112160814Ssimon
1113296341Sdelphijint i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
1114296341Sdelphij{
1115296341Sdelphij    int ret = 0, ok = 0;
1116296341Sdelphij    unsigned char *buffer = NULL;
1117296341Sdelphij    size_t buf_len = 0, tmp_len, bn_len;
1118296341Sdelphij    EC_PRIVATEKEY *priv_key = NULL;
1119160814Ssimon
1120296341Sdelphij    if (a == NULL || a->group == NULL || a->priv_key == NULL ||
1121296341Sdelphij        (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) {
1122296341Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
1123296341Sdelphij        goto err;
1124296341Sdelphij    }
1125160814Ssimon
1126296341Sdelphij    if ((priv_key = EC_PRIVATEKEY_new()) == NULL) {
1127296341Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1128296341Sdelphij        goto err;
1129296341Sdelphij    }
1130160814Ssimon
1131296341Sdelphij    priv_key->version = a->version;
1132160814Ssimon
1133296341Sdelphij    bn_len = (size_t)BN_num_bytes(a->priv_key);
1134160814Ssimon
1135296341Sdelphij    /* Octetstring may need leading zeros if BN is to short */
1136160814Ssimon
1137296341Sdelphij    buf_len = (EC_GROUP_get_degree(a->group) + 7) / 8;
1138160814Ssimon
1139296341Sdelphij    if (bn_len > buf_len) {
1140296341Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL);
1141296341Sdelphij        goto err;
1142296341Sdelphij    }
1143160814Ssimon
1144296341Sdelphij    buffer = OPENSSL_malloc(buf_len);
1145296341Sdelphij    if (buffer == NULL) {
1146296341Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1147296341Sdelphij        goto err;
1148296341Sdelphij    }
1149160814Ssimon
1150296341Sdelphij    if (!BN_bn2bin(a->priv_key, buffer + buf_len - bn_len)) {
1151296341Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB);
1152296341Sdelphij        goto err;
1153296341Sdelphij    }
1154160814Ssimon
1155296341Sdelphij    if (buf_len - bn_len > 0) {
1156296341Sdelphij        memset(buffer, 0, buf_len - bn_len);
1157296341Sdelphij    }
1158160814Ssimon
1159296341Sdelphij    if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
1160296341Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1161296341Sdelphij        goto err;
1162296341Sdelphij    }
1163160814Ssimon
1164296341Sdelphij    if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) {
1165296341Sdelphij        if ((priv_key->parameters =
1166296341Sdelphij             ec_asn1_group2pkparameters(a->group,
1167296341Sdelphij                                        priv_key->parameters)) == NULL) {
1168296341Sdelphij            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1169296341Sdelphij            goto err;
1170296341Sdelphij        }
1171296341Sdelphij    }
1172160814Ssimon
1173296341Sdelphij    if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) {
1174296341Sdelphij        priv_key->publicKey = M_ASN1_BIT_STRING_new();
1175296341Sdelphij        if (priv_key->publicKey == NULL) {
1176296341Sdelphij            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1177296341Sdelphij            goto err;
1178296341Sdelphij        }
1179160814Ssimon
1180296341Sdelphij        tmp_len = EC_POINT_point2oct(a->group, a->pub_key,
1181296341Sdelphij                                     a->conv_form, NULL, 0, NULL);
1182296341Sdelphij
1183296341Sdelphij        if (tmp_len > buf_len) {
1184296341Sdelphij            unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
1185296341Sdelphij            if (!tmp_buffer) {
1186296341Sdelphij                ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1187296341Sdelphij                goto err;
1188296341Sdelphij            }
1189296341Sdelphij            buffer = tmp_buffer;
1190296341Sdelphij            buf_len = tmp_len;
1191296341Sdelphij        }
1192296341Sdelphij
1193296341Sdelphij        if (!EC_POINT_point2oct(a->group, a->pub_key,
1194296341Sdelphij                                a->conv_form, buffer, buf_len, NULL)) {
1195296341Sdelphij            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1196296341Sdelphij            goto err;
1197296341Sdelphij        }
1198296341Sdelphij
1199296341Sdelphij        priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
1200296341Sdelphij        priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
1201296341Sdelphij        if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
1202296341Sdelphij            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1203296341Sdelphij            goto err;
1204296341Sdelphij        }
1205296341Sdelphij    }
1206296341Sdelphij
1207296341Sdelphij    if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) {
1208296341Sdelphij        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1209296341Sdelphij        goto err;
1210296341Sdelphij    }
1211296341Sdelphij    ok = 1;
1212296341Sdelphij err:
1213296341Sdelphij    if (buffer)
1214296341Sdelphij        OPENSSL_free(buffer);
1215296341Sdelphij    if (priv_key)
1216296341Sdelphij        EC_PRIVATEKEY_free(priv_key);
1217296341Sdelphij    return (ok ? ret : 0);
1218296341Sdelphij}
1219296341Sdelphij
1220160814Ssimonint i2d_ECParameters(EC_KEY *a, unsigned char **out)
1221296341Sdelphij{
1222296341Sdelphij    if (a == NULL) {
1223296341Sdelphij        ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1224296341Sdelphij        return 0;
1225296341Sdelphij    }
1226296341Sdelphij    return i2d_ECPKParameters(a->group, out);
1227296341Sdelphij}
1228160814Ssimon
1229160814SsimonEC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
1230296341Sdelphij{
1231296341Sdelphij    EC_KEY *ret;
1232160814Ssimon
1233296341Sdelphij    if (in == NULL || *in == NULL) {
1234296341Sdelphij        ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1235296341Sdelphij        return NULL;
1236296341Sdelphij    }
1237160814Ssimon
1238296341Sdelphij    if (a == NULL || *a == NULL) {
1239296341Sdelphij        if ((ret = EC_KEY_new()) == NULL) {
1240296341Sdelphij            ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
1241296341Sdelphij            return NULL;
1242296341Sdelphij        }
1243296341Sdelphij    } else
1244296341Sdelphij        ret = *a;
1245160814Ssimon
1246296341Sdelphij    if (!d2i_ECPKParameters(&ret->group, in, len)) {
1247296341Sdelphij        ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB);
1248296341Sdelphij        if (a == NULL || *a != ret)
1249296341Sdelphij             EC_KEY_free(ret);
1250296341Sdelphij        return NULL;
1251296341Sdelphij    }
1252160814Ssimon
1253296341Sdelphij    if (a)
1254296341Sdelphij        *a = ret;
1255160814Ssimon
1256296341Sdelphij    return ret;
1257296341Sdelphij}
1258296341Sdelphij
1259160814SsimonEC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
1260296341Sdelphij{
1261296341Sdelphij    EC_KEY *ret = NULL;
1262160814Ssimon
1263296341Sdelphij    if (a == NULL || (*a) == NULL || (*a)->group == NULL) {
1264296341Sdelphij        /*
1265296341Sdelphij         * sorry, but a EC_GROUP-structur is necessary to set the public key
1266296341Sdelphij         */
1267296341Sdelphij        ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1268296341Sdelphij        return 0;
1269296341Sdelphij    }
1270296341Sdelphij    ret = *a;
1271296341Sdelphij    if (ret->pub_key == NULL &&
1272296341Sdelphij        (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
1273296341Sdelphij        ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1274296341Sdelphij        return 0;
1275296341Sdelphij    }
1276296341Sdelphij    if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) {
1277296341Sdelphij        ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB);
1278296341Sdelphij        return 0;
1279296341Sdelphij    }
1280296341Sdelphij    /* save the point conversion form */
1281296341Sdelphij    ret->conv_form = (point_conversion_form_t) (*in[0] & ~0x01);
1282296341Sdelphij    *in += len;
1283296341Sdelphij    return ret;
1284296341Sdelphij}
1285160814Ssimon
1286160814Ssimonint i2o_ECPublicKey(EC_KEY *a, unsigned char **out)
1287296341Sdelphij{
1288296341Sdelphij    size_t buf_len = 0;
1289296341Sdelphij    int new_buffer = 0;
1290160814Ssimon
1291296341Sdelphij    if (a == NULL) {
1292296341Sdelphij        ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1293296341Sdelphij        return 0;
1294296341Sdelphij    }
1295160814Ssimon
1296296341Sdelphij    buf_len = EC_POINT_point2oct(a->group, a->pub_key,
1297296341Sdelphij                                 a->conv_form, NULL, 0, NULL);
1298160814Ssimon
1299296341Sdelphij    if (out == NULL || buf_len == 0)
1300296341Sdelphij        /* out == NULL => just return the length of the octet string */
1301296341Sdelphij        return buf_len;
1302160814Ssimon
1303296341Sdelphij    if (*out == NULL) {
1304296341Sdelphij        if ((*out = OPENSSL_malloc(buf_len)) == NULL) {
1305296341Sdelphij            ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1306296341Sdelphij            return 0;
1307296341Sdelphij        }
1308296341Sdelphij        new_buffer = 1;
1309296341Sdelphij    }
1310296341Sdelphij    if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
1311296341Sdelphij                            *out, buf_len, NULL)) {
1312296341Sdelphij        ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB);
1313296341Sdelphij        if (new_buffer) {
1314296341Sdelphij            OPENSSL_free(*out);
1315296341Sdelphij            *out = NULL;
1316296341Sdelphij        }
1317296341Sdelphij        return 0;
1318296341Sdelphij    }
1319296341Sdelphij    if (!new_buffer)
1320296341Sdelphij        *out += buf_len;
1321296341Sdelphij    return buf_len;
1322296341Sdelphij}
1323