]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/evp/bio_ok.c
Identify and move common internal libcrypto header files
[thirdparty/openssl.git] / crypto / evp / bio_ok.c
1 /* crypto/evp/bio_ok.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
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 (tjh@cryptsoft.com).
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 (eay@cryptsoft.com)"
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 (tjh@cryptsoft.com)"
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 <arne@cyber.ee>
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 "internal/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 __owur int sig_out(BIO *b);
137 static __owur int sig_in(BIO *b);
138 static __owur int block_out(BIO *b);
139 static __owur 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 size_t buf_len;
147 size_t buf_off;
148 size_t buf_len_save;
149 size_t buf_off_save;
150 int cont; /* <= 0 when finished */
151 int finished;
152 EVP_MD_CTX md;
153 int blockout; /* output block is ready */
154 int sigio; /* must process signature */
155 unsigned char buf[IOBS];
156 } BIO_OK_CTX;
157
158 static BIO_METHOD methods_ok = {
159 BIO_TYPE_CIPHER, "reliable",
160 ok_write,
161 ok_read,
162 NULL, /* ok_puts, */
163 NULL, /* ok_gets, */
164 ok_ctrl,
165 ok_new,
166 ok_free,
167 ok_callback_ctrl,
168 };
169
170 BIO_METHOD *BIO_f_reliable(void)
171 {
172 return (&methods_ok);
173 }
174
175 static int ok_new(BIO *bi)
176 {
177 BIO_OK_CTX *ctx;
178
179 ctx = OPENSSL_malloc(sizeof(*ctx));
180 if (ctx == NULL)
181 return (0);
182
183 ctx->buf_len = 0;
184 ctx->buf_off = 0;
185 ctx->buf_len_save = 0;
186 ctx->buf_off_save = 0;
187 ctx->cont = 1;
188 ctx->finished = 0;
189 ctx->blockout = 0;
190 ctx->sigio = 1;
191
192 EVP_MD_CTX_init(&ctx->md);
193
194 bi->init = 0;
195 bi->ptr = (char *)ctx;
196 bi->flags = 0;
197 return (1);
198 }
199
200 static int ok_free(BIO *a)
201 {
202 if (a == NULL)
203 return (0);
204 EVP_MD_CTX_cleanup(&((BIO_OK_CTX *)a->ptr)->md);
205 OPENSSL_clear_free(a->ptr, sizeof(BIO_OK_CTX));
206 a->ptr = NULL;
207 a->init = 0;
208 a->flags = 0;
209 return (1);
210 }
211
212 static int ok_read(BIO *b, char *out, int outl)
213 {
214 int ret = 0, i, n;
215 BIO_OK_CTX *ctx;
216
217 if (out == NULL)
218 return (0);
219 ctx = (BIO_OK_CTX *)b->ptr;
220
221 if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0))
222 return (0);
223
224 while (outl > 0) {
225
226 /* copy clean bytes to output buffer */
227 if (ctx->blockout) {
228 i = ctx->buf_len - ctx->buf_off;
229 if (i > outl)
230 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 ctx->buf_off = 0;
240
241 /*
242 * copy start of the next block into proper place
243 */
244 if (ctx->buf_len_save - ctx->buf_off_save > 0) {
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 } else {
249 ctx->buf_len = 0;
250 }
251 ctx->blockout = 0;
252 }
253 }
254
255 /* output buffer full -- cancel */
256 if (outl == 0)
257 break;
258
259 /* no clean bytes in buffer -- fill it */
260 n = IOBS - ctx->buf_len;
261 i = BIO_read(b->next_bio, &(ctx->buf[ctx->buf_len]), n);
262
263 if (i <= 0)
264 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 if (!sig_in(b)) {
271 BIO_clear_retry_flags(b);
272 return 0;
273 }
274 }
275
276 /* signature ok -- check if we got block */
277 if (ctx->sigio == 0) {
278 if (!block_in(b)) {
279 BIO_clear_retry_flags(b);
280 return 0;
281 }
282 }
283
284 /* invalid block -- cancel */
285 if (ctx->cont <= 0)
286 break;
287
288 }
289
290 BIO_clear_retry_flags(b);
291 BIO_copy_next_retry(b);
292 return (ret);
293 }
294
295 static int ok_write(BIO *b, const char *in, int inl)
296 {
297 int ret = 0, n, i;
298 BIO_OK_CTX *ctx;
299
300 if (inl <= 0)
301 return inl;
302
303 ctx = (BIO_OK_CTX *)b->ptr;
304 ret = inl;
305
306 if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0))
307 return (0);
308
309 if (ctx->sigio && !sig_out(b))
310 return 0;
311
312 do {
313 BIO_clear_retry_flags(b);
314 n = ctx->buf_len - ctx->buf_off;
315 while (ctx->blockout && n > 0) {
316 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
317 if (i <= 0) {
318 BIO_copy_next_retry(b);
319 if (!BIO_should_retry(b))
320 ctx->cont = 0;
321 return (i);
322 }
323 ctx->buf_off += i;
324 n -= i;
325 }
326
327 /* at this point all pending data has been written */
328 ctx->blockout = 0;
329 if (ctx->buf_len == ctx->buf_off) {
330 ctx->buf_len = OK_BLOCK_BLOCK;
331 ctx->buf_off = 0;
332 }
333
334 if ((in == NULL) || (inl <= 0))
335 return (0);
336
337 n = (inl + ctx->buf_len > OK_BLOCK_SIZE + OK_BLOCK_BLOCK) ?
338 (int)(OK_BLOCK_SIZE + OK_BLOCK_BLOCK - ctx->buf_len) : inl;
339
340 memcpy(&ctx->buf[ctx->buf_len], in, n);
341 ctx->buf_len += n;
342 inl -= n;
343 in += n;
344
345 if (ctx->buf_len >= OK_BLOCK_SIZE + OK_BLOCK_BLOCK) {
346 if (!block_out(b)) {
347 BIO_clear_retry_flags(b);
348 return 0;
349 }
350 }
351 } while (inl > 0);
352
353 BIO_clear_retry_flags(b);
354 BIO_copy_next_retry(b);
355 return (ret);
356 }
357
358 static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
359 {
360 BIO_OK_CTX *ctx;
361 EVP_MD *md;
362 const EVP_MD **ppmd;
363 long ret = 1;
364 int i;
365
366 ctx = b->ptr;
367
368 switch (cmd) {
369 case BIO_CTRL_RESET:
370 ctx->buf_len = 0;
371 ctx->buf_off = 0;
372 ctx->buf_len_save = 0;
373 ctx->buf_off_save = 0;
374 ctx->cont = 1;
375 ctx->finished = 0;
376 ctx->blockout = 0;
377 ctx->sigio = 1;
378 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
379 break;
380 case BIO_CTRL_EOF: /* More to read */
381 if (ctx->cont <= 0)
382 ret = 1;
383 else
384 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
385 break;
386 case BIO_CTRL_PENDING: /* More to read in buffer */
387 case BIO_CTRL_WPENDING: /* More to read in buffer */
388 ret = ctx->blockout ? ctx->buf_len - ctx->buf_off : 0;
389 if (ret <= 0)
390 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
391 break;
392 case BIO_CTRL_FLUSH:
393 /* do a final write */
394 if (ctx->blockout == 0)
395 if (!block_out(b))
396 return 0;
397
398 while (ctx->blockout) {
399 i = ok_write(b, NULL, 0);
400 if (i < 0) {
401 ret = i;
402 break;
403 }
404 }
405
406 ctx->finished = 1;
407 ctx->buf_off = ctx->buf_len = 0;
408 ctx->cont = (int)ret;
409
410 /* Finally flush the underlying BIO */
411 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
412 break;
413 case BIO_C_DO_STATE_MACHINE:
414 BIO_clear_retry_flags(b);
415 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
416 BIO_copy_next_retry(b);
417 break;
418 case BIO_CTRL_INFO:
419 ret = (long)ctx->cont;
420 break;
421 case BIO_C_SET_MD:
422 md = ptr;
423 if (!EVP_DigestInit_ex(&ctx->md, md, NULL))
424 return 0;
425 b->init = 1;
426 break;
427 case BIO_C_GET_MD:
428 if (b->init) {
429 ppmd = ptr;
430 *ppmd = ctx->md.digest;
431 } else
432 ret = 0;
433 break;
434 default:
435 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
436 break;
437 }
438 return (ret);
439 }
440
441 static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
442 {
443 long ret = 1;
444
445 if (b->next_bio == NULL)
446 return (0);
447 switch (cmd) {
448 default:
449 ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
450 break;
451 }
452 return (ret);
453 }
454
455 static void longswap(void *_ptr, size_t len)
456 {
457 const union {
458 long one;
459 char little;
460 } is_endian = {
461 1
462 };
463
464 if (is_endian.little) {
465 size_t i;
466 unsigned char *p = _ptr, c;
467
468 for (i = 0; i < len; i += 4) {
469 c = p[0], p[0] = p[3], p[3] = c;
470 c = p[1], p[1] = p[2], p[2] = c;
471 }
472 }
473 }
474
475 static int sig_out(BIO *b)
476 {
477 BIO_OK_CTX *ctx;
478 EVP_MD_CTX *md;
479
480 ctx = b->ptr;
481 md = &ctx->md;
482
483 if (ctx->buf_len + 2 * md->digest->md_size > OK_BLOCK_SIZE)
484 return 1;
485
486 if (!EVP_DigestInit_ex(md, md->digest, NULL))
487 goto berr;
488 /*
489 * FIXME: there's absolutely no guarantee this makes any sense at all,
490 * particularly now EVP_MD_CTX has been restructured.
491 */
492 if (RAND_bytes(md->md_data, md->digest->md_size) <= 0)
493 goto berr;
494 memcpy(&(ctx->buf[ctx->buf_len]), md->md_data, md->digest->md_size);
495 longswap(&(ctx->buf[ctx->buf_len]), md->digest->md_size);
496 ctx->buf_len += md->digest->md_size;
497
498 if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN)))
499 goto berr;
500 if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
501 goto berr;
502 ctx->buf_len += md->digest->md_size;
503 ctx->blockout = 1;
504 ctx->sigio = 0;
505 return 1;
506 berr:
507 BIO_clear_retry_flags(b);
508 return 0;
509 }
510
511 static int sig_in(BIO *b)
512 {
513 BIO_OK_CTX *ctx;
514 EVP_MD_CTX *md;
515 unsigned char tmp[EVP_MAX_MD_SIZE];
516 int ret = 0;
517
518 ctx = b->ptr;
519 md = &ctx->md;
520
521 if ((int)(ctx->buf_len - ctx->buf_off) < 2 * md->digest->md_size)
522 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 ctx->sigio = 0;
538 if (ctx->buf_len != ctx->buf_off) {
539 memmove(ctx->buf, &(ctx->buf[ctx->buf_off]),
540 ctx->buf_len - ctx->buf_off);
541 }
542 ctx->buf_len -= ctx->buf_off;
543 ctx->buf_off = 0;
544 } else {
545 ctx->cont = 0;
546 }
547 return 1;
548 berr:
549 BIO_clear_retry_flags(b);
550 return 0;
551 }
552
553 static int block_out(BIO *b)
554 {
555 BIO_OK_CTX *ctx;
556 EVP_MD_CTX *md;
557 unsigned long tl;
558
559 ctx = b->ptr;
560 md = &ctx->md;
561
562 tl = ctx->buf_len - OK_BLOCK_BLOCK;
563 ctx->buf[0] = (unsigned char)(tl >> 24);
564 ctx->buf[1] = (unsigned char)(tl >> 16);
565 ctx->buf[2] = (unsigned char)(tl >> 8);
566 ctx->buf[3] = (unsigned char)(tl);
567 if (!EVP_DigestUpdate(md,
568 (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl))
569 goto berr;
570 if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
571 goto berr;
572 ctx->buf_len += md->digest->md_size;
573 ctx->blockout = 1;
574 return 1;
575 berr:
576 BIO_clear_retry_flags(b);
577 return 0;
578 }
579
580 static int block_in(BIO *b)
581 {
582 BIO_OK_CTX *ctx;
583 EVP_MD_CTX *md;
584 unsigned long tl = 0;
585 unsigned char tmp[EVP_MAX_MD_SIZE];
586
587 ctx = b->ptr;
588 md = &ctx->md;
589
590 assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */
591 tl = ctx->buf[0];
592 tl <<= 8;
593 tl |= ctx->buf[1];
594 tl <<= 8;
595 tl |= ctx->buf[2];
596 tl <<= 8;
597 tl |= ctx->buf[3];
598
599 if (ctx->buf_len < tl + OK_BLOCK_BLOCK + md->digest->md_size)
600 return 1;
601
602 if (!EVP_DigestUpdate(md,
603 (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl))
604 goto berr;
605 if (!EVP_DigestFinal_ex(md, tmp, NULL))
606 goto berr;
607 if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, md->digest->md_size) ==
608 0) {
609 /* there might be parts from next block lurking around ! */
610 ctx->buf_off_save = tl + OK_BLOCK_BLOCK + md->digest->md_size;
611 ctx->buf_len_save = ctx->buf_len;
612 ctx->buf_off = OK_BLOCK_BLOCK;
613 ctx->buf_len = tl + OK_BLOCK_BLOCK;
614 ctx->blockout = 1;
615 } else {
616 ctx->cont = 0;
617 }
618 return 1;
619 berr:
620 BIO_clear_retry_flags(b);
621 return 0;
622 }