1280304Sjkim/*
2280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3280304Sjkim * 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
13280304Sjkim *    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
65280304Sjkim# include <openssl/cms.h>
66238384Sjkim#endif
67238384Sjkim#include "asn1_locl.h"
68238384Sjkim
69238384Sjkimstatic int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
70280304Sjkim{
71280304Sjkim    const EC_GROUP *group;
72280304Sjkim    int nid;
73280304Sjkim    if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
74280304Sjkim        ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
75280304Sjkim        return 0;
76280304Sjkim    }
77280304Sjkim    if (EC_GROUP_get_asn1_flag(group)
78280304Sjkim        && (nid = EC_GROUP_get_curve_name(group)))
79280304Sjkim        /* we have a 'named curve' => just set the OID */
80280304Sjkim    {
81280304Sjkim        *ppval = OBJ_nid2obj(nid);
82280304Sjkim        *pptype = V_ASN1_OBJECT;
83280304Sjkim    } else {                    /* explicit parameters */
84238384Sjkim
85280304Sjkim        ASN1_STRING *pstr = NULL;
86280304Sjkim        pstr = ASN1_STRING_new();
87280304Sjkim        if (!pstr)
88280304Sjkim            return 0;
89280304Sjkim        pstr->length = i2d_ECParameters(ec_key, &pstr->data);
90280304Sjkim        if (pstr->length <= 0) {
91280304Sjkim            ASN1_STRING_free(pstr);
92280304Sjkim            ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
93280304Sjkim            return 0;
94280304Sjkim        }
95280304Sjkim        *ppval = pstr;
96280304Sjkim        *pptype = V_ASN1_SEQUENCE;
97280304Sjkim    }
98280304Sjkim    return 1;
99280304Sjkim}
100280304Sjkim
101238384Sjkimstatic int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
102280304Sjkim{
103280304Sjkim    EC_KEY *ec_key = pkey->pkey.ec;
104280304Sjkim    void *pval = NULL;
105280304Sjkim    int ptype;
106280304Sjkim    unsigned char *penc = NULL, *p;
107280304Sjkim    int penclen;
108238384Sjkim
109280304Sjkim    if (!eckey_param2type(&ptype, &pval, ec_key)) {
110280304Sjkim        ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
111280304Sjkim        return 0;
112280304Sjkim    }
113280304Sjkim    penclen = i2o_ECPublicKey(ec_key, NULL);
114280304Sjkim    if (penclen <= 0)
115280304Sjkim        goto err;
116280304Sjkim    penc = OPENSSL_malloc(penclen);
117280304Sjkim    if (!penc)
118280304Sjkim        goto err;
119280304Sjkim    p = penc;
120280304Sjkim    penclen = i2o_ECPublicKey(ec_key, &p);
121280304Sjkim    if (penclen <= 0)
122280304Sjkim        goto err;
123280304Sjkim    if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
124280304Sjkim                               ptype, pval, penc, penclen))
125280304Sjkim        return 1;
126280304Sjkim err:
127280304Sjkim    if (ptype == V_ASN1_OBJECT)
128280304Sjkim        ASN1_OBJECT_free(pval);
129280304Sjkim    else
130280304Sjkim        ASN1_STRING_free(pval);
131280304Sjkim    if (penc)
132280304Sjkim        OPENSSL_free(penc);
133280304Sjkim    return 0;
134280304Sjkim}
135238384Sjkim
136238384Sjkimstatic EC_KEY *eckey_type2param(int ptype, void *pval)
137280304Sjkim{
138280304Sjkim    EC_KEY *eckey = NULL;
139280304Sjkim    if (ptype == V_ASN1_SEQUENCE) {
140280304Sjkim        ASN1_STRING *pstr = pval;
141280304Sjkim        const unsigned char *pm = NULL;
142280304Sjkim        int pmlen;
143280304Sjkim        pm = pstr->data;
144280304Sjkim        pmlen = pstr->length;
145280304Sjkim        if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) {
146280304Sjkim            ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
147280304Sjkim            goto ecerr;
148280304Sjkim        }
149280304Sjkim    } else if (ptype == V_ASN1_OBJECT) {
150280304Sjkim        ASN1_OBJECT *poid = pval;
151280304Sjkim        EC_GROUP *group;
152238384Sjkim
153280304Sjkim        /*
154280304Sjkim         * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
155280304Sjkim         */
156280304Sjkim        if ((eckey = EC_KEY_new()) == NULL) {
157280304Sjkim            ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
158280304Sjkim            goto ecerr;
159280304Sjkim        }
160280304Sjkim        group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
161280304Sjkim        if (group == NULL)
162280304Sjkim            goto ecerr;
163280304Sjkim        EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
164280304Sjkim        if (EC_KEY_set_group(eckey, group) == 0)
165280304Sjkim            goto ecerr;
166280304Sjkim        EC_GROUP_free(group);
167280304Sjkim    } else {
168280304Sjkim        ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
169280304Sjkim        goto ecerr;
170280304Sjkim    }
171238384Sjkim
172280304Sjkim    return eckey;
173238384Sjkim
174280304Sjkim ecerr:
175280304Sjkim    if (eckey)
176280304Sjkim        EC_KEY_free(eckey);
177280304Sjkim    return NULL;
178280304Sjkim}
179238384Sjkim
180238384Sjkimstatic int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
181280304Sjkim{
182280304Sjkim    const unsigned char *p = NULL;
183280304Sjkim    void *pval;
184280304Sjkim    int ptype, pklen;
185280304Sjkim    EC_KEY *eckey = NULL;
186280304Sjkim    X509_ALGOR *palg;
187238384Sjkim
188280304Sjkim    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
189280304Sjkim        return 0;
190280304Sjkim    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
191238384Sjkim
192280304Sjkim    eckey = eckey_type2param(ptype, pval);
193238384Sjkim
194280304Sjkim    if (!eckey) {
195280304Sjkim        ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
196280304Sjkim        return 0;
197280304Sjkim    }
198238384Sjkim
199280304Sjkim    /* We have parameters now set public key */
200280304Sjkim    if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
201280304Sjkim        ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
202280304Sjkim        goto ecerr;
203280304Sjkim    }
204238384Sjkim
205280304Sjkim    EVP_PKEY_assign_EC_KEY(pkey, eckey);
206280304Sjkim    return 1;
207238384Sjkim
208280304Sjkim ecerr:
209280304Sjkim    if (eckey)
210280304Sjkim        EC_KEY_free(eckey);
211280304Sjkim    return 0;
212280304Sjkim}
213238384Sjkim
214238384Sjkimstatic int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
215280304Sjkim{
216280304Sjkim    int r;
217280304Sjkim    const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
218280304Sjkim    const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
219280304Sjkim        *pb = EC_KEY_get0_public_key(b->pkey.ec);
220280304Sjkim    r = EC_POINT_cmp(group, pa, pb, NULL);
221280304Sjkim    if (r == 0)
222280304Sjkim        return 1;
223280304Sjkim    if (r == 1)
224280304Sjkim        return 0;
225280304Sjkim    return -2;
226280304Sjkim}
227238384Sjkim
228238384Sjkimstatic int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
229280304Sjkim{
230280304Sjkim    const unsigned char *p = NULL;
231280304Sjkim    void *pval;
232280304Sjkim    int ptype, pklen;
233280304Sjkim    EC_KEY *eckey = NULL;
234280304Sjkim    X509_ALGOR *palg;
235238384Sjkim
236280304Sjkim    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
237280304Sjkim        return 0;
238280304Sjkim    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
239238384Sjkim
240280304Sjkim    eckey = eckey_type2param(ptype, pval);
241238384Sjkim
242280304Sjkim    if (!eckey)
243280304Sjkim        goto ecliberr;
244238384Sjkim
245280304Sjkim    /* We have parameters now set private key */
246280304Sjkim    if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
247280304Sjkim        ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
248280304Sjkim        goto ecerr;
249280304Sjkim    }
250238384Sjkim
251280304Sjkim    /* calculate public key (if necessary) */
252280304Sjkim    if (EC_KEY_get0_public_key(eckey) == NULL) {
253280304Sjkim        const BIGNUM *priv_key;
254280304Sjkim        const EC_GROUP *group;
255280304Sjkim        EC_POINT *pub_key;
256280304Sjkim        /*
257280304Sjkim         * the public key was not included in the SEC1 private key =>
258280304Sjkim         * calculate the public key
259280304Sjkim         */
260280304Sjkim        group = EC_KEY_get0_group(eckey);
261280304Sjkim        pub_key = EC_POINT_new(group);
262280304Sjkim        if (pub_key == NULL) {
263280304Sjkim            ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
264280304Sjkim            goto ecliberr;
265280304Sjkim        }
266280304Sjkim        if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
267280304Sjkim            EC_POINT_free(pub_key);
268280304Sjkim            ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
269280304Sjkim            goto ecliberr;
270280304Sjkim        }
271280304Sjkim        priv_key = EC_KEY_get0_private_key(eckey);
272280304Sjkim        if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
273280304Sjkim            EC_POINT_free(pub_key);
274280304Sjkim            ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
275280304Sjkim            goto ecliberr;
276280304Sjkim        }
277280304Sjkim        if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
278280304Sjkim            EC_POINT_free(pub_key);
279280304Sjkim            ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
280280304Sjkim            goto ecliberr;
281280304Sjkim        }
282280304Sjkim        EC_POINT_free(pub_key);
283280304Sjkim    }
284238384Sjkim
285280304Sjkim    EVP_PKEY_assign_EC_KEY(pkey, eckey);
286280304Sjkim    return 1;
287238384Sjkim
288280304Sjkim ecliberr:
289280304Sjkim    ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
290280304Sjkim ecerr:
291280304Sjkim    if (eckey)
292280304Sjkim        EC_KEY_free(eckey);
293280304Sjkim    return 0;
294280304Sjkim}
295238384Sjkim
296238384Sjkimstatic int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
297238384Sjkim{
298280304Sjkim    EC_KEY *ec_key;
299280304Sjkim    unsigned char *ep, *p;
300280304Sjkim    int eplen, ptype;
301280304Sjkim    void *pval;
302280304Sjkim    unsigned int tmp_flags, old_flags;
303238384Sjkim
304280304Sjkim    ec_key = pkey->pkey.ec;
305238384Sjkim
306280304Sjkim    if (!eckey_param2type(&ptype, &pval, ec_key)) {
307280304Sjkim        ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
308280304Sjkim        return 0;
309280304Sjkim    }
310238384Sjkim
311280304Sjkim    /* set the private key */
312238384Sjkim
313280304Sjkim    /*
314280304Sjkim     * do not include the parameters in the SEC1 private key see PKCS#11
315280304Sjkim     * 12.11
316280304Sjkim     */
317280304Sjkim    old_flags = EC_KEY_get_enc_flags(ec_key);
318280304Sjkim    tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
319280304Sjkim    EC_KEY_set_enc_flags(ec_key, tmp_flags);
320280304Sjkim    eplen = i2d_ECPrivateKey(ec_key, NULL);
321280304Sjkim    if (!eplen) {
322280304Sjkim        EC_KEY_set_enc_flags(ec_key, old_flags);
323280304Sjkim        ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
324280304Sjkim        return 0;
325280304Sjkim    }
326280304Sjkim    ep = (unsigned char *)OPENSSL_malloc(eplen);
327280304Sjkim    if (!ep) {
328280304Sjkim        EC_KEY_set_enc_flags(ec_key, old_flags);
329280304Sjkim        ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
330280304Sjkim        return 0;
331280304Sjkim    }
332280304Sjkim    p = ep;
333280304Sjkim    if (!i2d_ECPrivateKey(ec_key, &p)) {
334280304Sjkim        EC_KEY_set_enc_flags(ec_key, old_flags);
335280304Sjkim        OPENSSL_free(ep);
336280304Sjkim        ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
337280304Sjkim        return 0;
338280304Sjkim    }
339280304Sjkim    /* restore old encoding flags */
340280304Sjkim    EC_KEY_set_enc_flags(ec_key, old_flags);
341238384Sjkim
342280304Sjkim    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
343280304Sjkim                         ptype, pval, ep, eplen))
344280304Sjkim        return 0;
345238384Sjkim
346280304Sjkim    return 1;
347238384Sjkim}
348238384Sjkim
349238384Sjkimstatic int int_ec_size(const EVP_PKEY *pkey)
350280304Sjkim{
351280304Sjkim    return ECDSA_size(pkey->pkey.ec);
352280304Sjkim}
353238384Sjkim
354238384Sjkimstatic int ec_bits(const EVP_PKEY *pkey)
355280304Sjkim{
356280304Sjkim    BIGNUM *order = BN_new();
357280304Sjkim    const EC_GROUP *group;
358280304Sjkim    int ret;
359238384Sjkim
360280304Sjkim    if (!order) {
361280304Sjkim        ERR_clear_error();
362280304Sjkim        return 0;
363280304Sjkim    }
364280304Sjkim    group = EC_KEY_get0_group(pkey->pkey.ec);
365280304Sjkim    if (!EC_GROUP_get_order(group, order, NULL)) {
366280304Sjkim        ERR_clear_error();
367280304Sjkim        return 0;
368280304Sjkim    }
369238384Sjkim
370280304Sjkim    ret = BN_num_bits(order);
371280304Sjkim    BN_free(order);
372280304Sjkim    return ret;
373280304Sjkim}
374238384Sjkim
375238384Sjkimstatic int ec_missing_parameters(const EVP_PKEY *pkey)
376280304Sjkim{
377280304Sjkim    if (EC_KEY_get0_group(pkey->pkey.ec) == NULL)
378280304Sjkim        return 1;
379280304Sjkim    return 0;
380280304Sjkim}
381238384Sjkim
382238384Sjkimstatic int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
383280304Sjkim{
384280304Sjkim    EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
385280304Sjkim    if (group == NULL)
386280304Sjkim        return 0;
387280304Sjkim    if (EC_KEY_set_group(to->pkey.ec, group) == 0)
388280304Sjkim        return 0;
389280304Sjkim    EC_GROUP_free(group);
390280304Sjkim    return 1;
391280304Sjkim}
392238384Sjkim
393238384Sjkimstatic int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
394280304Sjkim{
395280304Sjkim    const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
396280304Sjkim        *group_b = EC_KEY_get0_group(b->pkey.ec);
397280304Sjkim    if (EC_GROUP_cmp(group_a, group_b, NULL))
398280304Sjkim        return 0;
399280304Sjkim    else
400280304Sjkim        return 1;
401280304Sjkim}
402238384Sjkim
403238384Sjkimstatic void int_ec_free(EVP_PKEY *pkey)
404280304Sjkim{
405280304Sjkim    EC_KEY_free(pkey->pkey.ec);
406280304Sjkim}
407238384Sjkim
408238384Sjkimstatic int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
409280304Sjkim{
410280304Sjkim    unsigned char *buffer = NULL;
411280304Sjkim    const char *ecstr;
412280304Sjkim    size_t buf_len = 0, i;
413280304Sjkim    int ret = 0, reason = ERR_R_BIO_LIB;
414280304Sjkim    BIGNUM *pub_key = NULL, *order = NULL;
415280304Sjkim    BN_CTX *ctx = NULL;
416280304Sjkim    const EC_GROUP *group;
417280304Sjkim    const EC_POINT *public_key;
418280304Sjkim    const BIGNUM *priv_key;
419238384Sjkim
420280304Sjkim    if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
421280304Sjkim        reason = ERR_R_PASSED_NULL_PARAMETER;
422280304Sjkim        goto err;
423280304Sjkim    }
424238384Sjkim
425280304Sjkim    ctx = BN_CTX_new();
426280304Sjkim    if (ctx == NULL) {
427280304Sjkim        reason = ERR_R_MALLOC_FAILURE;
428280304Sjkim        goto err;
429280304Sjkim    }
430238384Sjkim
431280304Sjkim    if (ktype > 0) {
432280304Sjkim        public_key = EC_KEY_get0_public_key(x);
433280304Sjkim        if (public_key != NULL) {
434280304Sjkim            if ((pub_key = EC_POINT_point2bn(group, public_key,
435280304Sjkim                                             EC_KEY_get_conv_form(x), NULL,
436280304Sjkim                                             ctx)) == NULL) {
437280304Sjkim                reason = ERR_R_EC_LIB;
438280304Sjkim                goto err;
439280304Sjkim            }
440280304Sjkim            buf_len = (size_t)BN_num_bytes(pub_key);
441280304Sjkim        }
442280304Sjkim    }
443238384Sjkim
444280304Sjkim    if (ktype == 2) {
445280304Sjkim        priv_key = EC_KEY_get0_private_key(x);
446280304Sjkim        if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
447280304Sjkim            buf_len = i;
448280304Sjkim    } else
449280304Sjkim        priv_key = NULL;
450238384Sjkim
451280304Sjkim    if (ktype > 0) {
452280304Sjkim        buf_len += 10;
453280304Sjkim        if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
454280304Sjkim            reason = ERR_R_MALLOC_FAILURE;
455280304Sjkim            goto err;
456280304Sjkim        }
457280304Sjkim    }
458280304Sjkim    if (ktype == 2)
459280304Sjkim        ecstr = "Private-Key";
460280304Sjkim    else if (ktype == 1)
461280304Sjkim        ecstr = "Public-Key";
462280304Sjkim    else
463280304Sjkim        ecstr = "ECDSA-Parameters";
464238384Sjkim
465280304Sjkim    if (!BIO_indent(bp, off, 128))
466280304Sjkim        goto err;
467280304Sjkim    if ((order = BN_new()) == NULL)
468280304Sjkim        goto err;
469280304Sjkim    if (!EC_GROUP_get_order(group, order, NULL))
470280304Sjkim        goto err;
471280304Sjkim    if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0)
472280304Sjkim        goto err;
473280304Sjkim
474280304Sjkim    if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key,
475280304Sjkim                                             buffer, off))
476280304Sjkim        goto err;
477280304Sjkim    if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key,
478280304Sjkim                                            buffer, off))
479280304Sjkim        goto err;
480280304Sjkim    if (!ECPKParameters_print(bp, group, off))
481280304Sjkim        goto err;
482280304Sjkim    ret = 1;
483280304Sjkim err:
484280304Sjkim    if (!ret)
485280304Sjkim        ECerr(EC_F_DO_EC_KEY_PRINT, reason);
486280304Sjkim    if (pub_key)
487280304Sjkim        BN_free(pub_key);
488280304Sjkim    if (order)
489280304Sjkim        BN_free(order);
490280304Sjkim    if (ctx)
491280304Sjkim        BN_CTX_free(ctx);
492280304Sjkim    if (buffer != NULL)
493280304Sjkim        OPENSSL_free(buffer);
494280304Sjkim    return (ret);
495280304Sjkim}
496280304Sjkim
497238384Sjkimstatic int eckey_param_decode(EVP_PKEY *pkey,
498280304Sjkim                              const unsigned char **pder, int derlen)
499280304Sjkim{
500280304Sjkim    EC_KEY *eckey;
501280304Sjkim    if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
502280304Sjkim        ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
503280304Sjkim        return 0;
504280304Sjkim    }
505280304Sjkim    EVP_PKEY_assign_EC_KEY(pkey, eckey);
506280304Sjkim    return 1;
507280304Sjkim}
508238384Sjkim
509238384Sjkimstatic int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
510280304Sjkim{
511280304Sjkim    return i2d_ECParameters(pkey->pkey.ec, pder);
512280304Sjkim}
513238384Sjkim
514238384Sjkimstatic int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
515280304Sjkim                             ASN1_PCTX *ctx)
516280304Sjkim{
517280304Sjkim    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
518280304Sjkim}
519238384Sjkim
520238384Sjkimstatic int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
521280304Sjkim                           ASN1_PCTX *ctx)
522280304Sjkim{
523280304Sjkim    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
524280304Sjkim}
525238384Sjkim
526238384Sjkimstatic int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
527280304Sjkim                            ASN1_PCTX *ctx)
528280304Sjkim{
529280304Sjkim    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
530280304Sjkim}
531238384Sjkim
532238384Sjkimstatic int old_ec_priv_decode(EVP_PKEY *pkey,
533280304Sjkim                              const unsigned char **pder, int derlen)
534280304Sjkim{
535280304Sjkim    EC_KEY *ec;
536280304Sjkim    if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
537280304Sjkim        ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
538280304Sjkim        return 0;
539280304Sjkim    }
540280304Sjkim    EVP_PKEY_assign_EC_KEY(pkey, ec);
541280304Sjkim    return 1;
542280304Sjkim}
543238384Sjkim
544238384Sjkimstatic int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
545280304Sjkim{
546280304Sjkim    return i2d_ECPrivateKey(pkey->pkey.ec, pder);
547280304Sjkim}
548238384Sjkim
549238384Sjkimstatic int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
550280304Sjkim{
551280304Sjkim    switch (op) {
552280304Sjkim    case ASN1_PKEY_CTRL_PKCS7_SIGN:
553280304Sjkim        if (arg1 == 0) {
554280304Sjkim            int snid, hnid;
555280304Sjkim            X509_ALGOR *alg1, *alg2;
556280304Sjkim            PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
557280304Sjkim            if (alg1 == NULL || alg1->algorithm == NULL)
558280304Sjkim                return -1;
559280304Sjkim            hnid = OBJ_obj2nid(alg1->algorithm);
560280304Sjkim            if (hnid == NID_undef)
561280304Sjkim                return -1;
562280304Sjkim            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
563280304Sjkim                return -1;
564280304Sjkim            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
565280304Sjkim        }
566280304Sjkim        return 1;
567238384Sjkim#ifndef OPENSSL_NO_CMS
568280304Sjkim    case ASN1_PKEY_CTRL_CMS_SIGN:
569280304Sjkim        if (arg1 == 0) {
570280304Sjkim            int snid, hnid;
571280304Sjkim            X509_ALGOR *alg1, *alg2;
572280304Sjkim            CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
573280304Sjkim            if (alg1 == NULL || alg1->algorithm == NULL)
574280304Sjkim                return -1;
575280304Sjkim            hnid = OBJ_obj2nid(alg1->algorithm);
576280304Sjkim            if (hnid == NID_undef)
577280304Sjkim                return -1;
578280304Sjkim            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
579280304Sjkim                return -1;
580280304Sjkim            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
581280304Sjkim        }
582280304Sjkim        return 1;
583238384Sjkim#endif
584238384Sjkim
585280304Sjkim    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
586280304Sjkim        *(int *)arg2 = NID_sha1;
587280304Sjkim        return 2;
588238384Sjkim
589280304Sjkim    default:
590280304Sjkim        return -2;
591238384Sjkim
592280304Sjkim    }
593238384Sjkim
594280304Sjkim}
595238384Sjkim
596280304Sjkimconst EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
597280304Sjkim    EVP_PKEY_EC,
598280304Sjkim    EVP_PKEY_EC,
599280304Sjkim    0,
600280304Sjkim    "EC",
601280304Sjkim    "OpenSSL EC algorithm",
602238384Sjkim
603280304Sjkim    eckey_pub_decode,
604280304Sjkim    eckey_pub_encode,
605280304Sjkim    eckey_pub_cmp,
606280304Sjkim    eckey_pub_print,
607238384Sjkim
608280304Sjkim    eckey_priv_decode,
609280304Sjkim    eckey_priv_encode,
610280304Sjkim    eckey_priv_print,
611238384Sjkim
612280304Sjkim    int_ec_size,
613280304Sjkim    ec_bits,
614238384Sjkim
615280304Sjkim    eckey_param_decode,
616280304Sjkim    eckey_param_encode,
617280304Sjkim    ec_missing_parameters,
618280304Sjkim    ec_copy_parameters,
619280304Sjkim    ec_cmp_parameters,
620280304Sjkim    eckey_param_print,
621280304Sjkim    0,
622238384Sjkim
623280304Sjkim    int_ec_free,
624280304Sjkim    ec_pkey_ctrl,
625280304Sjkim    old_ec_priv_decode,
626280304Sjkim    old_ec_priv_encode
627280304Sjkim};
628