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
17296341Sdelphij# include <openssl/cms.h>
18238384Sjkim#endif
19238384Sjkim#include "gost_params.h"
20238384Sjkim#include "gost_lcl.h"
21238384Sjkim#include "e_gost_err.h"
22238384Sjkim
23296341Sdelphijint gost94_nid_by_params(DSA *p)
24296341Sdelphij{
25296341Sdelphij    R3410_params *gost_params;
26296341Sdelphij    BIGNUM *q = BN_new();
27296341Sdelphij    for (gost_params = R3410_paramset; gost_params->q != NULL; gost_params++) {
28296341Sdelphij        BN_dec2bn(&q, gost_params->q);
29296341Sdelphij        if (!BN_cmp(q, p->q)) {
30296341Sdelphij            BN_free(q);
31296341Sdelphij            return gost_params->nid;
32296341Sdelphij        }
33296341Sdelphij    }
34296341Sdelphij    BN_free(q);
35296341Sdelphij    return NID_undef;
36296341Sdelphij}
37238384Sjkim
38296341Sdelphijstatic ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
39296341Sdelphij{
40296341Sdelphij    ASN1_STRING *params = ASN1_STRING_new();
41296341Sdelphij    GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
42296341Sdelphij    int pkey_param_nid = NID_undef;
43238384Sjkim
44296341Sdelphij    if (!params || !gkp) {
45296341Sdelphij        GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
46296341Sdelphij        ASN1_STRING_free(params);
47296341Sdelphij        params = NULL;
48296341Sdelphij        goto err;
49296341Sdelphij    }
50296341Sdelphij    switch (EVP_PKEY_base_id(key)) {
51296341Sdelphij    case NID_id_GostR3410_2001:
52296341Sdelphij        pkey_param_nid =
53296341Sdelphij            EC_GROUP_get_curve_name(EC_KEY_get0_group
54296341Sdelphij                                    (EVP_PKEY_get0((EVP_PKEY *)key)));
55296341Sdelphij        break;
56296341Sdelphij    case NID_id_GostR3410_94:
57296341Sdelphij        pkey_param_nid =
58296341Sdelphij            (int)gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
59296341Sdelphij        if (pkey_param_nid == NID_undef) {
60296341Sdelphij            GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
61296341Sdelphij                    GOST_R_INVALID_GOST94_PARMSET);
62296341Sdelphij            ASN1_STRING_free(params);
63296341Sdelphij            params = NULL;
64296341Sdelphij            goto err;
65296341Sdelphij        }
66296341Sdelphij        break;
67296341Sdelphij    }
68296341Sdelphij    gkp->key_params = OBJ_nid2obj(pkey_param_nid);
69296341Sdelphij    gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
70296341Sdelphij    /*
71296341Sdelphij     * gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);
72296341Sdelphij     */
73296341Sdelphij    params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
74296341Sdelphij    if (params->length <= 0) {
75296341Sdelphij        GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
76296341Sdelphij        ASN1_STRING_free(params);
77296341Sdelphij        params = NULL;
78296341Sdelphij        goto err;
79296341Sdelphij    }
80296341Sdelphij    params->type = V_ASN1_SEQUENCE;
81296341Sdelphij err:
82296341Sdelphij    GOST_KEY_PARAMS_free(gkp);
83296341Sdelphij    return params;
84296341Sdelphij}
85238384Sjkim
86296341Sdelphij/*
87296341Sdelphij * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting
88296341Sdelphij * NID and parameters
89238384Sjkim */
90296341Sdelphijstatic int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
91296341Sdelphij{
92296341Sdelphij    ASN1_OBJECT *palg_obj = NULL;
93296341Sdelphij    int ptype = V_ASN1_UNDEF;
94296341Sdelphij    int pkey_nid = NID_undef, param_nid = NID_undef;
95296341Sdelphij    void *_pval;
96296341Sdelphij    ASN1_STRING *pval = NULL;
97296341Sdelphij    const unsigned char *p;
98296341Sdelphij    GOST_KEY_PARAMS *gkp = NULL;
99238384Sjkim
100296341Sdelphij    X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg);
101296341Sdelphij    pval = _pval;
102296341Sdelphij    if (ptype != V_ASN1_SEQUENCE) {
103296341Sdelphij        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
104296341Sdelphij                GOST_R_BAD_KEY_PARAMETERS_FORMAT);
105296341Sdelphij        return 0;
106296341Sdelphij    }
107296341Sdelphij    p = pval->data;
108296341Sdelphij    pkey_nid = OBJ_obj2nid(palg_obj);
109238384Sjkim
110296341Sdelphij    gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length);
111296341Sdelphij    if (!gkp) {
112296341Sdelphij        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
113296341Sdelphij                GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
114296341Sdelphij        return 0;
115296341Sdelphij    }
116296341Sdelphij    param_nid = OBJ_obj2nid(gkp->key_params);
117296341Sdelphij    GOST_KEY_PARAMS_free(gkp);
118296341Sdelphij    if(!EVP_PKEY_set_type(pkey, pkey_nid)) {
119296341Sdelphij        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR);
120296341Sdelphij        return 0;
121296341Sdelphij    }
122296341Sdelphij    switch (pkey_nid) {
123296341Sdelphij    case NID_id_GostR3410_94:
124296341Sdelphij        {
125296341Sdelphij            DSA *dsa = EVP_PKEY_get0(pkey);
126296341Sdelphij            if (!dsa) {
127296341Sdelphij                dsa = DSA_new();
128296341Sdelphij                if (!EVP_PKEY_assign(pkey, pkey_nid, dsa))
129296341Sdelphij                    return 0;
130296341Sdelphij            }
131296341Sdelphij            if (!fill_GOST94_params(dsa, param_nid))
132296341Sdelphij                return 0;
133296341Sdelphij            break;
134296341Sdelphij        }
135296341Sdelphij    case NID_id_GostR3410_2001:
136296341Sdelphij        {
137296341Sdelphij            EC_KEY *ec = EVP_PKEY_get0(pkey);
138296341Sdelphij            if (!ec) {
139296341Sdelphij                ec = EC_KEY_new();
140296341Sdelphij                if (!EVP_PKEY_assign(pkey, pkey_nid, ec))
141296341Sdelphij                    return 0;
142296341Sdelphij            }
143296341Sdelphij            if (!fill_GOST2001_params(ec, param_nid))
144296341Sdelphij                return 0;
145296341Sdelphij        }
146296341Sdelphij    }
147238384Sjkim
148296341Sdelphij    return 1;
149296341Sdelphij}
150238384Sjkim
151296341Sdelphijstatic int gost_set_priv_key(EVP_PKEY *pkey, BIGNUM *priv)
152296341Sdelphij{
153296341Sdelphij    switch (EVP_PKEY_base_id(pkey)) {
154296341Sdelphij    case NID_id_GostR3410_94:
155296341Sdelphij        {
156296341Sdelphij            DSA *dsa = EVP_PKEY_get0(pkey);
157296341Sdelphij            if (!dsa) {
158296341Sdelphij                dsa = DSA_new();
159296341Sdelphij                EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), dsa);
160296341Sdelphij            }
161296341Sdelphij            dsa->priv_key = BN_dup(priv);
162296341Sdelphij            if (!EVP_PKEY_missing_parameters(pkey))
163296341Sdelphij                gost94_compute_public(dsa);
164296341Sdelphij            break;
165296341Sdelphij        }
166296341Sdelphij    case NID_id_GostR3410_2001:
167296341Sdelphij        {
168296341Sdelphij            EC_KEY *ec = EVP_PKEY_get0(pkey);
169296341Sdelphij            if (!ec) {
170296341Sdelphij                ec = EC_KEY_new();
171296341Sdelphij                EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), ec);
172296341Sdelphij            }
173296341Sdelphij            if (!EC_KEY_set_private_key(ec, priv))
174296341Sdelphij                return 0;
175296341Sdelphij            if (!EVP_PKEY_missing_parameters(pkey))
176296341Sdelphij                gost2001_compute_public(ec);
177296341Sdelphij            break;
178296341Sdelphij        }
179296341Sdelphij    }
180296341Sdelphij    return 1;
181296341Sdelphij}
182238384Sjkim
183296341SdelphijBIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
184296341Sdelphij{
185296341Sdelphij    switch (EVP_PKEY_base_id(pkey)) {
186296341Sdelphij    case NID_id_GostR3410_94:
187296341Sdelphij        {
188296341Sdelphij            DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
189296341Sdelphij            if (!dsa) {
190296341Sdelphij                return NULL;
191296341Sdelphij            }
192296341Sdelphij            if (!dsa->priv_key)
193296341Sdelphij                return NULL;
194296341Sdelphij            return dsa->priv_key;
195296341Sdelphij            break;
196296341Sdelphij        }
197296341Sdelphij    case NID_id_GostR3410_2001:
198296341Sdelphij        {
199296341Sdelphij            EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
200296341Sdelphij            const BIGNUM *priv;
201296341Sdelphij            if (!ec) {
202296341Sdelphij                return NULL;
203296341Sdelphij            }
204296341Sdelphij            if (!(priv = EC_KEY_get0_private_key(ec)))
205296341Sdelphij                return NULL;
206296341Sdelphij            return (BIGNUM *)priv;
207296341Sdelphij            break;
208296341Sdelphij        }
209296341Sdelphij    }
210296341Sdelphij    return NULL;
211296341Sdelphij}
212296341Sdelphij
213296341Sdelphijstatic int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
214296341Sdelphij{
215296341Sdelphij    switch (op) {
216296341Sdelphij    case ASN1_PKEY_CTRL_PKCS7_SIGN:
217296341Sdelphij        if (arg1 == 0) {
218296341Sdelphij            X509_ALGOR *alg1 = NULL, *alg2 = NULL;
219296341Sdelphij            int nid = EVP_PKEY_base_id(pkey);
220296341Sdelphij            PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO *)arg2,
221296341Sdelphij                                        NULL, &alg1, &alg2);
222296341Sdelphij            X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
223296341Sdelphij                            V_ASN1_NULL, 0);
224296341Sdelphij            if (nid == NID_undef) {
225296341Sdelphij                return (-1);
226296341Sdelphij            }
227296341Sdelphij            X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
228296341Sdelphij        }
229296341Sdelphij        return 1;
230238384Sjkim#ifndef OPENSSL_NO_CMS
231296341Sdelphij    case ASN1_PKEY_CTRL_CMS_SIGN:
232296341Sdelphij        if (arg1 == 0) {
233296341Sdelphij            X509_ALGOR *alg1 = NULL, *alg2 = NULL;
234296341Sdelphij            int nid = EVP_PKEY_base_id(pkey);
235296341Sdelphij            CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2,
236296341Sdelphij                                     NULL, NULL, &alg1, &alg2);
237296341Sdelphij            X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
238296341Sdelphij                            V_ASN1_NULL, 0);
239296341Sdelphij            if (nid == NID_undef) {
240296341Sdelphij                return (-1);
241296341Sdelphij            }
242296341Sdelphij            X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
243296341Sdelphij        }
244296341Sdelphij        return 1;
245238384Sjkim#endif
246296341Sdelphij    case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
247296341Sdelphij        if (arg1 == 0) {
248296341Sdelphij            X509_ALGOR *alg;
249296341Sdelphij            ASN1_STRING *params = encode_gost_algor_params(pkey);
250296341Sdelphij            if (!params) {
251296341Sdelphij                return -1;
252296341Sdelphij            }
253296341Sdelphij            PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO *)arg2, &alg);
254296341Sdelphij            X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type),
255296341Sdelphij                            V_ASN1_SEQUENCE, params);
256296341Sdelphij        }
257296341Sdelphij        return 1;
258238384Sjkim#ifndef OPENSSL_NO_CMS
259296341Sdelphij    case ASN1_PKEY_CTRL_CMS_ENVELOPE:
260296341Sdelphij        if (arg1 == 0) {
261296341Sdelphij            X509_ALGOR *alg = NULL;
262296341Sdelphij            ASN1_STRING *params = encode_gost_algor_params(pkey);
263296341Sdelphij            if (!params) {
264296341Sdelphij                return -1;
265296341Sdelphij            }
266296341Sdelphij            CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
267296341Sdelphij                                             NULL, &alg);
268296341Sdelphij            X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type), V_ASN1_SEQUENCE,
269296341Sdelphij                            params);
270296341Sdelphij        }
271296341Sdelphij        return 1;
272238384Sjkim#endif
273296341Sdelphij    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
274296341Sdelphij        *(int *)arg2 = NID_id_GostR3411_94;
275296341Sdelphij        return 2;
276296341Sdelphij    }
277238384Sjkim
278296341Sdelphij    return -2;
279296341Sdelphij}
280238384Sjkim
281296341Sdelphij/* --------------------- free functions * ------------------------------*/
282296341Sdelphijstatic void pkey_free_gost94(EVP_PKEY *key)
283296341Sdelphij{
284296341Sdelphij    if (key->pkey.dsa) {
285296341Sdelphij        DSA_free(key->pkey.dsa);
286296341Sdelphij    }
287296341Sdelphij}
288296341Sdelphij
289296341Sdelphijstatic void pkey_free_gost01(EVP_PKEY *key)
290296341Sdelphij{
291296341Sdelphij    if (key->pkey.ec) {
292296341Sdelphij        EC_KEY_free(key->pkey.ec);
293296341Sdelphij    }
294296341Sdelphij}
295296341Sdelphij
296238384Sjkim/* ------------------ private key functions  -----------------------------*/
297296341Sdelphijstatic int priv_decode_gost(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
298296341Sdelphij{
299296341Sdelphij    const unsigned char *pkey_buf = NULL, *p = NULL;
300296341Sdelphij    int priv_len = 0;
301296341Sdelphij    BIGNUM *pk_num = NULL;
302296341Sdelphij    int ret = 0;
303296341Sdelphij    X509_ALGOR *palg = NULL;
304296341Sdelphij    ASN1_OBJECT *palg_obj = NULL;
305296341Sdelphij    ASN1_INTEGER *priv_key = NULL;
306238384Sjkim
307296341Sdelphij    if (!PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf))
308296341Sdelphij        return 0;
309296341Sdelphij    p = pkey_buf;
310296341Sdelphij    if (!decode_gost_algor_params(pk, palg)) {
311296341Sdelphij        return 0;
312296341Sdelphij    }
313296341Sdelphij    if (V_ASN1_OCTET_STRING == *p) {
314296341Sdelphij        /* New format - Little endian octet string */
315296341Sdelphij        unsigned char rev_buf[32];
316296341Sdelphij        int i;
317296341Sdelphij        ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
318296341Sdelphij        if (!s || s->length != 32) {
319296341Sdelphij            GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
320296341Sdelphij            return 0;
321296341Sdelphij        }
322296341Sdelphij        for (i = 0; i < 32; i++) {
323296341Sdelphij            rev_buf[31 - i] = s->data[i];
324296341Sdelphij        }
325296341Sdelphij        ASN1_STRING_free(s);
326296341Sdelphij        pk_num = getbnfrombuf(rev_buf, 32);
327296341Sdelphij    } else {
328296341Sdelphij        priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
329296341Sdelphij        if (!priv_key)
330296341Sdelphij            return 0;
331296341Sdelphij        ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
332296341Sdelphij        ASN1_INTEGER_free(priv_key);
333296341Sdelphij        if (!ret) {
334296341Sdelphij            GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
335296341Sdelphij            return 0;
336296341Sdelphij        }
337296341Sdelphij    }
338238384Sjkim
339296341Sdelphij    ret = gost_set_priv_key(pk, pk_num);
340296341Sdelphij    BN_free(pk_num);
341296341Sdelphij    return ret;
342296341Sdelphij}
343238384Sjkim
344238384Sjkim/* ----------------------------------------------------------------------*/
345238384Sjkimstatic int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
346296341Sdelphij{
347296341Sdelphij    ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
348296341Sdelphij    ASN1_STRING *params = encode_gost_algor_params(pk);
349296341Sdelphij    unsigned char *priv_buf = NULL;
350296341Sdelphij    int priv_len;
351238384Sjkim
352296341Sdelphij    ASN1_INTEGER *asn1key = NULL;
353296341Sdelphij    if (!params) {
354296341Sdelphij        return 0;
355296341Sdelphij    }
356296341Sdelphij    asn1key = BN_to_ASN1_INTEGER(gost_get0_priv_key(pk), NULL);
357296341Sdelphij    priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
358296341Sdelphij    ASN1_INTEGER_free(asn1key);
359296341Sdelphij    return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
360296341Sdelphij                           priv_buf, priv_len);
361296341Sdelphij}
362296341Sdelphij
363238384Sjkim/* --------- printing keys --------------------------------*/
364238384Sjkimstatic int print_gost_94(BIO *out, const EVP_PKEY *pkey, int indent,
365296341Sdelphij                         ASN1_PCTX *pctx, int type)
366296341Sdelphij{
367296341Sdelphij    int param_nid = NID_undef;
368238384Sjkim
369296341Sdelphij    if (type == 2) {
370296341Sdelphij        BIGNUM *key;
371238384Sjkim
372296341Sdelphij        if (!BIO_indent(out, indent, 128))
373296341Sdelphij            return 0;
374296341Sdelphij        BIO_printf(out, "Private key: ");
375296341Sdelphij        key = gost_get0_priv_key(pkey);
376296341Sdelphij        if (!key)
377296341Sdelphij            BIO_printf(out, "<undefined>");
378296341Sdelphij        else
379296341Sdelphij            BN_print(out, key);
380296341Sdelphij        BIO_printf(out, "\n");
381296341Sdelphij    }
382296341Sdelphij    if (type >= 1) {
383296341Sdelphij        BIGNUM *pubkey;
384238384Sjkim
385296341Sdelphij        pubkey = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
386296341Sdelphij        BIO_indent(out, indent, 128);
387296341Sdelphij        BIO_printf(out, "Public key: ");
388296341Sdelphij        BN_print(out, pubkey);
389296341Sdelphij        BIO_printf(out, "\n");
390296341Sdelphij    }
391296341Sdelphij
392296341Sdelphij    param_nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
393296341Sdelphij    BIO_indent(out, indent, 128);
394296341Sdelphij    BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
395296341Sdelphij    return 1;
396238384Sjkim}
397238384Sjkim
398238384Sjkimstatic int param_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
399296341Sdelphij                              ASN1_PCTX *pctx)
400296341Sdelphij{
401296341Sdelphij    return print_gost_94(out, pkey, indent, pctx, 0);
402296341Sdelphij}
403238384Sjkim
404238384Sjkimstatic int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
405296341Sdelphij                            ASN1_PCTX *pctx)
406296341Sdelphij{
407296341Sdelphij    return print_gost_94(out, pkey, indent, pctx, 1);
408296341Sdelphij}
409238384Sjkim
410296341Sdelphijstatic int priv_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
411296341Sdelphij                             ASN1_PCTX *pctx)
412296341Sdelphij{
413296341Sdelphij    return print_gost_94(out, pkey, indent, pctx, 2);
414296341Sdelphij}
415296341Sdelphij
416238384Sjkimstatic int print_gost_01(BIO *out, const EVP_PKEY *pkey, int indent,
417296341Sdelphij                         ASN1_PCTX *pctx, int type)
418296341Sdelphij{
419296341Sdelphij    int param_nid = NID_undef;
420296341Sdelphij    if (type == 2) {
421296341Sdelphij        BIGNUM *key;
422238384Sjkim
423296341Sdelphij        if (!BIO_indent(out, indent, 128))
424296341Sdelphij            return 0;
425296341Sdelphij        BIO_printf(out, "Private key: ");
426296341Sdelphij        key = gost_get0_priv_key(pkey);
427296341Sdelphij        if (!key)
428296341Sdelphij            BIO_printf(out, "<undefined)");
429296341Sdelphij        else
430296341Sdelphij            BN_print(out, key);
431296341Sdelphij        BIO_printf(out, "\n");
432296341Sdelphij    }
433296341Sdelphij    if (type >= 1) {
434296341Sdelphij        BN_CTX *ctx = BN_CTX_new();
435296341Sdelphij        BIGNUM *X, *Y;
436296341Sdelphij        const EC_POINT *pubkey;
437296341Sdelphij        const EC_GROUP *group;
438238384Sjkim
439296341Sdelphij        if (!ctx) {
440296341Sdelphij            GOSTerr(GOST_F_PRINT_GOST_01, ERR_R_MALLOC_FAILURE);
441296341Sdelphij            return 0;
442296341Sdelphij        }
443296341Sdelphij        BN_CTX_start(ctx);
444296341Sdelphij        X = BN_CTX_get(ctx);
445296341Sdelphij        Y = BN_CTX_get(ctx);
446296341Sdelphij        pubkey =
447296341Sdelphij            EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
448296341Sdelphij        group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
449296341Sdelphij        if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) {
450296341Sdelphij            GOSTerr(GOST_F_PRINT_GOST_01, ERR_R_EC_LIB);
451296341Sdelphij            BN_CTX_free(ctx);
452296341Sdelphij            return 0;
453296341Sdelphij        }
454296341Sdelphij        if (!BIO_indent(out, indent, 128))
455296341Sdelphij            return 0;
456296341Sdelphij        BIO_printf(out, "Public key:\n");
457296341Sdelphij        if (!BIO_indent(out, indent + 3, 128))
458296341Sdelphij            return 0;
459296341Sdelphij        BIO_printf(out, "X:");
460296341Sdelphij        BN_print(out, X);
461296341Sdelphij        BIO_printf(out, "\n");
462296341Sdelphij        BIO_indent(out, indent + 3, 128);
463296341Sdelphij        BIO_printf(out, "Y:");
464296341Sdelphij        BN_print(out, Y);
465296341Sdelphij        BIO_printf(out, "\n");
466296341Sdelphij        BN_CTX_end(ctx);
467296341Sdelphij        BN_CTX_free(ctx);
468296341Sdelphij    }
469238384Sjkim
470296341Sdelphij    param_nid =
471296341Sdelphij        EC_GROUP_get_curve_name(EC_KEY_get0_group
472296341Sdelphij                                (EVP_PKEY_get0((EVP_PKEY *)pkey)));
473296341Sdelphij    if (!BIO_indent(out, indent, 128))
474296341Sdelphij        return 0;
475296341Sdelphij    BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
476296341Sdelphij    return 1;
477238384Sjkim}
478296341Sdelphij
479238384Sjkimstatic int param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
480296341Sdelphij                              ASN1_PCTX *pctx)
481296341Sdelphij{
482296341Sdelphij    return print_gost_01(out, pkey, indent, pctx, 0);
483296341Sdelphij}
484296341Sdelphij
485238384Sjkimstatic int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
486296341Sdelphij                            ASN1_PCTX *pctx)
487296341Sdelphij{
488296341Sdelphij    return print_gost_01(out, pkey, indent, pctx, 1);
489296341Sdelphij}
490296341Sdelphij
491296341Sdelphijstatic int priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
492296341Sdelphij                             ASN1_PCTX *pctx)
493296341Sdelphij{
494296341Sdelphij    return print_gost_01(out, pkey, indent, pctx, 2);
495296341Sdelphij}
496296341Sdelphij
497238384Sjkim/* ---------------------------------------------------------------------*/
498296341Sdelphijstatic int param_missing_gost94(const EVP_PKEY *pk)
499296341Sdelphij{
500296341Sdelphij    const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
501296341Sdelphij    if (!dsa)
502296341Sdelphij        return 1;
503296341Sdelphij    if (!dsa->q)
504296341Sdelphij        return 1;
505296341Sdelphij    return 0;
506296341Sdelphij}
507238384Sjkim
508296341Sdelphijstatic int param_missing_gost01(const EVP_PKEY *pk)
509296341Sdelphij{
510296341Sdelphij    const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
511296341Sdelphij    if (!ec)
512296341Sdelphij        return 1;
513296341Sdelphij    if (!EC_KEY_get0_group(ec))
514296341Sdelphij        return 1;
515296341Sdelphij    return 0;
516296341Sdelphij}
517238384Sjkim
518296341Sdelphijstatic int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from)
519296341Sdelphij{
520296341Sdelphij    const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from);
521296341Sdelphij    DSA *dto = EVP_PKEY_get0(to);
522296341Sdelphij    if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
523296341Sdelphij        GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_INCOMPATIBLE_ALGORITHMS);
524296341Sdelphij        return 0;
525296341Sdelphij    }
526296341Sdelphij    if (!dfrom) {
527296341Sdelphij        GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_KEY_PARAMETERS_MISSING);
528296341Sdelphij        return 0;
529296341Sdelphij    }
530296341Sdelphij    if (!dto) {
531296341Sdelphij        dto = DSA_new();
532296341Sdelphij        EVP_PKEY_assign(to, EVP_PKEY_base_id(from), dto);
533296341Sdelphij    }
534296341Sdelphij#define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x);
535296341Sdelphij    COPYBIGNUM(dto, dfrom, p)
536296341Sdelphij        COPYBIGNUM(dto, dfrom, q)
537296341Sdelphij        COPYBIGNUM(dto, dfrom, g)
538238384Sjkim
539296341Sdelphij        if (dto->priv_key)
540296341Sdelphij        gost94_compute_public(dto);
541296341Sdelphij    return 1;
542296341Sdelphij}
543238384Sjkim
544296341Sdelphijstatic int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
545296341Sdelphij{
546296341Sdelphij    EC_KEY *eto = EVP_PKEY_get0(to);
547296341Sdelphij    const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
548296341Sdelphij    if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
549296341Sdelphij        GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_INCOMPATIBLE_ALGORITHMS);
550296341Sdelphij        return 0;
551296341Sdelphij    }
552296341Sdelphij    if (!efrom) {
553296341Sdelphij        GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_KEY_PARAMETERS_MISSING);
554296341Sdelphij        return 0;
555296341Sdelphij    }
556296341Sdelphij    if (!eto) {
557296341Sdelphij        eto = EC_KEY_new();
558296341Sdelphij        if(!eto) {
559296341Sdelphij            GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_MALLOC_FAILURE);
560296341Sdelphij            return 0;
561296341Sdelphij        }
562296341Sdelphij        if(!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
563296341Sdelphij            GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
564296341Sdelphij            return 0;
565296341Sdelphij        }
566296341Sdelphij    }
567296341Sdelphij    if(!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
568296341Sdelphij        GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
569296341Sdelphij        return 0;
570296341Sdelphij    }
571296341Sdelphij    if (EC_KEY_get0_private_key(eto)) {
572296341Sdelphij        gost2001_compute_public(eto);
573296341Sdelphij    }
574296341Sdelphij    return 1;
575296341Sdelphij}
576238384Sjkim
577296341Sdelphijstatic int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
578296341Sdelphij{
579296341Sdelphij    const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
580296341Sdelphij    const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
581296341Sdelphij    if (!BN_cmp(da->q, db->q))
582296341Sdelphij        return 1;
583296341Sdelphij    return 0;
584296341Sdelphij}
585238384Sjkim
586296341Sdelphijstatic int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
587296341Sdelphij{
588296341Sdelphij    if (EC_GROUP_get_curve_name
589296341Sdelphij        (EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a))) ==
590296341Sdelphij        EC_GROUP_get_curve_name(EC_KEY_get0_group
591296341Sdelphij                                (EVP_PKEY_get0((EVP_PKEY *)b)))) {
592296341Sdelphij        return 1;
593296341Sdelphij    }
594296341Sdelphij    return 0;
595238384Sjkim
596296341Sdelphij}
597296341Sdelphij
598238384Sjkim/* ---------- Public key functions * --------------------------------------*/
599238384Sjkimstatic int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
600296341Sdelphij{
601296341Sdelphij    X509_ALGOR *palg = NULL;
602296341Sdelphij    const unsigned char *pubkey_buf = NULL;
603296341Sdelphij    unsigned char *databuf;
604296341Sdelphij    ASN1_OBJECT *palgobj = NULL;
605296341Sdelphij    int pub_len, i, j;
606296341Sdelphij    DSA *dsa;
607296341Sdelphij    ASN1_OCTET_STRING *octet = NULL;
608238384Sjkim
609296341Sdelphij    if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
610296341Sdelphij        return 0;
611296341Sdelphij    EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
612296341Sdelphij    if (!decode_gost_algor_params(pk, palg))
613296341Sdelphij        return 0;
614296341Sdelphij    octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
615296341Sdelphij    if (!octet) {
616296341Sdelphij        GOSTerr(GOST_F_PUB_DECODE_GOST94, ERR_R_MALLOC_FAILURE);
617296341Sdelphij        return 0;
618296341Sdelphij    }
619296341Sdelphij    databuf = OPENSSL_malloc(octet->length);
620296341Sdelphij    for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
621296341Sdelphij        databuf[j] = octet->data[i];
622296341Sdelphij    }
623296341Sdelphij    dsa = EVP_PKEY_get0(pk);
624296341Sdelphij    dsa->pub_key = BN_bin2bn(databuf, octet->length, NULL);
625296341Sdelphij    ASN1_OCTET_STRING_free(octet);
626296341Sdelphij    OPENSSL_free(databuf);
627296341Sdelphij    return 1;
628238384Sjkim
629296341Sdelphij}
630238384Sjkim
631296341Sdelphijstatic int pub_encode_gost94(X509_PUBKEY *pub, const EVP_PKEY *pk)
632296341Sdelphij{
633296341Sdelphij    ASN1_OBJECT *algobj = NULL;
634296341Sdelphij    ASN1_OCTET_STRING *octet = NULL;
635296341Sdelphij    void *pval = NULL;
636296341Sdelphij    unsigned char *buf = NULL, *databuf, *sptr;
637296341Sdelphij    int i, j, data_len, ret = 0;
638238384Sjkim
639296341Sdelphij    int ptype = V_ASN1_UNDEF;
640296341Sdelphij    DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
641296341Sdelphij    algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
642296341Sdelphij    if (pk->save_parameters) {
643296341Sdelphij        ASN1_STRING *params = encode_gost_algor_params(pk);
644296341Sdelphij        pval = params;
645296341Sdelphij        ptype = V_ASN1_SEQUENCE;
646296341Sdelphij    }
647296341Sdelphij    data_len = BN_num_bytes(dsa->pub_key);
648296341Sdelphij    databuf = OPENSSL_malloc(data_len);
649296341Sdelphij    BN_bn2bin(dsa->pub_key, databuf);
650296341Sdelphij    octet = ASN1_OCTET_STRING_new();
651296341Sdelphij    ASN1_STRING_set(octet, NULL, data_len);
652296341Sdelphij    sptr = ASN1_STRING_data(octet);
653296341Sdelphij    for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
654296341Sdelphij        sptr[i] = databuf[j];
655296341Sdelphij    }
656296341Sdelphij    OPENSSL_free(databuf);
657296341Sdelphij    ret = i2d_ASN1_OCTET_STRING(octet, &buf);
658296341Sdelphij    ASN1_BIT_STRING_free(octet);
659296341Sdelphij    if (ret < 0)
660296341Sdelphij        return 0;
661296341Sdelphij    return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
662296341Sdelphij}
663238384Sjkim
664296341Sdelphijstatic int pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
665296341Sdelphij{
666296341Sdelphij    X509_ALGOR *palg = NULL;
667296341Sdelphij    const unsigned char *pubkey_buf = NULL;
668296341Sdelphij    unsigned char *databuf;
669296341Sdelphij    ASN1_OBJECT *palgobj = NULL;
670296341Sdelphij    int pub_len, i, j;
671296341Sdelphij    EC_POINT *pub_key;
672296341Sdelphij    BIGNUM *X, *Y;
673296341Sdelphij    ASN1_OCTET_STRING *octet = NULL;
674296341Sdelphij    int len;
675296341Sdelphij    const EC_GROUP *group;
676238384Sjkim
677296341Sdelphij    if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
678296341Sdelphij        return 0;
679296341Sdelphij    EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
680296341Sdelphij    if (!decode_gost_algor_params(pk, palg))
681296341Sdelphij        return 0;
682296341Sdelphij    group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
683296341Sdelphij    octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
684296341Sdelphij    if (!octet) {
685296341Sdelphij        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
686296341Sdelphij        return 0;
687296341Sdelphij    }
688296341Sdelphij    databuf = OPENSSL_malloc(octet->length);
689296341Sdelphij    for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
690296341Sdelphij        databuf[j] = octet->data[i];
691296341Sdelphij    }
692296341Sdelphij    len = octet->length / 2;
693296341Sdelphij    ASN1_OCTET_STRING_free(octet);
694238384Sjkim
695296341Sdelphij    Y = getbnfrombuf(databuf, len);
696296341Sdelphij    X = getbnfrombuf(databuf + len, len);
697296341Sdelphij    OPENSSL_free(databuf);
698296341Sdelphij    pub_key = EC_POINT_new(group);
699296341Sdelphij    if (!EC_POINT_set_affine_coordinates_GFp(group, pub_key, X, Y, NULL)) {
700296341Sdelphij        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB);
701296341Sdelphij        EC_POINT_free(pub_key);
702296341Sdelphij        BN_free(X);
703296341Sdelphij        BN_free(Y);
704296341Sdelphij        return 0;
705296341Sdelphij    }
706296341Sdelphij    BN_free(X);
707296341Sdelphij    BN_free(Y);
708296341Sdelphij    if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
709296341Sdelphij        GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB);
710296341Sdelphij        EC_POINT_free(pub_key);
711296341Sdelphij        return 0;
712296341Sdelphij    }
713296341Sdelphij    EC_POINT_free(pub_key);
714296341Sdelphij    return 1;
715238384Sjkim
716296341Sdelphij}
717238384Sjkim
718296341Sdelphijstatic int pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
719296341Sdelphij{
720296341Sdelphij    ASN1_OBJECT *algobj = NULL;
721296341Sdelphij    ASN1_OCTET_STRING *octet = NULL;
722296341Sdelphij    void *pval = NULL;
723296341Sdelphij    unsigned char *buf = NULL, *databuf, *sptr;
724296341Sdelphij    int i, j, data_len, ret = 0;
725296341Sdelphij    const EC_POINT *pub_key;
726296341Sdelphij    BIGNUM *X, *Y, *order;
727296341Sdelphij    const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
728296341Sdelphij    int ptype = V_ASN1_UNDEF;
729238384Sjkim
730296341Sdelphij    algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
731296341Sdelphij    if (pk->save_parameters) {
732296341Sdelphij        ASN1_STRING *params = encode_gost_algor_params(pk);
733296341Sdelphij        pval = params;
734296341Sdelphij        ptype = V_ASN1_SEQUENCE;
735296341Sdelphij    }
736296341Sdelphij    order = BN_new();
737296341Sdelphij    EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
738296341Sdelphij    pub_key = EC_KEY_get0_public_key(ec);
739296341Sdelphij    if (!pub_key) {
740296341Sdelphij        GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED);
741296341Sdelphij        return 0;
742296341Sdelphij    }
743296341Sdelphij    X = BN_new();
744296341Sdelphij    Y = BN_new();
745296341Sdelphij    if(!X || !Y) {
746296341Sdelphij        GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
747296341Sdelphij        if(X) BN_free(X);
748296341Sdelphij        if(Y) BN_free(Y);
749296341Sdelphij        BN_free(order);
750296341Sdelphij        return 0;
751296341Sdelphij    }
752296341Sdelphij    if(!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
753296341Sdelphij                                        pub_key, X, Y, NULL)) {
754296341Sdelphij        GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR);
755296341Sdelphij        BN_free(X);
756296341Sdelphij        BN_free(Y);
757296341Sdelphij        BN_free(order);
758296341Sdelphij        return 0;
759296341Sdelphij    }
760296341Sdelphij    data_len = 2 * BN_num_bytes(order);
761296341Sdelphij    BN_free(order);
762296341Sdelphij    databuf = OPENSSL_malloc(data_len);
763296341Sdelphij    memset(databuf, 0, data_len);
764296341Sdelphij
765296341Sdelphij    store_bignum(X, databuf + data_len / 2, data_len / 2);
766296341Sdelphij    store_bignum(Y, databuf, data_len / 2);
767296341Sdelphij
768296341Sdelphij    BN_free(X);
769296341Sdelphij    BN_free(Y);
770296341Sdelphij    octet = ASN1_OCTET_STRING_new();
771296341Sdelphij    ASN1_STRING_set(octet, NULL, data_len);
772296341Sdelphij    sptr = ASN1_STRING_data(octet);
773296341Sdelphij    for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
774296341Sdelphij        sptr[i] = databuf[j];
775296341Sdelphij    }
776238384Sjkim    OPENSSL_free(databuf);
777296341Sdelphij    ret = i2d_ASN1_OCTET_STRING(octet, &buf);
778296341Sdelphij    ASN1_BIT_STRING_free(octet);
779296341Sdelphij    if (ret < 0)
780296341Sdelphij        return 0;
781296341Sdelphij    return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
782296341Sdelphij}
783238384Sjkim
784238384Sjkimstatic int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
785296341Sdelphij{
786296341Sdelphij    const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
787296341Sdelphij    const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
788296341Sdelphij    if (da && db && da->pub_key && db->pub_key
789296341Sdelphij        && !BN_cmp(da->pub_key, db->pub_key)) {
790296341Sdelphij        return 1;
791296341Sdelphij    }
792296341Sdelphij    return 0;
793296341Sdelphij}
794238384Sjkim
795296341Sdelphijstatic int pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
796296341Sdelphij{
797296341Sdelphij    const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
798296341Sdelphij    const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
799296341Sdelphij    const EC_POINT *ka, *kb;
800296341Sdelphij    int ret = 0;
801296341Sdelphij    if (!ea || !eb)
802296341Sdelphij        return 0;
803296341Sdelphij    ka = EC_KEY_get0_public_key(ea);
804296341Sdelphij    kb = EC_KEY_get0_public_key(eb);
805296341Sdelphij    if (!ka || !kb)
806296341Sdelphij        return 0;
807296341Sdelphij    ret = (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
808296341Sdelphij    return ret;
809296341Sdelphij}
810238384Sjkim
811238384Sjkimstatic int pkey_size_gost(const EVP_PKEY *pk)
812296341Sdelphij{
813296341Sdelphij    return 64;
814296341Sdelphij}
815238384Sjkim
816238384Sjkimstatic int pkey_bits_gost(const EVP_PKEY *pk)
817238384Sjkim{
818296341Sdelphij    return 256;
819296341Sdelphij}
820238384Sjkim
821296341Sdelphij/* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
822296341Sdelphijstatic void mackey_free_gost(EVP_PKEY *pk)
823238384Sjkim{
824296341Sdelphij    if (pk->pkey.ptr) {
825296341Sdelphij        OPENSSL_free(pk->pkey.ptr);
826296341Sdelphij    }
827238384Sjkim}
828296341Sdelphij
829296341Sdelphijstatic int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
830238384Sjkim{
831296341Sdelphij    switch (op) {
832296341Sdelphij    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
833296341Sdelphij        *(int *)arg2 = NID_id_Gost28147_89_MAC;
834296341Sdelphij        return 2;
835296341Sdelphij    }
836296341Sdelphij    return -2;
837238384Sjkim}
838238384Sjkim
839296341Sdelphijstatic int gost94_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
840238384Sjkim{
841296341Sdelphij    int nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
842296341Sdelphij    return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
843296341Sdelphij}
844238384Sjkim
845296341Sdelphijstatic int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
846296341Sdelphij{
847296341Sdelphij    int nid =
848296341Sdelphij        EC_GROUP_get_curve_name(EC_KEY_get0_group
849296341Sdelphij                                (EVP_PKEY_get0((EVP_PKEY *)pkey)));
850296341Sdelphij    return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
851296341Sdelphij}
852238384Sjkim
853296341Sdelphijstatic int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
854296341Sdelphij                               int derlen)
855296341Sdelphij{
856296341Sdelphij    ASN1_OBJECT *obj = NULL;
857296341Sdelphij    DSA *dsa = EVP_PKEY_get0(pkey);
858296341Sdelphij    int nid;
859296341Sdelphij    if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
860296341Sdelphij        return 0;
861296341Sdelphij    }
862296341Sdelphij    nid = OBJ_obj2nid(obj);
863296341Sdelphij    ASN1_OBJECT_free(obj);
864296341Sdelphij    if (!dsa) {
865296341Sdelphij        dsa = DSA_new();
866296341Sdelphij        if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_94, dsa))
867296341Sdelphij            return 0;
868296341Sdelphij    }
869296341Sdelphij    if (!fill_GOST94_params(dsa, nid))
870296341Sdelphij        return 0;
871296341Sdelphij    return 1;
872296341Sdelphij}
873238384Sjkim
874296341Sdelphijstatic int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
875296341Sdelphij                                 int derlen)
876296341Sdelphij{
877296341Sdelphij    ASN1_OBJECT *obj = NULL;
878296341Sdelphij    int nid;
879296341Sdelphij    EC_KEY *ec = EVP_PKEY_get0(pkey);
880296341Sdelphij    if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
881296341Sdelphij        return 0;
882296341Sdelphij    }
883296341Sdelphij    nid = OBJ_obj2nid(obj);
884296341Sdelphij    ASN1_OBJECT_free(obj);
885296341Sdelphij    if (!ec) {
886296341Sdelphij        ec = EC_KEY_new();
887296341Sdelphij        if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec))
888296341Sdelphij            return 0;
889296341Sdelphij    }
890296341Sdelphij    if (!fill_GOST2001_params(ec, nid))
891296341Sdelphij        return 0;
892296341Sdelphij    return 1;
893296341Sdelphij}
894238384Sjkim
895296341Sdelphij/* ----------------------------------------------------------------------*/
896296341Sdelphijint register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
897296341Sdelphij                        const char *pemstr, const char *info)
898296341Sdelphij{
899296341Sdelphij    *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
900296341Sdelphij    if (!*ameth)
901296341Sdelphij        return 0;
902296341Sdelphij    switch (nid) {
903296341Sdelphij    case NID_id_GostR3410_94:
904296341Sdelphij        EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost94);
905296341Sdelphij        EVP_PKEY_asn1_set_private(*ameth,
906296341Sdelphij                                  priv_decode_gost, priv_encode_gost,
907296341Sdelphij                                  priv_print_gost94);
908238384Sjkim
909296341Sdelphij        EVP_PKEY_asn1_set_param(*ameth,
910296341Sdelphij                                gost94_param_decode, gost94_param_encode,
911296341Sdelphij                                param_missing_gost94, param_copy_gost94,
912296341Sdelphij                                param_cmp_gost94, param_print_gost94);
913296341Sdelphij        EVP_PKEY_asn1_set_public(*ameth,
914296341Sdelphij                                 pub_decode_gost94, pub_encode_gost94,
915296341Sdelphij                                 pub_cmp_gost94, pub_print_gost94,
916296341Sdelphij                                 pkey_size_gost, pkey_bits_gost);
917238384Sjkim
918296341Sdelphij        EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
919296341Sdelphij        break;
920296341Sdelphij    case NID_id_GostR3410_2001:
921296341Sdelphij        EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost01);
922296341Sdelphij        EVP_PKEY_asn1_set_private(*ameth,
923296341Sdelphij                                  priv_decode_gost, priv_encode_gost,
924296341Sdelphij                                  priv_print_gost01);
925238384Sjkim
926296341Sdelphij        EVP_PKEY_asn1_set_param(*ameth,
927296341Sdelphij                                gost2001_param_decode, gost2001_param_encode,
928296341Sdelphij                                param_missing_gost01, param_copy_gost01,
929296341Sdelphij                                param_cmp_gost01, param_print_gost01);
930296341Sdelphij        EVP_PKEY_asn1_set_public(*ameth,
931296341Sdelphij                                 pub_decode_gost01, pub_encode_gost01,
932296341Sdelphij                                 pub_cmp_gost01, pub_print_gost01,
933296341Sdelphij                                 pkey_size_gost, pkey_bits_gost);
934238384Sjkim
935296341Sdelphij        EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
936296341Sdelphij        break;
937296341Sdelphij    case NID_id_Gost28147_89_MAC:
938296341Sdelphij        EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
939296341Sdelphij        EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
940296341Sdelphij        break;
941296341Sdelphij    }
942296341Sdelphij    return 1;
943296341Sdelphij}
944