06f8c1e19a206039060205a791df0e5fd02ac582
[openssl.git] / engines / ccgost / gost_ameth.c
1 /**********************************************************************
2  *                          gost_ameth.c                              *
3  *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4  *         This file is distributed under the same license as OpenSSL *
5  *                                                                    *
6  *       Implementation of RFC 4490/4491 ASN1 method                  *
7  *       for OpenSSL                                                  *
8  *          Requires OpenSSL 0.9.9 for compilation                    *
9  **********************************************************************/
10 #include <openssl/engine.h>
11 #include <openssl/evp.h>
12 #include <string.h>
13 #include "gost_params.h"
14 #include "gost_lcl.h"
15 #include "e_gost_err.h"
16
17 int gost94_nid_by_params(DSA *p) 
18         {
19         R3410_params *gost_params;
20         BIGNUM *q=BN_new();
21         for (gost_params = R3410_paramset;gost_params->q!=NULL; gost_params++) 
22                 {
23                 BN_dec2bn(&q,gost_params->q);
24                 if (!BN_cmp(q,p->q)) 
25                         {
26                         BN_free(q);
27                         return gost_params->nid;
28                         }
29                 }       
30         BN_free(q);
31         return NID_undef;
32         }
33
34 static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
35         {
36         ASN1_STRING *params = ASN1_STRING_new();
37         GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
38         int pkey_param_nid = NID_undef;
39         int cipher_param_nid = NID_undef;
40         if (!params || !gkp) 
41                 {
42                 GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
43                         ERR_R_MALLOC_FAILURE);
44                 ASN1_STRING_free(params);
45                 params = NULL;
46                 goto err;
47                 }       
48         switch (EVP_PKEY_base_id(key)) 
49                 {
50                 case NID_id_GostR3410_2001_cc:
51                         pkey_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
52                         cipher_param_nid = NID_id_Gost28147_89_cc;
53                         break;
54                 case NID_id_GostR3410_94_cc:
55                         pkey_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
56                         cipher_param_nid = NID_id_Gost28147_89_cc;
57                         break;
58                 case NID_id_GostR3410_2001:
59                         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
60                         cipher_param_nid = get_encryption_params(NULL)->nid;
61                         break;
62                 case NID_id_GostR3410_94:
63                         pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
64                         if (pkey_param_nid == NID_undef) 
65                                 {
66                                 GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
67                                         GOST_R_INVALID_GOST94_PARMSET);
68                                 ASN1_STRING_free(params);
69                                 params=NULL;
70                                 goto err;
71                                 }       
72                         cipher_param_nid = get_encryption_params(NULL)->nid;
73                         break;
74                 }       
75         gkp->key_params = OBJ_nid2obj(pkey_param_nid);
76         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
77         /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);*/
78         params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
79         if (params->length <=0 ) 
80                 {
81                 GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
82                         ERR_R_MALLOC_FAILURE);
83                 ASN1_STRING_free(params);
84                 params = NULL;
85                 goto err;
86                 }
87         params ->type = V_ASN1_SEQUENCE;
88         err:
89         GOST_KEY_PARAMS_free(gkp);
90         return params;
91         }
92
93 /* Parses GOST algorithm parameters from X509_ALGOR and
94  * modifies pkey setting NID and parameters
95  */
96 static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) 
97         {
98         ASN1_OBJECT *palg_obj =NULL;
99         int ptype = V_ASN1_UNDEF;
100         int pkey_nid = NID_undef,param_nid = NID_undef;
101         void *_pval;
102         ASN1_STRING *pval = NULL;
103         const unsigned char  *p;
104         GOST_KEY_PARAMS *gkp = NULL;
105
106         X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg);
107         pval = _pval;
108         if (ptype != V_ASN1_SEQUENCE) 
109                 {
110                 GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
111                         GOST_R_BAD_KEY_PARAMETERS_FORMAT);
112                 return 0;
113                 }       
114         p=pval->data;
115         pkey_nid = OBJ_obj2nid(palg_obj);
116
117         gkp = d2i_GOST_KEY_PARAMS(NULL,&p,pval->length);
118         if (!gkp) 
119                 {
120                 GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
121                         GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
122                 }       
123         param_nid = OBJ_obj2nid(gkp->key_params);
124         GOST_KEY_PARAMS_free(gkp);
125         EVP_PKEY_set_type(pkey,pkey_nid);
126         switch (pkey_nid) 
127                 {
128                 case NID_id_GostR3410_94:
129                 case NID_id_GostR3410_94_cc:
130                 {
131                 DSA *dsa= EVP_PKEY_get0(pkey);
132                 if (!dsa) 
133                         {
134                         dsa = DSA_new();
135                         if (!EVP_PKEY_assign(pkey,pkey_nid,dsa)) return 0;
136                         }
137                 if (!fill_GOST94_params(dsa,param_nid)) return 0;
138                 break;
139                 }
140                 case NID_id_GostR3410_2001:
141                 case NID_id_GostR3410_2001_cc:
142                 {
143                 EC_KEY *ec = EVP_PKEY_get0(pkey);
144                 if (!ec) 
145                         {
146                         ec = EC_KEY_new();
147                         if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
148                         }
149                 if (!fill_GOST2001_params(ec,param_nid)) return 0;
150                 }
151                 }
152
153         return 1;
154         }
155
156 static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv) 
157         {
158         switch (EVP_PKEY_base_id(pkey)) 
159                 {
160                 case NID_id_GostR3410_94:
161                 case NID_id_GostR3410_94_cc:
162                 {
163                 DSA *dsa = EVP_PKEY_get0(pkey);
164                 if (!dsa) 
165                         {
166                         dsa = DSA_new();
167                         EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),dsa);
168                         }       
169                 dsa->priv_key = BN_dup(priv);
170                 if (!EVP_PKEY_missing_parameters(pkey)) 
171                         gost94_compute_public(dsa);
172                 break;
173                 }       
174                 case NID_id_GostR3410_2001:
175                 case NID_id_GostR3410_2001_cc:
176                 {
177                 EC_KEY *ec = EVP_PKEY_get0(pkey);
178                 if (!ec) 
179                         {
180                         ec = EC_KEY_new();
181                         EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),ec);
182                         }       
183                 if (!EC_KEY_set_private_key(ec,priv)) return 0;
184                 if (!EVP_PKEY_missing_parameters(pkey)) 
185                         gost2001_compute_public(ec);
186                 break;
187                 }
188                 }
189         return 1;               
190         }
191 BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) 
192         {
193         switch (EVP_PKEY_base_id(pkey)) 
194                 {
195                 case NID_id_GostR3410_94:
196                 case NID_id_GostR3410_94_cc:
197                 {
198                 DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
199                 if (!dsa) 
200                         {
201                         return NULL;
202                         }       
203                 if (!dsa->priv_key) return NULL;
204                 return BN_dup(dsa->priv_key);
205                 break;
206                 }       
207                 case NID_id_GostR3410_2001:
208                 case NID_id_GostR3410_2001_cc:
209                 {
210                 EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
211                 const BIGNUM* priv;
212                 if (!ec) 
213                         {
214                         return NULL;
215                         }       
216                 if (!(priv=EC_KEY_get0_private_key(ec))) return NULL;
217                 return BN_dup(priv);
218                 break;
219                 }
220                 }
221         return NULL;            
222         }
223
224 static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
225         long arg1, void *arg2)
226         {
227         switch (op)
228                 {
229                 case ASN1_PKEY_CTRL_PKCS7_SIGN:
230                         if (arg1 == 0) 
231                                 {
232                                 X509_ALGOR *alg1 = NULL, *alg2 = NULL;
233                                 int nid = EVP_PKEY_base_id(pkey);
234                                 PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2, 
235                                         NULL, &alg1, &alg2);
236                                 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
237                                         V_ASN1_NULL, 0);
238                                 if (nid == NID_undef) 
239                                         {
240                                         return (-1);
241                                         }
242                                 X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
243                                 }
244                         return 1;
245                 case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
246                         if (arg1 == 0)
247                                 {
248                                 X509_ALGOR *alg;
249                                 ASN1_STRING * params = encode_gost_algor_params(pkey);
250                                 if (!params) 
251                                         {
252                                         return -1;
253                                         }
254                                 PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO*)arg2, &alg);
255                                 X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type),
256                                         V_ASN1_SEQUENCE, params);
257                                 }
258                         return 1;
259                 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
260                         *(int *)arg2 = NID_id_GostR3411_94;
261                         return 2;
262                 }
263         
264         return -2;
265         }
266 /*----------------------- free functions * ------------------------------*/
267 static void pkey_free_gost94(EVP_PKEY *key) 
268         {
269         if (key->pkey.dsa) 
270                 {
271                 DSA_free(key->pkey.dsa);
272                 }
273         }
274
275 static void pkey_free_gost01(EVP_PKEY *key) 
276         {
277         if (key->pkey.ec) 
278                 {
279                 EC_KEY_free(key->pkey.ec);
280                 }
281         }       
282
283 /* ------------------ private key functions  -----------------------------*/
284 static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) 
285         {
286         const unsigned char *pkey_buf = NULL,*p=NULL;
287         int priv_len = 0;
288         BIGNUM *pk_num=NULL;
289         int ret =0;
290         X509_ALGOR *palg =NULL;
291         ASN1_OBJECT *palg_obj = NULL;
292         ASN1_INTEGER *priv_key=NULL;
293
294         if (!PKCS8_pkey_get0(&palg_obj,&pkey_buf,&priv_len,&palg,p8inf)) 
295                 return 0;
296         p = pkey_buf;
297         if (!decode_gost_algor_params(pk,palg)) 
298                 {
299                 return 0;
300                 }
301         if (V_ASN1_OCTET_STRING == *p) 
302                 {
303                 /* New format - Little endian octet string */
304                 unsigned char rev_buf[32];
305                 int i;
306                 ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL,&p,priv_len);
307                 if (!s||s->length !=32) 
308                         {
309                         GOSTerr(GOST_F_PRIV_DECODE_GOST_94,
310                                 EVP_R_DECODE_ERROR);
311                         return 0;       
312                         }
313                 for (i=0;i<32;i++)
314                         {
315                         rev_buf[31-i]=s->data[i];
316                         }
317                 ASN1_STRING_free(s);
318                 pk_num = getbnfrombuf(rev_buf,32);
319                 } 
320         else
321                 {
322                 priv_key=d2i_ASN1_INTEGER(NULL,&p,priv_len);
323                 if (!priv_key || !(pk_num =  ASN1_INTEGER_to_BN(priv_key, NULL))) 
324                         {
325                         GOSTerr(GOST_F_PRIV_DECODE_GOST_94,
326                                 EVP_R_DECODE_ERROR);
327                         return 0;       
328                         }
329                 }
330
331         ret= gost_set_priv_key(pk,pk_num);
332         BN_free(pk_num);
333         return ret;
334         }
335
336 /* ----------------------------------------------------------------------*/
337 static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
338         {
339         ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
340         ASN1_STRING *params = encode_gost_algor_params(pk);
341         unsigned char *priv_buf = NULL;
342         int priv_len;
343         BIGNUM *key;
344
345         ASN1_INTEGER *asn1key=NULL;
346         if (!params) 
347                 {
348                 return 0;
349                 }
350         key = gost_get_priv_key(pk);
351         asn1key = BN_to_ASN1_INTEGER(key,NULL);
352         BN_free(key);
353         priv_len = i2d_ASN1_INTEGER(asn1key,&priv_buf);
354         ASN1_INTEGER_free(asn1key);
355         return PKCS8_pkey_set0(p8,algobj,0,V_ASN1_SEQUENCE,params,
356                 priv_buf,priv_len);
357         }
358
359 static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent,
360         ASN1_PCTX *pctx) 
361         {
362         BIGNUM *key;
363         if (!BIO_indent(out,indent,128)) return 0;
364         key = gost_get_priv_key(pkey);
365         if (!key) return 0;
366         BN_print(out,key);
367         BN_free(key);
368         return 1;
369         }
370
371 /* ---------------------------------------------------------------------*/
372 static int param_missing_gost94(const EVP_PKEY *pk) 
373         {
374         const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
375         if (!dsa) return 1;
376         if (!dsa->q) return 1;
377         return 0;
378         }
379
380 static int param_missing_gost01(const EVP_PKEY *pk) 
381         {
382         const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
383         if (!ec) return 1;
384         if (!EC_KEY_get0_group(ec)) return 1;
385         return 0;
386         }
387
388 static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from) 
389         {
390         const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from);
391         DSA *dto = EVP_PKEY_get0(to);
392         if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) 
393                 {
394                 GOSTerr(GOST_F_PARAM_COPY_GOST94,
395                         GOST_R_INCOMPATIBLE_ALGORITHMS);
396                 return 0;
397                 }       
398         if (!dfrom) 
399                 {
400                 GOSTerr(GOST_F_PARAM_COPY_GOST94,
401                         GOST_R_KEY_PARAMETERS_MISSING);
402                 return 0;
403                 }       
404         if (!dto) 
405                 {
406                 dto = DSA_new();
407                 EVP_PKEY_assign(to,EVP_PKEY_base_id(from),dto);
408                 }       
409 #define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x);   
410         COPYBIGNUM(dto,dfrom,p)
411                 COPYBIGNUM(dto,dfrom,q)
412                 COPYBIGNUM(dto,dfrom,g)
413
414                 if (dto->priv_key) 
415                         gost94_compute_public(dto);
416         return 1;       
417         }
418 static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) 
419         {
420         EC_KEY *eto = EVP_PKEY_get0(to);
421         const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
422         if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) 
423                 {
424                 GOSTerr(GOST_F_PARAM_COPY_GOST01,
425                         GOST_R_INCOMPATIBLE_ALGORITHMS);
426                 return 0;
427                 }       
428         if (!efrom) 
429                 {
430                 GOSTerr(GOST_F_PARAM_COPY_GOST94,
431                         GOST_R_KEY_PARAMETERS_MISSING);
432                 return 0;
433                 }       
434         if (!eto) 
435                 {
436                 eto = EC_KEY_new();
437                 EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto);
438                 }       
439         EC_KEY_set_group(eto,EC_GROUP_dup(EC_KEY_get0_group(efrom)));
440         if (EC_KEY_get0_private_key(eto)) 
441                 {
442                 gost2001_compute_public(eto);
443                 }
444         return 1;
445         }
446
447 static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b) 
448         {
449         const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
450         const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
451         if (!BN_cmp(da->q,db->q)) return 1;
452         return 0;
453         }
454
455 static int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) 
456         {
457         if (EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a)))==
458                 EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)b)))) 
459                 {
460                 return 1;
461                 }
462         return 0;
463
464         }
465
466 /* ---------- Public key functions * --------------------------------------*/
467 static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
468         {
469         X509_ALGOR *palg = NULL;
470         const unsigned char *pubkey_buf = NULL;
471         unsigned char *databuf;
472         ASN1_OBJECT *palgobj = NULL;
473         int pub_len,i,j;
474         DSA *dsa;
475         ASN1_OCTET_STRING *octet= NULL;
476
477         if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
478                         &palg, pub)) return 0;
479         EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL);  
480         if (!decode_gost_algor_params(pk,palg)) return 0;
481         octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len);
482         if (!octet) 
483                 {
484                 GOSTerr(GOST_F_PUB_DECODE_GOST94,ERR_R_MALLOC_FAILURE);
485                 return 0;
486                 }       
487         databuf = OPENSSL_malloc(octet->length);
488         for (i=0,j=octet->length-1;i<octet->length;i++,j--)
489                 {
490                 databuf[j]=octet->data[i];
491                 }       
492         dsa = EVP_PKEY_get0(pk);
493         dsa->pub_key=BN_bin2bn(databuf,octet->length,NULL);
494         ASN1_OCTET_STRING_free(octet);
495         OPENSSL_free(databuf);
496         return 1;
497
498         }
499
500 static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk)
501         {
502         ASN1_OBJECT *algobj = NULL;
503         ASN1_OCTET_STRING *octet = NULL;
504         void *pval = NULL;
505         unsigned char *buf=NULL,*databuf,*sptr;
506         int i,j,data_len,ret=0;
507
508         int ptype = V_ASN1_UNDEF;
509         DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
510         algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
511         if (pk->save_parameters) 
512                 {
513                 ASN1_STRING *params = encode_gost_algor_params(pk);
514                 pval = params;
515                 ptype = V_ASN1_SEQUENCE;
516                 }       
517         data_len = BN_num_bytes(dsa->pub_key);
518         databuf = OPENSSL_malloc(data_len);
519         BN_bn2bin(dsa->pub_key,databuf);
520         octet = ASN1_OCTET_STRING_new();
521         ASN1_STRING_set(octet,NULL,data_len);
522         sptr = ASN1_STRING_data(octet);
523         for (i=0,j=data_len-1; i< data_len;i++,j--)
524                 {
525                 sptr[i]=databuf[j];
526                 }
527         OPENSSL_free(databuf);
528         ret = i2d_ASN1_OCTET_STRING(octet,&buf);
529         ASN1_BIT_STRING_free(octet);
530         if (ret <0)  return 0;
531         return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
532         }
533
534 static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
535         {
536         X509_ALGOR *palg = NULL;
537         const unsigned char *pubkey_buf = NULL;
538         unsigned char *databuf;
539         ASN1_OBJECT *palgobj = NULL;
540         int pub_len,i,j;
541         EC_POINT *pub_key;
542         BIGNUM *X,*Y;
543         ASN1_OCTET_STRING *octet= NULL;
544         const EC_GROUP *group;
545
546         if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
547                         &palg, pub)) return 0;
548         EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL);  
549         if (!decode_gost_algor_params(pk,palg)) return 0;
550         group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
551         octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len);
552         if (!octet) 
553                 {
554                 GOSTerr(GOST_F_PUB_DECODE_GOST94,ERR_R_MALLOC_FAILURE);
555                 return 0;
556                 }       
557         databuf = OPENSSL_malloc(octet->length);
558         for (i=0,j=octet->length-1;i<octet->length;i++,j--)
559                 {
560                 databuf[j]=octet->data[i];
561                 }
562         if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc) 
563                 {
564                 X= getbnfrombuf(databuf,octet->length/2);
565                 Y= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
566                 }
567         else 
568                 {
569                 Y= getbnfrombuf(databuf,octet->length/2);
570                 X= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
571                 }
572         OPENSSL_free(databuf);
573         pub_key = EC_POINT_new(group);
574         if (!EC_POINT_set_affine_coordinates_GFp(group
575                         ,pub_key,X,Y,NULL))
576                 {
577                 GOSTerr(GOST_F_PUB_DECODE_GOST01,
578                         ERR_R_EC_LIB);
579                 return 0;
580                 }       
581         BN_free(X);
582         BN_free(Y);
583         if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk),pub_key))
584                 {
585                 GOSTerr(GOST_F_PUB_DECODE_GOST01,
586                         ERR_R_EC_LIB);
587                 return 0;
588                 }       
589         /*EC_POINT_free(pub_key);*/
590         return 1;
591
592         }
593
594 static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
595         {
596         ASN1_OBJECT *algobj = NULL;
597         ASN1_OCTET_STRING *octet = NULL;
598         void *pval = NULL;
599         unsigned char *buf=NULL,*databuf,*sptr;
600         int i,j,data_len,ret=0;
601         const EC_POINT *pub_key;
602         BIGNUM *X,*Y,*order;
603         const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
604         int ptype = V_ASN1_UNDEF;
605
606         algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
607         if (pk->save_parameters) 
608                 {
609                 ASN1_STRING *params = encode_gost_algor_params(pk);
610                 pval = params;
611                 ptype = V_ASN1_SEQUENCE;
612                 }
613         order = BN_new();
614         EC_GROUP_get_order(EC_KEY_get0_group(ec),order,NULL);
615         pub_key=EC_KEY_get0_public_key(ec);
616         if (!pub_key) 
617                 {
618                 GOSTerr(GOST_F_PUB_ENCODE_GOST01,
619                         GOST_R_PUBLIC_KEY_UNDEFINED);
620                 return 0;
621                 }       
622         X=BN_new();
623         Y=BN_new();
624         EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
625                 pub_key,X,Y,NULL);
626         data_len = 2*BN_num_bytes(order);
627         BN_free(order);
628         databuf = OPENSSL_malloc(data_len);
629         memset(databuf,0,data_len);
630         if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc) 
631                 {
632                 store_bignum(X,databuf,data_len/2);
633                 store_bignum(Y,databuf+data_len/2,data_len/2);
634                 }
635         else 
636                 {
637                 store_bignum(X,databuf+data_len/2,data_len/2);
638                 store_bignum(Y,databuf,data_len/2);
639                 }
640         BN_free(X);
641         BN_free(Y);
642         octet = ASN1_OCTET_STRING_new();
643         ASN1_STRING_set(octet,NULL,data_len);
644         sptr=ASN1_STRING_data(octet);
645     for (i=0,j=data_len-1;i<data_len;i++,j--) 
646                 {
647         sptr[i]=databuf[j];
648                 }
649     OPENSSL_free(databuf);
650         ret = i2d_ASN1_OCTET_STRING(octet,&buf);
651         ASN1_BIT_STRING_free(octet);
652         if (ret <0)  return 0;
653         return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
654         }
655
656 static int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
657         {
658         const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
659         const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
660         if (da && db && da->pub_key && db->pub_key
661                 && !BN_cmp(da->pub_key,db->pub_key)) 
662                 {
663                 return 1;
664                 }               
665         return 0;
666         }
667
668 static int pub_cmp_gost01(const EVP_PKEY *a,const EVP_PKEY *b)
669         {
670         const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
671         const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
672         const EC_POINT *ka,*kb;
673         int ret=0;
674         if (!ea || !eb) return 0;
675         ka = EC_KEY_get0_public_key(ea);
676         kb = EC_KEY_get0_public_key(eb);
677         if (!ka || !kb) return 0;
678         ret = (0==EC_POINT_cmp(EC_KEY_get0_group(ea),ka,kb,NULL)) ;
679         return ret;
680         }
681
682 static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
683         ASN1_PCTX *pctx)
684         {
685         const BIGNUM *key;
686         if (!BIO_indent(out,indent,128)) return 0;
687         key = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
688         if (!key) return 0;
689         BN_print(out,key);
690         return 1;
691         }
692
693 static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
694         ASN1_PCTX *pctx)
695         {
696         return 0;
697         }
698
699 static int pkey_size_gost(const EVP_PKEY *pk)
700         {
701         return 64;
702         }
703
704 static int pkey_bits_gost(const EVP_PKEY *pk)
705         {
706         return 256;
707         }
708
709 /* ----------------------------------------------------------------------*/
710 int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info) 
711         {
712         *ameth =        EVP_PKEY_asn1_new(nid, 
713                 ASN1_PKEY_SIGPARAM_NULL, pemstr, info); 
714         if (!*ameth) return 0;
715         switch (nid) 
716                 {
717                 case NID_id_GostR3410_94_cc:
718                 case NID_id_GostR3410_94:
719                         EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost94);
720                         EVP_PKEY_asn1_set_private (*ameth, 
721                                 priv_decode_gost, priv_encode_gost, 
722                                 priv_print_gost);
723
724                         EVP_PKEY_asn1_set_param (*ameth, 0, 0,
725                                 param_missing_gost94, param_copy_gost94, 
726                                 param_cmp_gost94,0 );
727                         EVP_PKEY_asn1_set_public (*ameth,
728                                 pub_decode_gost94, pub_encode_gost94,
729                                 pub_cmp_gost94, pub_print_gost94,
730                                 pkey_size_gost, pkey_bits_gost);
731         
732                         EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
733                         break;
734                 case NID_id_GostR3410_2001_cc:
735                 case NID_id_GostR3410_2001:
736                         EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
737                         EVP_PKEY_asn1_set_private (*ameth, 
738                                 priv_decode_gost, priv_encode_gost, 
739                                 priv_print_gost);
740
741                         EVP_PKEY_asn1_set_param (*ameth, 0, 0,
742                                 param_missing_gost01, param_copy_gost01, 
743                                 param_cmp_gost01, 0);
744                         EVP_PKEY_asn1_set_public (*ameth,
745                                 pub_decode_gost01, pub_encode_gost01,
746                                 pub_cmp_gost01, pub_print_gost01,
747                                 pkey_size_gost, pkey_bits_gost);
748         
749                         EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
750                         break;
751                 }               
752         return 1;
753         }