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
17280304Sjkim# include <openssl/cms.h>
18238384Sjkim#endif
19238384Sjkim#include "gost_params.h"
20238384Sjkim#include "gost_lcl.h"
21238384Sjkim#include "e_gost_err.h"
22238384Sjkim
23280304Sjkimint gost94_nid_by_params(DSA *p)
24280304Sjkim{
25280304Sjkim    R3410_params *gost_params;
26280304Sjkim    BIGNUM *q = BN_new();
27280304Sjkim    for (gost_params = R3410_paramset; gost_params->q != NULL; gost_params++) {
28280304Sjkim        BN_dec2bn(&q, gost_params->q);
29280304Sjkim        if (!BN_cmp(q, p->q)) {
30280304Sjkim            BN_free(q);
31280304Sjkim            return gost_params->nid;
32280304Sjkim        }
33280304Sjkim    }
34280304Sjkim    BN_free(q);
35280304Sjkim    return NID_undef;
36280304Sjkim}
37238384Sjkim
38280304Sjkimstatic ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
39280304Sjkim{
40280304Sjkim    ASN1_STRING *params = ASN1_STRING_new();
41280304Sjkim    GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
42280304Sjkim    int pkey_param_nid = NID_undef;
43238384Sjkim
44280304Sjkim    if (!params || !gkp) {
45280304Sjkim        GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
46280304Sjkim        ASN1_STRING_free(params);
47280304Sjkim        params = NULL;
48280304Sjkim        goto err;
49280304Sjkim    }
50280304Sjkim    switch (EVP_PKEY_base_id(key)) {
51280304Sjkim    case NID_id_GostR3410_2001:
52280304Sjkim        pkey_param_nid =
53280304Sjkim            EC_GROUP_get_curve_name(EC_KEY_get0_group
54280304Sjkim                                    (EVP_PKEY_get0((EVP_PKEY *)key)));
55280304Sjkim        break;
56280304Sjkim    case NID_id_GostR3410_94:
57280304Sjkim        pkey_param_nid =
58280304Sjkim            (int)gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
59280304Sjkim        if (pkey_param_nid == NID_undef) {
60280304Sjkim            GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
61280304Sjkim                    GOST_R_INVALID_GOST94_PARMSET);
62280304Sjkim            ASN1_STRING_free(params);
63280304Sjkim            params = NULL;
64280304Sjkim            goto err;
65280304Sjkim        }
66280304Sjkim        break;
67280304Sjkim    }
68280304Sjkim    gkp->key_params = OBJ_nid2obj(pkey_param_nid);
69280304Sjkim    gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
70280304Sjkim    /*
71280304Sjkim     * gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);
72280304Sjkim     */
73280304Sjkim    params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
74280304Sjkim    if (params->length <= 0) {
75280304Sjkim        GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
76280304Sjkim        ASN1_STRING_free(params);
77280304Sjkim        params = NULL;
78280304Sjkim        goto err;
79280304Sjkim    }
80280304Sjkim    params->type = V_ASN1_SEQUENCE;
81280304Sjkim err:
82280304Sjkim    GOST_KEY_PARAMS_free(gkp);
83280304Sjkim    return params;
84280304Sjkim}
85238384Sjkim
86280304Sjkim/*
87280304Sjkim * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting
88280304Sjkim * NID and parameters
89238384Sjkim */
90280304Sjkimstatic int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
91280304Sjkim{
92280304Sjkim    ASN1_OBJECT *palg_obj = NULL;
93280304Sjkim    int ptype = V_ASN1_UNDEF;
94280304Sjkim    int pkey_nid = NID_undef, param_nid = NID_undef;
95280304Sjkim    void *_pval;
96280304Sjkim    ASN1_STRING *pval = NULL;
97280304Sjkim    const unsigned char *p;
98280304Sjkim    GOST_KEY_PARAMS *gkp = NULL;
99238384Sjkim
100280304Sjkim    X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg);
101280304Sjkim    pval = _pval;
102280304Sjkim    if (ptype != V_ASN1_SEQUENCE) {
103280304Sjkim        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
104280304Sjkim                GOST_R_BAD_KEY_PARAMETERS_FORMAT);
105280304Sjkim        return 0;
106280304Sjkim    }
107280304Sjkim    p = pval->data;
108280304Sjkim    pkey_nid = OBJ_obj2nid(palg_obj);
109238384Sjkim
110280304Sjkim    gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length);
111280304Sjkim    if (!gkp) {
112280304Sjkim        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
113280304Sjkim                GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
114280304Sjkim        return 0;
115280304Sjkim    }
116280304Sjkim    param_nid = OBJ_obj2nid(gkp->key_params);
117280304Sjkim    GOST_KEY_PARAMS_free(gkp);
118284285Sjkim    if(!EVP_PKEY_set_type(pkey, pkey_nid)) {
119284285Sjkim        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR);
120284285Sjkim        return 0;
121284285Sjkim    }
122280304Sjkim    switch (pkey_nid) {
123280304Sjkim    case NID_id_GostR3410_94:
124280304Sjkim        {
125280304Sjkim            DSA *dsa = EVP_PKEY_get0(pkey);
126280304Sjkim            if (!dsa) {
127280304Sjkim                dsa = DSA_new();
128280304Sjkim                if (!EVP_PKEY_assign(pkey, pkey_nid, dsa))
129280304Sjkim                    return 0;
130280304Sjkim            }
131280304Sjkim            if (!fill_GOST94_params(dsa, param_nid))
132280304Sjkim                return 0;
133280304Sjkim            break;
134280304Sjkim        }
135280304Sjkim    case NID_id_GostR3410_2001:
136280304Sjkim        {
137280304Sjkim            EC_KEY *ec = EVP_PKEY_get0(pkey);
138280304Sjkim            if (!ec) {
139280304Sjkim                ec = EC_KEY_new();
140280304Sjkim                if (!EVP_PKEY_assign(pkey, pkey_nid, ec))
141280304Sjkim                    return 0;
142280304Sjkim            }
143280304Sjkim            if (!fill_GOST2001_params(ec, param_nid))
144280304Sjkim                return 0;
145280304Sjkim        }
146280304Sjkim    }
147238384Sjkim
148280304Sjkim    return 1;
149280304Sjkim}
150238384Sjkim
151280304Sjkimstatic int gost_set_priv_key(EVP_PKEY *pkey, BIGNUM *priv)
152280304Sjkim{
153280304Sjkim    switch (EVP_PKEY_base_id(pkey)) {
154280304Sjkim    case NID_id_GostR3410_94:
155280304Sjkim        {
156280304Sjkim            DSA *dsa = EVP_PKEY_get0(pkey);
157280304Sjkim            if (!dsa) {
158280304Sjkim                dsa = DSA_new();
159280304Sjkim                EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), dsa);
160280304Sjkim            }
161280304Sjkim            dsa->priv_key = BN_dup(priv);
162280304Sjkim            if (!EVP_PKEY_missing_parameters(pkey))
163280304Sjkim                gost94_compute_public(dsa);
164280304Sjkim            break;
165280304Sjkim        }
166280304Sjkim    case NID_id_GostR3410_2001:
167280304Sjkim        {
168280304Sjkim            EC_KEY *ec = EVP_PKEY_get0(pkey);
169280304Sjkim            if (!ec) {
170280304Sjkim                ec = EC_KEY_new();
171280304Sjkim                EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), ec);
172280304Sjkim            }
173280304Sjkim            if (!EC_KEY_set_private_key(ec, priv))
174280304Sjkim                return 0;
175280304Sjkim            if (!EVP_PKEY_missing_parameters(pkey))
176280304Sjkim                gost2001_compute_public(ec);
177280304Sjkim            break;
178280304Sjkim        }
179280304Sjkim    }
180280304Sjkim    return 1;
181280304Sjkim}
182238384Sjkim
183280304SjkimBIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
184280304Sjkim{
185280304Sjkim    switch (EVP_PKEY_base_id(pkey)) {
186280304Sjkim    case NID_id_GostR3410_94:
187280304Sjkim        {
188280304Sjkim            DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
189280304Sjkim            if (!dsa) {
190280304Sjkim                return NULL;
191280304Sjkim            }
192280304Sjkim            if (!dsa->priv_key)
193280304Sjkim                return NULL;
194280304Sjkim            return dsa->priv_key;
195280304Sjkim            break;
196280304Sjkim        }
197280304Sjkim    case NID_id_GostR3410_2001:
198280304Sjkim        {
199280304Sjkim            EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
200280304Sjkim            const BIGNUM *priv;
201280304Sjkim            if (!ec) {
202280304Sjkim                return NULL;
203280304Sjkim            }
204280304Sjkim            if (!(priv = EC_KEY_get0_private_key(ec)))
205280304Sjkim                return NULL;
206280304Sjkim            return (BIGNUM *)priv;
207280304Sjkim            break;
208280304Sjkim        }
209280304Sjkim    }
210280304Sjkim    return NULL;
211280304Sjkim}
212280304Sjkim
213280304Sjkimstatic int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
214280304Sjkim{
215280304Sjkim    switch (op) {
216280304Sjkim    case ASN1_PKEY_CTRL_PKCS7_SIGN:
217280304Sjkim        if (arg1 == 0) {
218280304Sjkim            X509_ALGOR *alg1 = NULL, *alg2 = NULL;
219280304Sjkim            int nid = EVP_PKEY_base_id(pkey);
220280304Sjkim            PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO *)arg2,
221280304Sjkim                                        NULL, &alg1, &alg2);
222280304Sjkim            X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
223280304Sjkim                            V_ASN1_NULL, 0);
224280304Sjkim            if (nid == NID_undef) {
225280304Sjkim                return (-1);
226280304Sjkim            }
227280304Sjkim            X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
228280304Sjkim        }
229280304Sjkim        return 1;
230238384Sjkim#ifndef OPENSSL_NO_CMS
231280304Sjkim    case ASN1_PKEY_CTRL_CMS_SIGN:
232280304Sjkim        if (arg1 == 0) {
233280304Sjkim            X509_ALGOR *alg1 = NULL, *alg2 = NULL;
234280304Sjkim            int nid = EVP_PKEY_base_id(pkey);
235280304Sjkim            CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2,
236280304Sjkim                                     NULL, NULL, &alg1, &alg2);
237280304Sjkim            X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
238280304Sjkim                            V_ASN1_NULL, 0);
239280304Sjkim            if (nid == NID_undef) {
240280304Sjkim                return (-1);
241280304Sjkim            }
242280304Sjkim            X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
243280304Sjkim        }
244280304Sjkim        return 1;
245238384Sjkim#endif
246280304Sjkim    case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
247280304Sjkim        if (arg1 == 0) {
248280304Sjkim            X509_ALGOR *alg;
249280304Sjkim            ASN1_STRING *params = encode_gost_algor_params(pkey);
250280304Sjkim            if (!params) {
251280304Sjkim                return -1;
252280304Sjkim            }
253280304Sjkim            PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO *)arg2, &alg);
254280304Sjkim            X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type),
255280304Sjkim                            V_ASN1_SEQUENCE, params);
256280304Sjkim        }
257280304Sjkim        return 1;
258238384Sjkim#ifndef OPENSSL_NO_CMS
259280304Sjkim    case ASN1_PKEY_CTRL_CMS_ENVELOPE:
260280304Sjkim        if (arg1 == 0) {
261280304Sjkim            X509_ALGOR *alg = NULL;
262280304Sjkim            ASN1_STRING *params = encode_gost_algor_params(pkey);
263280304Sjkim            if (!params) {
264280304Sjkim                return -1;
265280304Sjkim            }
266280304Sjkim            CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
267280304Sjkim                                             NULL, &alg);
268280304Sjkim            X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type), V_ASN1_SEQUENCE,
269280304Sjkim                            params);
270280304Sjkim        }
271280304Sjkim        return 1;
272238384Sjkim#endif
273280304Sjkim    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
274280304Sjkim        *(int *)arg2 = NID_id_GostR3411_94;
275280304Sjkim        return 2;
276280304Sjkim    }
277238384Sjkim
278280304Sjkim    return -2;
279280304Sjkim}
280238384Sjkim
281280304Sjkim/* --------------------- free functions * ------------------------------*/
282280304Sjkimstatic void pkey_free_gost94(EVP_PKEY *key)
283280304Sjkim{
284280304Sjkim    if (key->pkey.dsa) {
285280304Sjkim        DSA_free(key->pkey.dsa);
286280304Sjkim    }
287280304Sjkim}
288280304Sjkim
289280304Sjkimstatic void pkey_free_gost01(EVP_PKEY *key)
290280304Sjkim{
291280304Sjkim    if (key->pkey.ec) {
292280304Sjkim        EC_KEY_free(key->pkey.ec);
293280304Sjkim    }
294280304Sjkim}
295280304Sjkim
296238384Sjkim/* ------------------ private key functions  -----------------------------*/
297280304Sjkimstatic int priv_decode_gost(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
298280304Sjkim{
299280304Sjkim    const unsigned char *pkey_buf = NULL, *p = NULL;
300280304Sjkim    int priv_len = 0;
301280304Sjkim    BIGNUM *pk_num = NULL;
302280304Sjkim    int ret = 0;
303280304Sjkim    X509_ALGOR *palg = NULL;
304280304Sjkim    ASN1_OBJECT *palg_obj = NULL;
305280304Sjkim    ASN1_INTEGER *priv_key = NULL;
306238384Sjkim
307280304Sjkim    if (!PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf))
308280304Sjkim        return 0;
309280304Sjkim    p = pkey_buf;
310280304Sjkim    if (!decode_gost_algor_params(pk, palg)) {
311280304Sjkim        return 0;
312280304Sjkim    }
313280304Sjkim    if (V_ASN1_OCTET_STRING == *p) {
314280304Sjkim        /* New format - Little endian octet string */
315280304Sjkim        unsigned char rev_buf[32];
316280304Sjkim        int i;
317280304Sjkim        ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
318280304Sjkim        if (!s || s->length != 32) {
319280304Sjkim            GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
320280304Sjkim            return 0;
321280304Sjkim        }
322280304Sjkim        for (i = 0; i < 32; i++) {
323280304Sjkim            rev_buf[31 - i] = s->data[i];
324280304Sjkim        }
325280304Sjkim        ASN1_STRING_free(s);
326280304Sjkim        pk_num = getbnfrombuf(rev_buf, 32);
327280304Sjkim    } else {
328280304Sjkim        priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
329280304Sjkim        if (!priv_key)
330280304Sjkim            return 0;
331280304Sjkim        ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
332280304Sjkim        ASN1_INTEGER_free(priv_key);
333280304Sjkim        if (!ret) {
334280304Sjkim            GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
335280304Sjkim            return 0;
336280304Sjkim        }
337280304Sjkim    }
338238384Sjkim
339280304Sjkim    ret = gost_set_priv_key(pk, pk_num);
340280304Sjkim    BN_free(pk_num);
341280304Sjkim    return ret;
342280304Sjkim}
343238384Sjkim
344238384Sjkim/* ----------------------------------------------------------------------*/
345238384Sjkimstatic int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
346280304Sjkim{
347280304Sjkim    ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
348280304Sjkim    ASN1_STRING *params = encode_gost_algor_params(pk);
349280304Sjkim    unsigned char *priv_buf = NULL;
350280304Sjkim    int priv_len;
351238384Sjkim
352280304Sjkim    ASN1_INTEGER *asn1key = NULL;
353280304Sjkim    if (!params) {
354280304Sjkim        return 0;
355280304Sjkim    }
356280304Sjkim    asn1key = BN_to_ASN1_INTEGER(gost_get0_priv_key(pk), NULL);
357280304Sjkim    priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
358280304Sjkim    ASN1_INTEGER_free(asn1key);
359280304Sjkim    return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
360280304Sjkim                           priv_buf, priv_len);
361280304Sjkim}
362280304Sjkim
363238384Sjkim/* --------- printing keys --------------------------------*/
364238384Sjkimstatic int print_gost_94(BIO *out, const EVP_PKEY *pkey, int indent,
365280304Sjkim                         ASN1_PCTX *pctx, int type)
366280304Sjkim{
367280304Sjkim    int param_nid = NID_undef;
368238384Sjkim
369280304Sjkim    if (type == 2) {
370280304Sjkim        BIGNUM *key;
371238384Sjkim
372280304Sjkim        if (!BIO_indent(out, indent, 128))
373280304Sjkim            return 0;
374280304Sjkim        BIO_printf(out, "Private key: ");
375280304Sjkim        key = gost_get0_priv_key(pkey);
376280304Sjkim        if (!key)
377280304Sjkim            BIO_printf(out, "<undefined>");
378280304Sjkim        else
379280304Sjkim            BN_print(out, key);
380280304Sjkim        BIO_printf(out, "\n");
381280304Sjkim    }
382280304Sjkim    if (type >= 1) {
383280304Sjkim        BIGNUM *pubkey;
384238384Sjkim
385280304Sjkim        pubkey = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
386280304Sjkim        BIO_indent(out, indent, 128);
387280304Sjkim        BIO_printf(out, "Public key: ");
388280304Sjkim        BN_print(out, pubkey);
389280304Sjkim        BIO_printf(out, "\n");
390280304Sjkim    }
391280304Sjkim
392280304Sjkim    param_nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
393280304Sjkim    BIO_indent(out, indent, 128);
394280304Sjkim    BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
395280304Sjkim    return 1;
396238384Sjkim}
397238384Sjkim
398238384Sjkimstatic int param_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
399280304Sjkim                              ASN1_PCTX *pctx)
400280304Sjkim{
401280304Sjkim    return print_gost_94(out, pkey, indent, pctx, 0);
402280304Sjkim}
403238384Sjkim
404238384Sjkimstatic int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
405280304Sjkim                            ASN1_PCTX *pctx)
406280304Sjkim{
407280304Sjkim    return print_gost_94(out, pkey, indent, pctx, 1);
408280304Sjkim}
409238384Sjkim
410280304Sjkimstatic int priv_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
411280304Sjkim                             ASN1_PCTX *pctx)
412280304Sjkim{
413280304Sjkim    return print_gost_94(out, pkey, indent, pctx, 2);
414280304Sjkim}
415280304Sjkim
416238384Sjkimstatic int print_gost_01(BIO *out, const EVP_PKEY *pkey, int indent,
417280304Sjkim                         ASN1_PCTX *pctx, int type)
418280304Sjkim{
419280304Sjkim    int param_nid = NID_undef;
420280304Sjkim    if (type == 2) {
421280304Sjkim        BIGNUM *key;
422238384Sjkim
423280304Sjkim        if (!BIO_indent(out, indent, 128))
424280304Sjkim            return 0;
425280304Sjkim        BIO_printf(out, "Private key: ");
426280304Sjkim        key = gost_get0_priv_key(pkey);
427280304Sjkim        if (!key)
428280304Sjkim            BIO_printf(out, "<undefined)");
429280304Sjkim        else
430280304Sjkim            BN_print(out, key);
431280304Sjkim        BIO_printf(out, "\n");
432280304Sjkim    }
433280304Sjkim    if (type >= 1) {
434280304Sjkim        BN_CTX *ctx = BN_CTX_new();
435280304Sjkim        BIGNUM *X, *Y;
436280304Sjkim        const EC_POINT *pubkey;
437280304Sjkim        const EC_GROUP *group;
438238384Sjkim
439280304Sjkim        if (!ctx) {
440280304Sjkim            GOSTerr(GOST_F_PRINT_GOST_01, ERR_R_MALLOC_FAILURE);
441280304Sjkim            return 0;
442280304Sjkim        }
443280304Sjkim        BN_CTX_start(ctx);
444280304Sjkim        X = BN_CTX_get(ctx);
445280304Sjkim        Y = BN_CTX_get(ctx);
446280304Sjkim        pubkey =
447280304Sjkim            EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
448280304Sjkim        group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
449280304Sjkim        if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) {
450280304Sjkim            GOSTerr(GOST_F_PRINT_GOST_01, ERR_R_EC_LIB);
451280304Sjkim            BN_CTX_free(ctx);
452280304Sjkim            return 0;
453280304Sjkim        }
454280304Sjkim        if (!BIO_indent(out, indent, 128))
455280304Sjkim            return 0;
456280304Sjkim        BIO_printf(out, "Public key:\n");
457280304Sjkim        if (!BIO_indent(out, indent + 3, 128))
458280304Sjkim            return 0;
459280304Sjkim        BIO_printf(out, "X:");
460280304Sjkim        BN_print(out, X);
461280304Sjkim        BIO_printf(out, "\n");
462280304Sjkim        BIO_indent(out, indent + 3, 128);
463280304Sjkim        BIO_printf(out, "Y:");
464280304Sjkim        BN_print(out, Y);
465280304Sjkim        BIO_printf(out, "\n");
466280304Sjkim        BN_CTX_end(ctx);
467280304Sjkim        BN_CTX_free(ctx);
468280304Sjkim    }
469238384Sjkim
470280304Sjkim    param_nid =
471280304Sjkim        EC_GROUP_get_curve_name(EC_KEY_get0_group
472280304Sjkim                                (EVP_PKEY_get0((EVP_PKEY *)pkey)));
473280304Sjkim    if (!BIO_indent(out, indent, 128))
474280304Sjkim        return 0;
475280304Sjkim    BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
476280304Sjkim    return 1;
477238384Sjkim}
478280304Sjkim
479238384Sjkimstatic int param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
480280304Sjkim                              ASN1_PCTX *pctx)
481280304Sjkim{
482280304Sjkim    return print_gost_01(out, pkey, indent, pctx, 0);
483280304Sjkim}
484280304Sjkim
485238384Sjkimstatic int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
486280304Sjkim                            ASN1_PCTX *pctx)
487280304Sjkim{
488280304Sjkim    return print_gost_01(out, pkey, indent, pctx, 1);
489280304Sjkim}
490280304Sjkim
491280304Sjkimstatic int priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
492280304Sjkim                             ASN1_PCTX *pctx)
493280304Sjkim{
494280304Sjkim    return print_gost_01(out, pkey, indent, pctx, 2);
495280304Sjkim}
496280304Sjkim
497238384Sjkim/* ---------------------------------------------------------------------*/
498280304Sjkimstatic int param_missing_gost94(const EVP_PKEY *pk)
499280304Sjkim{
500280304Sjkim    const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
501280304Sjkim    if (!dsa)
502280304Sjkim        return 1;
503280304Sjkim    if (!dsa->q)
504280304Sjkim        return 1;
505280304Sjkim    return 0;
506280304Sjkim}
507238384Sjkim
508280304Sjkimstatic int param_missing_gost01(const EVP_PKEY *pk)
509280304Sjkim{
510280304Sjkim    const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
511280304Sjkim    if (!ec)
512280304Sjkim        return 1;
513280304Sjkim    if (!EC_KEY_get0_group(ec))
514280304Sjkim        return 1;
515280304Sjkim    return 0;
516280304Sjkim}
517238384Sjkim
518280304Sjkimstatic int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from)
519280304Sjkim{
520280304Sjkim    const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from);
521280304Sjkim    DSA *dto = EVP_PKEY_get0(to);
522280304Sjkim    if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
523280304Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_INCOMPATIBLE_ALGORITHMS);
524280304Sjkim        return 0;
525280304Sjkim    }
526280304Sjkim    if (!dfrom) {
527280304Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_KEY_PARAMETERS_MISSING);
528280304Sjkim        return 0;
529280304Sjkim    }
530280304Sjkim    if (!dto) {
531280304Sjkim        dto = DSA_new();
532280304Sjkim        EVP_PKEY_assign(to, EVP_PKEY_base_id(from), dto);
533280304Sjkim    }
534280304Sjkim#define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x);
535280304Sjkim    COPYBIGNUM(dto, dfrom, p)
536280304Sjkim        COPYBIGNUM(dto, dfrom, q)
537280304Sjkim        COPYBIGNUM(dto, dfrom, g)
538238384Sjkim
539280304Sjkim        if (dto->priv_key)
540280304Sjkim        gost94_compute_public(dto);
541280304Sjkim    return 1;
542280304Sjkim}
543238384Sjkim
544280304Sjkimstatic int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
545280304Sjkim{
546280304Sjkim    EC_KEY *eto = EVP_PKEY_get0(to);
547280304Sjkim    const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
548280304Sjkim    if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
549280304Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_INCOMPATIBLE_ALGORITHMS);
550280304Sjkim        return 0;
551280304Sjkim    }
552280304Sjkim    if (!efrom) {
553280304Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_KEY_PARAMETERS_MISSING);
554280304Sjkim        return 0;
555280304Sjkim    }
556280304Sjkim    if (!eto) {
557280304Sjkim        eto = EC_KEY_new();
558284285Sjkim        if(!eto) {
559284285Sjkim            GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_MALLOC_FAILURE);
560284285Sjkim            return 0;
561284285Sjkim        }
562284285Sjkim        if(!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
563284285Sjkim            GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
564284285Sjkim            return 0;
565284285Sjkim        }
566280304Sjkim    }
567284285Sjkim    if(!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
568284285Sjkim        GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
569284285Sjkim        return 0;
570284285Sjkim    }
571280304Sjkim    if (EC_KEY_get0_private_key(eto)) {
572280304Sjkim        gost2001_compute_public(eto);
573280304Sjkim    }
574280304Sjkim    return 1;
575280304Sjkim}
576238384Sjkim
577280304Sjkimstatic int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
578280304Sjkim{
579280304Sjkim    const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
580280304Sjkim    const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
581280304Sjkim    if (!BN_cmp(da->q, db->q))
582280304Sjkim        return 1;
583280304Sjkim    return 0;
584280304Sjkim}
585238384Sjkim
586280304Sjkimstatic int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
587280304Sjkim{
588280304Sjkim    if (EC_GROUP_get_curve_name
589280304Sjkim        (EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a))) ==
590280304Sjkim        EC_GROUP_get_curve_name(EC_KEY_get0_group
591280304Sjkim                                (EVP_PKEY_get0((EVP_PKEY *)b)))) {
592280304Sjkim        return 1;
593280304Sjkim    }
594280304Sjkim    return 0;
595238384Sjkim
596280304Sjkim}
597280304Sjkim
598238384Sjkim/* ---------- Public key functions * --------------------------------------*/
599238384Sjkimstatic int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
600280304Sjkim{
601280304Sjkim    X509_ALGOR *palg = NULL;
602280304Sjkim    const unsigned char *pubkey_buf = NULL;
603280304Sjkim    unsigned char *databuf;
604280304Sjkim    ASN1_OBJECT *palgobj = NULL;
605280304Sjkim    int pub_len, i, j;
606280304Sjkim    DSA *dsa;
607280304Sjkim    ASN1_OCTET_STRING *octet = NULL;
608238384Sjkim
609280304Sjkim    if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
610280304Sjkim        return 0;
611280304Sjkim    EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
612280304Sjkim    if (!decode_gost_algor_params(pk, palg))
613280304Sjkim        return 0;
614280304Sjkim    octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
615280304Sjkim    if (!octet) {
616280304Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST94, ERR_R_MALLOC_FAILURE);
617280304Sjkim        return 0;
618280304Sjkim    }
619280304Sjkim    databuf = OPENSSL_malloc(octet->length);
620280304Sjkim    for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
621280304Sjkim        databuf[j] = octet->data[i];
622280304Sjkim    }
623280304Sjkim    dsa = EVP_PKEY_get0(pk);
624280304Sjkim    dsa->pub_key = BN_bin2bn(databuf, octet->length, NULL);
625280304Sjkim    ASN1_OCTET_STRING_free(octet);
626280304Sjkim    OPENSSL_free(databuf);
627280304Sjkim    return 1;
628238384Sjkim
629280304Sjkim}
630238384Sjkim
631280304Sjkimstatic int pub_encode_gost94(X509_PUBKEY *pub, const EVP_PKEY *pk)
632280304Sjkim{
633280304Sjkim    ASN1_OBJECT *algobj = NULL;
634280304Sjkim    ASN1_OCTET_STRING *octet = NULL;
635280304Sjkim    void *pval = NULL;
636280304Sjkim    unsigned char *buf = NULL, *databuf, *sptr;
637280304Sjkim    int i, j, data_len, ret = 0;
638238384Sjkim
639280304Sjkim    int ptype = V_ASN1_UNDEF;
640280304Sjkim    DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
641280304Sjkim    algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
642280304Sjkim    if (pk->save_parameters) {
643280304Sjkim        ASN1_STRING *params = encode_gost_algor_params(pk);
644280304Sjkim        pval = params;
645280304Sjkim        ptype = V_ASN1_SEQUENCE;
646280304Sjkim    }
647280304Sjkim    data_len = BN_num_bytes(dsa->pub_key);
648280304Sjkim    databuf = OPENSSL_malloc(data_len);
649280304Sjkim    BN_bn2bin(dsa->pub_key, databuf);
650280304Sjkim    octet = ASN1_OCTET_STRING_new();
651280304Sjkim    ASN1_STRING_set(octet, NULL, data_len);
652280304Sjkim    sptr = ASN1_STRING_data(octet);
653280304Sjkim    for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
654280304Sjkim        sptr[i] = databuf[j];
655280304Sjkim    }
656280304Sjkim    OPENSSL_free(databuf);
657280304Sjkim    ret = i2d_ASN1_OCTET_STRING(octet, &buf);
658280304Sjkim    ASN1_BIT_STRING_free(octet);
659280304Sjkim    if (ret < 0)
660280304Sjkim        return 0;
661280304Sjkim    return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
662280304Sjkim}
663238384Sjkim
664280304Sjkimstatic int pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
665280304Sjkim{
666280304Sjkim    X509_ALGOR *palg = NULL;
667280304Sjkim    const unsigned char *pubkey_buf = NULL;
668280304Sjkim    unsigned char *databuf;
669280304Sjkim    ASN1_OBJECT *palgobj = NULL;
670280304Sjkim    int pub_len, i, j;
671280304Sjkim    EC_POINT *pub_key;
672280304Sjkim    BIGNUM *X, *Y;
673280304Sjkim    ASN1_OCTET_STRING *octet = NULL;
674280304Sjkim    int len;
675280304Sjkim    const EC_GROUP *group;
676238384Sjkim
677280304Sjkim    if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
678280304Sjkim        return 0;
679280304Sjkim    EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
680280304Sjkim    if (!decode_gost_algor_params(pk, palg))
681280304Sjkim        return 0;
682280304Sjkim    group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
683280304Sjkim    octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
684280304Sjkim    if (!octet) {
685280304Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
686280304Sjkim        return 0;
687280304Sjkim    }
688280304Sjkim    databuf = OPENSSL_malloc(octet->length);
689280304Sjkim    for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
690280304Sjkim        databuf[j] = octet->data[i];
691280304Sjkim    }
692280304Sjkim    len = octet->length / 2;
693280304Sjkim    ASN1_OCTET_STRING_free(octet);
694238384Sjkim
695280304Sjkim    Y = getbnfrombuf(databuf, len);
696280304Sjkim    X = getbnfrombuf(databuf + len, len);
697280304Sjkim    OPENSSL_free(databuf);
698280304Sjkim    pub_key = EC_POINT_new(group);
699280304Sjkim    if (!EC_POINT_set_affine_coordinates_GFp(group, pub_key, X, Y, NULL)) {
700280304Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB);
701280304Sjkim        EC_POINT_free(pub_key);
702280304Sjkim        BN_free(X);
703280304Sjkim        BN_free(Y);
704280304Sjkim        return 0;
705280304Sjkim    }
706280304Sjkim    BN_free(X);
707280304Sjkim    BN_free(Y);
708280304Sjkim    if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
709280304Sjkim        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB);
710280304Sjkim        EC_POINT_free(pub_key);
711280304Sjkim        return 0;
712280304Sjkim    }
713280304Sjkim    EC_POINT_free(pub_key);
714280304Sjkim    return 1;
715238384Sjkim
716280304Sjkim}
717238384Sjkim
718280304Sjkimstatic int pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
719280304Sjkim{
720280304Sjkim    ASN1_OBJECT *algobj = NULL;
721280304Sjkim    ASN1_OCTET_STRING *octet = NULL;
722280304Sjkim    void *pval = NULL;
723280304Sjkim    unsigned char *buf = NULL, *databuf, *sptr;
724280304Sjkim    int i, j, data_len, ret = 0;
725280304Sjkim    const EC_POINT *pub_key;
726280304Sjkim    BIGNUM *X, *Y, *order;
727280304Sjkim    const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
728280304Sjkim    int ptype = V_ASN1_UNDEF;
729238384Sjkim
730280304Sjkim    algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
731280304Sjkim    if (pk->save_parameters) {
732280304Sjkim        ASN1_STRING *params = encode_gost_algor_params(pk);
733280304Sjkim        pval = params;
734280304Sjkim        ptype = V_ASN1_SEQUENCE;
735280304Sjkim    }
736280304Sjkim    order = BN_new();
737280304Sjkim    EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
738280304Sjkim    pub_key = EC_KEY_get0_public_key(ec);
739280304Sjkim    if (!pub_key) {
740280304Sjkim        GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED);
741280304Sjkim        return 0;
742280304Sjkim    }
743280304Sjkim    X = BN_new();
744280304Sjkim    Y = BN_new();
745284285Sjkim    if(!X || !Y) {
746284285Sjkim        GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
747284285Sjkim        if(X) BN_free(X);
748284285Sjkim        if(Y) BN_free(Y);
749284285Sjkim        BN_free(order);
750284285Sjkim        return 0;
751284285Sjkim    }
752284285Sjkim    if(!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
753284285Sjkim                                        pub_key, X, Y, NULL)) {
754284285Sjkim        GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR);
755284285Sjkim        BN_free(X);
756284285Sjkim        BN_free(Y);
757284285Sjkim        BN_free(order);
758284285Sjkim        return 0;
759284285Sjkim    }
760280304Sjkim    data_len = 2 * BN_num_bytes(order);
761280304Sjkim    BN_free(order);
762280304Sjkim    databuf = OPENSSL_malloc(data_len);
763280304Sjkim    memset(databuf, 0, data_len);
764280304Sjkim
765280304Sjkim    store_bignum(X, databuf + data_len / 2, data_len / 2);
766280304Sjkim    store_bignum(Y, databuf, data_len / 2);
767280304Sjkim
768280304Sjkim    BN_free(X);
769280304Sjkim    BN_free(Y);
770280304Sjkim    octet = ASN1_OCTET_STRING_new();
771280304Sjkim    ASN1_STRING_set(octet, NULL, data_len);
772280304Sjkim    sptr = ASN1_STRING_data(octet);
773280304Sjkim    for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
774280304Sjkim        sptr[i] = databuf[j];
775280304Sjkim    }
776238384Sjkim    OPENSSL_free(databuf);
777280304Sjkim    ret = i2d_ASN1_OCTET_STRING(octet, &buf);
778280304Sjkim    ASN1_BIT_STRING_free(octet);
779280304Sjkim    if (ret < 0)
780280304Sjkim        return 0;
781280304Sjkim    return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
782280304Sjkim}
783238384Sjkim
784238384Sjkimstatic int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
785280304Sjkim{
786280304Sjkim    const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
787280304Sjkim    const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
788280304Sjkim    if (da && db && da->pub_key && db->pub_key
789280304Sjkim        && !BN_cmp(da->pub_key, db->pub_key)) {
790280304Sjkim        return 1;
791280304Sjkim    }
792280304Sjkim    return 0;
793280304Sjkim}
794238384Sjkim
795280304Sjkimstatic int pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
796280304Sjkim{
797280304Sjkim    const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
798280304Sjkim    const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
799280304Sjkim    const EC_POINT *ka, *kb;
800280304Sjkim    int ret = 0;
801280304Sjkim    if (!ea || !eb)
802280304Sjkim        return 0;
803280304Sjkim    ka = EC_KEY_get0_public_key(ea);
804280304Sjkim    kb = EC_KEY_get0_public_key(eb);
805280304Sjkim    if (!ka || !kb)
806280304Sjkim        return 0;
807280304Sjkim    ret = (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
808280304Sjkim    return ret;
809280304Sjkim}
810238384Sjkim
811238384Sjkimstatic int pkey_size_gost(const EVP_PKEY *pk)
812280304Sjkim{
813280304Sjkim    return 64;
814280304Sjkim}
815238384Sjkim
816238384Sjkimstatic int pkey_bits_gost(const EVP_PKEY *pk)
817238384Sjkim{
818280304Sjkim    return 256;
819280304Sjkim}
820238384Sjkim
821280304Sjkim/* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
822280304Sjkimstatic void mackey_free_gost(EVP_PKEY *pk)
823238384Sjkim{
824280304Sjkim    if (pk->pkey.ptr) {
825280304Sjkim        OPENSSL_free(pk->pkey.ptr);
826280304Sjkim    }
827238384Sjkim}
828280304Sjkim
829280304Sjkimstatic int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
830238384Sjkim{
831280304Sjkim    switch (op) {
832280304Sjkim    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
833280304Sjkim        *(int *)arg2 = NID_id_Gost28147_89_MAC;
834280304Sjkim        return 2;
835280304Sjkim    }
836280304Sjkim    return -2;
837238384Sjkim}
838238384Sjkim
839280304Sjkimstatic int gost94_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
840238384Sjkim{
841280304Sjkim    int nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
842280304Sjkim    return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
843280304Sjkim}
844238384Sjkim
845280304Sjkimstatic int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
846280304Sjkim{
847280304Sjkim    int nid =
848280304Sjkim        EC_GROUP_get_curve_name(EC_KEY_get0_group
849280304Sjkim                                (EVP_PKEY_get0((EVP_PKEY *)pkey)));
850280304Sjkim    return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
851280304Sjkim}
852238384Sjkim
853280304Sjkimstatic int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
854280304Sjkim                               int derlen)
855280304Sjkim{
856280304Sjkim    ASN1_OBJECT *obj = NULL;
857280304Sjkim    DSA *dsa = EVP_PKEY_get0(pkey);
858280304Sjkim    int nid;
859280304Sjkim    if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
860280304Sjkim        return 0;
861280304Sjkim    }
862280304Sjkim    nid = OBJ_obj2nid(obj);
863280304Sjkim    ASN1_OBJECT_free(obj);
864280304Sjkim    if (!dsa) {
865280304Sjkim        dsa = DSA_new();
866280304Sjkim        if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_94, dsa))
867280304Sjkim            return 0;
868280304Sjkim    }
869280304Sjkim    if (!fill_GOST94_params(dsa, nid))
870280304Sjkim        return 0;
871280304Sjkim    return 1;
872280304Sjkim}
873238384Sjkim
874280304Sjkimstatic int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
875280304Sjkim                                 int derlen)
876280304Sjkim{
877280304Sjkim    ASN1_OBJECT *obj = NULL;
878280304Sjkim    int nid;
879280304Sjkim    EC_KEY *ec = EVP_PKEY_get0(pkey);
880280304Sjkim    if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
881280304Sjkim        return 0;
882280304Sjkim    }
883280304Sjkim    nid = OBJ_obj2nid(obj);
884280304Sjkim    ASN1_OBJECT_free(obj);
885280304Sjkim    if (!ec) {
886280304Sjkim        ec = EC_KEY_new();
887280304Sjkim        if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec))
888280304Sjkim            return 0;
889280304Sjkim    }
890280304Sjkim    if (!fill_GOST2001_params(ec, nid))
891280304Sjkim        return 0;
892280304Sjkim    return 1;
893280304Sjkim}
894238384Sjkim
895280304Sjkim/* ----------------------------------------------------------------------*/
896280304Sjkimint register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
897280304Sjkim                        const char *pemstr, const char *info)
898280304Sjkim{
899280304Sjkim    *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
900280304Sjkim    if (!*ameth)
901280304Sjkim        return 0;
902280304Sjkim    switch (nid) {
903280304Sjkim    case NID_id_GostR3410_94:
904280304Sjkim        EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost94);
905280304Sjkim        EVP_PKEY_asn1_set_private(*ameth,
906280304Sjkim                                  priv_decode_gost, priv_encode_gost,
907280304Sjkim                                  priv_print_gost94);
908238384Sjkim
909280304Sjkim        EVP_PKEY_asn1_set_param(*ameth,
910280304Sjkim                                gost94_param_decode, gost94_param_encode,
911280304Sjkim                                param_missing_gost94, param_copy_gost94,
912280304Sjkim                                param_cmp_gost94, param_print_gost94);
913280304Sjkim        EVP_PKEY_asn1_set_public(*ameth,
914280304Sjkim                                 pub_decode_gost94, pub_encode_gost94,
915280304Sjkim                                 pub_cmp_gost94, pub_print_gost94,
916280304Sjkim                                 pkey_size_gost, pkey_bits_gost);
917238384Sjkim
918280304Sjkim        EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
919280304Sjkim        break;
920280304Sjkim    case NID_id_GostR3410_2001:
921280304Sjkim        EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost01);
922280304Sjkim        EVP_PKEY_asn1_set_private(*ameth,
923280304Sjkim                                  priv_decode_gost, priv_encode_gost,
924280304Sjkim                                  priv_print_gost01);
925238384Sjkim
926280304Sjkim        EVP_PKEY_asn1_set_param(*ameth,
927280304Sjkim                                gost2001_param_decode, gost2001_param_encode,
928280304Sjkim                                param_missing_gost01, param_copy_gost01,
929280304Sjkim                                param_cmp_gost01, param_print_gost01);
930280304Sjkim        EVP_PKEY_asn1_set_public(*ameth,
931280304Sjkim                                 pub_decode_gost01, pub_encode_gost01,
932280304Sjkim                                 pub_cmp_gost01, pub_print_gost01,
933280304Sjkim                                 pkey_size_gost, pkey_bits_gost);
934238384Sjkim
935280304Sjkim        EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
936280304Sjkim        break;
937280304Sjkim    case NID_id_Gost28147_89_MAC:
938280304Sjkim        EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
939280304Sjkim        EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
940280304Sjkim        break;
941280304Sjkim    }
942280304Sjkim    return 1;
943280304Sjkim}
944