1904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * project 2006.
3904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom */
4904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom/* ====================================================================
5904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
6904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
7904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * Redistribution and use in source and binary forms, with or without
8904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * modification, are permitted provided that the following conditions
9904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * are met:
10904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
11904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * 1. Redistributions of source code must retain the above copyright
12904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    notice, this list of conditions and the following disclaimer.
13904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
14904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * 2. Redistributions in binary form must reproduce the above copyright
15904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    notice, this list of conditions and the following disclaimer in
16904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    the documentation and/or other materials provided with the
17904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    distribution.
18904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
19904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * 3. All advertising materials mentioning features or use of this
20904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    software must display the following acknowledgment:
21904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
22904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
24904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    endorse or promote products derived from this software without
26904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    prior written permission. For written permission, please contact
27904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    licensing@OpenSSL.org.
28904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
29904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * 5. Products derived from this software may not be called "OpenSSL"
30904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    nor may "OpenSSL" appear in their names without prior written
31904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    permission of the OpenSSL Project.
32904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
33904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * 6. Redistributions of any form whatsoever must retain the following
34904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    acknowledgment:
35904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
36904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
38904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * OF THE POSSIBILITY OF SUCH DAMAGE.
50904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * ====================================================================
51904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
52904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * This product includes cryptographic software written by Eric Young
53904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * (eay@cryptsoft.com).  This product includes software written by Tim
54904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom * Hudson (tjh@cryptsoft.com).
55904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom *
56904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom */
57904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
58904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#include <stdio.h>
59904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#include "cryptlib.h"
60904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#include <openssl/x509.h>
61904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#include <openssl/ec.h>
62904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#include <openssl/bn.h>
63904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#ifndef OPENSSL_NO_CMS
64904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#include <openssl/cms.h>
65904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#endif
66904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#include "asn1_locl.h"
67904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
68904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
69904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
70904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const EC_GROUP  *group;
71904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int nid;
72904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL)
73904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
74904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
75904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
76904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
77904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (EC_GROUP_get_asn1_flag(group)
78904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom                     && (nid = EC_GROUP_get_curve_name(group)))
79904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		/* we have a 'named curve' => just set the OID */
80904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
81904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		*ppval = OBJ_nid2obj(nid);
82904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		*pptype = V_ASN1_OBJECT;
83904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
84904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	else	/* explicit parameters */
85904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
86904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ASN1_STRING *pstr = NULL;
87904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		pstr = ASN1_STRING_new();
88904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (!pstr)
89904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			return 0;
90904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		pstr->length = i2d_ECParameters(ec_key, &pstr->data);
91904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (pstr->length < 0)
92904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
93904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			ASN1_STRING_free(pstr);
94904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
95904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			return 0;
96904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
97904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		*ppval = pstr;
98904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		*pptype = V_ASN1_SEQUENCE;
99904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
100904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 1;
101904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
102904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
103904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
104904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
105904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY *ec_key = pkey->pkey.ec;
106904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	void *pval = NULL;
107904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int ptype;
108904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	unsigned char *penc = NULL, *p;
109904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int penclen;
110904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
111904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!eckey_param2type(&ptype, &pval, ec_key))
112904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
113904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
114904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
115904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
116904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	penclen = i2o_ECPublicKey(ec_key, NULL);
117904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (penclen <= 0)
118904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
119904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	penc = OPENSSL_malloc(penclen);
120904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!penc)
121904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
122904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	p = penc;
123904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	penclen = i2o_ECPublicKey(ec_key, &p);
124904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (penclen <= 0)
125904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
126904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
127904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom				ptype, pval, penc, penclen))
128904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 1;
129904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	err:
130904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (ptype == V_ASN1_OBJECT)
131904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ASN1_OBJECT_free(pval);
132904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	else
133904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ASN1_STRING_free(pval);
134904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (penc)
135904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		OPENSSL_free(penc);
136904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 0;
137904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
138904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
139904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic EC_KEY *eckey_type2param(int ptype, void *pval)
140904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
141904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY *eckey = NULL;
142904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (ptype == V_ASN1_SEQUENCE)
143904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
144904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ASN1_STRING *pstr = pval;
145904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		const unsigned char *pm = NULL;
146904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		int pmlen;
147904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		pm = pstr->data;
148904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		pmlen = pstr->length;
149904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen)))
150904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
151904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
152904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto ecerr;
153904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
154904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
155904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	else if (ptype == V_ASN1_OBJECT)
156904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
157904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ASN1_OBJECT *poid = pval;
158904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_GROUP *group;
159904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
160904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		/* type == V_ASN1_OBJECT => the parameters are given
161904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		 * by an asn1 OID
162904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		 */
163904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if ((eckey = EC_KEY_new()) == NULL)
164904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
165904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
166904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto ecerr;
167904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
168904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
169904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (group == NULL)
170904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto ecerr;
171904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
172904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (EC_KEY_set_group(eckey, group) == 0)
173904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto ecerr;
174904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_GROUP_free(group);
175904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
176904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	else
177904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
178904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
179904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto ecerr;
180904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
181904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
182904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return eckey;
183904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
184904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ecerr:
185904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (eckey)
186904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_KEY_free(eckey);
187904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return NULL;
188904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
189904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
190904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
191904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
192904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const unsigned char *p = NULL;
193904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	void *pval;
194904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int ptype, pklen;
195904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY *eckey = NULL;
196904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	X509_ALGOR *palg;
197904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
198904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
199904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
200904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	X509_ALGOR_get0(NULL, &ptype, &pval, palg);
201904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
202904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey = eckey_type2param(ptype, pval);
203904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
204904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!eckey)
205904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
206904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
207904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
208904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
209904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
210904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	/* We have parameters now set public key */
211904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!o2i_ECPublicKey(&eckey, &p, pklen))
212904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
213904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
214904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto ecerr;
215904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
216904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
217904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EVP_PKEY_assign_EC_KEY(pkey, eckey);
218904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 1;
219904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
220904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ecerr:
221904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (eckey)
222904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_KEY_free(eckey);
223904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 0;
224904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
225904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
226904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
227904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
228904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int  r;
229904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
230904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
231904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	               *pb = EC_KEY_get0_public_key(b->pkey.ec);
232904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	r = EC_POINT_cmp(group, pa, pb, NULL);
233904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (r == 0)
234904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 1;
235904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (r == 1)
236904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
237904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return -2;
238904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
239904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
240904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
241904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
242904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const unsigned char *p = NULL;
243904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	void *pval;
244904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int ptype, pklen;
245904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY *eckey = NULL;
246904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	X509_ALGOR *palg;
247904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
248904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
249904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
250904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	X509_ALGOR_get0(NULL, &ptype, &pval, palg);
251904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
252904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey = eckey_type2param(ptype, pval);
253904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
254904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!eckey)
255904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto ecliberr;
256904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
257904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	/* We have parameters now set private key */
258904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!d2i_ECPrivateKey(&eckey, &p, pklen))
259904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
260904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
261904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto ecerr;
262904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
263904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
264904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	/* calculate public key (if necessary) */
265904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (EC_KEY_get0_public_key(eckey) == NULL)
266904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
267904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		const BIGNUM *priv_key;
268904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		const EC_GROUP *group;
269904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_POINT *pub_key;
270904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		/* the public key was not included in the SEC1 private
271904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		 * key => calculate the public key */
272904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		group   = EC_KEY_get0_group(eckey);
273904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		pub_key = EC_POINT_new(group);
274904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (pub_key == NULL)
275904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
276904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
277904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto ecliberr;
278904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
279904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group)))
280904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
281904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			EC_POINT_free(pub_key);
282904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
283904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto ecliberr;
284904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
285904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		priv_key = EC_KEY_get0_private_key(eckey);
286904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL))
287904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
288904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			EC_POINT_free(pub_key);
289904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
290904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto ecliberr;
291904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
292904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (EC_KEY_set_public_key(eckey, pub_key) == 0)
293904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
294904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			EC_POINT_free(pub_key);
295904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
296904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto ecliberr;
297904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
298904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_POINT_free(pub_key);
299904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
300904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
301904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EVP_PKEY_assign_EC_KEY(pkey, eckey);
302904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 1;
303904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
304904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ecliberr:
305904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
306904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ecerr:
307904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (eckey)
308904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_KEY_free(eckey);
309904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 0;
310904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
311904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
312904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
313904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom{
314904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY		*ec_key;
315904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	unsigned char	*ep, *p;
316904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int 		eplen, ptype;
317904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	void		*pval;
318904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	unsigned int    tmp_flags, old_flags;
319904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
320904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ec_key = pkey->pkey.ec;
321904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
322904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!eckey_param2type(&ptype, &pval, ec_key))
323904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
324904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
325904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
326904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
327904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
328904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	/* set the private key */
329904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
330904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	/* do not include the parameters in the SEC1 private key
331904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	 * see PKCS#11 12.11 */
332904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	old_flags = EC_KEY_get_enc_flags(ec_key);
333904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
334904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY_set_enc_flags(ec_key, tmp_flags);
335904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eplen = i2d_ECPrivateKey(ec_key, NULL);
336904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!eplen)
337904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
338904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_KEY_set_enc_flags(ec_key, old_flags);
339904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
340904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
341904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
342904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ep = (unsigned char *) OPENSSL_malloc(eplen);
343904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!ep)
344904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
345904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_KEY_set_enc_flags(ec_key, old_flags);
346904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
347904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
348904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
349904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	p = ep;
350904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!i2d_ECPrivateKey(ec_key, &p))
351904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
352904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		EC_KEY_set_enc_flags(ec_key, old_flags);
353904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		OPENSSL_free(ep);
354904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
355904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
356904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	/* restore old encoding flags */
357904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY_set_enc_flags(ec_key, old_flags);
358904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
359904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
360904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom				ptype, pval, ep, eplen))
361904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
362904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
363904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 1;
364904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom}
365904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
366904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int int_ec_size(const EVP_PKEY *pkey)
367904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
368904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return ECDSA_size(pkey->pkey.ec);
369904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
370904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
371904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int ec_bits(const EVP_PKEY *pkey)
372904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
373904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	BIGNUM *order = BN_new();
374904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const EC_GROUP *group;
375904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int ret;
376904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
377904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!order)
378904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
379904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ERR_clear_error();
380904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
381904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
382904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	group = EC_KEY_get0_group(pkey->pkey.ec);
383904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!EC_GROUP_get_order(group, order, NULL))
384904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
385904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ERR_clear_error();
386904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
387904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
388904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
389904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ret = BN_num_bits(order);
390904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	BN_free(order);
391904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return ret;
392904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
393904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
394904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int ec_missing_parameters(const EVP_PKEY *pkey)
395904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
396904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (EC_KEY_get0_group(pkey->pkey.ec) == NULL)
397904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 1;
398904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 0;
399904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
400904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
401904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
402904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
403904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
404904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (group == NULL)
405904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
406904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (EC_KEY_set_group(to->pkey.ec, group) == 0)
407904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
408904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_GROUP_free(group);
409904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 1;
410904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
411904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
412904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
413904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
414904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
415904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	               *group_b = EC_KEY_get0_group(b->pkey.ec);
416904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (EC_GROUP_cmp(group_a, group_b, NULL))
417904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
418904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	else
419904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 1;
420904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
421904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
422904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic void int_ec_free(EVP_PKEY *pkey)
423904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
424904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY_free(pkey->pkey.ec);
425904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
426904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
427904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
428904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
429904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	unsigned char *buffer=NULL;
430904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const char *ecstr;
431904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	size_t	buf_len=0, i;
432904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int     ret=0, reason=ERR_R_BIO_LIB;
433904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	BIGNUM  *pub_key=NULL, *order=NULL;
434904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	BN_CTX  *ctx=NULL;
435904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const EC_GROUP *group;
436904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const EC_POINT *public_key;
437904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	const BIGNUM *priv_key;
438904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
439904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL)
440904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
441904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		reason = ERR_R_PASSED_NULL_PARAMETER;
442904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
443904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
444904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
445904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ctx = BN_CTX_new();
446904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (ctx == NULL)
447904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
448904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		reason = ERR_R_MALLOC_FAILURE;
449904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
450904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
451904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
452904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (ktype > 0)
453904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
454904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		public_key = EC_KEY_get0_public_key(x);
455904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if ((pub_key = EC_POINT_point2bn(group, public_key,
456904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			EC_KEY_get_conv_form(x), NULL, ctx)) == NULL)
457904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
458904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			reason = ERR_R_EC_LIB;
459904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto err;
460904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
461904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (pub_key)
462904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			buf_len = (size_t)BN_num_bytes(pub_key);
463904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
464904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
465904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (ktype == 2)
466904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
467904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		priv_key = EC_KEY_get0_private_key(x);
468904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
469904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			buf_len = i;
470904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
471904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	else
472904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		priv_key = NULL;
473904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
474904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (ktype > 0)
475904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
476904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		buf_len += 10;
477904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
478904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
479904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			reason = ERR_R_MALLOC_FAILURE;
480904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			goto err;
481904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
482904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
483904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (ktype == 2)
484904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ecstr = "Private-Key";
485904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	else if (ktype == 1)
486904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ecstr = "Public-Key";
487904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	else
488904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ecstr = "ECDSA-Parameters";
489904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
490904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!BIO_indent(bp, off, 128))
491904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
492904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if ((order = BN_new()) == NULL)
493904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
494904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!EC_GROUP_get_order(group, order, NULL))
495904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
496904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (BIO_printf(bp, "%s: (%d bit)\n", ecstr,
497904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		BN_num_bits(order)) <= 0) goto err;
498904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
499904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key,
500904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		buffer, off))
501904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
502904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key,
503904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		buffer, off))
504904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
505904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!ECPKParameters_print(bp, group, off))
506904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		goto err;
507904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ret=1;
508904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromerr:
509904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!ret)
510904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom 		ECerr(EC_F_DO_EC_KEY_PRINT, reason);
511904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (pub_key)
512904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		BN_free(pub_key);
513904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (order)
514904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		BN_free(order);
515904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (ctx)
516904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		BN_CTX_free(ctx);
517904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (buffer != NULL)
518904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		OPENSSL_free(buffer);
519904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return(ret);
520904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
521904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
522904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_param_decode(EVP_PKEY *pkey,
523904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom					const unsigned char **pder, int derlen)
524904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
525904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY *eckey;
526904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!(eckey = d2i_ECParameters(NULL, pder, derlen)))
527904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
528904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
529904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
530904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
531904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EVP_PKEY_assign_EC_KEY(pkey, eckey);
532904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 1;
533904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
534904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
535904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
536904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
537904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return i2d_ECParameters(pkey->pkey.ec, pder);
538904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
539904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
540904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
541904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom							ASN1_PCTX *ctx)
542904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
543904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
544904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
545904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
546904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
547904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom							ASN1_PCTX *ctx)
548904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
549904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
550904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
551904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
552904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
553904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
554904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom							ASN1_PCTX *ctx)
555904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
556904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
557904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
558904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
559904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int old_ec_priv_decode(EVP_PKEY *pkey,
560904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom					const unsigned char **pder, int derlen)
561904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
562904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EC_KEY *ec;
563904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	if (!(ec = d2i_ECPrivateKey (NULL, pder, derlen)))
564904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
565904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
566904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 0;
567904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
568904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EVP_PKEY_assign_EC_KEY(pkey, ec);
569904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return 1;
570904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
571904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
572904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
573904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
574904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	return i2d_ECPrivateKey(pkey->pkey.ec, pder);
575904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
576904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
577904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromstatic int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
578904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
579904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	switch (op)
580904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		{
581904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		case ASN1_PKEY_CTRL_PKCS7_SIGN:
582904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (arg1 == 0)
583904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
584904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			int snid, hnid;
585904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			X509_ALGOR *alg1, *alg2;
586904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
587904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			if (alg1 == NULL || alg1->algorithm == NULL)
588904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom				return -1;
589904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			hnid = OBJ_obj2nid(alg1->algorithm);
590904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			if (hnid == NID_undef)
591904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom				return -1;
592904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
593904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom				return -1;
594904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
595904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
596904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 1;
597904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#ifndef OPENSSL_NO_CMS
598904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		case ASN1_PKEY_CTRL_CMS_SIGN:
599904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		if (arg1 == 0)
600904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			{
601904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			int snid, hnid;
602904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			X509_ALGOR *alg1, *alg2;
603904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			CMS_SignerInfo_get0_algs(arg2, NULL, NULL,
604904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom								&alg1, &alg2);
605904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			if (alg1 == NULL || alg1->algorithm == NULL)
606904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom				return -1;
607904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			hnid = OBJ_obj2nid(alg1->algorithm);
608904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			if (hnid == NID_undef)
609904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom				return -1;
610904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
611904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom				return -1;
612904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
613904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom			}
614904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 1;
615904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom#endif
616904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
617904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
618904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		*(int *)arg2 = NID_sha1;
619904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return 2;
620904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
621904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		default:
622904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		return -2;
623904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
624904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom		}
625904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
626904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	}
627904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
628904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstromconst EVP_PKEY_ASN1_METHOD eckey_asn1_meth =
629904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	{
630904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EVP_PKEY_EC,
631904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	EVP_PKEY_EC,
632904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	0,
633904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	"EC",
634904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	"OpenSSL EC algorithm",
635904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
636904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_pub_decode,
637904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_pub_encode,
638904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_pub_cmp,
639904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_pub_print,
640904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
641904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_priv_decode,
642904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_priv_encode,
643904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_priv_print,
644904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
645904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int_ec_size,
646904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ec_bits,
647904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
648904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_param_decode,
649904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_param_encode,
650904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ec_missing_parameters,
651904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ec_copy_parameters,
652904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ec_cmp_parameters,
653904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	eckey_param_print,
654392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0,
655904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom
656904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	int_ec_free,
657904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	ec_pkey_ctrl,
658904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	old_ec_priv_decode,
659904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	old_ec_priv_encode
660904c5bb06deb8e0b17c3673c0ceb7d80420c16f3Brian Carlstrom	};
661