]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/crypto/evp/bio_ok.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / 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 "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 void sig_out(BIO *b);
137 static void sig_in(BIO *b);
138 static void block_out(BIO *b);
139 static void 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 = (BIO_OK_CTX *)OPENSSL_malloc(sizeof(BIO_OK_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_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)
219         return (0);
220     ctx = (BIO_OK_CTX *)b->ptr;
221
222     if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0))
223         return (0);
224
225     while (outl > 0) {
226
227         /* copy clean bytes to output buffer */
228         if (ctx->blockout) {
229             i = ctx->buf_len - ctx->buf_off;
230             if (i > outl)
231                 i = outl;
232             memcpy(out, &(ctx->buf[ctx->buf_off]), i);
233             ret += i;
234             out += i;
235             outl -= i;
236             ctx->buf_off += i;
237
238             /* all clean bytes are out */
239             if (ctx->buf_len == ctx->buf_off) {
240                 ctx->buf_off = 0;
241
242                 /*
243                  * copy start of the next block into proper place
244                  */
245                 if (ctx->buf_len_save - ctx->buf_off_save > 0) {
246                     ctx->buf_len = ctx->buf_len_save - ctx->buf_off_save;
247                     memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]),
248                             ctx->buf_len);
249                 } else {
250                     ctx->buf_len = 0;
251                 }
252                 ctx->blockout = 0;
253             }
254         }
255
256         /* output buffer full -- cancel */
257         if (outl == 0)
258             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)
265             break;              /* nothing new */
266
267         ctx->buf_len += i;
268
269         /* no signature yet -- check if we got one */
270         if (ctx->sigio == 1)
271             sig_in(b);
272
273         /* signature ok -- check if we got block */
274         if (ctx->sigio == 0)
275             block_in(b);
276
277         /* invalid block -- cancel */
278         if (ctx->cont <= 0)
279             break;
280
281     }
282
283     BIO_clear_retry_flags(b);
284     BIO_copy_next_retry(b);
285     return (ret);
286 }
287
288 static int ok_write(BIO *b, const char *in, int inl)
289 {
290     int ret = 0, n, i;
291     BIO_OK_CTX *ctx;
292
293     if (inl <= 0)
294         return inl;
295
296     ctx = (BIO_OK_CTX *)b->ptr;
297     ret = inl;
298
299     if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0))
300         return (0);
301
302     if (ctx->sigio)
303         sig_out(b);
304
305     do {
306         BIO_clear_retry_flags(b);
307         n = ctx->buf_len - ctx->buf_off;
308         while (ctx->blockout && n > 0) {
309             i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
310             if (i <= 0) {
311                 BIO_copy_next_retry(b);
312                 if (!BIO_should_retry(b))
313                     ctx->cont = 0;
314                 return (i);
315             }
316             ctx->buf_off += i;
317             n -= i;
318         }
319
320         /* at this point all pending data has been written */
321         ctx->blockout = 0;
322         if (ctx->buf_len == ctx->buf_off) {
323             ctx->buf_len = OK_BLOCK_BLOCK;
324             ctx->buf_off = 0;
325         }
326
327         if ((in == NULL) || (inl <= 0))
328             return (0);
329
330         n = (inl + ctx->buf_len > OK_BLOCK_SIZE + OK_BLOCK_BLOCK) ?
331             (int)(OK_BLOCK_SIZE + OK_BLOCK_BLOCK - ctx->buf_len) : inl;
332
333         memcpy((unsigned char *)(&(ctx->buf[ctx->buf_len])),
334                (unsigned char *)in, n);
335         ctx->buf_len += n;
336         inl -= n;
337         in += n;
338
339         if (ctx->buf_len >= OK_BLOCK_SIZE + OK_BLOCK_BLOCK) {
340             block_out(b);
341         }
342     } while (inl > 0);
343
344     BIO_clear_retry_flags(b);
345     BIO_copy_next_retry(b);
346     return (ret);
347 }
348
349 static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
350 {
351     BIO_OK_CTX *ctx;
352     EVP_MD *md;
353     const EVP_MD **ppmd;
354     long ret = 1;
355     int i;
356
357     ctx = b->ptr;
358
359     switch (cmd) {
360     case BIO_CTRL_RESET:
361         ctx->buf_len = 0;
362         ctx->buf_off = 0;
363         ctx->buf_len_save = 0;
364         ctx->buf_off_save = 0;
365         ctx->cont = 1;
366         ctx->finished = 0;
367         ctx->blockout = 0;
368         ctx->sigio = 1;
369         ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
370         break;
371     case BIO_CTRL_EOF:         /* More to read */
372         if (ctx->cont <= 0)
373             ret = 1;
374         else
375             ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
376         break;
377     case BIO_CTRL_PENDING:     /* More to read in buffer */
378     case BIO_CTRL_WPENDING:    /* More to read in buffer */
379         ret = ctx->blockout ? ctx->buf_len - ctx->buf_off : 0;
380         if (ret <= 0)
381             ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
382         break;
383     case BIO_CTRL_FLUSH:
384         /* do a final write */
385         if (ctx->blockout == 0)
386             block_out(b);
387
388         while (ctx->blockout) {
389             i = ok_write(b, NULL, 0);
390             if (i < 0) {
391                 ret = i;
392                 break;
393             }
394         }
395
396         ctx->finished = 1;
397         ctx->buf_off = ctx->buf_len = 0;
398         ctx->cont = (int)ret;
399
400         /* Finally flush the underlying BIO */
401         ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
402         break;
403     case BIO_C_DO_STATE_MACHINE:
404         BIO_clear_retry_flags(b);
405         ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
406         BIO_copy_next_retry(b);
407         break;
408     case BIO_CTRL_INFO:
409         ret = (long)ctx->cont;
410         break;
411     case BIO_C_SET_MD:
412         md = ptr;
413         EVP_DigestInit_ex(&ctx->md, md, NULL);
414         b->init = 1;
415         break;
416     case BIO_C_GET_MD:
417         if (b->init) {
418             ppmd = ptr;
419             *ppmd = ctx->md.digest;
420         } else
421             ret = 0;
422         break;
423     default:
424         ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
425         break;
426     }
427     return (ret);
428 }
429
430 static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
431 {
432     long ret = 1;
433
434     if (b->next_bio == NULL)
435         return (0);
436     switch (cmd) {
437     default:
438         ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
439         break;
440     }
441     return (ret);
442 }
443
444 static void longswap(void *_ptr, size_t len)
445 {
446     const union {
447         long one;
448         char little;
449     } is_endian = {
450         1
451     };
452
453     if (is_endian.little) {
454         size_t i;
455         unsigned char *p = _ptr, c;
456
457         for (i = 0; i < len; i += 4) {
458             c = p[0], p[0] = p[3], p[3] = c;
459             c = p[1], p[1] = p[2], p[2] = c;
460         }
461     }
462 }
463
464 static void sig_out(BIO *b)
465 {
466     BIO_OK_CTX *ctx;
467     EVP_MD_CTX *md;
468
469     ctx = b->ptr;
470     md = &ctx->md;
471
472     if (ctx->buf_len + 2 * md->digest->md_size > OK_BLOCK_SIZE)
473         return;
474
475     EVP_DigestInit_ex(md, md->digest, NULL);
476     /*
477      * FIXME: there's absolutely no guarantee this makes any sense at all,
478      * particularly now EVP_MD_CTX has been restructured.
479      */
480     RAND_pseudo_bytes(md->md_data, md->digest->md_size);
481     memcpy(&(ctx->buf[ctx->buf_len]), md->md_data, md->digest->md_size);
482     longswap(&(ctx->buf[ctx->buf_len]), md->digest->md_size);
483     ctx->buf_len += md->digest->md_size;
484
485     EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN));
486     EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL);
487     ctx->buf_len += md->digest->md_size;
488     ctx->blockout = 1;
489     ctx->sigio = 0;
490 }
491
492 static void sig_in(BIO *b)
493 {
494     BIO_OK_CTX *ctx;
495     EVP_MD_CTX *md;
496     unsigned char tmp[EVP_MAX_MD_SIZE];
497     int ret = 0;
498
499     ctx = b->ptr;
500     md = &ctx->md;
501
502     if ((int)(ctx->buf_len - ctx->buf_off) < 2 * md->digest->md_size)
503         return;
504
505     EVP_DigestInit_ex(md, md->digest, NULL);
506     memcpy(md->md_data, &(ctx->buf[ctx->buf_off]), md->digest->md_size);
507     longswap(md->md_data, md->digest->md_size);
508     ctx->buf_off += md->digest->md_size;
509
510     EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN));
511     EVP_DigestFinal_ex(md, tmp, NULL);
512     ret = memcmp(&(ctx->buf[ctx->buf_off]), tmp, md->digest->md_size) == 0;
513     ctx->buf_off += md->digest->md_size;
514     if (ret == 1) {
515         ctx->sigio = 0;
516         if (ctx->buf_len != ctx->buf_off) {
517             memmove(ctx->buf, &(ctx->buf[ctx->buf_off]),
518                     ctx->buf_len - ctx->buf_off);
519         }
520         ctx->buf_len -= ctx->buf_off;
521         ctx->buf_off = 0;
522     } else {
523         ctx->cont = 0;
524     }
525 }
526
527 static void block_out(BIO *b)
528 {
529     BIO_OK_CTX *ctx;
530     EVP_MD_CTX *md;
531     unsigned long tl;
532
533     ctx = b->ptr;
534     md = &ctx->md;
535
536     tl = ctx->buf_len - OK_BLOCK_BLOCK;
537     ctx->buf[0] = (unsigned char)(tl >> 24);
538     ctx->buf[1] = (unsigned char)(tl >> 16);
539     ctx->buf[2] = (unsigned char)(tl >> 8);
540     ctx->buf[3] = (unsigned char)(tl);
541     EVP_DigestUpdate(md, (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl);
542     EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL);
543     ctx->buf_len += md->digest->md_size;
544     ctx->blockout = 1;
545 }
546
547 static void block_in(BIO *b)
548 {
549     BIO_OK_CTX *ctx;
550     EVP_MD_CTX *md;
551     unsigned long tl = 0;
552     unsigned char tmp[EVP_MAX_MD_SIZE];
553
554     ctx = b->ptr;
555     md = &ctx->md;
556
557     assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */
558     tl = ctx->buf[0];
559     tl <<= 8;
560     tl |= ctx->buf[1];
561     tl <<= 8;
562     tl |= ctx->buf[2];
563     tl <<= 8;
564     tl |= ctx->buf[3];
565
566     if (ctx->buf_len < tl + OK_BLOCK_BLOCK + md->digest->md_size)
567         return;
568
569     EVP_DigestUpdate(md, (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl);
570     EVP_DigestFinal_ex(md, tmp, NULL);
571     if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, md->digest->md_size) ==
572         0) {
573         /* there might be parts from next block lurking around ! */
574         ctx->buf_off_save = tl + OK_BLOCK_BLOCK + md->digest->md_size;
575         ctx->buf_len_save = ctx->buf_len;
576         ctx->buf_off = OK_BLOCK_BLOCK;
577         ctx->buf_len = tl + OK_BLOCK_BLOCK;
578         ctx->blockout = 1;
579     } else {
580         ctx->cont = 0;
581     }
582 }