OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
gost_crypt.c
Go to the documentation of this file.
1 /**********************************************************************
2  * gost_crypt.c *
3  * Copyright (c) 2005-2006 Cryptocom LTD *
4  * This file is distributed under the same license as OpenSSL *
5  * *
6  * OpenSSL interface to GOST 28147-89 cipher functions *
7  * Requires OpenSSL 0.9.9 for compilation *
8  **********************************************************************/
9 #include <string.h>
10 #include "gost89.h"
11 #include <openssl/rand.h>
12 #include "e_gost_err.h"
13 #include "gost_lcl.h"
14 static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
15  const unsigned char *iv, int enc);
16 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
17  const unsigned char *iv, int enc);
18 /* Handles block of data in CFB mode */
19 static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
20  const unsigned char *in, size_t inl);
21 /* Handles block of data in CNT mode */
22 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
23  const unsigned char *in, size_t inl);
24 /* Cleanup function */
25 static int gost_cipher_cleanup(EVP_CIPHER_CTX *);
26 /* set/get cipher parameters */
27 static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params);
28 static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params);
29 /* Control function */
30 static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr);
31 
33  {
35  1,/*block_size*/
36  32,/*key_size*/
37  8,/*iv_len */
40  gost_cipher_init,
41  gost_cipher_do_cfb,
42  gost_cipher_cleanup,
43  sizeof(struct ossl_gost_cipher_ctx),/* ctx_size */
44  gost89_set_asn1_parameters,
45  gost89_get_asn1_parameters,
46  gost_cipher_ctl,
47  NULL,
48  };
49 
51  {
53  1,/*block_size*/
54  32,/*key_size*/
55  8,/*iv_len */
58  gost_cipher_init_cpa,
59  gost_cipher_do_cnt,
60  gost_cipher_cleanup,
61  sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
62  gost89_set_asn1_parameters,
63  gost89_get_asn1_parameters,
64  gost_cipher_ctl,
65  NULL,
66  };
67 
68 /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */
69 /* Init functions which set specific parameters */
70 static int gost_imit_init_cpa(EVP_MD_CTX *ctx);
71 /* process block of data */
72 static int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count);
73 /* Return computed value */
74 static int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md);
75 /* Copies context */
76 static int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from);
77 static int gost_imit_cleanup(EVP_MD_CTX *ctx);
78 /* Control function, knows how to set MAC key.*/
79 static int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr);
80 
82  {
84  NID_undef,
85  4,
86  0,
87  gost_imit_init_cpa,
88  gost_imit_update,
89  gost_imit_final,
90  gost_imit_copy,
91  gost_imit_cleanup,
92  NULL,
93  NULL,
94  {0,0,0,0,0},
95  8,
96  sizeof(struct ossl_gost_imit_ctx),
97  gost_imit_ctrl
98  };
99 
100 /*
101  * Correspondence between gost parameter OIDs and substitution blocks
102  * NID field is filed by register_gost_NID function in engine.c
103  * upon engine initialization
104  */
105 
107  {
108 /* NID */ /* Subst block */ /* Key meshing*/
109 /*{NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},*/
116  {NID_undef,NULL,0}
117  };
118 
119 /* get encryption parameters from crypto network settings
120  FIXME For now we use environment var CRYPT_PARAMS as place to
121  store these settings. Actually, it is better to use engine control command, read from configuration file to set them */
123  {
124  int nid;
125  struct gost_cipher_info *param;
126  if (!obj)
127  {
128  const char * params = get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS);
129  if (!params || !strlen(params))
130  return &gost_cipher_list[1];
131 
132  nid = OBJ_txt2nid(params);
133  if (nid == NID_undef)
134  {
137  return NULL;
138  }
139  }
140  else
141  {
142  nid= OBJ_obj2nid(obj);
143  }
144  for (param=gost_cipher_list;param->sblock!=NULL && param->nid!=nid;
145  param++);
146  if (!param->sblock)
147  {
149  return NULL;
150  }
151  return param;
152  }
153 
154 /* Sets cipher param from paramset NID. */
155 static int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c,int nid)
156  {
157  const struct gost_cipher_info *param;
158  param=get_encryption_params((nid==NID_undef?NULL:OBJ_nid2obj(nid)));
159  if (!param) return 0;
160 
161  c->paramNID = param->nid;
162  c->key_meshing=param->key_meshing;
163  c->count=0;
164  gost_init(&(c->cctx), param->sblock);
165  return 1;
166  }
167 
168 /* Initializes EVP_CIPHER_CTX by paramset NID */
169 static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, const unsigned char *key,
170  const unsigned char *iv, int enc, int paramNID,int mode)
171  {
172  struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
173  if (ctx->app_data == NULL)
174  {
175  if (!gost_cipher_set_param(c,paramNID)) return 0;
176  ctx->app_data = ctx->cipher_data;
177  }
178  if (key) gost_key(&(c->cctx),key);
179  if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
180  memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
181  return 1;
182  }
183 
184 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
185  const unsigned char *iv, int enc)
186  {
187  struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
189  c->key_meshing=1;
190  c->count=0;
191  if(key) gost_key(&(c->cctx),key);
192  if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
193  memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
194  return 1;
195  }
196 
197 /* Initializes EVP_CIPHER_CTX with default values */
198 int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
199  const unsigned char *iv, int enc)
200  {
201  return gost_cipher_init_param(ctx,key,iv,enc,NID_undef,EVP_CIPH_CFB_MODE);
202  }
203 /* Wrapper around gostcrypt function from gost89.c which perform
204  * key meshing when nesseccary
205  */
206 static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf)
207  {
208  struct ossl_gost_cipher_ctx *c = ctx;
209  if (c->count&&c->key_meshing && c->count%1024==0)
210  {
211  cryptopro_key_meshing(&(c->cctx),iv);
212  }
213  gostcrypt(&(c->cctx),iv,buf);
214  c->count+=8;
215  }
216 
217 static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf)
218  {
219  struct ossl_gost_cipher_ctx *c = ctx;
220  word32 g,go;
221  unsigned char buf1[8];
222  if (c->count && c->key_meshing && c->count %1024 ==0)
223  {
224  cryptopro_key_meshing(&(c->cctx),iv);
225  }
226  if (c->count==0)
227  {
228  gostcrypt(&(c->cctx),iv,buf1);
229  }
230  else
231  {
232  memcpy(buf1,iv,8);
233  }
234  g = buf1[0]|(buf1[1]<<8)|(buf1[2]<<16)|(buf1[3]<<24);
235  g += 0x01010101;
236  buf1[0]=(unsigned char)(g&0xff);
237  buf1[1]=(unsigned char)((g>>8)&0xff);
238  buf1[2]=(unsigned char)((g>>16)&0xff);
239  buf1[3]=(unsigned char)((g>>24)&0xff);
240  g = buf1[4]|(buf1[5]<<8)|(buf1[6]<<16)|(buf1[7]<<24);
241  go = g;
242  g += 0x01010104;
243  if (go > g) /* overflow*/
244  g++;
245  buf1[4]=(unsigned char)(g&0xff);
246  buf1[5]=(unsigned char)((g>>8)&0xff);
247  buf1[6]=(unsigned char)((g>>16)&0xff);
248  buf1[7]=(unsigned char)((g>>24)&0xff);
249  memcpy(iv,buf1,8);
250  gostcrypt(&(c->cctx),buf1,buf);
251  c->count +=8;
252  }
253 
254 /* GOST encryption in CFB mode */
255 int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
256  const unsigned char *in, size_t inl)
257  {
258  const unsigned char *in_ptr=in;
259  unsigned char *out_ptr=out;
260  size_t i=0;
261  size_t j=0;
262 /* process partial block if any */
263  if (ctx->num)
264  {
265  for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++)
266  {
267  if (!ctx->encrypt) ctx->buf[j+8]=*in_ptr;
268  *out_ptr=ctx->buf[j]^(*in_ptr);
269  if (ctx->encrypt) ctx->buf[j+8]=*out_ptr;
270  }
271  if (j==8)
272  {
273  memcpy(ctx->iv,ctx->buf+8,8);
274  ctx->num=0;
275  }
276  else
277  {
278  ctx->num=j;
279  return 1;
280  }
281  }
282 
283  for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8)
284  {
285  /*block cipher current iv */
286  gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
287  /*xor next block of input text with it and output it*/
288  /*output this block */
289  if (!ctx->encrypt) memcpy(ctx->iv,in_ptr,8);
290  for (j=0;j<8;j++)
291  {
292  out_ptr[j]=ctx->buf[j]^in_ptr[j];
293  }
294  /* Encrypt */
295  /* Next iv is next block of cipher text*/
296  if (ctx->encrypt) memcpy(ctx->iv,out_ptr,8);
297  }
298 /* Process rest of buffer */
299  if (i<inl)
300  {
301  gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
302  if (!ctx->encrypt) memcpy(ctx->buf+8,in_ptr,inl-i);
303  for (j=0;i<inl;j++,i++)
304  {
305  out_ptr[j]=ctx->buf[j]^in_ptr[j];
306  }
307  ctx->num = j;
308  if (ctx->encrypt) memcpy(ctx->buf+8,out_ptr,j);
309  }
310  else
311  {
312  ctx->num = 0;
313  }
314  return 1;
315  }
316 
317 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
318  const unsigned char *in, size_t inl)
319  {
320  const unsigned char *in_ptr=in;
321  unsigned char *out_ptr=out;
322  size_t i=0;
323  size_t j;
324 /* process partial block if any */
325  if (ctx->num)
326  {
327  for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++)
328  {
329  *out_ptr=ctx->buf[j]^(*in_ptr);
330  }
331  if (j==8)
332  {
333  ctx->num=0;
334  }
335  else
336  {
337  ctx->num=j;
338  return 1;
339  }
340  }
341 
342  for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8)
343  {
344  /*block cipher current iv */
345  /* Encrypt */
346  gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
347  /*xor next block of input text with it and output it*/
348  /*output this block */
349  for (j=0;j<8;j++)
350  {
351  out_ptr[j]=ctx->buf[j]^in_ptr[j];
352  }
353  }
354 /* Process rest of buffer */
355  if (i<inl)
356  {
357  gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
358  for (j=0;i<inl;j++,i++)
359  {
360  out_ptr[j]=ctx->buf[j]^in_ptr[j];
361  }
362  ctx->num = j;
363  }
364  else
365  {
366  ctx->num = 0;
367  }
368  return 1;
369  }
370 
371 /* Cleaning up of EVP_CIPHER_CTX */
372 int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx)
373  {
374  gost_destroy(&((struct ossl_gost_cipher_ctx *)ctx->cipher_data)->cctx);
375  ctx->app_data = NULL;
376  return 1;
377  }
378 
379 /* Control function for gost cipher */
380 int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr)
381  {
382  switch (type)
383  {
384  case EVP_CTRL_RAND_KEY:
385  {
386  if (RAND_bytes((unsigned char *)ptr,ctx->key_len)<=0)
387  {
389  return -1;
390  }
391  break;
392  }
394  if (ptr) {
395  *((int *)ptr)= NID_id_HMACGostR3411_94;
396  return 1;
397  } else {
398  return 0;
399  }
400 
401  default:
403  return -1;
404  }
405  return 1;
406  }
407 
408 /* Set cipher parameters from ASN1 structure */
409 int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
410  {
411  int len=0;
412  unsigned char *buf=NULL;
413  unsigned char *p=NULL;
414  struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
415  GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
416  ASN1_OCTET_STRING *os = NULL;
417  if (!gcp)
418  {
420  return 0;
421  }
422  if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len))
423  {
424  GOST_CIPHER_PARAMS_free(gcp);
426  return 0;
427  }
430 
431  len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
432  p = buf = (unsigned char*)OPENSSL_malloc(len);
433  if (!buf)
434  {
435  GOST_CIPHER_PARAMS_free(gcp);
437  return 0;
438  }
439  i2d_GOST_CIPHER_PARAMS(gcp, &p);
440  GOST_CIPHER_PARAMS_free(gcp);
441 
442  os = ASN1_OCTET_STRING_new();
443 
444  if(!os || !ASN1_OCTET_STRING_set(os, buf, len))
445  {
446  OPENSSL_free(buf);
448  return 0;
449  }
450  OPENSSL_free(buf);
451 
452  ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
453  return 1;
454  }
455 
456 /* Store parameters into ASN1 structure */
457 int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
458  {
459  int ret = -1;
460  int len;
461  GOST_CIPHER_PARAMS *gcp = NULL;
462  unsigned char *p;
463  struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
464  if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE)
465  {
466  return ret;
467  }
468 
469  p = params->value.sequence->data;
470 
471  gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p,
472  params->value.sequence->length);
473 
474  len = gcp->iv->length;
475  if (len != ctx->cipher->iv_len)
476  {
477  GOST_CIPHER_PARAMS_free(gcp);
480  return -1;
481  }
482  if (!gost_cipher_set_param(c,OBJ_obj2nid(gcp->enc_param_set)))
483  {
484  GOST_CIPHER_PARAMS_free(gcp);
485  return -1;
486  }
487  memcpy(ctx->oiv, gcp->iv->data, len);
488 
489  GOST_CIPHER_PARAMS_free(gcp);
490 
491  return 1;
492  }
493 
494 
495 int gost_imit_init_cpa(EVP_MD_CTX *ctx)
496  {
497  struct ossl_gost_imit_ctx *c = ctx->md_data;
498  memset(c->buffer,0,sizeof(c->buffer));
499  memset(c->partial_block,0,sizeof(c->partial_block));
500  c->count = 0;
501  c->bytes_left=0;
502  c->key_meshing=1;
504  return 1;
505  }
506 
507 static void mac_block_mesh(struct ossl_gost_imit_ctx *c,const unsigned char *data)
508  {
509  unsigned char buffer[8];
510  /* We are using local buffer for iv because CryptoPro doesn't
511  * interpret internal state of MAC algorithm as iv during keymeshing
512  * (but does initialize internal state from iv in key transport
513  */
514  if (c->key_meshing&& c->count && c->count %1024 ==0)
515  {
516  cryptopro_key_meshing(&(c->cctx),buffer);
517  }
518  mac_block(&(c->cctx),c->buffer,data);
519  c->count +=8;
520  }
521 
522 int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
523  {
524  struct ossl_gost_imit_ctx *c = ctx->md_data;
525  const unsigned char *p = data;
526  size_t bytes = count,i;
527  if (!(c->key_set)) {
529  return 0;
530  }
531  if (c->bytes_left)
532  {
533  for (i=c->bytes_left;i<8&&bytes>0;bytes--,i++,p++)
534  {
535  c->partial_block[i]=*p;
536  }
537  if (i==8)
538  {
539  mac_block_mesh(c,c->partial_block);
540  }
541  else
542  {
543  c->bytes_left = i;
544  return 1;
545  }
546  }
547  while (bytes>8)
548  {
549  mac_block_mesh(c,p);
550  p+=8;
551  bytes-=8;
552  }
553  if (bytes>0)
554  {
555  memcpy(c->partial_block,p,bytes);
556  }
557  c->bytes_left=bytes;
558  return 1;
559  }
560 
561 int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md)
562  {
563  struct ossl_gost_imit_ctx *c = ctx->md_data;
564  if (!c->key_set) {
566  return 0;
567  }
568  if (c->bytes_left)
569  {
570  int i;
571  for (i=c->bytes_left;i<8;i++)
572  {
573  c->partial_block[i]=0;
574  }
575  mac_block_mesh(c,c->partial_block);
576  }
577  get_mac(c->buffer,32,md);
578  return 1;
579  }
580 
581 int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr)
582  {
583  switch (type)
584  {
585  case EVP_MD_CTRL_KEY_LEN:
586  *((unsigned int*)(ptr)) = 32;
587  return 1;
588  case EVP_MD_CTRL_SET_KEY:
589  {
590  if (arg!=32) {
592  return 0;
593  }
594 
595  gost_key(&(((struct ossl_gost_imit_ctx*)(ctx->md_data))->cctx),ptr) ;
596  ((struct ossl_gost_imit_ctx*)(ctx->md_data))->key_set = 1;
597  return 1;
598 
599  }
600  default:
601  return 0;
602  }
603  }
604 
605 int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
606  {
607  memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_imit_ctx));
608  return 1;
609  }
610 
611 /* Clean up imit ctx */
612 int gost_imit_cleanup(EVP_MD_CTX *ctx)
613  {
614  memset(ctx->md_data,0,sizeof(struct ossl_gost_imit_ctx));
615  return 1;
616  }
617