0a15680c4bbdbc673bf11831e0ddef66ba44c911
[openssl.git] / crypto / evp / bio_ok.c
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 /*-
11         From: Arne Ansper <arne@cyber.ee>
12
13         Why BIO_f_reliable?
14
15         I wrote function which took BIO* as argument, read data from it
16         and processed it. Then I wanted to store the input file in
17         encrypted form. OK I pushed BIO_f_cipher to the BIO stack
18         and everything was OK. BUT if user types wrong password
19         BIO_f_cipher outputs only garbage and my function crashes. Yes
20         I can and I should fix my function, but BIO_f_cipher is
21         easy way to add encryption support to many existing applications
22         and it's hard to debug and fix them all.
23
24         So I wanted another BIO which would catch the incorrect passwords and
25         file damages which cause garbage on BIO_f_cipher's output.
26
27         The easy way is to push the BIO_f_md and save the checksum at
28         the end of the file. However there are several problems with this
29         approach:
30
31         1) you must somehow separate checksum from actual data.
32         2) you need lot's of memory when reading the file, because you
33         must read to the end of the file and verify the checksum before
34         letting the application to read the data.
35
36         BIO_f_reliable tries to solve both problems, so that you can
37         read and write arbitrary long streams using only fixed amount
38         of memory.
39
40         BIO_f_reliable splits data stream into blocks. Each block is prefixed
41         with it's length and suffixed with it's digest. So you need only
42         several Kbytes of memory to buffer single block before verifying
43         it's digest.
44
45         BIO_f_reliable goes further and adds several important capabilities:
46
47         1) the digest of the block is computed over the whole stream
48         -- so nobody can rearrange the blocks or remove or replace them.
49
50         2) to detect invalid passwords right at the start BIO_f_reliable
51         adds special prefix to the stream. In order to avoid known plain-text
52         attacks this prefix is generated as follows:
53
54                 *) digest is initialized with random seed instead of
55                 standardized one.
56                 *) same seed is written to output
57                 *) well-known text is then hashed and the output
58                 of the digest is also written to output.
59
60         reader can now read the seed from stream, hash the same string
61         and then compare the digest output.
62
63         Bad things: BIO_f_reliable knows what's going on in EVP_Digest. I
64         initially wrote and tested this code on x86 machine and wrote the
65         digests out in machine-dependent order :( There are people using
66         this code and I cannot change this easily without making existing
67         data files unreadable.
68
69 */
70
71 #include <stdio.h>
72 #include <errno.h>
73 #include <assert.h>
74 #include "internal/cryptlib.h"
75 #include <openssl/buffer.h>
76 #include "internal/bio.h"
77 #include <openssl/evp.h>
78 #include <openssl/rand.h>
79 #include "internal/evp_int.h"
80
81 static int ok_write(BIO *h, const char *buf, int num);
82 static int ok_read(BIO *h, char *buf, int size);
83 static long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2);
84 static int ok_new(BIO *h);
85 static int ok_free(BIO *data);
86 static long ok_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
87
88 static __owur int sig_out(BIO *b);
89 static __owur int sig_in(BIO *b);
90 static __owur int block_out(BIO *b);
91 static __owur int block_in(BIO *b);
92 #define OK_BLOCK_SIZE   (1024*4)
93 #define OK_BLOCK_BLOCK  4
94 #define IOBS            (OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE)
95 #define WELLKNOWN "The quick brown fox jumped over the lazy dog's back."
96
97 typedef struct ok_struct {
98     size_t buf_len;
99     size_t buf_off;
100     size_t buf_len_save;
101     size_t buf_off_save;
102     int cont;                   /* <= 0 when finished */
103     int finished;
104     EVP_MD_CTX *md;
105     int blockout;               /* output block is ready */
106     int sigio;                  /* must process signature */
107     unsigned char buf[IOBS];
108 } BIO_OK_CTX;
109
110 static const BIO_METHOD methods_ok = {
111     BIO_TYPE_CIPHER, "reliable",
112     ok_write,
113     /* TODO: Convert to new style read function */
114     bread_conv,
115     ok_read,
116     NULL,                       /* ok_puts, */
117     NULL,                       /* ok_gets, */
118     ok_ctrl,
119     ok_new,
120     ok_free,
121     ok_callback_ctrl,
122 };
123
124 const BIO_METHOD *BIO_f_reliable(void)
125 {
126     return (&methods_ok);
127 }
128
129 static int ok_new(BIO *bi)
130 {
131     BIO_OK_CTX *ctx;
132
133     ctx = OPENSSL_zalloc(sizeof(*ctx));
134     if (ctx == NULL)
135         return 0;
136
137     ctx->cont = 1;
138     ctx->sigio = 1;
139     ctx->md = EVP_MD_CTX_new();
140     if (ctx->md == NULL) {
141         OPENSSL_free(ctx);
142         return 0;
143     }
144     BIO_set_init(bi, 0);
145     BIO_set_data(bi, ctx);
146
147     return 1;
148 }
149
150 static int ok_free(BIO *a)
151 {
152     BIO_OK_CTX *ctx;
153
154     if (a == NULL)
155         return 0;
156
157     ctx = BIO_get_data(a);
158
159     EVP_MD_CTX_free(ctx->md);
160     OPENSSL_clear_free(ctx, sizeof(BIO_OK_CTX));
161     BIO_set_data(a, NULL);
162     BIO_set_init(a, 0);
163
164     return 1;
165 }
166
167 static int ok_read(BIO *b, char *out, int outl)
168 {
169     int ret = 0, i, n;
170     BIO_OK_CTX *ctx;
171     BIO *next;
172
173     if (out == NULL)
174         return 0;
175
176     ctx = BIO_get_data(b);
177     next = BIO_next(b);
178
179     if ((ctx == NULL) || (next == NULL) || (BIO_get_init(b) == 0))
180         return 0;
181
182     while (outl > 0) {
183
184         /* copy clean bytes to output buffer */
185         if (ctx->blockout) {
186             i = ctx->buf_len - ctx->buf_off;
187             if (i > outl)
188                 i = outl;
189             memcpy(out, &(ctx->buf[ctx->buf_off]), i);
190             ret += i;
191             out += i;
192             outl -= i;
193             ctx->buf_off += i;
194
195             /* all clean bytes are out */
196             if (ctx->buf_len == ctx->buf_off) {
197                 ctx->buf_off = 0;
198
199                 /*
200                  * copy start of the next block into proper place
201                  */
202                 if (ctx->buf_len_save - ctx->buf_off_save > 0) {
203                     ctx->buf_len = ctx->buf_len_save - ctx->buf_off_save;
204                     memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]),
205                             ctx->buf_len);
206                 } else {
207                     ctx->buf_len = 0;
208                 }
209                 ctx->blockout = 0;
210             }
211         }
212
213         /* output buffer full -- cancel */
214         if (outl == 0)
215             break;
216
217         /* no clean bytes in buffer -- fill it */
218         n = IOBS - ctx->buf_len;
219         i = BIO_read(next, &(ctx->buf[ctx->buf_len]), n);
220
221         if (i <= 0)
222             break;              /* nothing new */
223
224         ctx->buf_len += i;
225
226         /* no signature yet -- check if we got one */
227         if (ctx->sigio == 1) {
228             if (!sig_in(b)) {
229                 BIO_clear_retry_flags(b);
230                 return 0;
231             }
232         }
233
234         /* signature ok -- check if we got block */
235         if (ctx->sigio == 0) {
236             if (!block_in(b)) {
237                 BIO_clear_retry_flags(b);
238                 return 0;
239             }
240         }
241
242         /* invalid block -- cancel */
243         if (ctx->cont <= 0)
244             break;
245
246     }
247
248     BIO_clear_retry_flags(b);
249     BIO_copy_next_retry(b);
250     return ret;
251 }
252
253 static int ok_write(BIO *b, const char *in, int inl)
254 {
255     int ret = 0, n, i;
256     BIO_OK_CTX *ctx;
257     BIO *next;
258
259     if (inl <= 0)
260         return inl;
261
262     ctx = BIO_get_data(b);
263     next = BIO_next(b);
264     ret = inl;
265
266     if ((ctx == NULL) || (next == NULL) || (BIO_get_init(b) == 0))
267         return (0);
268
269     if (ctx->sigio && !sig_out(b))
270         return 0;
271
272     do {
273         BIO_clear_retry_flags(b);
274         n = ctx->buf_len - ctx->buf_off;
275         while (ctx->blockout && n > 0) {
276             i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n);
277             if (i <= 0) {
278                 BIO_copy_next_retry(b);
279                 if (!BIO_should_retry(b))
280                     ctx->cont = 0;
281                 return (i);
282             }
283             ctx->buf_off += i;
284             n -= i;
285         }
286
287         /* at this point all pending data has been written */
288         ctx->blockout = 0;
289         if (ctx->buf_len == ctx->buf_off) {
290             ctx->buf_len = OK_BLOCK_BLOCK;
291             ctx->buf_off = 0;
292         }
293
294         if ((in == NULL) || (inl <= 0))
295             return (0);
296
297         n = (inl + ctx->buf_len > OK_BLOCK_SIZE + OK_BLOCK_BLOCK) ?
298             (int)(OK_BLOCK_SIZE + OK_BLOCK_BLOCK - ctx->buf_len) : inl;
299
300         memcpy(&ctx->buf[ctx->buf_len], in, n);
301         ctx->buf_len += n;
302         inl -= n;
303         in += n;
304
305         if (ctx->buf_len >= OK_BLOCK_SIZE + OK_BLOCK_BLOCK) {
306             if (!block_out(b)) {
307                 BIO_clear_retry_flags(b);
308                 return 0;
309             }
310         }
311     } while (inl > 0);
312
313     BIO_clear_retry_flags(b);
314     BIO_copy_next_retry(b);
315     return (ret);
316 }
317
318 static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
319 {
320     BIO_OK_CTX *ctx;
321     EVP_MD *md;
322     const EVP_MD **ppmd;
323     long ret = 1;
324     int i;
325     BIO *next;
326
327     ctx = BIO_get_data(b);
328     next = BIO_next(b);
329
330     switch (cmd) {
331     case BIO_CTRL_RESET:
332         ctx->buf_len = 0;
333         ctx->buf_off = 0;
334         ctx->buf_len_save = 0;
335         ctx->buf_off_save = 0;
336         ctx->cont = 1;
337         ctx->finished = 0;
338         ctx->blockout = 0;
339         ctx->sigio = 1;
340         ret = BIO_ctrl(next, cmd, num, ptr);
341         break;
342     case BIO_CTRL_EOF:         /* More to read */
343         if (ctx->cont <= 0)
344             ret = 1;
345         else
346             ret = BIO_ctrl(next, cmd, num, ptr);
347         break;
348     case BIO_CTRL_PENDING:     /* More to read in buffer */
349     case BIO_CTRL_WPENDING:    /* More to read in buffer */
350         ret = ctx->blockout ? ctx->buf_len - ctx->buf_off : 0;
351         if (ret <= 0)
352             ret = BIO_ctrl(next, cmd, num, ptr);
353         break;
354     case BIO_CTRL_FLUSH:
355         /* do a final write */
356         if (ctx->blockout == 0)
357             if (!block_out(b))
358                 return 0;
359
360         while (ctx->blockout) {
361             i = ok_write(b, NULL, 0);
362             if (i < 0) {
363                 ret = i;
364                 break;
365             }
366         }
367
368         ctx->finished = 1;
369         ctx->buf_off = ctx->buf_len = 0;
370         ctx->cont = (int)ret;
371
372         /* Finally flush the underlying BIO */
373         ret = BIO_ctrl(next, cmd, num, ptr);
374         break;
375     case BIO_C_DO_STATE_MACHINE:
376         BIO_clear_retry_flags(b);
377         ret = BIO_ctrl(next, cmd, num, ptr);
378         BIO_copy_next_retry(b);
379         break;
380     case BIO_CTRL_INFO:
381         ret = (long)ctx->cont;
382         break;
383     case BIO_C_SET_MD:
384         md = ptr;
385         if (!EVP_DigestInit_ex(ctx->md, md, NULL))
386             return 0;
387         BIO_set_init(b, 1);
388         break;
389     case BIO_C_GET_MD:
390         if (BIO_get_init(b)) {
391             ppmd = ptr;
392             *ppmd = EVP_MD_CTX_md(ctx->md);
393         } else
394             ret = 0;
395         break;
396     default:
397         ret = BIO_ctrl(next, cmd, num, ptr);
398         break;
399     }
400     return ret;
401 }
402
403 static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
404 {
405     long ret = 1;
406     BIO *next;
407
408     next = BIO_next(b);
409
410     if (next == NULL)
411         return 0;
412
413     switch (cmd) {
414     default:
415         ret = BIO_callback_ctrl(next, cmd, fp);
416         break;
417     }
418
419     return ret;
420 }
421
422 static void longswap(void *_ptr, size_t len)
423 {
424     const union {
425         long one;
426         char little;
427     } is_endian = {
428         1
429     };
430
431     if (is_endian.little) {
432         size_t i;
433         unsigned char *p = _ptr, c;
434
435         for (i = 0; i < len; i += 4) {
436             c = p[0], p[0] = p[3], p[3] = c;
437             c = p[1], p[1] = p[2], p[2] = c;
438         }
439     }
440 }
441
442 static int sig_out(BIO *b)
443 {
444     BIO_OK_CTX *ctx;
445     EVP_MD_CTX *md;
446     const EVP_MD *digest;
447     int md_size;
448     void *md_data;
449
450     ctx = BIO_get_data(b);
451     md = ctx->md;
452     digest = EVP_MD_CTX_md(md);
453     md_size = EVP_MD_size(digest);
454     md_data = EVP_MD_CTX_md_data(md);
455
456     if (ctx->buf_len + 2 * md_size > OK_BLOCK_SIZE)
457         return 1;
458
459     if (!EVP_DigestInit_ex(md, digest, NULL))
460         goto berr;
461     /*
462      * FIXME: there's absolutely no guarantee this makes any sense at all,
463      * particularly now EVP_MD_CTX has been restructured.
464      */
465     if (RAND_bytes(md_data, md_size) <= 0)
466         goto berr;
467     memcpy(&(ctx->buf[ctx->buf_len]), md_data, md_size);
468     longswap(&(ctx->buf[ctx->buf_len]), md_size);
469     ctx->buf_len += md_size;
470
471     if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN)))
472         goto berr;
473     if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
474         goto berr;
475     ctx->buf_len += md_size;
476     ctx->blockout = 1;
477     ctx->sigio = 0;
478     return 1;
479  berr:
480     BIO_clear_retry_flags(b);
481     return 0;
482 }
483
484 static int sig_in(BIO *b)
485 {
486     BIO_OK_CTX *ctx;
487     EVP_MD_CTX *md;
488     unsigned char tmp[EVP_MAX_MD_SIZE];
489     int ret = 0;
490     const EVP_MD *digest;
491     int md_size;
492     void *md_data;
493
494     ctx = BIO_get_data(b);
495     md = ctx->md;
496     digest = EVP_MD_CTX_md(md);
497     md_size = EVP_MD_size(digest);
498     md_data = EVP_MD_CTX_md_data(md);
499
500     if ((int)(ctx->buf_len - ctx->buf_off) < 2 * md_size)
501         return 1;
502
503     if (!EVP_DigestInit_ex(md, digest, NULL))
504         goto berr;
505     memcpy(md_data, &(ctx->buf[ctx->buf_off]), md_size);
506     longswap(md_data, md_size);
507     ctx->buf_off += md_size;
508
509     if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN)))
510         goto berr;
511     if (!EVP_DigestFinal_ex(md, tmp, NULL))
512         goto berr;
513     ret = memcmp(&(ctx->buf[ctx->buf_off]), tmp, md_size) == 0;
514     ctx->buf_off += md_size;
515     if (ret == 1) {
516         ctx->sigio = 0;
517         if (ctx->buf_len != ctx->buf_off) {
518             memmove(ctx->buf, &(ctx->buf[ctx->buf_off]),
519                     ctx->buf_len - ctx->buf_off);
520         }
521         ctx->buf_len -= ctx->buf_off;
522         ctx->buf_off = 0;
523     } else {
524         ctx->cont = 0;
525     }
526     return 1;
527  berr:
528     BIO_clear_retry_flags(b);
529     return 0;
530 }
531
532 static int block_out(BIO *b)
533 {
534     BIO_OK_CTX *ctx;
535     EVP_MD_CTX *md;
536     unsigned long tl;
537     const EVP_MD *digest;
538     int md_size;
539
540     ctx = BIO_get_data(b);
541     md = ctx->md;
542     digest = EVP_MD_CTX_md(md);
543     md_size = EVP_MD_size(digest);
544
545     tl = ctx->buf_len - OK_BLOCK_BLOCK;
546     ctx->buf[0] = (unsigned char)(tl >> 24);
547     ctx->buf[1] = (unsigned char)(tl >> 16);
548     ctx->buf[2] = (unsigned char)(tl >> 8);
549     ctx->buf[3] = (unsigned char)(tl);
550     if (!EVP_DigestUpdate(md,
551                           (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl))
552         goto berr;
553     if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
554         goto berr;
555     ctx->buf_len += md_size;
556     ctx->blockout = 1;
557     return 1;
558  berr:
559     BIO_clear_retry_flags(b);
560     return 0;
561 }
562
563 static int block_in(BIO *b)
564 {
565     BIO_OK_CTX *ctx;
566     EVP_MD_CTX *md;
567     unsigned long tl = 0;
568     unsigned char tmp[EVP_MAX_MD_SIZE];
569     int md_size;
570
571     ctx = BIO_get_data(b);
572     md = ctx->md;
573     md_size = EVP_MD_size(EVP_MD_CTX_md(md));
574
575     assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */
576     tl = ctx->buf[0];
577     tl <<= 8;
578     tl |= ctx->buf[1];
579     tl <<= 8;
580     tl |= ctx->buf[2];
581     tl <<= 8;
582     tl |= ctx->buf[3];
583
584     if (ctx->buf_len < tl + OK_BLOCK_BLOCK + md_size)
585         return 1;
586
587     if (!EVP_DigestUpdate(md,
588                           (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl))
589         goto berr;
590     if (!EVP_DigestFinal_ex(md, tmp, NULL))
591         goto berr;
592     if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, md_size) == 0) {
593         /* there might be parts from next block lurking around ! */
594         ctx->buf_off_save = tl + OK_BLOCK_BLOCK + md_size;
595         ctx->buf_len_save = ctx->buf_len;
596         ctx->buf_off = OK_BLOCK_BLOCK;
597         ctx->buf_len = tl + OK_BLOCK_BLOCK;
598         ctx->blockout = 1;
599     } else {
600         ctx->cont = 0;
601     }
602     return 1;
603  berr:
604     BIO_clear_retry_flags(b);
605     return 0;
606 }