OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
bio_ok.c
Go to the documentation of this file.
1 /* crypto/evp/bio_ok.c */
2 /* Copyright (C) 1995-1998 Eric Young ([email protected])
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young ([email protected]).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to. The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson ([email protected]).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  * notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  * notice, this list of conditions and the following disclaimer in the
30  * documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  * must display the following acknowledgement:
33  * "This product includes cryptographic software written by
34  * Eric Young ([email protected])"
35  * The word 'cryptographic' can be left out if the rouines from the library
36  * being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  * the apps directory (application code) you must include an acknowledgement:
39  * "This product includes software written by Tim Hudson ([email protected])"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed. i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 /*
60  From: Arne Ansper <[email protected]>
61 
62  Why BIO_f_reliable?
63 
64  I wrote function which took BIO* as argument, read data from it
65  and processed it. Then I wanted to store the input file in
66  encrypted form. OK I pushed BIO_f_cipher to the BIO stack
67  and everything was OK. BUT if user types wrong password
68  BIO_f_cipher outputs only garbage and my function crashes. Yes
69  I can and I should fix my function, but BIO_f_cipher is
70  easy way to add encryption support to many existing applications
71  and it's hard to debug and fix them all.
72 
73  So I wanted another BIO which would catch the incorrect passwords and
74  file damages which cause garbage on BIO_f_cipher's output.
75 
76  The easy way is to push the BIO_f_md and save the checksum at
77  the end of the file. However there are several problems with this
78  approach:
79 
80  1) you must somehow separate checksum from actual data.
81  2) you need lot's of memory when reading the file, because you
82  must read to the end of the file and verify the checksum before
83  letting the application to read the data.
84 
85  BIO_f_reliable tries to solve both problems, so that you can
86  read and write arbitrary long streams using only fixed amount
87  of memory.
88 
89  BIO_f_reliable splits data stream into blocks. Each block is prefixed
90  with it's length and suffixed with it's digest. So you need only
91  several Kbytes of memory to buffer single block before verifying
92  it's digest.
93 
94  BIO_f_reliable goes further and adds several important capabilities:
95 
96  1) the digest of the block is computed over the whole stream
97  -- so nobody can rearrange the blocks or remove or replace them.
98 
99  2) to detect invalid passwords right at the start BIO_f_reliable
100  adds special prefix to the stream. In order to avoid known plain-text
101  attacks this prefix is generated as follows:
102 
103  *) digest is initialized with random seed instead of
104  standardized one.
105  *) same seed is written to output
106  *) well-known text is then hashed and the output
107  of the digest is also written to output.
108 
109  reader can now read the seed from stream, hash the same string
110  and then compare the digest output.
111 
112  Bad things: BIO_f_reliable knows what's going on in EVP_Digest. I
113  initially wrote and tested this code on x86 machine and wrote the
114  digests out in machine-dependent order :( There are people using
115  this code and I cannot change this easily without making existing
116  data files unreadable.
117 
118 */
119 
120 #include <stdio.h>
121 #include <errno.h>
122 #include <assert.h>
123 #include "cryptlib.h"
124 #include <openssl/buffer.h>
125 #include <openssl/bio.h>
126 #include <openssl/evp.h>
127 #include <openssl/rand.h>
128 
129 static int ok_write(BIO *h, const char *buf, int num);
130 static int ok_read(BIO *h, char *buf, int size);
131 static long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2);
132 static int ok_new(BIO *h);
133 static int ok_free(BIO *data);
134 static long ok_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
135 
136 static int sig_out(BIO* b);
137 static int sig_in(BIO* b);
138 static int block_out(BIO* b);
139 static int block_in(BIO* b);
140 #define OK_BLOCK_SIZE (1024*4)
141 #define OK_BLOCK_BLOCK 4
142 #define IOBS (OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE)
143 #define WELLKNOWN "The quick brown fox jumped over the lazy dog's back."
144 
145 typedef struct ok_struct
146  {
147  size_t buf_len;
148  size_t buf_off;
149  size_t buf_len_save;
150  size_t buf_off_save;
151  int cont; /* <= 0 when finished */
152  int finished;
154  int blockout; /* output block is ready */
155  int sigio; /* must process signature */
156  unsigned char buf[IOBS];
157  } BIO_OK_CTX;
158 
159 static BIO_METHOD methods_ok=
160  {
161  BIO_TYPE_CIPHER,"reliable",
162  ok_write,
163  ok_read,
164  NULL, /* ok_puts, */
165  NULL, /* ok_gets, */
166  ok_ctrl,
167  ok_new,
168  ok_free,
169  ok_callback_ctrl,
170  };
171 
173  {
174  return(&methods_ok);
175  }
176 
177 static int ok_new(BIO *bi)
178  {
179  BIO_OK_CTX *ctx;
180 
181  ctx=(BIO_OK_CTX *)OPENSSL_malloc(sizeof(BIO_OK_CTX));
182  if (ctx == NULL) return(0);
183 
184  ctx->buf_len=0;
185  ctx->buf_off=0;
186  ctx->buf_len_save=0;
187  ctx->buf_off_save=0;
188  ctx->cont=1;
189  ctx->finished=0;
190  ctx->blockout= 0;
191  ctx->sigio=1;
192 
193  EVP_MD_CTX_init(&ctx->md);
194 
195  bi->init=0;
196  bi->ptr=(char *)ctx;
197  bi->flags=0;
198  return(1);
199  }
200 
201 static int ok_free(BIO *a)
202  {
203  if (a == NULL) return(0);
204  EVP_MD_CTX_cleanup(&((BIO_OK_CTX *)a->ptr)->md);
205  OPENSSL_cleanse(a->ptr,sizeof(BIO_OK_CTX));
206  OPENSSL_free(a->ptr);
207  a->ptr=NULL;
208  a->init=0;
209  a->flags=0;
210  return(1);
211  }
212 
213 static int ok_read(BIO *b, char *out, int outl)
214  {
215  int ret=0,i,n;
216  BIO_OK_CTX *ctx;
217 
218  if (out == NULL) return(0);
219  ctx=(BIO_OK_CTX *)b->ptr;
220 
221  if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return(0);
222 
223  while(outl > 0)
224  {
225 
226  /* copy clean bytes to output buffer */
227  if (ctx->blockout)
228  {
229  i=ctx->buf_len-ctx->buf_off;
230  if (i > outl) i=outl;
231  memcpy(out,&(ctx->buf[ctx->buf_off]),i);
232  ret+=i;
233  out+=i;
234  outl-=i;
235  ctx->buf_off+=i;
236 
237  /* all clean bytes are out */
238  if (ctx->buf_len == ctx->buf_off)
239  {
240  ctx->buf_off=0;
241 
242  /* copy start of the next block into proper place */
243  if(ctx->buf_len_save- ctx->buf_off_save > 0)
244  {
245  ctx->buf_len= ctx->buf_len_save- ctx->buf_off_save;
246  memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]),
247  ctx->buf_len);
248  }
249  else
250  {
251  ctx->buf_len=0;
252  }
253  ctx->blockout= 0;
254  }
255  }
256 
257  /* output buffer full -- cancel */
258  if (outl == 0) break;
259 
260  /* no clean bytes in buffer -- fill it */
261  n=IOBS- ctx->buf_len;
262  i=BIO_read(b->next_bio,&(ctx->buf[ctx->buf_len]),n);
263 
264  if (i <= 0) break; /* nothing new */
265 
266  ctx->buf_len+= i;
267 
268  /* no signature yet -- check if we got one */
269  if (ctx->sigio == 1)
270  {
271  if (!sig_in(b))
272  {
274  return 0;
275  }
276  }
277 
278  /* signature ok -- check if we got block */
279  if (ctx->sigio == 0)
280  {
281  if (!block_in(b))
282  {
284  return 0;
285  }
286  }
287 
288  /* invalid block -- cancel */
289  if (ctx->cont <= 0) break;
290 
291  }
292 
295  return(ret);
296  }
297 
298 static int ok_write(BIO *b, const char *in, int inl)
299  {
300  int ret=0,n,i;
301  BIO_OK_CTX *ctx;
302 
303  if (inl <= 0) return inl;
304 
305  ctx=(BIO_OK_CTX *)b->ptr;
306  ret=inl;
307 
308  if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return(0);
309 
310  if(ctx->sigio && !sig_out(b))
311  return 0;
312 
313  do{
315  n=ctx->buf_len-ctx->buf_off;
316  while (ctx->blockout && n > 0)
317  {
318  i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
319  if (i <= 0)
320  {
322  if(!BIO_should_retry(b))
323  ctx->cont= 0;
324  return(i);
325  }
326  ctx->buf_off+=i;
327  n-=i;
328  }
329 
330  /* at this point all pending data has been written */
331  ctx->blockout= 0;
332  if (ctx->buf_len == ctx->buf_off)
333  {
334  ctx->buf_len=OK_BLOCK_BLOCK;
335  ctx->buf_off=0;
336  }
337 
338  if ((in == NULL) || (inl <= 0)) return(0);
339 
340  n= (inl+ ctx->buf_len > OK_BLOCK_SIZE+ OK_BLOCK_BLOCK) ?
341  (int)(OK_BLOCK_SIZE+OK_BLOCK_BLOCK-ctx->buf_len) : inl;
342 
343  memcpy((unsigned char *)(&(ctx->buf[ctx->buf_len])),(unsigned char *)in,n);
344  ctx->buf_len+= n;
345  inl-=n;
346  in+=n;
347 
349  {
350  if (!block_out(b))
351  {
353  return 0;
354  }
355  }
356  }while(inl > 0);
357 
360  return(ret);
361  }
362 
363 static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
364  {
365  BIO_OK_CTX *ctx;
366  EVP_MD *md;
367  const EVP_MD **ppmd;
368  long ret=1;
369  int i;
370 
371  ctx=b->ptr;
372 
373  switch (cmd)
374  {
375  case BIO_CTRL_RESET:
376  ctx->buf_len=0;
377  ctx->buf_off=0;
378  ctx->buf_len_save=0;
379  ctx->buf_off_save=0;
380  ctx->cont=1;
381  ctx->finished=0;
382  ctx->blockout= 0;
383  ctx->sigio=1;
384  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
385  break;
386  case BIO_CTRL_EOF: /* More to read */
387  if (ctx->cont <= 0)
388  ret=1;
389  else
390  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
391  break;
392  case BIO_CTRL_PENDING: /* More to read in buffer */
393  case BIO_CTRL_WPENDING: /* More to read in buffer */
394  ret=ctx->blockout ? ctx->buf_len-ctx->buf_off : 0;
395  if (ret <= 0)
396  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
397  break;
398  case BIO_CTRL_FLUSH:
399  /* do a final write */
400  if(ctx->blockout == 0)
401  if (!block_out(b))
402  return 0;
403 
404  while (ctx->blockout)
405  {
406  i=ok_write(b,NULL,0);
407  if (i < 0)
408  {
409  ret=i;
410  break;
411  }
412  }
413 
414  ctx->finished=1;
415  ctx->buf_off=ctx->buf_len=0;
416  ctx->cont=(int)ret;
417 
418  /* Finally flush the underlying BIO */
419  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
420  break;
423  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
425  break;
426  case BIO_CTRL_INFO:
427  ret=(long)ctx->cont;
428  break;
429  case BIO_C_SET_MD:
430  md=ptr;
431  if (!EVP_DigestInit_ex(&ctx->md, md, NULL))
432  return 0;
433  b->init=1;
434  break;
435  case BIO_C_GET_MD:
436  if (b->init)
437  {
438  ppmd=ptr;
439  *ppmd=ctx->md.digest;
440  }
441  else
442  ret=0;
443  break;
444  default:
445  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
446  break;
447  }
448  return(ret);
449  }
450 
451 static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
452  {
453  long ret=1;
454 
455  if (b->next_bio == NULL) return(0);
456  switch (cmd)
457  {
458  default:
459  ret=BIO_callback_ctrl(b->next_bio,cmd,fp);
460  break;
461  }
462  return(ret);
463  }
464 
465 static void longswap(void *_ptr, size_t len)
466 { const union { long one; char little; } is_endian = {1};
467 
468  if (is_endian.little) {
469  size_t i;
470  unsigned char *p=_ptr,c;
471 
472  for(i= 0;i < len;i+= 4) {
473  c=p[0],p[0]=p[3],p[3]=c;
474  c=p[1],p[1]=p[2],p[2]=c;
475  }
476  }
477 }
478 
479 static int sig_out(BIO* b)
480  {
481  BIO_OK_CTX *ctx;
482  EVP_MD_CTX *md;
483 
484  ctx=b->ptr;
485  md=&ctx->md;
486 
487  if(ctx->buf_len+ 2* md->digest->md_size > OK_BLOCK_SIZE) return 1;
488 
489  if (!EVP_DigestInit_ex(md, md->digest, NULL))
490  goto berr;
491  /* FIXME: there's absolutely no guarantee this makes any sense at all,
492  * particularly now EVP_MD_CTX has been restructured.
493  */
495  memcpy(&(ctx->buf[ctx->buf_len]), md->md_data, md->digest->md_size);
496  longswap(&(ctx->buf[ctx->buf_len]), md->digest->md_size);
497  ctx->buf_len+= md->digest->md_size;
498 
499  if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN)))
500  goto berr;
501  if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
502  goto berr;
503  ctx->buf_len+= md->digest->md_size;
504  ctx->blockout= 1;
505  ctx->sigio= 0;
506  return 1;
507  berr:
509  return 0;
510  }
511 
512 static int sig_in(BIO* b)
513  {
514  BIO_OK_CTX *ctx;
515  EVP_MD_CTX *md;
516  unsigned char tmp[EVP_MAX_MD_SIZE];
517  int ret= 0;
518 
519  ctx=b->ptr;
520  md=&ctx->md;
521 
522  if((int)(ctx->buf_len-ctx->buf_off) < 2*md->digest->md_size) return 1;
523 
524  if (!EVP_DigestInit_ex(md, md->digest, NULL))
525  goto berr;
526  memcpy(md->md_data, &(ctx->buf[ctx->buf_off]), md->digest->md_size);
527  longswap(md->md_data, md->digest->md_size);
528  ctx->buf_off+= md->digest->md_size;
529 
530  if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN)))
531  goto berr;
532  if (!EVP_DigestFinal_ex(md, tmp, NULL))
533  goto berr;
534  ret= memcmp(&(ctx->buf[ctx->buf_off]), tmp, md->digest->md_size) == 0;
535  ctx->buf_off+= md->digest->md_size;
536  if(ret == 1)
537  {
538  ctx->sigio= 0;
539  if(ctx->buf_len != ctx->buf_off)
540  {
541  memmove(ctx->buf, &(ctx->buf[ctx->buf_off]), ctx->buf_len- ctx->buf_off);
542  }
543  ctx->buf_len-= ctx->buf_off;
544  ctx->buf_off= 0;
545  }
546  else
547  {
548  ctx->cont= 0;
549  }
550  return 1;
551  berr:
553  return 0;
554  }
555 
556 static int block_out(BIO* b)
557  {
558  BIO_OK_CTX *ctx;
559  EVP_MD_CTX *md;
560  unsigned long tl;
561 
562  ctx=b->ptr;
563  md=&ctx->md;
564 
565  tl= ctx->buf_len- OK_BLOCK_BLOCK;
566  ctx->buf[0]=(unsigned char)(tl>>24);
567  ctx->buf[1]=(unsigned char)(tl>>16);
568  ctx->buf[2]=(unsigned char)(tl>>8);
569  ctx->buf[3]=(unsigned char)(tl);
570  if (!EVP_DigestUpdate(md,
571  (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl))
572  goto berr;
573  if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
574  goto berr;
575  ctx->buf_len+= md->digest->md_size;
576  ctx->blockout= 1;
577  return 1;
578  berr:
580  return 0;
581  }
582 
583 static int block_in(BIO* b)
584  {
585  BIO_OK_CTX *ctx;
586  EVP_MD_CTX *md;
587  unsigned long tl= 0;
588  unsigned char tmp[EVP_MAX_MD_SIZE];
589 
590  ctx=b->ptr;
591  md=&ctx->md;
592 
593  assert(sizeof(tl)>=OK_BLOCK_BLOCK); /* always true */
594  tl =ctx->buf[0]; tl<<=8;
595  tl|=ctx->buf[1]; tl<<=8;
596  tl|=ctx->buf[2]; tl<<=8;
597  tl|=ctx->buf[3];
598 
599  if (ctx->buf_len < tl+ OK_BLOCK_BLOCK+ md->digest->md_size) return 1;
600 
601  if (!EVP_DigestUpdate(md,
602  (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl))
603  goto berr;
604  if (!EVP_DigestFinal_ex(md, tmp, NULL))
605  goto berr;
606  if(memcmp(&(ctx->buf[tl+ OK_BLOCK_BLOCK]), tmp, md->digest->md_size) == 0)
607  {
608  /* there might be parts from next block lurking around ! */
609  ctx->buf_off_save= tl+ OK_BLOCK_BLOCK+ md->digest->md_size;
610  ctx->buf_len_save= ctx->buf_len;
611  ctx->buf_off= OK_BLOCK_BLOCK;
612  ctx->buf_len= tl+ OK_BLOCK_BLOCK;
613  ctx->blockout= 1;
614  }
615  else
616  {
617  ctx->cont= 0;
618  }
619  return 1;
620  berr:
622  return 0;
623  }
624