Fix warning and back out bad modification.
[openssl.git] / engines / ccgost / gost_pmeth.c
1 /**********************************************************************
2  *                          gost_pmeth.c                              *
3  *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4  *         This file is distributed under the same license as OpenSSL *
5  *                                                                    *
6  *   Implementation of RFC 4357 (GOST R 34.10) Publick key method     *
7  *       for OpenSSL                                                  *
8  *          Requires OpenSSL 0.9.9 for compilation                    *
9  **********************************************************************/
10 #include <openssl/evp.h>
11 #include <openssl/objects.h>
12 #include <openssl/ec.h>
13 #include <openssl/x509v3.h> /*For string_to_hex */
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include "gost_params.h"
18 #include "gost_lcl.h"
19 #include "e_gost_err.h"
20 /*-------init, cleanup, copy - uniform for all algs  ---------------*/
21 /* Allocates new gost_pmeth_data structure and assigns it as data */
22 static int pkey_gost_init(EVP_PKEY_CTX *ctx)
23         {
24         struct gost_pmeth_data *data;
25         data = OPENSSL_malloc(sizeof(struct gost_pmeth_data));
26         if (!data) return 0;
27         memset(data,0,sizeof(struct gost_pmeth_data));
28         EVP_PKEY_CTX_set_data(ctx,data);
29         return 1;
30         }
31
32 /* Copies contents of gost_pmeth_data structure */
33 static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
34         {
35         struct gost_pmeth_data *dst_data,*src_data;
36         if (!pkey_gost_init(dst))
37                 {
38                 return 0;
39                 }
40         src_data = EVP_PKEY_CTX_get_data(src);
41         dst_data = EVP_PKEY_CTX_get_data(dst);
42         *dst_data = *src_data;
43         if (src_data -> eph_seckey)
44                 {
45                 dst_data ->eph_seckey = NULL;
46                 }       
47         return 1;
48         }
49
50 /* Frees up gost_pmeth_data structure */
51 static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx)
52         {
53         struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
54         if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
55         OPENSSL_free(data);
56         }       
57
58 /* --------------------- control functions  ------------------------------*/
59 static int pkey_gost_ctrl (EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
60         {
61         struct gost_pmeth_data *pctx = (struct gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx);
62         switch (type)
63                 {
64                 case EVP_PKEY_CTRL_MD:
65                 {
66                 if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94)
67                         {
68                         GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
69                         return 0;
70                         }
71                 pctx->md = (EVP_MD *)p2;
72                 return 1;
73                 }
74                 break;
75
76                 case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
77                 case EVP_PKEY_CTRL_PKCS7_DECRYPT:
78                 case EVP_PKEY_CTRL_PKCS7_SIGN:
79                         return 1;
80
81                 case EVP_PKEY_CTRL_GOST_PARAMSET:
82                         pctx->sign_param_nid = (int)p1;
83                         return 1;
84                         
85                 }
86         return -2;
87         }
88
89 static int pkey_gost_ctrl94cc_str(EVP_PKEY_CTX *ctx,
90         const char *type, const char *value)
91         {
92         if(!strcmp(type, param_ctrl_string))
93                 {
94                 return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
95                         NID_id_GostR3410_94_CryptoPro_A_ParamSet,
96                         NULL);
97                 }
98         return -2;
99         }
100
101 static int pkey_gost_ctrl01cc_str(EVP_PKEY_CTX *ctx,
102         const char *type, const char *value)
103         {
104         if(!strcmp(type, param_ctrl_string))
105                 {
106                 return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
107                         NID_id_GostR3410_2001_ParamSet_cc,NULL);
108                 }
109         return -2;
110         }
111
112 static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
113         const char *type, const char *value)
114         {
115         int param_nid=0;
116         if(!strcmp(type, param_ctrl_string))
117                 {
118                 if (!value)
119                         {
120                         return 0;
121                         }
122                 if (strlen(value) == 1)
123                         {
124                         switch(toupper(value[0]))
125                                 {
126                                 case 'A':
127                                         param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
128                                         break;
129                                 case 'B':
130                                         param_nid = NID_id_GostR3410_94_CryptoPro_B_ParamSet;
131                                         break;
132                                 case 'C':
133                                         param_nid = NID_id_GostR3410_94_CryptoPro_C_ParamSet;
134                                         break;
135                                 case 'D':
136                                         param_nid = NID_id_GostR3410_94_CryptoPro_D_ParamSet;
137                                         break;
138                                 default:
139                                         return 0;
140                                         break;
141                                 }
142                         }
143                 else if ((strlen(value) == 2) && (toupper(value[0]) == 'X'))
144                         {
145                         switch (toupper(value[1]))
146                                 {
147                                 case 'A':
148                                         param_nid = NID_id_GostR3410_94_CryptoPro_XchA_ParamSet;
149                                         break;
150                                 case 'B':
151                                         param_nid = NID_id_GostR3410_94_CryptoPro_XchB_ParamSet;
152                                         break;
153                                 case 'C':
154                                         param_nid = NID_id_GostR3410_94_CryptoPro_XchC_ParamSet;
155                                         break;
156                                 default:
157                                         return 0;
158                                         break;
159                                 }
160                         }
161                 else
162                         {
163                         R3410_params *p = R3410_paramset;
164                         param_nid = OBJ_txt2nid(value);
165                         if (param_nid == NID_undef)
166                                 {
167                                 return 0;
168                                 }
169                         for (;p->nid != NID_undef;p++)
170                                 {
171                                 if (p->nid == param_nid) break;
172                                 }
173                         if (p->nid == NID_undef)
174                                 {
175                                 GOSTerr(GOST_F_PKEY_GOST_CTRL94_STR,
176                                         GOST_R_INVALID_PARAMSET);
177                                 return 0;
178                                 }
179                         }
180
181                 return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
182                         param_nid, NULL);
183                 }
184         return -2;
185         }
186
187 static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
188         const char *type, const char *value)
189         {
190         int param_nid=0;
191         if(!strcmp(type, param_ctrl_string))
192                 {
193                 if (!value)
194                         {
195                         return 0;
196                         }
197                 if (strlen(value) == 1)
198                         {
199                         switch(toupper(value[0]))
200                                 {
201                                 case 'A':
202                                         param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet;
203                                         break;  
204                                 case 'B':
205                                         param_nid = NID_id_GostR3410_2001_CryptoPro_B_ParamSet;
206                                         break;
207                                 case 'C':
208                                         param_nid = NID_id_GostR3410_2001_CryptoPro_C_ParamSet;
209                                         break;
210                                 case '0':
211                                         param_nid = NID_id_GostR3410_2001_TestParamSet;
212                                         break;
213                                 default:
214                                         return 0;
215                                         break;
216                                 }
217                         }
218                 else if ((strlen(value) == 2) && (toupper(value[0]) == 'X'))
219                         {
220                         switch (toupper(value[1]))
221                                 {
222                                 case 'A':
223                                         param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet;
224                                         break;
225                                 case 'B':
226                                         param_nid = NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet;
227                                         break;
228                                 default:
229                                         return 0;
230                                         break;
231                                 }
232                         }
233                 else
234                         {
235                         R3410_2001_params *p = R3410_2001_paramset;
236                         param_nid = OBJ_txt2nid(value);
237                         if (param_nid == NID_undef)
238                                 {
239                                 return 0;
240                                 }
241                         for (;p->nid != NID_undef;p++)
242                                 {
243                                 if (p->nid == param_nid) break;
244                                 }
245                         if (p->nid == NID_undef)
246                                 {
247                                 GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR,
248                                         GOST_R_INVALID_PARAMSET);
249                                 return 0;
250                                 }
251                         }
252
253                 return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
254                         param_nid, NULL);
255                 }
256         return -2;
257         }
258
259 /* --------------------- key generation  --------------------------------*/
260 /* Generates GOST 94 key and assigns it setting specified type */
261 static int pkey_gost94_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
262         {
263         struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
264         DSA *dsa=NULL;
265         if (data->sign_param_nid == NID_undef)
266                 {
267                 if (type== NID_id_GostR3410_94_cc)
268                         {
269                         data->sign_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
270                         }
271                 else
272                         {
273                         GOSTerr(GOST_F_PKEY_GOST94_KEYGEN,
274                                 GOST_R_NO_PARAMETERS_SET);
275                         return 0;
276                         }       
277                 }
278         dsa = DSA_new();
279         if (!fill_GOST94_params(dsa,data->sign_param_nid))
280                 {
281                 DSA_free(dsa);
282                 return 0;
283                 }
284         gost_sign_keygen(dsa);
285         EVP_PKEY_assign(pkey,type,dsa);
286         return 1;
287         }
288
289 /* Generates Gost_R3410_94_cc key */
290 static int pkey_gost94cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
291         {
292         return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94_cc);
293         }
294
295 /* Generates Gost_R3410_94_cp key */
296 static int pkey_gost94cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
297         {
298         return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94);
299         }
300
301 /* Generates GOST_R3410 2001 key and assigns it using specified type */
302 static int pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
303         {
304         struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
305         EC_KEY *ec=NULL;
306         if (data->sign_param_nid == NID_undef)
307                 {
308                 if (type == NID_id_GostR3410_2001_cc)
309                         {
310                         data->sign_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
311                         }
312                 else {  
313                         GOSTerr(GOST_F_PKEY_GOST01_KEYGEN,
314                                 GOST_R_NO_PARAMETERS_SET);
315                         return 0;
316                         }
317                 }
318         ec = EC_KEY_new();
319         if (!fill_GOST2001_params(ec,data->sign_param_nid))
320                 {
321                 EC_KEY_free(ec);
322                 return 0;
323                 }
324         gost2001_keygen(ec);
325
326         EVP_PKEY_assign(pkey,type,ec);
327         return 1;
328         }
329
330 /* Generates GOST R3410 2001_cc key */
331 static int pkey_gost01cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
332         {
333         return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001_cc);
334         }
335
336 /* Generates GOST R3410 2001_cp key */
337 static int pkey_gost01cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
338         {
339         return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001);
340         }
341
342 /* ----------- sign callbacks --------------------------------------*/
343 static int pkey_gost94_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
344         const unsigned char *tbs, size_t tbs_len)
345         {
346         DSA_SIG *unpacked_sig=NULL;
347         EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
348         if (!siglen) return 0;
349         if (!sig)
350                 {
351                 *siglen= 64; /* better to check size of pkey->pkey.dsa-q */
352                 return 1;
353                 }       
354         unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
355         if (!unpacked_sig)
356                 {
357                 return 0;
358                 }
359         return pack_sign_cc(unpacked_sig,32,sig,siglen);
360         }
361
362 static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
363         const unsigned char *tbs, size_t tbs_len)
364         {
365         DSA_SIG *unpacked_sig=NULL;
366         EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
367         if (!siglen) return 0;
368         if (!sig)
369                 {
370                 *siglen= 64; /* better to check size of pkey->pkey.dsa-q */
371                 return 1;
372                 }       
373         unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
374         if (!unpacked_sig)
375                 {
376                 return 0;
377                 }
378         return pack_sign_cp(unpacked_sig,32,sig,siglen);
379         }
380
381 static int pkey_gost01_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
382         const unsigned char *tbs, size_t tbs_len)
383         {
384         DSA_SIG *unpacked_sig=NULL;
385         EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
386         if (!siglen) return 0;
387         if (!sig)
388                 {
389                 *siglen= 64; /* better to check size of curve order*/
390                 return 1;
391                 }       
392         unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
393         if (!unpacked_sig)
394                 {
395                 return 0;
396                 }
397         return pack_sign_cc(unpacked_sig,32,sig,siglen);
398         }
399
400 static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
401         const unsigned char *tbs, size_t tbs_len)
402         {
403         DSA_SIG *unpacked_sig=NULL;
404         EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
405         if (!siglen) return 0;
406         if (!sig)
407                 {
408                 *siglen= 64; /* better to check size of curve order*/
409                 return 1;
410                 }       
411         unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
412         if (!unpacked_sig)
413                 {
414                 return 0;
415                 }
416         return pack_sign_cp(unpacked_sig,32,sig,siglen);
417         }
418
419 /* ------------------- verify callbacks ---------------------------*/
420 static int pkey_gost94_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
421         size_t siglen, const unsigned char *tbs, size_t tbs_len)
422         {
423         int ok = 0;
424         EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
425         DSA_SIG *s=unpack_cc_signature(sig,siglen);
426         if (!s) return 0;
427         if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
428         DSA_SIG_free(s);
429         return ok;
430         }
431
432 static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
433         size_t siglen, const unsigned char *tbs, size_t tbs_len)
434         {
435         int ok = 0;
436         EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
437         DSA_SIG *s=unpack_cp_signature(sig,siglen);
438         if (!s) return 0;
439         if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
440         DSA_SIG_free(s);
441         return ok;
442         }
443
444 static int pkey_gost01_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
445         size_t siglen, const unsigned char *tbs, size_t tbs_len)
446         {
447         int ok = 0;
448         EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
449         DSA_SIG *s=unpack_cc_signature(sig,siglen);
450 #ifdef DEBUG_SIGN       
451         fprintf(stderr,"R=");
452         BN_print_fp(stderr,s->r);
453         fprintf(stderr,"\nS=");
454         BN_print_fp(stderr,s->s);
455         fprintf(stderr,"\n");
456 #endif  
457         if (!s) return 0;
458         if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
459         DSA_SIG_free(s);
460         return ok;
461         }
462
463 static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
464         size_t siglen, const unsigned char *tbs, size_t tbs_len)
465         {
466         int ok = 0;
467         EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
468         DSA_SIG *s=unpack_cp_signature(sig,siglen);
469         if (!s) return 0;
470 #ifdef DEBUG_SIGN       
471         fprintf(stderr,"R=");
472         BN_print_fp(stderr,s->r);
473         fprintf(stderr,"\nS=");
474         BN_print_fp(stderr,s->s);
475         fprintf(stderr,"\n");
476 #endif  
477         if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
478         DSA_SIG_free(s);
479         return ok;
480         }
481
482 /* ------------- encrypt init -------------------------------------*/
483 /* Generates ephermeral key */
484 static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
485         {
486         struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
487         EVP_PKEY *eph_key = EVP_PKEY_new();
488         EVP_PKEY *old_key =EVP_PKEY_CTX_get0_pkey(ctx);
489
490         if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
491         EVP_PKEY_assign(eph_key,EVP_PKEY_base_id(old_key),NULL);
492         if (!EVP_PKEY_copy_parameters(eph_key,old_key)) return 0;
493         switch (EVP_PKEY_base_id(old_key))
494                 {
495                 case NID_id_GostR3410_2001:
496                 case NID_id_GostR3410_2001_cc:
497                         gost2001_keygen(EVP_PKEY_get0(eph_key));
498                         break;
499                 case NID_id_GostR3410_94:
500                 case NID_id_GostR3410_94_cc:
501                         gost_sign_keygen(EVP_PKEY_get0(eph_key));
502                         break;
503         
504                         
505                 }
506
507         
508         data->eph_seckey=eph_key;
509         return 1;
510         }
511 /* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/
512 static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
513         {
514         struct gost_mac_pmeth_data *data;
515         data = OPENSSL_malloc(sizeof(struct gost_mac_pmeth_data));
516         if (!data) return 0;
517         memset(data,0,sizeof(struct gost_mac_pmeth_data));
518         EVP_PKEY_CTX_set_data(ctx,data);
519         return 1;
520         }       
521 static void pkey_gost_mac_cleanup (EVP_PKEY_CTX *ctx)
522         {
523         struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
524         OPENSSL_free(data);
525         }       
526 static int pkey_gost_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
527         {
528         struct gost_mac_pmeth_data *dst_data,*src_data;
529         if (!pkey_gost_mac_init(dst))
530                 {
531                 return 0;
532                 }
533         src_data = EVP_PKEY_CTX_get_data(src);
534         dst_data = EVP_PKEY_CTX_get_data(dst);
535         *dst_data = *src_data;
536         return 1;
537         }
538         
539 static int pkey_gost_mac_ctrl (EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
540         {
541         struct gost_mac_pmeth_data *data =
542 (struct gost_mac_pmeth_data*)EVP_PKEY_CTX_get_data(ctx);
543
544         switch (type)
545                 {
546                 case EVP_PKEY_CTRL_MD:
547                 {
548                 if (p2 != NULL)
549                         {
550                         GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_DIGEST_TYPE);
551                         return 0;
552                         }
553                 data->md = (EVP_MD *)p2;
554                 return 1;
555                 }
556                 break;
557
558                 case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
559                 case EVP_PKEY_CTRL_PKCS7_DECRYPT:
560                 case EVP_PKEY_CTRL_PKCS7_SIGN:
561                         return 1;
562                 case EVP_PKEY_CTRL_SET_MAC_KEY:
563                         if (p1 != 32) 
564                                 {
565                                 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
566                                         GOST_R_INVALID_MAC_KEY_LENGTH);
567                                 return 0;
568                                 }
569
570                         memcpy(data->key,p2,32);
571                         data->key_set = 1;
572                         return 1;
573                 case EVP_PKEY_CTRL_DIGESTINIT:
574                         { 
575                         EVP_MD_CTX *mctx = p2;
576                         void *key;
577                         if (!data->key_set)
578                                 { 
579                                 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
580                                 if (!pkey) 
581                                         {
582                                         GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_MAC_KEY_NOT_SET);
583                                         return 0;
584                                         }
585                                 key = EVP_PKEY_get0(pkey);
586                                 if (!key) 
587                                         {
588                                         GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_MAC_KEY_NOT_SET);
589                                         return 0;
590                                         }
591                                 } else {
592                                 key = &(data->key);
593                                 }
594                         return mctx->digest->md_ctrl(mctx,EVP_MD_CTRL_SET_KEY,32,key);
595                         }  
596                 }       
597         return -2;
598         }
599 static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
600         const char *type, const char *value)
601         {
602         if (!strcmp(type, key_ctrl_string)) 
603                 {
604                 if (strlen(value)!=32) 
605                         {
606                         GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
607                                 GOST_R_INVALID_MAC_KEY_LENGTH);
608                         return 0;       
609                         }
610                 return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
611                         32,(char *)value);
612                 }
613         if (!strcmp(type, hexkey_ctrl_string)) 
614                 {
615                         long keylen; int ret;
616                         unsigned char *keybuf=string_to_hex(value,&keylen);
617                         if (keylen != 32) 
618                                 {
619                                 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
620                                         GOST_R_INVALID_MAC_KEY_LENGTH);
621                                 return 0;       
622                                 }
623                         ret= pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
624                                 32,keybuf);
625                         OPENSSL_free(keybuf);
626                         return ret;
627         
628                 }
629         return -2;
630         }       
631
632 static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
633         {
634                 struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
635                 unsigned char *keydata;
636                 if (!data->key_set) 
637                 {
638                         GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN,GOST_R_MAC_KEY_NOT_SET);
639                         return 0;
640                 }
641                 keydata = OPENSSL_malloc(32);
642                 memcpy(keydata,data->key,32);
643                 EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata);
644                 return 1;
645         }
646
647 static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
648         {
649         return 1;
650 }
651
652 static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, EVP_MD_CTX *mctx)
653         {
654                 if (!sig) 
655                         {
656                         *siglen = 4;
657                         return 1;
658                         }
659                 return EVP_DigestFinal_ex(mctx,sig,siglen);
660         }
661 /* ----------------------------------------------------------------*/
662 int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
663         {
664         *pmeth = EVP_PKEY_meth_new(id, flags);
665         if (!*pmeth) return 0;
666
667         switch (id)
668                 {
669                 case NID_id_GostR3410_94_cc:
670                         EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94cc_str);
671                         EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cc_keygen);
672                         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cc_sign);
673                         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cc_verify);
674                         EVP_PKEY_meth_set_encrypt(*pmeth,
675                                 pkey_gost_encrypt_init, pkey_GOST94cc_encrypt);
676                         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cc_decrypt);
677                         break;
678                 case NID_id_GostR3410_94:
679                         EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94_str);
680                         EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cp_keygen);
681                         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cp_sign);
682                         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cp_verify);
683                         EVP_PKEY_meth_set_encrypt(*pmeth,
684                                 pkey_gost_encrypt_init, pkey_GOST94cp_encrypt);
685                         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cp_decrypt);
686
687         
688                         break;
689                 case NID_id_GostR3410_2001_cc:
690                         EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01cc_str);
691                         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cc_sign);
692                         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cc_verify);
693
694                         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cc_keygen);
695
696                         EVP_PKEY_meth_set_encrypt(*pmeth,
697                                 pkey_gost_encrypt_init, pkey_GOST01cc_encrypt);
698                         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cc_decrypt);
699                         break;
700                         /* There is intentionally no break here */
701                 case NID_id_GostR3410_2001:
702                         EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01_str);
703                         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
704                         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
705
706                         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cp_keygen);
707
708                         EVP_PKEY_meth_set_encrypt(*pmeth,
709                                 pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
710                         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
711                         break;
712                 case NID_id_Gost28147_89_MAC:
713                         EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_mac_ctrl, pkey_gost_mac_ctrl_str);
714                         EVP_PKEY_meth_set_signctx(*pmeth,pkey_gost_mac_signctx_init, pkey_gost_mac_signctx);
715                         EVP_PKEY_meth_set_keygen(*pmeth,NULL, pkey_gost_mac_keygen);
716                         EVP_PKEY_meth_set_init(*pmeth,pkey_gost_mac_init);
717                         EVP_PKEY_meth_set_cleanup(*pmeth,pkey_gost_mac_cleanup);
718                         EVP_PKEY_meth_set_copy(*pmeth,pkey_gost_mac_copy);
719                         return 1;
720                 default: /*Unsupported method*/
721                         return 0;
722                 }
723         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_init);
724         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_cleanup);
725
726         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_copy);
727         /*FIXME derive etc...*/
728         
729         return 1;
730         }
731