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