1/* $OpenBSD: ec_asn1.c,v 1.53 2024/04/17 23:24:18 tb Exp $ */
2/*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 2000-2003 The OpenSSL Project.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in
17 *    the documentation and/or other materials provided with the
18 *    distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 *    software must display the following acknowledgment:
22 *    "This product includes software developed by the OpenSSL Project
23 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 *    endorse or promote products derived from this software without
27 *    prior written permission. For written permission, please contact
28 *    licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 *    nor may "OpenSSL" appear in their names without prior written
32 *    permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 *    acknowledgment:
36 *    "This product includes software developed by the OpenSSL Project
37 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com).  This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <string.h>
60
61#include <openssl/opensslconf.h>
62
63#include <openssl/err.h>
64#include <openssl/asn1t.h>
65#include <openssl/objects.h>
66
67#include "asn1_local.h"
68#include "ec_local.h"
69
70int
71EC_GROUP_get_basis_type(const EC_GROUP *group)
72{
73	return 0;
74}
75LCRYPTO_ALIAS(EC_GROUP_get_basis_type);
76
77typedef struct x9_62_pentanomial_st {
78	long k1;
79	long k2;
80	long k3;
81} X9_62_PENTANOMIAL;
82
83typedef struct x9_62_characteristic_two_st {
84	long m;
85	ASN1_OBJECT *type;
86	union {
87		char *ptr;
88		/* NID_X9_62_onBasis */
89		ASN1_NULL *onBasis;
90		/* NID_X9_62_tpBasis */
91		ASN1_INTEGER *tpBasis;
92		/* NID_X9_62_ppBasis */
93		X9_62_PENTANOMIAL *ppBasis;
94		/* anything else */
95		ASN1_TYPE *other;
96	} p;
97} X9_62_CHARACTERISTIC_TWO;
98
99typedef struct x9_62_fieldid_st {
100	ASN1_OBJECT *fieldType;
101	union {
102		char *ptr;
103		/* NID_X9_62_prime_field */
104		ASN1_INTEGER *prime;
105		/* NID_X9_62_characteristic_two_field */
106		X9_62_CHARACTERISTIC_TWO *char_two;
107		/* anything else */
108		ASN1_TYPE *other;
109	} p;
110} X9_62_FIELDID;
111
112typedef struct x9_62_curve_st {
113	ASN1_OCTET_STRING *a;
114	ASN1_OCTET_STRING *b;
115	ASN1_BIT_STRING *seed;
116} X9_62_CURVE;
117
118typedef struct ec_parameters_st {
119	long version;
120	X9_62_FIELDID *fieldID;
121	X9_62_CURVE *curve;
122	ASN1_OCTET_STRING *base;
123	ASN1_INTEGER *order;
124	ASN1_INTEGER *cofactor;
125} ECPARAMETERS;
126
127typedef struct ecpk_parameters_st {
128	int type;
129	union {
130		ASN1_OBJECT *named_curve;
131		ECPARAMETERS *parameters;
132		ASN1_NULL *implicitlyCA;
133	} value;
134} ECPKPARAMETERS;
135
136typedef struct ec_privatekey_st {
137	long version;
138	ASN1_OCTET_STRING *privateKey;
139	ECPKPARAMETERS *parameters;
140	ASN1_BIT_STRING *publicKey;
141} EC_PRIVATEKEY;
142
143static const ASN1_TEMPLATE X9_62_PENTANOMIAL_seq_tt[] = {
144	{
145		.flags = 0,
146		.tag = 0,
147		.offset = offsetof(X9_62_PENTANOMIAL, k1),
148		.field_name = "k1",
149		.item = &LONG_it,
150	},
151	{
152		.flags = 0,
153		.tag = 0,
154		.offset = offsetof(X9_62_PENTANOMIAL, k2),
155		.field_name = "k2",
156		.item = &LONG_it,
157	},
158	{
159		.flags = 0,
160		.tag = 0,
161		.offset = offsetof(X9_62_PENTANOMIAL, k3),
162		.field_name = "k3",
163		.item = &LONG_it,
164	},
165};
166
167static const ASN1_ITEM X9_62_PENTANOMIAL_it = {
168	.itype = ASN1_ITYPE_SEQUENCE,
169	.utype = V_ASN1_SEQUENCE,
170	.templates = X9_62_PENTANOMIAL_seq_tt,
171	.tcount = sizeof(X9_62_PENTANOMIAL_seq_tt) / sizeof(ASN1_TEMPLATE),
172	.funcs = NULL,
173	.size = sizeof(X9_62_PENTANOMIAL),
174	.sname = "X9_62_PENTANOMIAL",
175};
176
177static const ASN1_TEMPLATE char_two_def_tt = {
178	.flags = 0,
179	.tag = 0,
180	.offset = offsetof(X9_62_CHARACTERISTIC_TWO, p.other),
181	.field_name = "p.other",
182	.item = &ASN1_ANY_it,
183};
184
185static const ASN1_ADB_TABLE X9_62_CHARACTERISTIC_TWO_adbtbl[] = {
186	{
187		.value = NID_X9_62_onBasis,
188		.tt = {
189			.flags = 0,
190			.tag = 0,
191			.offset = offsetof(X9_62_CHARACTERISTIC_TWO, p.onBasis),
192			.field_name = "p.onBasis",
193			.item = &ASN1_NULL_it,
194		},
195	},
196	{
197		.value = NID_X9_62_tpBasis,
198		.tt = {
199			.flags = 0,
200			.tag = 0,
201			.offset = offsetof(X9_62_CHARACTERISTIC_TWO, p.tpBasis),
202			.field_name = "p.tpBasis",
203			.item = &ASN1_INTEGER_it,
204		},
205	},
206	{
207		.value = NID_X9_62_ppBasis,
208		.tt = {
209			.flags = 0,
210			.tag = 0,
211			.offset = offsetof(X9_62_CHARACTERISTIC_TWO, p.ppBasis),
212			.field_name = "p.ppBasis",
213			.item = &X9_62_PENTANOMIAL_it,
214		},
215
216	},
217};
218
219static const ASN1_ADB X9_62_CHARACTERISTIC_TWO_adb = {
220	.flags = 0,
221	.offset = offsetof(X9_62_CHARACTERISTIC_TWO, type),
222	.tbl = X9_62_CHARACTERISTIC_TWO_adbtbl,
223	.tblcount = sizeof(X9_62_CHARACTERISTIC_TWO_adbtbl) / sizeof(ASN1_ADB_TABLE),
224	.default_tt = &char_two_def_tt,
225	.null_tt = NULL,
226};
227
228static const ASN1_TEMPLATE X9_62_CHARACTERISTIC_TWO_seq_tt[] = {
229	{
230		.flags = 0,
231		.tag = 0,
232		.offset = offsetof(X9_62_CHARACTERISTIC_TWO, m),
233		.field_name = "m",
234		.item = &LONG_it,
235	},
236	{
237		.flags = 0,
238		.tag = 0,
239		.offset = offsetof(X9_62_CHARACTERISTIC_TWO, type),
240		.field_name = "type",
241		.item = &ASN1_OBJECT_it,
242	},
243	{
244		.flags = ASN1_TFLG_ADB_OID,
245		.tag = -1,
246		.offset = 0,
247		.field_name = "X9_62_CHARACTERISTIC_TWO",
248		.item = (const ASN1_ITEM *)&X9_62_CHARACTERISTIC_TWO_adb,
249	},
250};
251
252static const ASN1_ITEM X9_62_CHARACTERISTIC_TWO_it = {
253	.itype = ASN1_ITYPE_SEQUENCE,
254	.utype = V_ASN1_SEQUENCE,
255	.templates = X9_62_CHARACTERISTIC_TWO_seq_tt,
256	.tcount = sizeof(X9_62_CHARACTERISTIC_TWO_seq_tt) / sizeof(ASN1_TEMPLATE),
257	.funcs = NULL,
258	.size = sizeof(X9_62_CHARACTERISTIC_TWO),
259	.sname = "X9_62_CHARACTERISTIC_TWO",
260};
261
262static const ASN1_TEMPLATE fieldID_def_tt = {
263	.flags = 0,
264	.tag = 0,
265	.offset = offsetof(X9_62_FIELDID, p.other),
266	.field_name = "p.other",
267	.item = &ASN1_ANY_it,
268};
269
270static const ASN1_ADB_TABLE X9_62_FIELDID_adbtbl[] = {
271	{
272		.value = NID_X9_62_prime_field,
273		.tt = {
274			.flags = 0,
275			.tag = 0,
276			.offset = offsetof(X9_62_FIELDID, p.prime),
277			.field_name = "p.prime",
278			.item = &ASN1_INTEGER_it,
279		},
280	},
281	{
282		.value = NID_X9_62_characteristic_two_field,
283		.tt = {
284			.flags = 0,
285			.tag = 0,
286			.offset = offsetof(X9_62_FIELDID, p.char_two),
287			.field_name = "p.char_two",
288			.item = &X9_62_CHARACTERISTIC_TWO_it,
289		},
290	},
291};
292
293static const ASN1_ADB X9_62_FIELDID_adb = {
294	.flags = 0,
295	.offset = offsetof(X9_62_FIELDID, fieldType),
296	.tbl = X9_62_FIELDID_adbtbl,
297	.tblcount = sizeof(X9_62_FIELDID_adbtbl) / sizeof(ASN1_ADB_TABLE),
298	.default_tt = &fieldID_def_tt,
299	.null_tt = NULL,
300};
301
302static const ASN1_TEMPLATE X9_62_FIELDID_seq_tt[] = {
303	{
304		.flags = 0,
305		.tag = 0,
306		.offset = offsetof(X9_62_FIELDID, fieldType),
307		.field_name = "fieldType",
308		.item = &ASN1_OBJECT_it,
309	},
310	{
311		.flags = ASN1_TFLG_ADB_OID,
312		.tag = -1,
313		.offset = 0,
314		.field_name = "X9_62_FIELDID",
315		.item = (const ASN1_ITEM *)&X9_62_FIELDID_adb,
316	},
317};
318
319static const ASN1_ITEM X9_62_FIELDID_it = {
320	.itype = ASN1_ITYPE_SEQUENCE,
321	.utype = V_ASN1_SEQUENCE,
322	.templates = X9_62_FIELDID_seq_tt,
323	.tcount = sizeof(X9_62_FIELDID_seq_tt) / sizeof(ASN1_TEMPLATE),
324	.funcs = NULL,
325	.size = sizeof(X9_62_FIELDID),
326	.sname = "X9_62_FIELDID",
327};
328
329static const ASN1_TEMPLATE X9_62_CURVE_seq_tt[] = {
330	{
331		.flags = 0,
332		.tag = 0,
333		.offset = offsetof(X9_62_CURVE, a),
334		.field_name = "a",
335		.item = &ASN1_OCTET_STRING_it,
336	},
337	{
338		.flags = 0,
339		.tag = 0,
340		.offset = offsetof(X9_62_CURVE, b),
341		.field_name = "b",
342		.item = &ASN1_OCTET_STRING_it,
343	},
344	{
345		.flags = ASN1_TFLG_OPTIONAL,
346		.tag = 0,
347		.offset = offsetof(X9_62_CURVE, seed),
348		.field_name = "seed",
349		.item = &ASN1_BIT_STRING_it,
350	},
351};
352
353static const ASN1_ITEM X9_62_CURVE_it = {
354	.itype = ASN1_ITYPE_SEQUENCE,
355	.utype = V_ASN1_SEQUENCE,
356	.templates = X9_62_CURVE_seq_tt,
357	.tcount = sizeof(X9_62_CURVE_seq_tt) / sizeof(ASN1_TEMPLATE),
358	.funcs = NULL,
359	.size = sizeof(X9_62_CURVE),
360	.sname = "X9_62_CURVE",
361};
362
363static const ASN1_TEMPLATE ECPARAMETERS_seq_tt[] = {
364	{
365		.flags = 0,
366		.tag = 0,
367		.offset = offsetof(ECPARAMETERS, version),
368		.field_name = "version",
369		.item = &LONG_it,
370	},
371	{
372		.flags = 0,
373		.tag = 0,
374		.offset = offsetof(ECPARAMETERS, fieldID),
375		.field_name = "fieldID",
376		.item = &X9_62_FIELDID_it,
377	},
378	{
379		.flags = 0,
380		.tag = 0,
381		.offset = offsetof(ECPARAMETERS, curve),
382		.field_name = "curve",
383		.item = &X9_62_CURVE_it,
384	},
385	{
386		.flags = 0,
387		.tag = 0,
388		.offset = offsetof(ECPARAMETERS, base),
389		.field_name = "base",
390		.item = &ASN1_OCTET_STRING_it,
391	},
392	{
393		.flags = 0,
394		.tag = 0,
395		.offset = offsetof(ECPARAMETERS, order),
396		.field_name = "order",
397		.item = &ASN1_INTEGER_it,
398	},
399	{
400		.flags = ASN1_TFLG_OPTIONAL,
401		.tag = 0,
402		.offset = offsetof(ECPARAMETERS, cofactor),
403		.field_name = "cofactor",
404		.item = &ASN1_INTEGER_it,
405	},
406};
407
408const ASN1_ITEM ECPARAMETERS_it = {
409	.itype = ASN1_ITYPE_SEQUENCE,
410	.utype = V_ASN1_SEQUENCE,
411	.templates = ECPARAMETERS_seq_tt,
412	.tcount = sizeof(ECPARAMETERS_seq_tt) / sizeof(ASN1_TEMPLATE),
413	.funcs = NULL,
414	.size = sizeof(ECPARAMETERS),
415	.sname = "ECPARAMETERS",
416};
417
418static ECPARAMETERS *
419ECPARAMETERS_new(void)
420{
421	return (ECPARAMETERS*)ASN1_item_new(&ECPARAMETERS_it);
422}
423
424static void
425ECPARAMETERS_free(ECPARAMETERS *a)
426{
427	ASN1_item_free((ASN1_VALUE *)a, &ECPARAMETERS_it);
428}
429
430static const ASN1_TEMPLATE ECPKPARAMETERS_ch_tt[] = {
431	{
432		.flags = 0,
433		.tag = 0,
434		.offset = offsetof(ECPKPARAMETERS, value.named_curve),
435		.field_name = "value.named_curve",
436		.item = &ASN1_OBJECT_it,
437	},
438	{
439		.flags = 0,
440		.tag = 0,
441		.offset = offsetof(ECPKPARAMETERS, value.parameters),
442		.field_name = "value.parameters",
443		.item = &ECPARAMETERS_it,
444	},
445	{
446		.flags = 0,
447		.tag = 0,
448		.offset = offsetof(ECPKPARAMETERS, value.implicitlyCA),
449		.field_name = "value.implicitlyCA",
450		.item = &ASN1_NULL_it,
451	},
452};
453
454const ASN1_ITEM ECPKPARAMETERS_it = {
455	.itype = ASN1_ITYPE_CHOICE,
456	.utype = offsetof(ECPKPARAMETERS, type),
457	.templates = ECPKPARAMETERS_ch_tt,
458	.tcount = sizeof(ECPKPARAMETERS_ch_tt) / sizeof(ASN1_TEMPLATE),
459	.funcs = NULL,
460	.size = sizeof(ECPKPARAMETERS),
461	.sname = "ECPKPARAMETERS",
462};
463
464static ECPKPARAMETERS *
465d2i_ECPKPARAMETERS(ECPKPARAMETERS **a, const unsigned char **in, long len)
466{
467	return (ECPKPARAMETERS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
468	    &ECPKPARAMETERS_it);
469}
470
471static int
472i2d_ECPKPARAMETERS(const ECPKPARAMETERS *a, unsigned char **out)
473{
474	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ECPKPARAMETERS_it);
475}
476
477static ECPKPARAMETERS *
478ECPKPARAMETERS_new(void)
479{
480	return (ECPKPARAMETERS *)ASN1_item_new(&ECPKPARAMETERS_it);
481}
482
483static void
484ECPKPARAMETERS_free(ECPKPARAMETERS *a)
485{
486	ASN1_item_free((ASN1_VALUE *)a, &ECPKPARAMETERS_it);
487}
488
489static const ASN1_TEMPLATE EC_PRIVATEKEY_seq_tt[] = {
490	{
491		.flags = 0,
492		.tag = 0,
493		.offset = offsetof(EC_PRIVATEKEY, version),
494		.field_name = "version",
495		.item = &LONG_it,
496	},
497	{
498		.flags = 0,
499		.tag = 0,
500		.offset = offsetof(EC_PRIVATEKEY, privateKey),
501		.field_name = "privateKey",
502		.item = &ASN1_OCTET_STRING_it,
503	},
504	{
505		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
506		.tag = 0,
507		.offset = offsetof(EC_PRIVATEKEY, parameters),
508		.field_name = "parameters",
509		.item = &ECPKPARAMETERS_it,
510	},
511	{
512		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
513		.tag = 1,
514		.offset = offsetof(EC_PRIVATEKEY, publicKey),
515		.field_name = "publicKey",
516		.item = &ASN1_BIT_STRING_it,
517	},
518};
519
520static const ASN1_ITEM EC_PRIVATEKEY_it = {
521	.itype = ASN1_ITYPE_SEQUENCE,
522	.utype = V_ASN1_SEQUENCE,
523	.templates = EC_PRIVATEKEY_seq_tt,
524	.tcount = sizeof(EC_PRIVATEKEY_seq_tt) / sizeof(ASN1_TEMPLATE),
525	.funcs = NULL,
526	.size = sizeof(EC_PRIVATEKEY),
527	.sname = "EC_PRIVATEKEY",
528};
529
530static EC_PRIVATEKEY *
531d2i_EC_PRIVATEKEY(EC_PRIVATEKEY **a, const unsigned char **in, long len)
532{
533	return (EC_PRIVATEKEY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
534	    &EC_PRIVATEKEY_it);
535}
536
537static int
538i2d_EC_PRIVATEKEY(const EC_PRIVATEKEY *a, unsigned char **out)
539{
540	return ASN1_item_i2d((ASN1_VALUE *)a, out, &EC_PRIVATEKEY_it);
541}
542
543static EC_PRIVATEKEY *
544EC_PRIVATEKEY_new(void)
545{
546	return (EC_PRIVATEKEY *)ASN1_item_new(&EC_PRIVATEKEY_it);
547}
548
549static void
550EC_PRIVATEKEY_free(EC_PRIVATEKEY *a)
551{
552	ASN1_item_free((ASN1_VALUE *)a, &EC_PRIVATEKEY_it);
553}
554
555static int
556ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
557{
558	int ok = 0, nid;
559	BIGNUM *tmp = NULL;
560
561	if (group == NULL || field == NULL)
562		return 0;
563
564	/* clear the old values (if necessary) */
565	if (field->fieldType != NULL)
566		ASN1_OBJECT_free(field->fieldType);
567	if (field->p.other != NULL)
568		ASN1_TYPE_free(field->p.other);
569
570	nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
571	/* set OID for the field */
572	if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) {
573		ECerror(ERR_R_OBJ_LIB);
574		goto err;
575	}
576	if (nid == NID_X9_62_prime_field) {
577		if ((tmp = BN_new()) == NULL) {
578			ECerror(ERR_R_MALLOC_FAILURE);
579			goto err;
580		}
581		/* the parameters are specified by the prime number p */
582		if (!EC_GROUP_get_curve(group, tmp, NULL, NULL, NULL)) {
583			ECerror(ERR_R_EC_LIB);
584			goto err;
585		}
586		/* set the prime number */
587		field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL);
588		if (field->p.prime == NULL) {
589			ECerror(ERR_R_ASN1_LIB);
590			goto err;
591		}
592	} else {
593		ECerror(EC_R_GF2M_NOT_SUPPORTED);
594		goto err;
595	}
596
597	ok = 1;
598
599 err:
600	BN_free(tmp);
601	return (ok);
602}
603
604static int
605ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
606{
607	BIGNUM *tmp_1 = NULL, *tmp_2 = NULL;
608	unsigned char *buffer_1 = NULL, *buffer_2 = NULL, *a_buf = NULL,
609	*b_buf = NULL;
610	size_t len_1, len_2;
611	unsigned char char_zero = 0;
612	int ok = 0;
613
614	if (!group || !curve || !curve->a || !curve->b)
615		return 0;
616
617	if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) {
618		ECerror(ERR_R_MALLOC_FAILURE);
619		goto err;
620	}
621
622	/* get a and b */
623	if (!EC_GROUP_get_curve(group, NULL, tmp_1, tmp_2, NULL)) {
624		ECerror(ERR_R_EC_LIB);
625		goto err;
626	}
627	len_1 = (size_t) BN_num_bytes(tmp_1);
628	len_2 = (size_t) BN_num_bytes(tmp_2);
629
630	if (len_1 == 0) {
631		/* len_1 == 0 => a == 0 */
632		a_buf = &char_zero;
633		len_1 = 1;
634	} else {
635		if ((buffer_1 = malloc(len_1)) == NULL) {
636			ECerror(ERR_R_MALLOC_FAILURE);
637			goto err;
638		}
639		if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) {
640			ECerror(ERR_R_BN_LIB);
641			goto err;
642		}
643		a_buf = buffer_1;
644	}
645
646	if (len_2 == 0) {
647		/* len_2 == 0 => b == 0 */
648		b_buf = &char_zero;
649		len_2 = 1;
650	} else {
651		if ((buffer_2 = malloc(len_2)) == NULL) {
652			ECerror(ERR_R_MALLOC_FAILURE);
653			goto err;
654		}
655		if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) {
656			ECerror(ERR_R_BN_LIB);
657			goto err;
658		}
659		b_buf = buffer_2;
660	}
661
662	/* set a and b */
663	if (!ASN1_STRING_set(curve->a, a_buf, len_1) ||
664	    !ASN1_STRING_set(curve->b, b_buf, len_2)) {
665		ECerror(ERR_R_ASN1_LIB);
666		goto err;
667	}
668
669	ASN1_BIT_STRING_free(curve->seed);
670	curve->seed = NULL;
671
672	/* set the seed (optional) */
673	if (group->seed != NULL) {
674		if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) {
675			ECerror(ERR_R_MALLOC_FAILURE);
676			goto err;
677		}
678		if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
679			(int) group->seed_len)) {
680			ECerror(ERR_R_ASN1_LIB);
681			goto err;
682		}
683		if (!asn1_abs_set_unused_bits(curve->seed, 0)) {
684			ECerror(ERR_R_ASN1_LIB);
685			goto err;
686		}
687	}
688
689	ok = 1;
690
691 err:
692	free(buffer_1);
693	free(buffer_2);
694	BN_free(tmp_1);
695	BN_free(tmp_2);
696	return (ok);
697}
698
699static ECPARAMETERS *
700ec_asn1_group2parameters(const EC_GROUP *group, ECPARAMETERS *param)
701{
702	int ok = 0;
703	size_t len = 0;
704	ECPARAMETERS *ret = NULL;
705	BIGNUM *tmp = NULL;
706	unsigned char *buffer = NULL;
707	const EC_POINT *point = NULL;
708	point_conversion_form_t form;
709
710	if ((tmp = BN_new()) == NULL) {
711		ECerror(ERR_R_MALLOC_FAILURE);
712		goto err;
713	}
714	if (param == NULL) {
715		if ((ret = ECPARAMETERS_new()) == NULL) {
716			ECerror(ERR_R_MALLOC_FAILURE);
717			goto err;
718		}
719	} else
720		ret = param;
721
722	/* set the version (always one) */
723	ret->version = (long) 0x1;
724
725	/* set the fieldID */
726	if (!ec_asn1_group2fieldid(group, ret->fieldID)) {
727		ECerror(ERR_R_EC_LIB);
728		goto err;
729	}
730	/* set the curve */
731	if (!ec_asn1_group2curve(group, ret->curve)) {
732		ECerror(ERR_R_EC_LIB);
733		goto err;
734	}
735	/* set the base point */
736	if ((point = EC_GROUP_get0_generator(group)) == NULL) {
737		ECerror(EC_R_UNDEFINED_GENERATOR);
738		goto err;
739	}
740	form = EC_GROUP_get_point_conversion_form(group);
741
742	len = EC_POINT_point2oct(group, point, form, NULL, len, NULL);
743	if (len == 0) {
744		ECerror(ERR_R_EC_LIB);
745		goto err;
746	}
747	if ((buffer = malloc(len)) == NULL) {
748		ECerror(ERR_R_MALLOC_FAILURE);
749		goto err;
750	}
751	if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) {
752		ECerror(ERR_R_EC_LIB);
753		goto err;
754	}
755	if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) {
756		ECerror(ERR_R_MALLOC_FAILURE);
757		goto err;
758	}
759	if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) {
760		ECerror(ERR_R_ASN1_LIB);
761		goto err;
762	}
763	/* set the order */
764	if (!EC_GROUP_get_order(group, tmp, NULL)) {
765		ECerror(ERR_R_EC_LIB);
766		goto err;
767	}
768	ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
769	if (ret->order == NULL) {
770		ECerror(ERR_R_ASN1_LIB);
771		goto err;
772	}
773	/* set the cofactor (optional) */
774	if (EC_GROUP_get_cofactor(group, tmp, NULL)) {
775		ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
776		if (ret->cofactor == NULL) {
777			ECerror(ERR_R_ASN1_LIB);
778			goto err;
779		}
780	}
781	ok = 1;
782
783 err:
784	if (!ok) {
785		if (ret && !param)
786			ECPARAMETERS_free(ret);
787		ret = NULL;
788	}
789	BN_free(tmp);
790	free(buffer);
791	return (ret);
792}
793
794ECPKPARAMETERS *
795ec_asn1_group2pkparameters(const EC_GROUP *group, ECPKPARAMETERS *params)
796{
797	int ok = 1, tmp;
798	ECPKPARAMETERS *ret = params;
799
800	if (ret == NULL) {
801		if ((ret = ECPKPARAMETERS_new()) == NULL) {
802			ECerror(ERR_R_MALLOC_FAILURE);
803			return NULL;
804		}
805	} else {
806		if (ret->type == 0 && ret->value.named_curve)
807			ASN1_OBJECT_free(ret->value.named_curve);
808		else if (ret->type == 1 && ret->value.parameters)
809			ECPARAMETERS_free(ret->value.parameters);
810	}
811
812	if (EC_GROUP_get_asn1_flag(group)) {
813		/*
814		 * use the asn1 OID to describe the elliptic curve
815		 * parameters
816		 */
817		tmp = EC_GROUP_get_curve_name(group);
818		if (tmp) {
819			ret->type = 0;
820			if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL)
821				ok = 0;
822		} else
823			/* we don't know the group => ERROR */
824			ok = 0;
825	} else {
826		/* use the ECPARAMETERS structure */
827		ret->type = 1;
828		if ((ret->value.parameters = ec_asn1_group2parameters(group,
829		    NULL)) == NULL)
830			ok = 0;
831	}
832
833	if (!ok) {
834		ECPKPARAMETERS_free(ret);
835		return NULL;
836	}
837	return ret;
838}
839
840static EC_GROUP *
841ec_asn1_parameters2group(const ECPARAMETERS *params)
842{
843	int ok = 0, tmp;
844	EC_GROUP *ret = NULL;
845	BIGNUM *p = NULL, *a = NULL, *b = NULL;
846	EC_POINT *point = NULL;
847	long field_bits;
848
849	if (!params->fieldID || !params->fieldID->fieldType ||
850	    !params->fieldID->p.ptr) {
851		ECerror(EC_R_ASN1_ERROR);
852		goto err;
853	}
854	/* now extract the curve parameters a and b */
855	if (!params->curve || !params->curve->a ||
856	    !params->curve->a->data || !params->curve->b ||
857	    !params->curve->b->data) {
858		ECerror(EC_R_ASN1_ERROR);
859		goto err;
860	}
861	a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
862	if (a == NULL) {
863		ECerror(ERR_R_BN_LIB);
864		goto err;
865	}
866	b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
867	if (b == NULL) {
868		ECerror(ERR_R_BN_LIB);
869		goto err;
870	}
871	/* get the field parameters */
872	tmp = OBJ_obj2nid(params->fieldID->fieldType);
873	if (tmp == NID_X9_62_characteristic_two_field) {
874		ECerror(EC_R_GF2M_NOT_SUPPORTED);
875		goto err;
876	} else if (tmp == NID_X9_62_prime_field) {
877		/* we have a curve over a prime field */
878		/* extract the prime number */
879		if (!params->fieldID->p.prime) {
880			ECerror(EC_R_ASN1_ERROR);
881			goto err;
882		}
883		p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
884		if (p == NULL) {
885			ECerror(ERR_R_ASN1_LIB);
886			goto err;
887		}
888		if (BN_is_negative(p) || BN_is_zero(p)) {
889			ECerror(EC_R_INVALID_FIELD);
890			goto err;
891		}
892		field_bits = BN_num_bits(p);
893		if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
894			ECerror(EC_R_FIELD_TOO_LARGE);
895			goto err;
896		}
897		/* create the EC_GROUP structure */
898		ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
899	} else {
900		ECerror(EC_R_INVALID_FIELD);
901		goto err;
902	}
903
904	if (ret == NULL) {
905		ECerror(ERR_R_EC_LIB);
906		goto err;
907	}
908	/* extract seed (optional) */
909	if (params->curve->seed != NULL) {
910		free(ret->seed);
911		if (!(ret->seed = malloc(params->curve->seed->length))) {
912			ECerror(ERR_R_MALLOC_FAILURE);
913			goto err;
914		}
915		memcpy(ret->seed, params->curve->seed->data,
916		    params->curve->seed->length);
917		ret->seed_len = params->curve->seed->length;
918	}
919	if (!params->order || !params->base || !params->base->data) {
920		ECerror(EC_R_ASN1_ERROR);
921		goto err;
922	}
923	if ((point = EC_POINT_new(ret)) == NULL)
924		goto err;
925
926	/* set the point conversion form */
927	EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
928	    (params->base->data[0] & ~0x01));
929
930	/* extract the ec point */
931	if (!EC_POINT_oct2point(ret, point, params->base->data,
932		params->base->length, NULL)) {
933		ECerror(ERR_R_EC_LIB);
934		goto err;
935	}
936	/* extract the order */
937	if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) {
938		ECerror(ERR_R_ASN1_LIB);
939		goto err;
940	}
941	if (BN_is_negative(a) || BN_is_zero(a)) {
942		ECerror(EC_R_INVALID_GROUP_ORDER);
943		goto err;
944	}
945	if (BN_num_bits(a) > (int) field_bits + 1) {	/* Hasse bound */
946		ECerror(EC_R_INVALID_GROUP_ORDER);
947		goto err;
948	}
949	/* extract the cofactor (optional) */
950	if (params->cofactor == NULL) {
951		BN_free(b);
952		b = NULL;
953	} else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) {
954		ECerror(ERR_R_ASN1_LIB);
955		goto err;
956	}
957	/* set the generator, order and cofactor (if present) */
958	if (!EC_GROUP_set_generator(ret, point, a, b)) {
959		ECerror(ERR_R_EC_LIB);
960		goto err;
961	}
962	ok = 1;
963
964 err:
965	if (!ok) {
966		EC_GROUP_free(ret);
967		ret = NULL;
968	}
969	BN_free(p);
970	BN_free(a);
971	BN_free(b);
972	EC_POINT_free(point);
973	return (ret);
974}
975
976EC_GROUP *
977ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
978{
979	EC_GROUP *ret = NULL;
980	int tmp = 0;
981
982	if (params == NULL) {
983		ECerror(EC_R_MISSING_PARAMETERS);
984		return NULL;
985	}
986	if (params->type == 0) {/* the curve is given by an OID */
987		tmp = OBJ_obj2nid(params->value.named_curve);
988		if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) {
989			ECerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
990			return NULL;
991		}
992		EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
993	} else if (params->type == 1) {	/* the parameters are given by a
994					 * ECPARAMETERS structure */
995		ret = ec_asn1_parameters2group(params->value.parameters);
996		if (!ret) {
997			ECerror(ERR_R_EC_LIB);
998			return NULL;
999		}
1000		EC_GROUP_set_asn1_flag(ret, 0x0);
1001	} else if (params->type == 2) {	/* implicitlyCA */
1002		return NULL;
1003	} else {
1004		ECerror(EC_R_ASN1_ERROR);
1005		return NULL;
1006	}
1007
1008	return ret;
1009}
1010
1011EC_GROUP *
1012d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
1013{
1014	EC_GROUP *group = NULL;
1015	ECPKPARAMETERS *params;
1016
1017	if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) {
1018		ECerror(EC_R_D2I_ECPKPARAMETERS_FAILURE);
1019		goto err;
1020	}
1021	if ((group = ec_asn1_pkparameters2group(params)) == NULL) {
1022		ECerror(EC_R_PKPARAMETERS2GROUP_FAILURE);
1023		goto err;
1024	}
1025
1026	if (a != NULL) {
1027		EC_GROUP_free(*a);
1028		*a = group;
1029	}
1030
1031 err:
1032	ECPKPARAMETERS_free(params);
1033	return (group);
1034}
1035LCRYPTO_ALIAS(d2i_ECPKParameters);
1036
1037int
1038i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
1039{
1040	int ret = 0;
1041	ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL);
1042	if (tmp == NULL) {
1043		ECerror(EC_R_GROUP2PKPARAMETERS_FAILURE);
1044		return 0;
1045	}
1046	if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) {
1047		ECerror(EC_R_I2D_ECPKPARAMETERS_FAILURE);
1048		ECPKPARAMETERS_free(tmp);
1049		return 0;
1050	}
1051	ECPKPARAMETERS_free(tmp);
1052	return (ret);
1053}
1054LCRYPTO_ALIAS(i2d_ECPKParameters);
1055
1056EC_KEY *
1057d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
1058{
1059	EC_KEY *ret = NULL;
1060	EC_PRIVATEKEY *priv_key = NULL;
1061
1062	if ((priv_key = d2i_EC_PRIVATEKEY(NULL, in, len)) == NULL) {
1063		ECerror(ERR_R_EC_LIB);
1064		return NULL;
1065	}
1066	if (a == NULL || *a == NULL) {
1067		if ((ret = EC_KEY_new()) == NULL) {
1068			ECerror(ERR_R_MALLOC_FAILURE);
1069			goto err;
1070		}
1071	} else
1072		ret = *a;
1073
1074	if (priv_key->parameters) {
1075		EC_GROUP_free(ret->group);
1076		ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
1077	}
1078	if (ret->group == NULL) {
1079		ECerror(ERR_R_EC_LIB);
1080		goto err;
1081	}
1082	ret->version = priv_key->version;
1083
1084	if (priv_key->privateKey) {
1085		ret->priv_key = BN_bin2bn(
1086		    ASN1_STRING_data(priv_key->privateKey),
1087		    ASN1_STRING_length(priv_key->privateKey),
1088		    ret->priv_key);
1089		if (ret->priv_key == NULL) {
1090			ECerror(ERR_R_BN_LIB);
1091			goto err;
1092		}
1093	} else {
1094		ECerror(EC_R_MISSING_PRIVATE_KEY);
1095		goto err;
1096	}
1097
1098	if (ret->pub_key)
1099		EC_POINT_free(ret->pub_key);
1100	ret->pub_key = EC_POINT_new(ret->group);
1101	if (ret->pub_key == NULL) {
1102		ECerror(ERR_R_EC_LIB);
1103		goto err;
1104	}
1105
1106	if (priv_key->publicKey) {
1107		const unsigned char *pub_oct;
1108		size_t pub_oct_len;
1109
1110		pub_oct = ASN1_STRING_data(priv_key->publicKey);
1111		pub_oct_len = ASN1_STRING_length(priv_key->publicKey);
1112		if (pub_oct == NULL || pub_oct_len <= 0) {
1113			ECerror(EC_R_BUFFER_TOO_SMALL);
1114			goto err;
1115		}
1116
1117		/* save the point conversion form */
1118		ret->conv_form = (point_conversion_form_t) (pub_oct[0] & ~0x01);
1119		if (!EC_POINT_oct2point(ret->group, ret->pub_key,
1120			pub_oct, pub_oct_len, NULL)) {
1121			ECerror(ERR_R_EC_LIB);
1122			goto err;
1123		}
1124	} else {
1125		if (!EC_POINT_mul(ret->group, ret->pub_key, ret->priv_key,
1126			NULL, NULL, NULL)) {
1127			ECerror(ERR_R_EC_LIB);
1128			goto err;
1129		}
1130		/* Remember the original private-key-only encoding. */
1131		ret->enc_flag |= EC_PKEY_NO_PUBKEY;
1132	}
1133
1134	EC_PRIVATEKEY_free(priv_key);
1135	if (a != NULL)
1136		*a = ret;
1137	return (ret);
1138
1139 err:
1140	if (a == NULL || *a != ret)
1141		EC_KEY_free(ret);
1142	if (priv_key)
1143		EC_PRIVATEKEY_free(priv_key);
1144
1145	return (NULL);
1146}
1147LCRYPTO_ALIAS(d2i_ECPrivateKey);
1148
1149int
1150i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
1151{
1152	int ret = 0, ok = 0;
1153	unsigned char *buffer = NULL;
1154	size_t buf_len = 0, tmp_len;
1155	EC_PRIVATEKEY *priv_key = NULL;
1156
1157	if (a == NULL || a->group == NULL || a->priv_key == NULL ||
1158	    (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) {
1159		ECerror(ERR_R_PASSED_NULL_PARAMETER);
1160		goto err;
1161	}
1162	if ((priv_key = EC_PRIVATEKEY_new()) == NULL) {
1163		ECerror(ERR_R_MALLOC_FAILURE);
1164		goto err;
1165	}
1166	priv_key->version = a->version;
1167
1168	buf_len = (size_t) BN_num_bytes(a->priv_key);
1169	buffer = malloc(buf_len);
1170	if (buffer == NULL) {
1171		ECerror(ERR_R_MALLOC_FAILURE);
1172		goto err;
1173	}
1174	if (!BN_bn2bin(a->priv_key, buffer)) {
1175		ECerror(ERR_R_BN_LIB);
1176		goto err;
1177	}
1178	if (!ASN1_STRING_set(priv_key->privateKey, buffer, buf_len)) {
1179		ECerror(ERR_R_ASN1_LIB);
1180		goto err;
1181	}
1182	if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) {
1183		if ((priv_key->parameters = ec_asn1_group2pkparameters(
1184			    a->group, priv_key->parameters)) == NULL) {
1185			ECerror(ERR_R_EC_LIB);
1186			goto err;
1187		}
1188	}
1189	if (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key != NULL) {
1190		priv_key->publicKey = ASN1_BIT_STRING_new();
1191		if (priv_key->publicKey == NULL) {
1192			ECerror(ERR_R_MALLOC_FAILURE);
1193			goto err;
1194		}
1195		tmp_len = EC_POINT_point2oct(a->group, a->pub_key,
1196		    a->conv_form, NULL, 0, NULL);
1197
1198		if (tmp_len > buf_len) {
1199			unsigned char *tmp_buffer = realloc(buffer, tmp_len);
1200			if (!tmp_buffer) {
1201				ECerror(ERR_R_MALLOC_FAILURE);
1202				goto err;
1203			}
1204			buffer = tmp_buffer;
1205			buf_len = tmp_len;
1206		}
1207		if (!EC_POINT_point2oct(a->group, a->pub_key,
1208			a->conv_form, buffer, buf_len, NULL)) {
1209			ECerror(ERR_R_EC_LIB);
1210			goto err;
1211		}
1212		if (!ASN1_STRING_set(priv_key->publicKey, buffer, buf_len)) {
1213			ECerror(ERR_R_ASN1_LIB);
1214			goto err;
1215		}
1216		if (!asn1_abs_set_unused_bits(priv_key->publicKey, 0)) {
1217			ECerror(ERR_R_ASN1_LIB);
1218			goto err;
1219		}
1220	}
1221	if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) {
1222		ECerror(ERR_R_EC_LIB);
1223		goto err;
1224	}
1225	ok = 1;
1226 err:
1227	free(buffer);
1228	if (priv_key)
1229		EC_PRIVATEKEY_free(priv_key);
1230	return (ok ? ret : 0);
1231}
1232LCRYPTO_ALIAS(i2d_ECPrivateKey);
1233
1234int
1235i2d_ECParameters(EC_KEY *a, unsigned char **out)
1236{
1237	if (a == NULL) {
1238		ECerror(ERR_R_PASSED_NULL_PARAMETER);
1239		return 0;
1240	}
1241	return i2d_ECPKParameters(a->group, out);
1242}
1243LCRYPTO_ALIAS(i2d_ECParameters);
1244
1245EC_KEY *
1246d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
1247{
1248	EC_KEY *ret;
1249
1250	if (in == NULL || *in == NULL) {
1251		ECerror(ERR_R_PASSED_NULL_PARAMETER);
1252		return NULL;
1253	}
1254	if (a == NULL || *a == NULL) {
1255		if ((ret = EC_KEY_new()) == NULL) {
1256			ECerror(ERR_R_MALLOC_FAILURE);
1257			return NULL;
1258		}
1259	} else
1260		ret = *a;
1261
1262	if (!d2i_ECPKParameters(&ret->group, in, len)) {
1263		ECerror(ERR_R_EC_LIB);
1264		if (a == NULL || *a != ret)
1265			EC_KEY_free(ret);
1266		return NULL;
1267	}
1268
1269	if (a != NULL)
1270		*a = ret;
1271	return ret;
1272}
1273LCRYPTO_ALIAS(d2i_ECParameters);
1274
1275EC_KEY *
1276o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
1277{
1278	EC_KEY *ret = NULL;
1279
1280	if (a == NULL || (*a) == NULL || (*a)->group == NULL) {
1281		/* An EC_GROUP structure is necessary to set the public key. */
1282		ECerror(ERR_R_PASSED_NULL_PARAMETER);
1283		return 0;
1284	}
1285	ret = *a;
1286	if (ret->pub_key == NULL &&
1287	    (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
1288		ECerror(ERR_R_MALLOC_FAILURE);
1289		return 0;
1290	}
1291	if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) {
1292		ECerror(ERR_R_EC_LIB);
1293		return 0;
1294	}
1295	/* save the point conversion form */
1296	ret->conv_form = (point_conversion_form_t) (*in[0] & ~0x01);
1297	*in += len;
1298	return ret;
1299}
1300LCRYPTO_ALIAS(o2i_ECPublicKey);
1301
1302int
1303i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
1304{
1305	size_t buf_len = 0;
1306	int new_buffer = 0;
1307
1308	if (a == NULL) {
1309		ECerror(ERR_R_PASSED_NULL_PARAMETER);
1310		return 0;
1311	}
1312	buf_len = EC_POINT_point2oct(a->group, a->pub_key,
1313	    a->conv_form, NULL, 0, NULL);
1314
1315	if (out == NULL || buf_len == 0)
1316		/* out == NULL => just return the length of the octet string */
1317		return buf_len;
1318
1319	if (*out == NULL) {
1320		if ((*out = malloc(buf_len)) == NULL) {
1321			ECerror(ERR_R_MALLOC_FAILURE);
1322			return 0;
1323		}
1324		new_buffer = 1;
1325	}
1326	if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
1327		*out, buf_len, NULL)) {
1328		ECerror(ERR_R_EC_LIB);
1329		if (new_buffer) {
1330			free(*out);
1331			*out = NULL;
1332		}
1333		return 0;
1334	}
1335	if (!new_buffer)
1336		*out += buf_len;
1337	return buf_len;
1338}
1339LCRYPTO_ALIAS(i2o_ECPublicKey);
1340