OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
gost_pmeth.c
Go to the documentation of this file.
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  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
26  data = OPENSSL_malloc(sizeof(struct gost_pmeth_data));
27  if (!data) return 0;
28  memset(data,0,sizeof(struct gost_pmeth_data));
29  if (pkey && EVP_PKEY_get0(pkey))
30  {
31  switch (EVP_PKEY_base_id(pkey)) {
34  break;
37  break;
38  default:
39  return 0;
40  }
41  }
42  EVP_PKEY_CTX_set_data(ctx,data);
43  return 1;
44  }
45 
46 /* Copies contents of gost_pmeth_data structure */
47 static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
48  {
49  struct gost_pmeth_data *dst_data,*src_data;
50  if (!pkey_gost_init(dst))
51  {
52  return 0;
53  }
54  src_data = EVP_PKEY_CTX_get_data(src);
55  dst_data = EVP_PKEY_CTX_get_data(dst);
56  *dst_data = *src_data;
57  if (src_data -> shared_ukm) {
58  dst_data->shared_ukm=NULL;
59  }
60  return 1;
61  }
62 
63 /* Frees up gost_pmeth_data structure */
64 static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx)
65  {
66  struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
67  if (data->shared_ukm) OPENSSL_free(data->shared_ukm);
68  OPENSSL_free(data);
69  }
70 
71 /* --------------------- control functions ------------------------------*/
72 static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
73  {
74  struct gost_pmeth_data *pctx = (struct gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx);
75  switch (type)
76  {
77  case EVP_PKEY_CTRL_MD:
78  {
79  if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94)
80  {
82  return 0;
83  }
84  pctx->md = (EVP_MD *)p2;
85  return 1;
86  }
87  break;
88 
93 #ifndef OPENSSL_NO_CMS
97 #endif
98  return 1;
99 
101  pctx->sign_param_nid = (int)p1;
102  return 1;
104  pctx->shared_ukm=OPENSSL_malloc((int)p1);
105  memcpy(pctx->shared_ukm,p2,(int) p1);
106  return 1;
108  if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */
109  return 1;
110  if (p1 == 2) /* TLS: peer key used? */
111  return pctx->peer_key_used;
112  if (p1 == 3) /* TLS: peer key used! */
113  return (pctx->peer_key_used = 1);
114  return -2;
115  }
116  return -2;
117  }
118 
119 
120 static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
121  const char *type, const char *value)
122  {
123  int param_nid=0;
124  if(!strcmp(type, param_ctrl_string))
125  {
126  if (!value)
127  {
128  return 0;
129  }
130  if (strlen(value) == 1)
131  {
132  switch(toupper((unsigned char)value[0]))
133  {
134  case 'A':
136  break;
137  case 'B':
139  break;
140  case 'C':
142  break;
143  case 'D':
145  break;
146  default:
147  return 0;
148  break;
149  }
150  }
151  else if ((strlen(value) == 2) && (toupper((unsigned char)value[0]) == 'X'))
152  {
153  switch (toupper((unsigned char)value[1]))
154  {
155  case 'A':
157  break;
158  case 'B':
160  break;
161  case 'C':
163  break;
164  default:
165  return 0;
166  break;
167  }
168  }
169  else
170  {
172  param_nid = OBJ_txt2nid(value);
173  if (param_nid == NID_undef)
174  {
175  return 0;
176  }
177  for (;p->nid != NID_undef;p++)
178  {
179  if (p->nid == param_nid) break;
180  }
181  if (p->nid == NID_undef)
182  {
185  return 0;
186  }
187  }
188 
189  return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
190  param_nid, NULL);
191  }
192  return -2;
193  }
194 
195 static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
196  const char *type, const char *value)
197  {
198  int param_nid=0;
199  if(!strcmp(type, param_ctrl_string))
200  {
201  if (!value)
202  {
203  return 0;
204  }
205  if (strlen(value) == 1)
206  {
207  switch(toupper((unsigned char)value[0]))
208  {
209  case 'A':
211  break;
212  case 'B':
214  break;
215  case 'C':
217  break;
218  case '0':
220  break;
221  default:
222  return 0;
223  break;
224  }
225  }
226  else if ((strlen(value) == 2) && (toupper((unsigned char)value[0]) == 'X'))
227  {
228  switch (toupper((unsigned char)value[1]))
229  {
230  case 'A':
232  break;
233  case 'B':
235  break;
236  default:
237  return 0;
238  break;
239  }
240  }
241  else
242  {
244  param_nid = OBJ_txt2nid(value);
245  if (param_nid == NID_undef)
246  {
247  return 0;
248  }
249  for (;p->nid != NID_undef;p++)
250  {
251  if (p->nid == param_nid) break;
252  }
253  if (p->nid == NID_undef)
254  {
257  return 0;
258  }
259  }
260 
261  return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
262  param_nid, NULL);
263  }
264  return -2;
265  }
266 
267 /* --------------------- key generation --------------------------------*/
268 
269 static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx) {
270  return 1;
271 }
272 static int pkey_gost94_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
273  {
274  struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
275  DSA *dsa=NULL;
276  if (data->sign_param_nid == NID_undef)
277  {
280  return 0;
281  }
282  dsa = DSA_new();
283  if (!fill_GOST94_params(dsa,data->sign_param_nid))
284  {
285  DSA_free(dsa);
286  return 0;
287  }
289  return 1;
290  }
291 static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
292  {
293  struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
294  EC_KEY *ec=NULL;
295 
296  if (data->sign_param_nid == NID_undef)
297  {
300  return 0;
301  }
302  if (!ec)
303  ec = EC_KEY_new();
304  if (!fill_GOST2001_params(ec,data->sign_param_nid))
305  {
306  EC_KEY_free(ec);
307  return 0;
308  }
310  return 1;
311  }
312 
313 /* Generates Gost_R3410_94_cp key */
314 static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
315  {
316  DSA *dsa;
317  if (!pkey_gost94_paramgen(ctx,pkey)) return 0;
318  dsa = EVP_PKEY_get0(pkey);
319  gost_sign_keygen(dsa);
320  return 1;
321  }
322 
323 /* Generates GOST_R3410 2001 key and assigns it using specified type */
324 static int pkey_gost01cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
325  {
326  EC_KEY *ec;
327  if (!pkey_gost01_paramgen(ctx,pkey)) return 0;
328  ec = EVP_PKEY_get0(pkey);
329  gost2001_keygen(ec);
330  return 1;
331  }
332 
333 
334 
335 /* ----------- sign callbacks --------------------------------------*/
336 
337 static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
338  const unsigned char *tbs, size_t tbs_len)
339  {
340  DSA_SIG *unpacked_sig=NULL;
341  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
342  if (!siglen) return 0;
343  if (!sig)
344  {
345  *siglen= 64; /* better to check size of pkey->pkey.dsa-q */
346  return 1;
347  }
348  unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
349  if (!unpacked_sig)
350  {
351  return 0;
352  }
353  return pack_sign_cp(unpacked_sig,32,sig,siglen);
354  }
355 
356 static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
357  const unsigned char *tbs, size_t tbs_len)
358  {
359  DSA_SIG *unpacked_sig=NULL;
360  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
361  if (!siglen) return 0;
362  if (!sig)
363  {
364  *siglen= 64; /* better to check size of curve order*/
365  return 1;
366  }
367  unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
368  if (!unpacked_sig)
369  {
370  return 0;
371  }
372  return pack_sign_cp(unpacked_sig,32,sig,siglen);
373  }
374 
375 /* ------------------- verify callbacks ---------------------------*/
376 
377 static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
378  size_t siglen, const unsigned char *tbs, size_t tbs_len)
379  {
380  int ok = 0;
381  EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
382  DSA_SIG *s=unpack_cp_signature(sig,siglen);
383  if (!s) return 0;
384  if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
385  DSA_SIG_free(s);
386  return ok;
387  }
388 
389 
390 static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
391  size_t siglen, const unsigned char *tbs, size_t tbs_len)
392  {
393  int ok = 0;
394  EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
395  DSA_SIG *s=unpack_cp_signature(sig,siglen);
396  if (!s) return 0;
397 #ifdef DEBUG_SIGN
398  fprintf(stderr,"R=");
399  BN_print_fp(stderr,s->r);
400  fprintf(stderr,"\nS=");
401  BN_print_fp(stderr,s->s);
402  fprintf(stderr,"\n");
403 #endif
404  if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
405  DSA_SIG_free(s);
406  return ok;
407  }
408 
409 /* ------------- encrypt init -------------------------------------*/
410 /* Generates ephermeral key */
411 static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
412  {
413  return 1;
414  }
415 /* --------------- Derive init ------------------------------------*/
416 static int pkey_gost_derive_init(EVP_PKEY_CTX *ctx)
417 {
418  return 1;
419 }
420 /* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/
421 static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
422  {
423  struct gost_mac_pmeth_data *data;
424  data = OPENSSL_malloc(sizeof(struct gost_mac_pmeth_data));
425  if (!data) return 0;
426  memset(data,0,sizeof(struct gost_mac_pmeth_data));
427  EVP_PKEY_CTX_set_data(ctx,data);
428  return 1;
429  }
430 static void pkey_gost_mac_cleanup (EVP_PKEY_CTX *ctx)
431  {
432  struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
433  OPENSSL_free(data);
434  }
435 static int pkey_gost_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
436  {
437  struct gost_mac_pmeth_data *dst_data,*src_data;
438  if (!pkey_gost_mac_init(dst))
439  {
440  return 0;
441  }
442  src_data = EVP_PKEY_CTX_get_data(src);
443  dst_data = EVP_PKEY_CTX_get_data(dst);
444  *dst_data = *src_data;
445  return 1;
446  }
447 
448 static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
449  {
450  struct gost_mac_pmeth_data *data =
452 
453  switch (type)
454  {
455  case EVP_PKEY_CTRL_MD:
456  {
457  if (EVP_MD_type((const EVP_MD *)p2) != NID_id_Gost28147_89_MAC)
458  {
460  return 0;
461  }
462  data->md = (EVP_MD *)p2;
463  return 1;
464  }
465  break;
466 
470  return 1;
472  if (p1 != 32)
473  {
476  return 0;
477  }
478 
479  memcpy(data->key,p2,32);
480  data->key_set = 1;
481  return 1;
483  {
484  EVP_MD_CTX *mctx = p2;
485  void *key;
486  if (!data->key_set)
487  {
488  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
489  if (!pkey)
490  {
492  return 0;
493  }
494  key = EVP_PKEY_get0(pkey);
495  if (!key)
496  {
498  return 0;
499  }
500  } else {
501  key = &(data->key);
502  }
503  return mctx->digest->md_ctrl(mctx,EVP_MD_CTRL_SET_KEY,32,key);
504  }
505  }
506  return -2;
507  }
508 static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
509  const char *type, const char *value)
510  {
511  if (!strcmp(type, key_ctrl_string))
512  {
513  if (strlen(value)!=32)
514  {
517  return 0;
518  }
519  return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
520  32,(char *)value);
521  }
522  if (!strcmp(type, hexkey_ctrl_string))
523  {
524  long keylen; int ret;
525  unsigned char *keybuf=string_to_hex(value,&keylen);
526  if (keylen != 32)
527  {
530  OPENSSL_free(keybuf);
531  return 0;
532  }
533  ret= pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
534  32,keybuf);
535  OPENSSL_free(keybuf);
536  return ret;
537 
538  }
539  return -2;
540  }
541 
542 static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
543  {
544  struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
545  unsigned char *keydata;
546  if (!data->key_set)
547  {
549  return 0;
550  }
551  keydata = OPENSSL_malloc(32);
552  memcpy(keydata,data->key,32);
554  return 1;
555  }
556 
557 static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
558  {
559  return 1;
560 }
561 
562 static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, EVP_MD_CTX *mctx)
563  {
564  unsigned int tmpsiglen=*siglen; /* for platforms where sizeof(int)!=sizeof(size_t)*/
565  int ret;
566  if (!sig)
567  {
568  *siglen = 4;
569  return 1;
570  }
571  ret=EVP_DigestFinal_ex(mctx,sig,&tmpsiglen);
572  *siglen = tmpsiglen;
573  return ret;
574  }
575 /* ----------------------------------------------------------------*/
576 int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
577  {
578  *pmeth = EVP_PKEY_meth_new(id, flags);
579  if (!*pmeth) return 0;
580 
581  switch (id)
582  {
583  case NID_id_GostR3410_94:
584  EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94_str);
585  EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cp_keygen);
586  EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cp_sign);
587  EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cp_verify);
589  pkey_gost_encrypt_init, pkey_GOST94cp_encrypt);
592  pkey_gost_derive_init, pkey_gost94_derive);
593  EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost94_paramgen);
594  break;
596  EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01_str);
597  EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
598  EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
599 
600  EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cp_keygen);
601 
603  pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
606  pkey_gost_derive_init, pkey_gost2001_derive);
607  EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost01_paramgen);
608  break;
610  EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_mac_ctrl, pkey_gost_mac_ctrl_str);
611  EVP_PKEY_meth_set_signctx(*pmeth,pkey_gost_mac_signctx_init, pkey_gost_mac_signctx);
612  EVP_PKEY_meth_set_keygen(*pmeth,NULL, pkey_gost_mac_keygen);
613  EVP_PKEY_meth_set_init(*pmeth,pkey_gost_mac_init);
614  EVP_PKEY_meth_set_cleanup(*pmeth,pkey_gost_mac_cleanup);
615  EVP_PKEY_meth_set_copy(*pmeth,pkey_gost_mac_copy);
616  return 1;
617  default: /*Unsupported method*/
618  return 0;
619  }
620  EVP_PKEY_meth_set_init(*pmeth, pkey_gost_init);
621  EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_cleanup);
622 
623  EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_copy);
624  /*FIXME derive etc...*/
625 
626  return 1;
627  }
628