1296341Sdelphij/*
2296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3296341Sdelphij * 2006.
4238384Sjkim */
5238384Sjkim/* ====================================================================
6238384Sjkim * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7238384Sjkim *
8238384Sjkim * Redistribution and use in source and binary forms, with or without
9238384Sjkim * modification, are permitted provided that the following conditions
10238384Sjkim * are met:
11238384Sjkim *
12238384Sjkim * 1. Redistributions of source code must retain the above copyright
13296341Sdelphij *    notice, this list of conditions and the following disclaimer.
14238384Sjkim *
15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
16238384Sjkim *    notice, this list of conditions and the following disclaimer in
17238384Sjkim *    the documentation and/or other materials provided with the
18238384Sjkim *    distribution.
19238384Sjkim *
20238384Sjkim * 3. All advertising materials mentioning features or use of this
21238384Sjkim *    software must display the following acknowledgment:
22238384Sjkim *    "This product includes software developed by the OpenSSL Project
23238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24238384Sjkim *
25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26238384Sjkim *    endorse or promote products derived from this software without
27238384Sjkim *    prior written permission. For written permission, please contact
28238384Sjkim *    licensing@OpenSSL.org.
29238384Sjkim *
30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
31238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
32238384Sjkim *    permission of the OpenSSL Project.
33238384Sjkim *
34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
35238384Sjkim *    acknowledgment:
36238384Sjkim *    "This product includes software developed by the OpenSSL Project
37238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38238384Sjkim *
39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
51238384Sjkim * ====================================================================
52238384Sjkim *
53238384Sjkim * This product includes cryptographic software written by Eric Young
54238384Sjkim * (eay@cryptsoft.com).  This product includes software written by Tim
55238384Sjkim * Hudson (tjh@cryptsoft.com).
56238384Sjkim *
57238384Sjkim */
58238384Sjkim
59238384Sjkim#include <stdio.h>
60238384Sjkim#include "cryptlib.h"
61238384Sjkim#include <openssl/x509.h>
62238384Sjkim#include <openssl/ec.h>
63238384Sjkim#include <openssl/bn.h>
64238384Sjkim#ifndef OPENSSL_NO_CMS
65296341Sdelphij# include <openssl/cms.h>
66238384Sjkim#endif
67238384Sjkim#include "asn1_locl.h"
68238384Sjkim
69238384Sjkimstatic int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
70296341Sdelphij{
71296341Sdelphij    const EC_GROUP *group;
72296341Sdelphij    int nid;
73296341Sdelphij    if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
74296341Sdelphij        ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
75296341Sdelphij        return 0;
76296341Sdelphij    }
77296341Sdelphij    if (EC_GROUP_get_asn1_flag(group)
78296341Sdelphij        && (nid = EC_GROUP_get_curve_name(group)))
79296341Sdelphij        /* we have a 'named curve' => just set the OID */
80296341Sdelphij    {
81296341Sdelphij        *ppval = OBJ_nid2obj(nid);
82296341Sdelphij        *pptype = V_ASN1_OBJECT;
83296341Sdelphij    } else {                    /* explicit parameters */
84238384Sjkim
85296341Sdelphij        ASN1_STRING *pstr = NULL;
86296341Sdelphij        pstr = ASN1_STRING_new();
87296341Sdelphij        if (!pstr)
88296341Sdelphij            return 0;
89296341Sdelphij        pstr->length = i2d_ECParameters(ec_key, &pstr->data);
90296341Sdelphij        if (pstr->length <= 0) {
91296341Sdelphij            ASN1_STRING_free(pstr);
92296341Sdelphij            ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
93296341Sdelphij            return 0;
94296341Sdelphij        }
95296341Sdelphij        *ppval = pstr;
96296341Sdelphij        *pptype = V_ASN1_SEQUENCE;
97296341Sdelphij    }
98296341Sdelphij    return 1;
99296341Sdelphij}
100296341Sdelphij
101238384Sjkimstatic int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
102296341Sdelphij{
103296341Sdelphij    EC_KEY *ec_key = pkey->pkey.ec;
104296341Sdelphij    void *pval = NULL;
105296341Sdelphij    int ptype;
106296341Sdelphij    unsigned char *penc = NULL, *p;
107296341Sdelphij    int penclen;
108238384Sjkim
109296341Sdelphij    if (!eckey_param2type(&ptype, &pval, ec_key)) {
110296341Sdelphij        ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
111296341Sdelphij        return 0;
112296341Sdelphij    }
113296341Sdelphij    penclen = i2o_ECPublicKey(ec_key, NULL);
114296341Sdelphij    if (penclen <= 0)
115296341Sdelphij        goto err;
116296341Sdelphij    penc = OPENSSL_malloc(penclen);
117296341Sdelphij    if (!penc)
118296341Sdelphij        goto err;
119296341Sdelphij    p = penc;
120296341Sdelphij    penclen = i2o_ECPublicKey(ec_key, &p);
121296341Sdelphij    if (penclen <= 0)
122296341Sdelphij        goto err;
123296341Sdelphij    if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
124296341Sdelphij                               ptype, pval, penc, penclen))
125296341Sdelphij        return 1;
126296341Sdelphij err:
127296341Sdelphij    if (ptype == V_ASN1_OBJECT)
128296341Sdelphij        ASN1_OBJECT_free(pval);
129296341Sdelphij    else
130296341Sdelphij        ASN1_STRING_free(pval);
131296341Sdelphij    if (penc)
132296341Sdelphij        OPENSSL_free(penc);
133296341Sdelphij    return 0;
134296341Sdelphij}
135238384Sjkim
136238384Sjkimstatic EC_KEY *eckey_type2param(int ptype, void *pval)
137296341Sdelphij{
138296341Sdelphij    EC_KEY *eckey = NULL;
139296341Sdelphij    if (ptype == V_ASN1_SEQUENCE) {
140296341Sdelphij        ASN1_STRING *pstr = pval;
141296341Sdelphij        const unsigned char *pm = NULL;
142296341Sdelphij        int pmlen;
143296341Sdelphij        pm = pstr->data;
144296341Sdelphij        pmlen = pstr->length;
145296341Sdelphij        if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) {
146296341Sdelphij            ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
147296341Sdelphij            goto ecerr;
148296341Sdelphij        }
149296341Sdelphij    } else if (ptype == V_ASN1_OBJECT) {
150296341Sdelphij        ASN1_OBJECT *poid = pval;
151296341Sdelphij        EC_GROUP *group;
152238384Sjkim
153296341Sdelphij        /*
154296341Sdelphij         * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
155296341Sdelphij         */
156296341Sdelphij        if ((eckey = EC_KEY_new()) == NULL) {
157296341Sdelphij            ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
158296341Sdelphij            goto ecerr;
159296341Sdelphij        }
160296341Sdelphij        group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
161296341Sdelphij        if (group == NULL)
162296341Sdelphij            goto ecerr;
163296341Sdelphij        EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
164296341Sdelphij        if (EC_KEY_set_group(eckey, group) == 0)
165296341Sdelphij            goto ecerr;
166296341Sdelphij        EC_GROUP_free(group);
167296341Sdelphij    } else {
168296341Sdelphij        ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
169296341Sdelphij        goto ecerr;
170296341Sdelphij    }
171238384Sjkim
172296341Sdelphij    return eckey;
173238384Sjkim
174296341Sdelphij ecerr:
175296341Sdelphij    if (eckey)
176296341Sdelphij        EC_KEY_free(eckey);
177296341Sdelphij    return NULL;
178296341Sdelphij}
179238384Sjkim
180238384Sjkimstatic int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
181296341Sdelphij{
182296341Sdelphij    const unsigned char *p = NULL;
183296341Sdelphij    void *pval;
184296341Sdelphij    int ptype, pklen;
185296341Sdelphij    EC_KEY *eckey = NULL;
186296341Sdelphij    X509_ALGOR *palg;
187238384Sjkim
188296341Sdelphij    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
189296341Sdelphij        return 0;
190296341Sdelphij    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
191238384Sjkim
192296341Sdelphij    eckey = eckey_type2param(ptype, pval);
193238384Sjkim
194296341Sdelphij    if (!eckey) {
195296341Sdelphij        ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
196296341Sdelphij        return 0;
197296341Sdelphij    }
198238384Sjkim
199296341Sdelphij    /* We have parameters now set public key */
200296341Sdelphij    if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
201296341Sdelphij        ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
202296341Sdelphij        goto ecerr;
203296341Sdelphij    }
204238384Sjkim
205296341Sdelphij    EVP_PKEY_assign_EC_KEY(pkey, eckey);
206296341Sdelphij    return 1;
207238384Sjkim
208296341Sdelphij ecerr:
209296341Sdelphij    if (eckey)
210296341Sdelphij        EC_KEY_free(eckey);
211296341Sdelphij    return 0;
212296341Sdelphij}
213238384Sjkim
214238384Sjkimstatic int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
215296341Sdelphij{
216296341Sdelphij    int r;
217296341Sdelphij    const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
218296341Sdelphij    const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
219296341Sdelphij        *pb = EC_KEY_get0_public_key(b->pkey.ec);
220296341Sdelphij    r = EC_POINT_cmp(group, pa, pb, NULL);
221296341Sdelphij    if (r == 0)
222296341Sdelphij        return 1;
223296341Sdelphij    if (r == 1)
224296341Sdelphij        return 0;
225296341Sdelphij    return -2;
226296341Sdelphij}
227238384Sjkim
228238384Sjkimstatic int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
229296341Sdelphij{
230296341Sdelphij    const unsigned char *p = NULL;
231296341Sdelphij    void *pval;
232296341Sdelphij    int ptype, pklen;
233296341Sdelphij    EC_KEY *eckey = NULL;
234296341Sdelphij    X509_ALGOR *palg;
235238384Sjkim
236296341Sdelphij    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
237296341Sdelphij        return 0;
238296341Sdelphij    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
239238384Sjkim
240296341Sdelphij    eckey = eckey_type2param(ptype, pval);
241238384Sjkim
242296341Sdelphij    if (!eckey)
243296341Sdelphij        goto ecliberr;
244238384Sjkim
245296341Sdelphij    /* We have parameters now set private key */
246296341Sdelphij    if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
247296341Sdelphij        ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
248296341Sdelphij        goto ecerr;
249296341Sdelphij    }
250238384Sjkim
251296341Sdelphij    /* calculate public key (if necessary) */
252296341Sdelphij    if (EC_KEY_get0_public_key(eckey) == NULL) {
253296341Sdelphij        const BIGNUM *priv_key;
254296341Sdelphij        const EC_GROUP *group;
255296341Sdelphij        EC_POINT *pub_key;
256296341Sdelphij        /*
257296341Sdelphij         * the public key was not included in the SEC1 private key =>
258296341Sdelphij         * calculate the public key
259296341Sdelphij         */
260296341Sdelphij        group = EC_KEY_get0_group(eckey);
261296341Sdelphij        pub_key = EC_POINT_new(group);
262296341Sdelphij        if (pub_key == NULL) {
263296341Sdelphij            ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
264296341Sdelphij            goto ecliberr;
265296341Sdelphij        }
266296341Sdelphij        if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
267296341Sdelphij            EC_POINT_free(pub_key);
268296341Sdelphij            ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
269296341Sdelphij            goto ecliberr;
270296341Sdelphij        }
271296341Sdelphij        priv_key = EC_KEY_get0_private_key(eckey);
272296341Sdelphij        if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
273296341Sdelphij            EC_POINT_free(pub_key);
274296341Sdelphij            ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
275296341Sdelphij            goto ecliberr;
276296341Sdelphij        }
277296341Sdelphij        if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
278296341Sdelphij            EC_POINT_free(pub_key);
279296341Sdelphij            ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
280296341Sdelphij            goto ecliberr;
281296341Sdelphij        }
282296341Sdelphij        EC_POINT_free(pub_key);
283296341Sdelphij    }
284238384Sjkim
285296341Sdelphij    EVP_PKEY_assign_EC_KEY(pkey, eckey);
286296341Sdelphij    return 1;
287238384Sjkim
288296341Sdelphij ecliberr:
289296341Sdelphij    ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
290296341Sdelphij ecerr:
291296341Sdelphij    if (eckey)
292296341Sdelphij        EC_KEY_free(eckey);
293296341Sdelphij    return 0;
294296341Sdelphij}
295238384Sjkim
296238384Sjkimstatic int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
297238384Sjkim{
298296341Sdelphij    EC_KEY *ec_key;
299296341Sdelphij    unsigned char *ep, *p;
300296341Sdelphij    int eplen, ptype;
301296341Sdelphij    void *pval;
302296341Sdelphij    unsigned int tmp_flags, old_flags;
303238384Sjkim
304296341Sdelphij    ec_key = pkey->pkey.ec;
305238384Sjkim
306296341Sdelphij    if (!eckey_param2type(&ptype, &pval, ec_key)) {
307296341Sdelphij        ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
308296341Sdelphij        return 0;
309296341Sdelphij    }
310238384Sjkim
311296341Sdelphij    /* set the private key */
312238384Sjkim
313296341Sdelphij    /*
314296341Sdelphij     * do not include the parameters in the SEC1 private key see PKCS#11
315296341Sdelphij     * 12.11
316296341Sdelphij     */
317296341Sdelphij    old_flags = EC_KEY_get_enc_flags(ec_key);
318296341Sdelphij    tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
319296341Sdelphij    EC_KEY_set_enc_flags(ec_key, tmp_flags);
320296341Sdelphij    eplen = i2d_ECPrivateKey(ec_key, NULL);
321296341Sdelphij    if (!eplen) {
322296341Sdelphij        EC_KEY_set_enc_flags(ec_key, old_flags);
323296341Sdelphij        ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
324296341Sdelphij        return 0;
325296341Sdelphij    }
326296341Sdelphij    ep = (unsigned char *)OPENSSL_malloc(eplen);
327296341Sdelphij    if (!ep) {
328296341Sdelphij        EC_KEY_set_enc_flags(ec_key, old_flags);
329296341Sdelphij        ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
330296341Sdelphij        return 0;
331296341Sdelphij    }
332296341Sdelphij    p = ep;
333296341Sdelphij    if (!i2d_ECPrivateKey(ec_key, &p)) {
334296341Sdelphij        EC_KEY_set_enc_flags(ec_key, old_flags);
335296341Sdelphij        OPENSSL_free(ep);
336296341Sdelphij        ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
337296341Sdelphij        return 0;
338296341Sdelphij    }
339296341Sdelphij    /* restore old encoding flags */
340296341Sdelphij    EC_KEY_set_enc_flags(ec_key, old_flags);
341238384Sjkim
342296341Sdelphij    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
343296341Sdelphij                         ptype, pval, ep, eplen))
344296341Sdelphij        return 0;
345238384Sjkim
346296341Sdelphij    return 1;
347238384Sjkim}
348238384Sjkim
349238384Sjkimstatic int int_ec_size(const EVP_PKEY *pkey)
350296341Sdelphij{
351296341Sdelphij    return ECDSA_size(pkey->pkey.ec);
352296341Sdelphij}
353238384Sjkim
354238384Sjkimstatic int ec_bits(const EVP_PKEY *pkey)
355296341Sdelphij{
356296341Sdelphij    BIGNUM *order = BN_new();
357296341Sdelphij    const EC_GROUP *group;
358296341Sdelphij    int ret;
359238384Sjkim
360296341Sdelphij    if (!order) {
361296341Sdelphij        ERR_clear_error();
362296341Sdelphij        return 0;
363296341Sdelphij    }
364296341Sdelphij    group = EC_KEY_get0_group(pkey->pkey.ec);
365296341Sdelphij    if (!EC_GROUP_get_order(group, order, NULL)) {
366296341Sdelphij        ERR_clear_error();
367296341Sdelphij        return 0;
368296341Sdelphij    }
369238384Sjkim
370296341Sdelphij    ret = BN_num_bits(order);
371296341Sdelphij    BN_free(order);
372296341Sdelphij    return ret;
373296341Sdelphij}
374238384Sjkim
375238384Sjkimstatic int ec_missing_parameters(const EVP_PKEY *pkey)
376296341Sdelphij{
377296341Sdelphij    if (EC_KEY_get0_group(pkey->pkey.ec) == NULL)
378296341Sdelphij        return 1;
379296341Sdelphij    return 0;
380296341Sdelphij}
381238384Sjkim
382238384Sjkimstatic int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
383296341Sdelphij{
384296341Sdelphij    EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
385296341Sdelphij    if (group == NULL)
386296341Sdelphij        return 0;
387296341Sdelphij    if (EC_KEY_set_group(to->pkey.ec, group) == 0)
388296341Sdelphij        return 0;
389296341Sdelphij    EC_GROUP_free(group);
390296341Sdelphij    return 1;
391296341Sdelphij}
392238384Sjkim
393238384Sjkimstatic int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
394296341Sdelphij{
395296341Sdelphij    const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
396296341Sdelphij        *group_b = EC_KEY_get0_group(b->pkey.ec);
397296341Sdelphij    if (EC_GROUP_cmp(group_a, group_b, NULL))
398296341Sdelphij        return 0;
399296341Sdelphij    else
400296341Sdelphij        return 1;
401296341Sdelphij}
402238384Sjkim
403238384Sjkimstatic void int_ec_free(EVP_PKEY *pkey)
404296341Sdelphij{
405296341Sdelphij    EC_KEY_free(pkey->pkey.ec);
406296341Sdelphij}
407238384Sjkim
408238384Sjkimstatic int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
409296341Sdelphij{
410296341Sdelphij    unsigned char *buffer = NULL;
411296341Sdelphij    const char *ecstr;
412296341Sdelphij    size_t buf_len = 0, i;
413296341Sdelphij    int ret = 0, reason = ERR_R_BIO_LIB;
414296341Sdelphij    BIGNUM *pub_key = NULL, *order = NULL;
415296341Sdelphij    BN_CTX *ctx = NULL;
416296341Sdelphij    const EC_GROUP *group;
417296341Sdelphij    const EC_POINT *public_key;
418296341Sdelphij    const BIGNUM *priv_key;
419238384Sjkim
420296341Sdelphij    if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
421296341Sdelphij        reason = ERR_R_PASSED_NULL_PARAMETER;
422296341Sdelphij        goto err;
423296341Sdelphij    }
424238384Sjkim
425296341Sdelphij    ctx = BN_CTX_new();
426296341Sdelphij    if (ctx == NULL) {
427296341Sdelphij        reason = ERR_R_MALLOC_FAILURE;
428296341Sdelphij        goto err;
429296341Sdelphij    }
430238384Sjkim
431296341Sdelphij    if (ktype > 0) {
432296341Sdelphij        public_key = EC_KEY_get0_public_key(x);
433296341Sdelphij        if (public_key != NULL) {
434296341Sdelphij            if ((pub_key = EC_POINT_point2bn(group, public_key,
435296341Sdelphij                                             EC_KEY_get_conv_form(x), NULL,
436296341Sdelphij                                             ctx)) == NULL) {
437296341Sdelphij                reason = ERR_R_EC_LIB;
438296341Sdelphij                goto err;
439296341Sdelphij            }
440296341Sdelphij            buf_len = (size_t)BN_num_bytes(pub_key);
441296341Sdelphij        }
442296341Sdelphij    }
443238384Sjkim
444296341Sdelphij    if (ktype == 2) {
445296341Sdelphij        priv_key = EC_KEY_get0_private_key(x);
446296341Sdelphij        if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
447296341Sdelphij            buf_len = i;
448296341Sdelphij    } else
449296341Sdelphij        priv_key = NULL;
450238384Sjkim
451296341Sdelphij    if (ktype > 0) {
452296341Sdelphij        buf_len += 10;
453296341Sdelphij        if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
454296341Sdelphij            reason = ERR_R_MALLOC_FAILURE;
455296341Sdelphij            goto err;
456296341Sdelphij        }
457296341Sdelphij    }
458296341Sdelphij    if (ktype == 2)
459296341Sdelphij        ecstr = "Private-Key";
460296341Sdelphij    else if (ktype == 1)
461296341Sdelphij        ecstr = "Public-Key";
462296341Sdelphij    else
463296341Sdelphij        ecstr = "ECDSA-Parameters";
464238384Sjkim
465296341Sdelphij    if (!BIO_indent(bp, off, 128))
466296341Sdelphij        goto err;
467296341Sdelphij    if ((order = BN_new()) == NULL)
468296341Sdelphij        goto err;
469296341Sdelphij    if (!EC_GROUP_get_order(group, order, NULL))
470296341Sdelphij        goto err;
471296341Sdelphij    if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0)
472296341Sdelphij        goto err;
473296341Sdelphij
474296341Sdelphij    if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key,
475296341Sdelphij                                             buffer, off))
476296341Sdelphij        goto err;
477296341Sdelphij    if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key,
478296341Sdelphij                                            buffer, off))
479296341Sdelphij        goto err;
480296341Sdelphij    if (!ECPKParameters_print(bp, group, off))
481296341Sdelphij        goto err;
482296341Sdelphij    ret = 1;
483296341Sdelphij err:
484296341Sdelphij    if (!ret)
485296341Sdelphij        ECerr(EC_F_DO_EC_KEY_PRINT, reason);
486296341Sdelphij    if (pub_key)
487296341Sdelphij        BN_free(pub_key);
488296341Sdelphij    if (order)
489296341Sdelphij        BN_free(order);
490296341Sdelphij    if (ctx)
491296341Sdelphij        BN_CTX_free(ctx);
492296341Sdelphij    if (buffer != NULL)
493296341Sdelphij        OPENSSL_free(buffer);
494296341Sdelphij    return (ret);
495296341Sdelphij}
496296341Sdelphij
497238384Sjkimstatic int eckey_param_decode(EVP_PKEY *pkey,
498296341Sdelphij                              const unsigned char **pder, int derlen)
499296341Sdelphij{
500296341Sdelphij    EC_KEY *eckey;
501296341Sdelphij    if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
502296341Sdelphij        ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
503296341Sdelphij        return 0;
504296341Sdelphij    }
505296341Sdelphij    EVP_PKEY_assign_EC_KEY(pkey, eckey);
506296341Sdelphij    return 1;
507296341Sdelphij}
508238384Sjkim
509238384Sjkimstatic int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
510296341Sdelphij{
511296341Sdelphij    return i2d_ECParameters(pkey->pkey.ec, pder);
512296341Sdelphij}
513238384Sjkim
514238384Sjkimstatic int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
515296341Sdelphij                             ASN1_PCTX *ctx)
516296341Sdelphij{
517296341Sdelphij    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
518296341Sdelphij}
519238384Sjkim
520238384Sjkimstatic int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
521296341Sdelphij                           ASN1_PCTX *ctx)
522296341Sdelphij{
523296341Sdelphij    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
524296341Sdelphij}
525238384Sjkim
526238384Sjkimstatic int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
527296341Sdelphij                            ASN1_PCTX *ctx)
528296341Sdelphij{
529296341Sdelphij    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
530296341Sdelphij}
531238384Sjkim
532238384Sjkimstatic int old_ec_priv_decode(EVP_PKEY *pkey,
533296341Sdelphij                              const unsigned char **pder, int derlen)
534296341Sdelphij{
535296341Sdelphij    EC_KEY *ec;
536296341Sdelphij    if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
537296341Sdelphij        ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
538296341Sdelphij        return 0;
539296341Sdelphij    }
540296341Sdelphij    EVP_PKEY_assign_EC_KEY(pkey, ec);
541296341Sdelphij    return 1;
542296341Sdelphij}
543238384Sjkim
544238384Sjkimstatic int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
545296341Sdelphij{
546296341Sdelphij    return i2d_ECPrivateKey(pkey->pkey.ec, pder);
547296341Sdelphij}
548238384Sjkim
549238384Sjkimstatic int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
550296341Sdelphij{
551296341Sdelphij    switch (op) {
552296341Sdelphij    case ASN1_PKEY_CTRL_PKCS7_SIGN:
553296341Sdelphij        if (arg1 == 0) {
554296341Sdelphij            int snid, hnid;
555296341Sdelphij            X509_ALGOR *alg1, *alg2;
556296341Sdelphij            PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
557296341Sdelphij            if (alg1 == NULL || alg1->algorithm == NULL)
558296341Sdelphij                return -1;
559296341Sdelphij            hnid = OBJ_obj2nid(alg1->algorithm);
560296341Sdelphij            if (hnid == NID_undef)
561296341Sdelphij                return -1;
562296341Sdelphij            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
563296341Sdelphij                return -1;
564296341Sdelphij            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
565296341Sdelphij        }
566296341Sdelphij        return 1;
567238384Sjkim#ifndef OPENSSL_NO_CMS
568296341Sdelphij    case ASN1_PKEY_CTRL_CMS_SIGN:
569296341Sdelphij        if (arg1 == 0) {
570296341Sdelphij            int snid, hnid;
571296341Sdelphij            X509_ALGOR *alg1, *alg2;
572296341Sdelphij            CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
573296341Sdelphij            if (alg1 == NULL || alg1->algorithm == NULL)
574296341Sdelphij                return -1;
575296341Sdelphij            hnid = OBJ_obj2nid(alg1->algorithm);
576296341Sdelphij            if (hnid == NID_undef)
577296341Sdelphij                return -1;
578296341Sdelphij            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
579296341Sdelphij                return -1;
580296341Sdelphij            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
581296341Sdelphij        }
582296341Sdelphij        return 1;
583238384Sjkim#endif
584238384Sjkim
585296341Sdelphij    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
586296341Sdelphij        *(int *)arg2 = NID_sha1;
587296341Sdelphij        return 2;
588238384Sjkim
589296341Sdelphij    default:
590296341Sdelphij        return -2;
591238384Sjkim
592296341Sdelphij    }
593238384Sjkim
594296341Sdelphij}
595238384Sjkim
596296341Sdelphijconst EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
597296341Sdelphij    EVP_PKEY_EC,
598296341Sdelphij    EVP_PKEY_EC,
599296341Sdelphij    0,
600296341Sdelphij    "EC",
601296341Sdelphij    "OpenSSL EC algorithm",
602238384Sjkim
603296341Sdelphij    eckey_pub_decode,
604296341Sdelphij    eckey_pub_encode,
605296341Sdelphij    eckey_pub_cmp,
606296341Sdelphij    eckey_pub_print,
607238384Sjkim
608296341Sdelphij    eckey_priv_decode,
609296341Sdelphij    eckey_priv_encode,
610296341Sdelphij    eckey_priv_print,
611238384Sjkim
612296341Sdelphij    int_ec_size,
613296341Sdelphij    ec_bits,
614238384Sjkim
615296341Sdelphij    eckey_param_decode,
616296341Sdelphij    eckey_param_encode,
617296341Sdelphij    ec_missing_parameters,
618296341Sdelphij    ec_copy_parameters,
619296341Sdelphij    ec_cmp_parameters,
620296341Sdelphij    eckey_param_print,
621296341Sdelphij    0,
622238384Sjkim
623296341Sdelphij    int_ec_free,
624296341Sdelphij    ec_pkey_ctrl,
625296341Sdelphij    old_ec_priv_decode,
626296341Sdelphij    old_ec_priv_encode
627296341Sdelphij};
628