1238384Sjkim/**********************************************************************
2238384Sjkim *                          gost_ameth.c                              *
3238384Sjkim *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4238384Sjkim *         This file is distributed under the same license as OpenSSL *
5238384Sjkim *                                                                    *
6238384Sjkim *       Implementation of RFC 4490/4491 ASN1 method                  *
7238384Sjkim *       for OpenSSL                                                  *
8238384Sjkim *          Requires OpenSSL 0.9.9 for compilation                    *
9238384Sjkim **********************************************************************/
10238384Sjkim#include <string.h>
11238384Sjkim#include <openssl/crypto.h>
12238384Sjkim#include <openssl/err.h>
13238384Sjkim#include <openssl/engine.h>
14238384Sjkim#include <openssl/evp.h>
15238384Sjkim#include <openssl/asn1.h>
16238384Sjkim#ifndef OPENSSL_NO_CMS
17280297Sjkim# include <openssl/cms.h>
18238384Sjkim#endif
19238384Sjkim#include "gost_params.h"
20238384Sjkim#include "gost_lcl.h"
21238384Sjkim#include "e_gost_err.h"
22238384Sjkim
23280297Sjkimint gost94_nid_by_params(DSA *p)
24280297Sjkim{
25280297Sjkim    R3410_params *gost_params;
26280297Sjkim    BIGNUM *q = BN_new();
27280297Sjkim    for (gost_params = R3410_paramset; gost_params->q != NULL; gost_params++) {
28280297Sjkim        BN_dec2bn(&q, gost_params->q);
29280297Sjkim        if (!BN_cmp(q, p->q)) {
30280297Sjkim            BN_free(q);
31280297Sjkim            return gost_params->nid;
32280297Sjkim        }
33280297Sjkim    }
34280297Sjkim    BN_free(q);
35280297Sjkim    return NID_undef;
36280297Sjkim}
37238384Sjkim
38280297Sjkimstatic ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
39280297Sjkim{
40280297Sjkim    ASN1_STRING *params = ASN1_STRING_new();
41280297Sjkim    GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
42280297Sjkim    int pkey_param_nid = NID_undef;
43238384Sjkim
44280297Sjkim    if (!params || !gkp) {
45280297Sjkim        GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
46280297Sjkim        ASN1_STRING_free(params);
47280297Sjkim        params = NULL;
48280297Sjkim        goto err;
49280297Sjkim    }
50280297Sjkim    switch (EVP_PKEY_base_id(key)) {
51280297Sjkim    case NID_id_GostR3410_2001:
52280297Sjkim        pkey_param_nid =
53280297Sjkim            EC_GROUP_get_curve_name(EC_KEY_get0_group
54280297Sjkim                                    (EVP_PKEY_get0((EVP_PKEY *)key)));
55280297Sjkim        break;
56280297Sjkim    case NID_id_GostR3410_94:
57280297Sjkim        pkey_param_nid =
58280297Sjkim            (int)gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
59280297Sjkim        if (pkey_param_nid == NID_undef) {
60280297Sjkim            GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
61280297Sjkim                    GOST_R_INVALID_GOST94_PARMSET);
62280297Sjkim            ASN1_STRING_free(params);
63280297Sjkim            params = NULL;
64280297Sjkim            goto err;
65280297Sjkim        }
66280297Sjkim        break;
67280297Sjkim    }
68280297Sjkim    gkp->key_params = OBJ_nid2obj(pkey_param_nid);
69280297Sjkim    gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
70280297Sjkim    /*
71280297Sjkim     * gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);
72280297Sjkim     */
73280297Sjkim    params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
74280297Sjkim    if (params->length <= 0) {
75280297Sjkim        GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
76280297Sjkim        ASN1_STRING_free(params);
77280297Sjkim        params = NULL;
78280297Sjkim        goto err;
79280297Sjkim    }
80280297Sjkim    params->type = V_ASN1_SEQUENCE;
81280297Sjkim err:
82280297Sjkim    GOST_KEY_PARAMS_free(gkp);
83280297Sjkim    return params;
84280297Sjkim}
85238384Sjkim
86280297Sjkim/*
87280297Sjkim * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting
88280297Sjkim * NID and parameters
89238384Sjkim */
90280297Sjkimstatic int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
91280297Sjkim{
92280297Sjkim    ASN1_OBJECT *palg_obj = NULL;
93280297Sjkim    int ptype = V_ASN1_UNDEF;
94280297Sjkim    int pkey_nid = NID_undef, param_nid = NID_undef;
95280297Sjkim    void *_pval;
96280297Sjkim    ASN1_STRING *pval = NULL;
97280297Sjkim    const unsigned char *p;
98280297Sjkim    GOST_KEY_PARAMS *gkp = NULL;
99238384Sjkim
100280297Sjkim    X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg);
101280297Sjkim    pval = _pval;
102280297Sjkim    if (ptype != V_ASN1_SEQUENCE) {
103280297Sjkim        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
104280297Sjkim                GOST_R_BAD_KEY_PARAMETERS_FORMAT);
105280297Sjkim        return 0;
106280297Sjkim    }
107280297Sjkim    p = pval->data;
108280297Sjkim    pkey_nid = OBJ_obj2nid(palg_obj);
109238384Sjkim
110280297Sjkim    gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length);
111280297Sjkim    if (!gkp) {
112280297Sjkim        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
113280297Sjkim                GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
114280297Sjkim        return 0;
115280297Sjkim    }
116280297Sjkim    param_nid = OBJ_obj2nid(gkp->key_params);
117280297Sjkim    GOST_KEY_PARAMS_free(gkp);
118284283Sjkim    if(!EVP_PKEY_set_type(pkey, pkey_nid)) {
119284283Sjkim        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR);
120284283Sjkim        return 0;
121284283Sjkim    }
122280297Sjkim    switch (pkey_nid) {
123280297Sjkim    case NID_id_GostR3410_94:
124280297Sjkim        {
125280297Sjkim            DSA *dsa = EVP_PKEY_get0(pkey);
126280297Sjkim            if (!dsa) {
127280297Sjkim                dsa = DSA_new();
128280297Sjkim                if (!EVP_PKEY_assign(pkey, pkey_nid, dsa))
129280297Sjkim                    return 0;
130280297Sjkim            }
131280297Sjkim            if (!fill_GOST94_params(dsa, param_nid))
132280297Sjkim                return 0;
133280297Sjkim            break;
134280297Sjkim        }
135280297Sjkim    case NID_id_GostR3410_2001:
136280297Sjkim        {
137280297Sjkim            EC_KEY *ec = EVP_PKEY_get0(pkey);
138280297Sjkim            if (!ec) {
139280297Sjkim                ec = EC_KEY_new();
140280297Sjkim                if (!EVP_PKEY_assign(pkey, pkey_nid, ec))
141280297Sjkim                    return 0;
142280297Sjkim            }
143280297Sjkim            if (!fill_GOST2001_params(ec, param_nid))
144280297Sjkim                return 0;
145280297Sjkim        }
146280297Sjkim    }
147238384Sjkim
148280297Sjkim    return 1;
149280297Sjkim}
150238384Sjkim
151280297Sjkimstatic int gost_set_priv_key(EVP_PKEY *pkey, BIGNUM *priv)
152280297Sjkim{
153280297Sjkim    switch (EVP_PKEY_base_id(pkey)) {
154280297Sjkim    case NID_id_GostR3410_94:
155280297Sjkim        {
156280297Sjkim            DSA *dsa = EVP_PKEY_get0(pkey);
157280297Sjkim            if (!dsa) {
158280297Sjkim                dsa = DSA_new();
159280297Sjkim                EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), dsa);
160280297Sjkim            }
161280297Sjkim            dsa->priv_key = BN_dup(priv);
162280297Sjkim            if (!EVP_PKEY_missing_parameters(pkey))
163280297Sjkim                gost94_compute_public(dsa);
164280297Sjkim            break;
165280297Sjkim        }
166280297Sjkim    case NID_id_GostR3410_2001:
167280297Sjkim        {
168280297Sjkim            EC_KEY *ec = EVP_PKEY_get0(pkey);
169280297Sjkim            if (!ec) {
170280297Sjkim                ec = EC_KEY_new();
171280297Sjkim                EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), ec);
172280297Sjkim            }
173280297Sjkim            if (!EC_KEY_set_private_key(ec, priv))
174280297Sjkim                return 0;
175280297Sjkim            if (!EVP_PKEY_missing_parameters(pkey))
176280297Sjkim                gost2001_compute_public(ec);
177280297Sjkim            break;
178280297Sjkim        }
179280297Sjkim    }
180280297Sjkim    return 1;
181280297Sjkim}
182238384Sjkim
183280297SjkimBIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
184280297Sjkim{
185280297Sjkim    switch (EVP_PKEY_base_id(pkey)) {
186280297Sjkim    case NID_id_GostR3410_94:
187280297Sjkim        {
188280297Sjkim            DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
189280297Sjkim            if (!dsa) {
190280297Sjkim                return NULL;
191280297Sjkim            }
192280297Sjkim            if (!dsa->priv_key)
193280297Sjkim                return NULL;
194280297Sjkim            return dsa->priv_key;
195280297Sjkim            break;
196280297Sjkim        }
197280297Sjkim    case NID_id_GostR3410_2001:
198280297Sjkim        {
199280297Sjkim            EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
200280297Sjkim            const BIGNUM *priv;
201280297Sjkim            if (!ec) {
202280297Sjkim                return NULL;
203280297Sjkim            }
204280297Sjkim            if (!(priv = EC_KEY_get0_private_key(ec)))
205280297Sjkim                return NULL;
206280297Sjkim            return (BIGNUM *)priv;
207280297Sjkim            break;
208280297Sjkim        }
209280297Sjkim    }
210280297Sjkim    return NULL;
211280297Sjkim}
212280297Sjkim
213280297Sjkimstatic int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
214280297Sjkim{
215280297Sjkim    switch (op) {
216280297Sjkim    case ASN1_PKEY_CTRL_PKCS7_SIGN:
217280297Sjkim        if (arg1 == 0) {
218280297Sjkim            X509_ALGOR *alg1 = NULL, *alg2 = NULL;
219280297Sjkim            int nid = EVP_PKEY_base_id(pkey);
220280297Sjkim            PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO *)arg2,
221280297Sjkim                                        NULL, &alg1, &alg2);
222280297Sjkim            X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
223280297Sjkim                            V_ASN1_NULL, 0);
224280297Sjkim            if (nid == NID_undef) {
225280297Sjkim                return (-1);
226280297Sjkim            }
227280297Sjkim            X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
228280297Sjkim        }
229280297Sjkim        return 1;
230238384Sjkim#ifndef OPENSSL_NO_CMS
231280297Sjkim    case ASN1_PKEY_CTRL_CMS_SIGN:
232280297Sjkim        if (arg1 == 0) {
233280297Sjkim            X509_ALGOR *alg1 = NULL, *alg2 = NULL;
234280297Sjkim            int nid = EVP_PKEY_base_id(pkey);
235280297Sjkim            CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2,
236280297Sjkim                                     NULL, NULL, &alg1, &alg2);
237280297Sjkim            X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
238280297Sjkim                            V_ASN1_NULL, 0);
239280297Sjkim            if (nid == NID_undef) {
240280297Sjkim                return (-1);
241280297Sjkim            }
242280297Sjkim            X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
243280297Sjkim        }
244280297Sjkim        return 1;
245238384Sjkim#endif
246280297Sjkim    case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
247280297Sjkim        if (arg1 == 0) {
248280297Sjkim            X509_ALGOR *alg;
249280297Sjkim            ASN1_STRING *params = encode_gost_algor_params(pkey);
250280297Sjkim            if (!params) {
251280297Sjkim                return -1;
252280297Sjkim            }
253280297Sjkim            PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO *)arg2, &alg);
254280297Sjkim            X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type),
255280297Sjkim                            V_ASN1_SEQUENCE, params);
256280297Sjkim        }
257280297Sjkim        return 1;
258238384Sjkim#ifndef OPENSSL_NO_CMS
259280297Sjkim    case ASN1_PKEY_CTRL_CMS_ENVELOPE:
260280297Sjkim        if (arg1 == 0) {
261280297Sjkim            X509_ALGOR *alg = NULL;
262280297Sjkim            ASN1_STRING *params = encode_gost_algor_params(pkey);
263280297Sjkim            if (!params) {
264280297Sjkim                return -1;
265280297Sjkim            }
266280297Sjkim            CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
267280297Sjkim                                             NULL, &alg);
268280297Sjkim            X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type), V_ASN1_SEQUENCE,
269280297Sjkim                            params);
270280297Sjkim        }
271280297Sjkim        return 1;
272238384Sjkim#endif
273280297Sjkim    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
274280297Sjkim        *(int *)arg2 = NID_id_GostR3411_94;
275280297Sjkim        return 2;
276280297Sjkim    }
277238384Sjkim
278280297Sjkim    return -2;
279280297Sjkim}
280238384Sjkim
281280297Sjkim/* --------------------- free functions * ------------------------------*/
282280297Sjkimstatic void pkey_free_gost94(EVP_PKEY *key)
283280297Sjkim{
284280297Sjkim    if (key->pkey.dsa) {
285280297Sjkim        DSA_free(key->pkey.dsa);
286280297Sjkim    }
287280297Sjkim}
288280297Sjkim
289280297Sjkimstatic void pkey_free_gost01(EVP_PKEY *key)
290280297Sjkim{
291280297Sjkim    if (key->pkey.ec) {
292280297Sjkim        EC_KEY_free(key->pkey.ec);
293280297Sjkim    }
294280297Sjkim}
295280297Sjkim
296238384Sjkim/* ------------------ private key functions  -----------------------------*/
297280297Sjkimstatic int priv_decode_gost(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
298280297Sjkim{
299280297Sjkim    const unsigned char *pkey_buf = NULL, *p = NULL;
300280297Sjkim    int priv_len = 0;
301280297Sjkim    BIGNUM *pk_num = NULL;
302280297Sjkim    int ret = 0;
303280297Sjkim    X509_ALGOR *palg = NULL;
304280297Sjkim    ASN1_OBJECT *palg_obj = NULL;
305280297Sjkim    ASN1_INTEGER *priv_key = NULL;
306238384Sjkim
307280297Sjkim    if (!PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf))
308280297Sjkim        return 0;
309280297Sjkim    p = pkey_buf;
310280297Sjkim    if (!decode_gost_algor_params(pk, palg)) {
311280297Sjkim        return 0;
312280297Sjkim    }
313280297Sjkim    if (V_ASN1_OCTET_STRING == *p) {
314280297Sjkim        /* New format - Little endian octet string */
315280297Sjkim        unsigned char rev_buf[32];
316280297Sjkim        int i;
317280297Sjkim        ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
318280297Sjkim        if (!s || s->length != 32) {
319280297Sjkim            GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
320280297Sjkim            return 0;
321280297Sjkim        }
322280297Sjkim        for (i = 0; i < 32; i++) {
323280297Sjkim            rev_buf[31 - i] = s->data[i];
324280297Sjkim        }
325280297Sjkim        ASN1_STRING_free(s);
326280297Sjkim        pk_num = getbnfrombuf(rev_buf, 32);
327280297Sjkim    } else {
328280297Sjkim        priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
329280297Sjkim        if (!priv_key)
330280297Sjkim            return 0;
331280297Sjkim        ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
332280297Sjkim        ASN1_INTEGER_free(priv_key);
333280297Sjkim        if (!ret) {
334280297Sjkim            GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
335280297Sjkim            return 0;
336280297Sjkim        }
337280297Sjkim    }
338238384Sjkim
339280297Sjkim    ret = gost_set_priv_key(pk, pk_num);
340280297Sjkim    BN_free(pk_num);
341280297Sjkim    return ret;
342280297Sjkim}
343238384Sjkim
344238384Sjkim/* ----------------------------------------------------------------------*/
345238384Sjkimstatic int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
346280297Sjkim{
347280297Sjkim    ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
348280297Sjkim    ASN1_STRING *params = encode_gost_algor_params(pk);
349280297Sjkim    unsigned char *priv_buf = NULL;
350280297Sjkim    int priv_len;
351238384Sjkim
352280297Sjkim    ASN1_INTEGER *asn1key = NULL;
353280297Sjkim    if (!params) {
354280297Sjkim        return 0;
355280297Sjkim    }
356280297Sjkim    asn1key = BN_to_ASN1_INTEGER(gost_get0_priv_key(pk), NULL);
357280297Sjkim    priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
358280297Sjkim    ASN1_INTEGER_free(asn1key);
359280297Sjkim    return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
360280297Sjkim                           priv_buf, priv_len);
361280297Sjkim}
362280297Sjkim
363238384Sjkim/* --------- printing keys --------------------------------*/
364238384Sjkimstatic int print_gost_94(BIO *out, const EVP_PKEY *pkey, int indent,
365280297Sjkim                         ASN1_PCTX *pctx, int type)
366280297Sjkim{
367280297Sjkim    int param_nid = NID_undef;
368238384Sjkim
369280297Sjkim    if (type == 2) {
370280297Sjkim        BIGNUM *key;
371238384Sjkim
372280297Sjkim        if (!BIO_indent(out, indent, 128))
373280297Sjkim            return 0;
374280297Sjkim        BIO_printf(out, "Private key: ");
375280297Sjkim        key = gost_get0_priv_key(pkey);
376280297Sjkim        if (!key)
377280297Sjkim            BIO_printf(out, "<undefined>");
378280297Sjkim        else
379280297Sjkim            BN_print(out, key);
380280297Sjkim        BIO_printf(out, "\n");
381280297Sjkim    }
382280297Sjkim    if (type >= 1) {
383280297Sjkim        BIGNUM *pubkey;
384238384Sjkim
385280297Sjkim        pubkey = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
386280297Sjkim        BIO_indent(out, indent, 128);
387280297Sjkim        BIO_printf(out, "Public key: ");
388280297Sjkim        BN_print(out, pubkey);
389280297Sjkim        BIO_printf(out, "\n");
390280297Sjkim    }
391280297Sjkim
392280297Sjkim    param_nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
393280297Sjkim    BIO_indent(out, indent, 128);
394280297Sjkim    BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
395280297Sjkim    return 1;
396238384Sjkim}
397238384Sjkim
398238384Sjkimstatic int param_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
399280297Sjkim                              ASN1_PCTX *pctx)
400280297Sjkim{
401280297Sjkim    return print_gost_94(out, pkey, indent, pctx, 0);
402280297Sjkim}
403238384Sjkim
404238384Sjkimstatic int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
405280297Sjkim                            ASN1_PCTX *pctx)
406280297Sjkim{
407280297Sjkim    return print_gost_94(out, pkey, indent, pctx, 1);
408280297Sjkim}
409238384Sjkim
410280297Sjkimstatic int priv_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
411280297Sjkim                             ASN1_PCTX *pctx)
412280297Sjkim{
413280297Sjkim    return print_gost_94(out, pkey, indent, pctx, 2);
414280297Sjkim}
415280297Sjkim
416238384Sjkimstatic int print_gost_01(BIO *out, const EVP_PKEY *pkey, int indent,
417280297Sjkim                         ASN1_PCTX *pctx, int type)
418280297Sjkim{
419280297Sjkim    int param_nid = NID_undef;
420280297Sjkim    if (type == 2) {
421280297Sjkim        BIGNUM *key;
422238384Sjkim
423280297Sjkim        if (!BIO_indent(out, indent, 128))
424280297Sjkim            return 0;
425280297Sjkim        BIO_printf(out, "Private key: ");
426280297Sjkim        key = gost_get0_priv_key(pkey);
427280297Sjkim        if (!key)
428280297Sjkim            BIO_printf(out, "<undefined)");
429280297Sjkim        else
430280297Sjkim            BN_print(out, key);
431280297Sjkim        BIO_printf(out, "\n");
432280297Sjkim    }
433280297Sjkim    if (type >= 1) {
434280297Sjkim        BN_CTX *ctx = BN_CTX_new();
435280297Sjkim        BIGNUM *X, *Y;
436280297Sjkim        const EC_POINT *pubkey;
437280297Sjkim        const EC_GROUP *group;
438238384Sjkim
439280297Sjkim        if (!ctx) {
440280297Sjkim            GOSTerr(GOST_F_PRINT_GOST_01, ERR_R_MALLOC_FAILURE);
441280297Sjkim            return 0;
442280297Sjkim        }
443280297Sjkim        BN_CTX_start(ctx);
444280297Sjkim        X = BN_CTX_get(ctx);
445280297Sjkim        Y = BN_CTX_get(ctx);
446280297Sjkim        pubkey =
447280297Sjkim            EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
448280297Sjkim        group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
449280297Sjkim        if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) {
450280297Sjkim            GOSTerr(GOST_F_PRINT_GOST_01, ERR_R_EC_LIB);
451280297Sjkim            BN_CTX_free(ctx);
452280297Sjkim            return 0;
453280297Sjkim        }
454280297Sjkim        if (!BIO_indent(out, indent, 128))
455280297Sjkim            return 0;
456280297Sjkim        BIO_printf(out, "Public key:\n");
457280297Sjkim        if (!BIO_indent(out, indent + 3, 128))
458280297Sjkim            return 0;
459280297Sjkim        BIO_printf(out, "X:");
460280297Sjkim        BN_print(out, X);
461280297Sjkim        BIO_printf(out, "\n");
462280297Sjkim        BIO_indent(out, indent + 3, 128);
463280297Sjkim        BIO_printf(out, "Y:");
464280297Sjkim        BN_print(out, Y);
465280297Sjkim        BIO_printf(out, "\n");
466280297Sjkim        BN_CTX_end(ctx);
467280297Sjkim        BN_CTX_free(ctx);
468280297Sjkim    }
469238384Sjkim
470280297Sjkim    param_nid =
471280297Sjkim        EC_GROUP_get_curve_name(EC_KEY_get0_group
472280297Sjkim                                (EVP_PKEY_get0((EVP_PKEY *)pkey)));
473280297Sjkim    if (!BIO_indent(out, indent, 128))
474280297Sjkim        return 0;
475280297Sjkim    BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
476280297Sjkim    return 1;
477238384Sjkim}
478280297Sjkim
479238384Sjkimstatic int param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
480280297Sjkim                              ASN1_PCTX *pctx)
481280297Sjkim{
482280297Sjkim    return print_gost_01(out, pkey, indent, pctx, 0);
483280297Sjkim}
484280297Sjkim
485238384Sjkimstatic int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
486280297Sjkim                            ASN1_PCTX *pctx)
487280297Sjkim{
488280297Sjkim    return print_gost_01(out, pkey, indent, pctx, 1);
489280297Sjkim}
490280297Sjkim
491280297Sjkimstatic int priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
492280297Sjkim                             ASN1_PCTX *pctx)
493280297Sjkim{
494280297Sjkim    return print_gost_01(out, pkey, indent, pctx, 2);
495280297Sjkim}
496280297Sjkim
497238384Sjkim/* ---------------------------------------------------------------------*/
498280297Sjkimstatic int param_missing_gost94(const EVP_PKEY *pk)
499280297Sjkim{
500280297Sjkim    const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
501280297Sjkim    if (!dsa)
502280297Sjkim        return 1;
503280297Sjkim    if (!dsa->q)
504280297Sjkim        return 1;
505280297Sjkim    return 0;
506280297Sjkim}
507238384Sjkim
508280297Sjkimstatic int param_missing_gost01(const EVP_PKEY *pk)
509280297Sjkim{
510280297Sjkim    const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
511280297Sjkim    if (!ec)
512280297Sjkim        return 1;
513280297Sjkim    if (!EC_KEY_get0_group(ec))
514280297Sjkim        return 1;
515280297Sjkim    return 0;
516280297Sjkim}
517238384Sjkim
518280297Sjkimstatic int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from)
519280297Sjkim{
520280297Sjkim    const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from);
521280297Sjkim    DSA *dto = EVP_PKEY_get0(to);
522280297Sjkim    if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
523280297Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_INCOMPATIBLE_ALGORITHMS);
524280297Sjkim        return 0;
525280297Sjkim    }
526280297Sjkim    if (!dfrom) {
527280297Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_KEY_PARAMETERS_MISSING);
528280297Sjkim        return 0;
529280297Sjkim    }
530280297Sjkim    if (!dto) {
531280297Sjkim        dto = DSA_new();
532280297Sjkim        EVP_PKEY_assign(to, EVP_PKEY_base_id(from), dto);
533280297Sjkim    }
534280297Sjkim#define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x);
535280297Sjkim    COPYBIGNUM(dto, dfrom, p)
536280297Sjkim        COPYBIGNUM(dto, dfrom, q)
537280297Sjkim        COPYBIGNUM(dto, dfrom, g)
538238384Sjkim
539280297Sjkim        if (dto->priv_key)
540280297Sjkim        gost94_compute_public(dto);
541280297Sjkim    return 1;
542280297Sjkim}
543238384Sjkim
544280297Sjkimstatic int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
545280297Sjkim{
546280297Sjkim    EC_KEY *eto = EVP_PKEY_get0(to);
547280297Sjkim    const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
548280297Sjkim    if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
549280297Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_INCOMPATIBLE_ALGORITHMS);
550280297Sjkim        return 0;
551280297Sjkim    }
552280297Sjkim    if (!efrom) {
553280297Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_KEY_PARAMETERS_MISSING);
554280297Sjkim        return 0;
555280297Sjkim    }
556280297Sjkim    if (!eto) {
557280297Sjkim        eto = EC_KEY_new();
558284283Sjkim        if(!eto) {
559284283Sjkim            GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_MALLOC_FAILURE);
560284283Sjkim            return 0;
561284283Sjkim        }
562284283Sjkim        if(!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
563284283Sjkim            GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
564284283Sjkim            return 0;
565284283Sjkim        }
566280297Sjkim    }
567284283Sjkim    if(!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
568284283Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
569284283Sjkim        return 0;
570284283Sjkim    }
571280297Sjkim    if (EC_KEY_get0_private_key(eto)) {
572280297Sjkim        gost2001_compute_public(eto);
573280297Sjkim    }
574280297Sjkim    return 1;
575280297Sjkim}
576238384Sjkim
577280297Sjkimstatic int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
578280297Sjkim{
579280297Sjkim    const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
580280297Sjkim    const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
581280297Sjkim    if (!BN_cmp(da->q, db->q))
582280297Sjkim        return 1;
583280297Sjkim    return 0;
584280297Sjkim}
585238384Sjkim
586280297Sjkimstatic int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
587280297Sjkim{
588280297Sjkim    if (EC_GROUP_get_curve_name
589280297Sjkim        (EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a))) ==
590280297Sjkim        EC_GROUP_get_curve_name(EC_KEY_get0_group
591280297Sjkim                                (EVP_PKEY_get0((EVP_PKEY *)b)))) {
592280297Sjkim        return 1;
593280297Sjkim    }
594280297Sjkim    return 0;
595238384Sjkim
596280297Sjkim}
597280297Sjkim
598238384Sjkim/* ---------- Public key functions * --------------------------------------*/
599238384Sjkimstatic int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
600280297Sjkim{
601280297Sjkim    X509_ALGOR *palg = NULL;
602280297Sjkim    const unsigned char *pubkey_buf = NULL;
603280297Sjkim    unsigned char *databuf;
604280297Sjkim    ASN1_OBJECT *palgobj = NULL;
605280297Sjkim    int pub_len, i, j;
606280297Sjkim    DSA *dsa;
607280297Sjkim    ASN1_OCTET_STRING *octet = NULL;
608238384Sjkim
609280297Sjkim    if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
610280297Sjkim        return 0;
611280297Sjkim    EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
612280297Sjkim    if (!decode_gost_algor_params(pk, palg))
613280297Sjkim        return 0;
614280297Sjkim    octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
615280297Sjkim    if (!octet) {
616280297Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST94, ERR_R_MALLOC_FAILURE);
617280297Sjkim        return 0;
618280297Sjkim    }
619280297Sjkim    databuf = OPENSSL_malloc(octet->length);
620306195Sjkim    if (databuf == NULL) {
621306195Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST94, ERR_R_MALLOC_FAILURE);
622306195Sjkim        return 0;
623306195Sjkim    }
624280297Sjkim    for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
625280297Sjkim        databuf[j] = octet->data[i];
626280297Sjkim    }
627280297Sjkim    dsa = EVP_PKEY_get0(pk);
628280297Sjkim    dsa->pub_key = BN_bin2bn(databuf, octet->length, NULL);
629280297Sjkim    ASN1_OCTET_STRING_free(octet);
630280297Sjkim    OPENSSL_free(databuf);
631280297Sjkim    return 1;
632238384Sjkim
633280297Sjkim}
634238384Sjkim
635280297Sjkimstatic int pub_encode_gost94(X509_PUBKEY *pub, const EVP_PKEY *pk)
636280297Sjkim{
637280297Sjkim    ASN1_OBJECT *algobj = NULL;
638280297Sjkim    ASN1_OCTET_STRING *octet = NULL;
639280297Sjkim    void *pval = NULL;
640280297Sjkim    unsigned char *buf = NULL, *databuf, *sptr;
641280297Sjkim    int i, j, data_len, ret = 0;
642238384Sjkim
643280297Sjkim    int ptype = V_ASN1_UNDEF;
644280297Sjkim    DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
645280297Sjkim    algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
646280297Sjkim    if (pk->save_parameters) {
647280297Sjkim        ASN1_STRING *params = encode_gost_algor_params(pk);
648280297Sjkim        pval = params;
649280297Sjkim        ptype = V_ASN1_SEQUENCE;
650280297Sjkim    }
651280297Sjkim    data_len = BN_num_bytes(dsa->pub_key);
652280297Sjkim    databuf = OPENSSL_malloc(data_len);
653306195Sjkim    if (databuf == NULL)
654306195Sjkim        return 0;
655280297Sjkim    BN_bn2bin(dsa->pub_key, databuf);
656280297Sjkim    octet = ASN1_OCTET_STRING_new();
657280297Sjkim    ASN1_STRING_set(octet, NULL, data_len);
658280297Sjkim    sptr = ASN1_STRING_data(octet);
659280297Sjkim    for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
660280297Sjkim        sptr[i] = databuf[j];
661280297Sjkim    }
662280297Sjkim    OPENSSL_free(databuf);
663280297Sjkim    ret = i2d_ASN1_OCTET_STRING(octet, &buf);
664280297Sjkim    ASN1_BIT_STRING_free(octet);
665280297Sjkim    if (ret < 0)
666280297Sjkim        return 0;
667280297Sjkim    return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
668280297Sjkim}
669238384Sjkim
670280297Sjkimstatic int pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
671280297Sjkim{
672280297Sjkim    X509_ALGOR *palg = NULL;
673280297Sjkim    const unsigned char *pubkey_buf = NULL;
674280297Sjkim    unsigned char *databuf;
675280297Sjkim    ASN1_OBJECT *palgobj = NULL;
676280297Sjkim    int pub_len, i, j;
677280297Sjkim    EC_POINT *pub_key;
678280297Sjkim    BIGNUM *X, *Y;
679280297Sjkim    ASN1_OCTET_STRING *octet = NULL;
680280297Sjkim    int len;
681280297Sjkim    const EC_GROUP *group;
682238384Sjkim
683280297Sjkim    if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
684280297Sjkim        return 0;
685280297Sjkim    EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
686280297Sjkim    if (!decode_gost_algor_params(pk, palg))
687280297Sjkim        return 0;
688280297Sjkim    group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
689280297Sjkim    octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
690280297Sjkim    if (!octet) {
691280297Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
692280297Sjkim        return 0;
693280297Sjkim    }
694280297Sjkim    databuf = OPENSSL_malloc(octet->length);
695306195Sjkim    if (databuf == NULL) {
696306195Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
697306195Sjkim        return 0;
698306195Sjkim    }
699280297Sjkim    for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
700280297Sjkim        databuf[j] = octet->data[i];
701280297Sjkim    }
702280297Sjkim    len = octet->length / 2;
703280297Sjkim    ASN1_OCTET_STRING_free(octet);
704238384Sjkim
705280297Sjkim    Y = getbnfrombuf(databuf, len);
706280297Sjkim    X = getbnfrombuf(databuf + len, len);
707280297Sjkim    OPENSSL_free(databuf);
708280297Sjkim    pub_key = EC_POINT_new(group);
709280297Sjkim    if (!EC_POINT_set_affine_coordinates_GFp(group, pub_key, X, Y, NULL)) {
710280297Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB);
711280297Sjkim        EC_POINT_free(pub_key);
712280297Sjkim        BN_free(X);
713280297Sjkim        BN_free(Y);
714280297Sjkim        return 0;
715280297Sjkim    }
716280297Sjkim    BN_free(X);
717280297Sjkim    BN_free(Y);
718280297Sjkim    if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
719280297Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB);
720280297Sjkim        EC_POINT_free(pub_key);
721280297Sjkim        return 0;
722280297Sjkim    }
723280297Sjkim    EC_POINT_free(pub_key);
724280297Sjkim    return 1;
725238384Sjkim
726280297Sjkim}
727238384Sjkim
728280297Sjkimstatic int pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
729280297Sjkim{
730280297Sjkim    ASN1_OBJECT *algobj = NULL;
731280297Sjkim    ASN1_OCTET_STRING *octet = NULL;
732280297Sjkim    void *pval = NULL;
733280297Sjkim    unsigned char *buf = NULL, *databuf, *sptr;
734280297Sjkim    int i, j, data_len, ret = 0;
735280297Sjkim    const EC_POINT *pub_key;
736280297Sjkim    BIGNUM *X, *Y, *order;
737280297Sjkim    const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
738280297Sjkim    int ptype = V_ASN1_UNDEF;
739238384Sjkim
740280297Sjkim    algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
741280297Sjkim    if (pk->save_parameters) {
742280297Sjkim        ASN1_STRING *params = encode_gost_algor_params(pk);
743280297Sjkim        pval = params;
744280297Sjkim        ptype = V_ASN1_SEQUENCE;
745280297Sjkim    }
746280297Sjkim    order = BN_new();
747280297Sjkim    EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
748280297Sjkim    pub_key = EC_KEY_get0_public_key(ec);
749280297Sjkim    if (!pub_key) {
750280297Sjkim        GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED);
751280297Sjkim        return 0;
752280297Sjkim    }
753280297Sjkim    X = BN_new();
754280297Sjkim    Y = BN_new();
755284283Sjkim    if(!X || !Y) {
756284283Sjkim        GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
757284283Sjkim        if(X) BN_free(X);
758284283Sjkim        if(Y) BN_free(Y);
759284283Sjkim        BN_free(order);
760284283Sjkim        return 0;
761284283Sjkim    }
762284283Sjkim    if(!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
763284283Sjkim                                        pub_key, X, Y, NULL)) {
764284283Sjkim        GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR);
765284283Sjkim        BN_free(X);
766284283Sjkim        BN_free(Y);
767284283Sjkim        BN_free(order);
768284283Sjkim        return 0;
769284283Sjkim    }
770280297Sjkim    data_len = 2 * BN_num_bytes(order);
771280297Sjkim    BN_free(order);
772280297Sjkim    databuf = OPENSSL_malloc(data_len);
773306195Sjkim    if (databuf == NULL) {
774306195Sjkim        GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
775306195Sjkim        return 0;
776306195Sjkim    }
777280297Sjkim    memset(databuf, 0, data_len);
778280297Sjkim
779280297Sjkim    store_bignum(X, databuf + data_len / 2, data_len / 2);
780280297Sjkim    store_bignum(Y, databuf, data_len / 2);
781280297Sjkim
782280297Sjkim    BN_free(X);
783280297Sjkim    BN_free(Y);
784280297Sjkim    octet = ASN1_OCTET_STRING_new();
785280297Sjkim    ASN1_STRING_set(octet, NULL, data_len);
786280297Sjkim    sptr = ASN1_STRING_data(octet);
787280297Sjkim    for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
788280297Sjkim        sptr[i] = databuf[j];
789280297Sjkim    }
790238384Sjkim    OPENSSL_free(databuf);
791280297Sjkim    ret = i2d_ASN1_OCTET_STRING(octet, &buf);
792280297Sjkim    ASN1_BIT_STRING_free(octet);
793280297Sjkim    if (ret < 0)
794280297Sjkim        return 0;
795280297Sjkim    return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
796280297Sjkim}
797238384Sjkim
798238384Sjkimstatic int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
799280297Sjkim{
800280297Sjkim    const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
801280297Sjkim    const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
802280297Sjkim    if (da && db && da->pub_key && db->pub_key
803280297Sjkim        && !BN_cmp(da->pub_key, db->pub_key)) {
804280297Sjkim        return 1;
805280297Sjkim    }
806280297Sjkim    return 0;
807280297Sjkim}
808238384Sjkim
809280297Sjkimstatic int pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
810280297Sjkim{
811280297Sjkim    const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
812280297Sjkim    const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
813280297Sjkim    const EC_POINT *ka, *kb;
814280297Sjkim    int ret = 0;
815280297Sjkim    if (!ea || !eb)
816280297Sjkim        return 0;
817280297Sjkim    ka = EC_KEY_get0_public_key(ea);
818280297Sjkim    kb = EC_KEY_get0_public_key(eb);
819280297Sjkim    if (!ka || !kb)
820280297Sjkim        return 0;
821280297Sjkim    ret = (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
822280297Sjkim    return ret;
823280297Sjkim}
824238384Sjkim
825238384Sjkimstatic int pkey_size_gost(const EVP_PKEY *pk)
826280297Sjkim{
827280297Sjkim    return 64;
828280297Sjkim}
829238384Sjkim
830238384Sjkimstatic int pkey_bits_gost(const EVP_PKEY *pk)
831238384Sjkim{
832280297Sjkim    return 256;
833280297Sjkim}
834238384Sjkim
835280297Sjkim/* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
836280297Sjkimstatic void mackey_free_gost(EVP_PKEY *pk)
837238384Sjkim{
838280297Sjkim    if (pk->pkey.ptr) {
839280297Sjkim        OPENSSL_free(pk->pkey.ptr);
840280297Sjkim    }
841238384Sjkim}
842280297Sjkim
843280297Sjkimstatic int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
844238384Sjkim{
845280297Sjkim    switch (op) {
846280297Sjkim    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
847280297Sjkim        *(int *)arg2 = NID_id_Gost28147_89_MAC;
848280297Sjkim        return 2;
849280297Sjkim    }
850280297Sjkim    return -2;
851238384Sjkim}
852238384Sjkim
853280297Sjkimstatic int gost94_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
854238384Sjkim{
855280297Sjkim    int nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
856280297Sjkim    return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
857280297Sjkim}
858238384Sjkim
859280297Sjkimstatic int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
860280297Sjkim{
861280297Sjkim    int nid =
862280297Sjkim        EC_GROUP_get_curve_name(EC_KEY_get0_group
863280297Sjkim                                (EVP_PKEY_get0((EVP_PKEY *)pkey)));
864280297Sjkim    return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
865280297Sjkim}
866238384Sjkim
867280297Sjkimstatic int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
868280297Sjkim                               int derlen)
869280297Sjkim{
870280297Sjkim    ASN1_OBJECT *obj = NULL;
871280297Sjkim    DSA *dsa = EVP_PKEY_get0(pkey);
872280297Sjkim    int nid;
873280297Sjkim    if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
874280297Sjkim        return 0;
875280297Sjkim    }
876280297Sjkim    nid = OBJ_obj2nid(obj);
877280297Sjkim    ASN1_OBJECT_free(obj);
878280297Sjkim    if (!dsa) {
879280297Sjkim        dsa = DSA_new();
880280297Sjkim        if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_94, dsa))
881280297Sjkim            return 0;
882280297Sjkim    }
883280297Sjkim    if (!fill_GOST94_params(dsa, nid))
884280297Sjkim        return 0;
885280297Sjkim    return 1;
886280297Sjkim}
887238384Sjkim
888280297Sjkimstatic int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
889280297Sjkim                                 int derlen)
890280297Sjkim{
891280297Sjkim    ASN1_OBJECT *obj = NULL;
892280297Sjkim    int nid;
893280297Sjkim    EC_KEY *ec = EVP_PKEY_get0(pkey);
894280297Sjkim    if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
895280297Sjkim        return 0;
896280297Sjkim    }
897280297Sjkim    nid = OBJ_obj2nid(obj);
898280297Sjkim    ASN1_OBJECT_free(obj);
899280297Sjkim    if (!ec) {
900280297Sjkim        ec = EC_KEY_new();
901280297Sjkim        if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec))
902280297Sjkim            return 0;
903280297Sjkim    }
904280297Sjkim    if (!fill_GOST2001_params(ec, nid))
905280297Sjkim        return 0;
906280297Sjkim    return 1;
907280297Sjkim}
908238384Sjkim
909280297Sjkim/* ----------------------------------------------------------------------*/
910280297Sjkimint register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
911280297Sjkim                        const char *pemstr, const char *info)
912280297Sjkim{
913280297Sjkim    *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
914280297Sjkim    if (!*ameth)
915280297Sjkim        return 0;
916280297Sjkim    switch (nid) {
917280297Sjkim    case NID_id_GostR3410_94:
918280297Sjkim        EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost94);
919280297Sjkim        EVP_PKEY_asn1_set_private(*ameth,
920280297Sjkim                                  priv_decode_gost, priv_encode_gost,
921280297Sjkim                                  priv_print_gost94);
922238384Sjkim
923280297Sjkim        EVP_PKEY_asn1_set_param(*ameth,
924280297Sjkim                                gost94_param_decode, gost94_param_encode,
925280297Sjkim                                param_missing_gost94, param_copy_gost94,
926280297Sjkim                                param_cmp_gost94, param_print_gost94);
927280297Sjkim        EVP_PKEY_asn1_set_public(*ameth,
928280297Sjkim                                 pub_decode_gost94, pub_encode_gost94,
929280297Sjkim                                 pub_cmp_gost94, pub_print_gost94,
930280297Sjkim                                 pkey_size_gost, pkey_bits_gost);
931238384Sjkim
932280297Sjkim        EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
933280297Sjkim        break;
934280297Sjkim    case NID_id_GostR3410_2001:
935280297Sjkim        EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost01);
936280297Sjkim        EVP_PKEY_asn1_set_private(*ameth,
937280297Sjkim                                  priv_decode_gost, priv_encode_gost,
938280297Sjkim                                  priv_print_gost01);
939238384Sjkim
940280297Sjkim        EVP_PKEY_asn1_set_param(*ameth,
941280297Sjkim                                gost2001_param_decode, gost2001_param_encode,
942280297Sjkim                                param_missing_gost01, param_copy_gost01,
943280297Sjkim                                param_cmp_gost01, param_print_gost01);
944280297Sjkim        EVP_PKEY_asn1_set_public(*ameth,
945280297Sjkim                                 pub_decode_gost01, pub_encode_gost01,
946280297Sjkim                                 pub_cmp_gost01, pub_print_gost01,
947280297Sjkim                                 pkey_size_gost, pkey_bits_gost);
948238384Sjkim
949280297Sjkim        EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
950280297Sjkim        break;
951280297Sjkim    case NID_id_Gost28147_89_MAC:
952280297Sjkim        EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
953280297Sjkim        EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
954280297Sjkim        break;
955280297Sjkim    }
956280297Sjkim    return 1;
957280297Sjkim}
958