Convert all {NAME}err() in crypto/ to their corresponding ERR_raise() call
[openssl.git] / crypto / evp / bio_ok.c
1 /*
2  * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (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
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 its length and suffixed with its digest. So you need only
42         several Kbytes of memory to buffer single block before verifying
43         its 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/endian.h"
80 #include "crypto/evp.h"
81
82 static int ok_write(BIO *h, const char *buf, int num);
83 static int ok_read(BIO *h, char *buf, int size);
84 static long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2);
85 static int ok_new(BIO *h);
86 static int ok_free(BIO *data);
87 static long ok_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
88
89 static __owur int sig_out(BIO *b);
90 static __owur int sig_in(BIO *b);
91 static __owur int block_out(BIO *b);
92 static __owur int block_in(BIO *b);
93 #define OK_BLOCK_SIZE   (1024*4)
94 #define OK_BLOCK_BLOCK  4
95 #define IOBS            (OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE)
96 #define WELLKNOWN "The quick brown fox jumped over the lazy dog's back."
97
98 typedef struct ok_struct {
99     size_t buf_len;
100     size_t buf_off;
101     size_t buf_len_save;
102     size_t buf_off_save;
103     int cont;                   /* <= 0 when finished */
104     int finished;
105     EVP_MD_CTX *md;
106     int blockout;               /* output block is ready */
107     int sigio;                  /* must process signature */
108     unsigned char buf[IOBS];
109 } BIO_OK_CTX;
110
111 static const BIO_METHOD methods_ok = {
112     BIO_TYPE_CIPHER,
113     "reliable",
114     /* TODO: Convert to new style write function */
115     bwrite_conv,
116     ok_write,
117     /* TODO: Convert to new style read function */
118     bread_conv,
119     ok_read,
120     NULL,                       /* ok_puts, */
121     NULL,                       /* ok_gets, */
122     ok_ctrl,
123     ok_new,
124     ok_free,
125     ok_callback_ctrl,
126 };
127
128 const BIO_METHOD *BIO_f_reliable(void)
129 {
130     return &methods_ok;
131 }
132
133 static int ok_new(BIO *bi)
134 {
135     BIO_OK_CTX *ctx;
136
137     if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
138         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
139         return 0;
140     }
141
142     ctx->cont = 1;
143     ctx->sigio = 1;
144     ctx->md = EVP_MD_CTX_new();
145     if (ctx->md == NULL) {
146         OPENSSL_free(ctx);
147         return 0;
148     }
149     BIO_set_init(bi, 0);
150     BIO_set_data(bi, ctx);
151
152     return 1;
153 }
154
155 static int ok_free(BIO *a)
156 {
157     BIO_OK_CTX *ctx;
158
159     if (a == NULL)
160         return 0;
161
162     ctx = BIO_get_data(a);
163
164     EVP_MD_CTX_free(ctx->md);
165     OPENSSL_clear_free(ctx, sizeof(BIO_OK_CTX));
166     BIO_set_data(a, NULL);
167     BIO_set_init(a, 0);
168
169     return 1;
170 }
171
172 static int ok_read(BIO *b, char *out, int outl)
173 {
174     int ret = 0, i, n;
175     BIO_OK_CTX *ctx;
176     BIO *next;
177
178     if (out == NULL)
179         return 0;
180
181     ctx = BIO_get_data(b);
182     next = BIO_next(b);
183
184     if ((ctx == NULL) || (next == NULL) || (BIO_get_init(b) == 0))
185         return 0;
186
187     while (outl > 0) {
188
189         /* copy clean bytes to output buffer */
190         if (ctx->blockout) {
191             i = ctx->buf_len - ctx->buf_off;
192             if (i > outl)
193                 i = outl;
194             memcpy(out, &(ctx->buf[ctx->buf_off]), i);
195             ret += i;
196             out += i;
197             outl -= i;
198             ctx->buf_off += i;
199
200             /* all clean bytes are out */
201             if (ctx->buf_len == ctx->buf_off) {
202                 ctx->buf_off = 0;
203
204                 /*
205                  * copy start of the next block into proper place
206                  */
207                 if (ctx->buf_len_save - ctx->buf_off_save > 0) {
208                     ctx->buf_len = ctx->buf_len_save - ctx->buf_off_save;
209                     memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]),
210                             ctx->buf_len);
211                 } else {
212                     ctx->buf_len = 0;
213                 }
214                 ctx->blockout = 0;
215             }
216         }
217
218         /* output buffer full -- cancel */
219         if (outl == 0)
220             break;
221
222         /* no clean bytes in buffer -- fill it */
223         n = IOBS - ctx->buf_len;
224         i = BIO_read(next, &(ctx->buf[ctx->buf_len]), n);
225
226         if (i <= 0)
227             break;              /* nothing new */
228
229         ctx->buf_len += i;
230
231         /* no signature yet -- check if we got one */
232         if (ctx->sigio == 1) {
233             if (!sig_in(b)) {
234                 BIO_clear_retry_flags(b);
235                 return 0;
236             }
237         }
238
239         /* signature ok -- check if we got block */
240         if (ctx->sigio == 0) {
241             if (!block_in(b)) {
242                 BIO_clear_retry_flags(b);
243                 return 0;
244             }
245         }
246
247         /* invalid block -- cancel */
248         if (ctx->cont <= 0)
249             break;
250
251     }
252
253     BIO_clear_retry_flags(b);
254     BIO_copy_next_retry(b);
255     return ret;
256 }
257
258 static int ok_write(BIO *b, const char *in, int inl)
259 {
260     int ret = 0, n, i;
261     BIO_OK_CTX *ctx;
262     BIO *next;
263
264     if (inl <= 0)
265         return inl;
266
267     ctx = BIO_get_data(b);
268     next = BIO_next(b);
269     ret = inl;
270
271     if ((ctx == NULL) || (next == NULL) || (BIO_get_init(b) == 0))
272         return 0;
273
274     if (ctx->sigio && !sig_out(b))
275         return 0;
276
277     do {
278         BIO_clear_retry_flags(b);
279         n = ctx->buf_len - ctx->buf_off;
280         while (ctx->blockout && n > 0) {
281             i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n);
282             if (i <= 0) {
283                 BIO_copy_next_retry(b);
284                 if (!BIO_should_retry(b))
285                     ctx->cont = 0;
286                 return i;
287             }
288             ctx->buf_off += i;
289             n -= i;
290         }
291
292         /* at this point all pending data has been written */
293         ctx->blockout = 0;
294         if (ctx->buf_len == ctx->buf_off) {
295             ctx->buf_len = OK_BLOCK_BLOCK;
296             ctx->buf_off = 0;
297         }
298
299         if ((in == NULL) || (inl <= 0))
300             return 0;
301
302         n = (inl + ctx->buf_len > OK_BLOCK_SIZE + OK_BLOCK_BLOCK) ?
303             (int)(OK_BLOCK_SIZE + OK_BLOCK_BLOCK - ctx->buf_len) : inl;
304
305         memcpy(&ctx->buf[ctx->buf_len], in, n);
306         ctx->buf_len += n;
307         inl -= n;
308         in += n;
309
310         if (ctx->buf_len >= OK_BLOCK_SIZE + OK_BLOCK_BLOCK) {
311             if (!block_out(b)) {
312                 BIO_clear_retry_flags(b);
313                 return 0;
314             }
315         }
316     } while (inl > 0);
317
318     BIO_clear_retry_flags(b);
319     BIO_copy_next_retry(b);
320     return ret;
321 }
322
323 static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
324 {
325     BIO_OK_CTX *ctx;
326     EVP_MD *md;
327     const EVP_MD **ppmd;
328     long ret = 1;
329     int i;
330     BIO *next;
331
332     ctx = BIO_get_data(b);
333     next = BIO_next(b);
334
335     switch (cmd) {
336     case BIO_CTRL_RESET:
337         ctx->buf_len = 0;
338         ctx->buf_off = 0;
339         ctx->buf_len_save = 0;
340         ctx->buf_off_save = 0;
341         ctx->cont = 1;
342         ctx->finished = 0;
343         ctx->blockout = 0;
344         ctx->sigio = 1;
345         ret = BIO_ctrl(next, cmd, num, ptr);
346         break;
347     case BIO_CTRL_EOF:         /* More to read */
348         if (ctx->cont <= 0)
349             ret = 1;
350         else
351             ret = BIO_ctrl(next, cmd, num, ptr);
352         break;
353     case BIO_CTRL_PENDING:     /* More to read in buffer */
354     case BIO_CTRL_WPENDING:    /* More to read in buffer */
355         ret = ctx->blockout ? ctx->buf_len - ctx->buf_off : 0;
356         if (ret <= 0)
357             ret = BIO_ctrl(next, cmd, num, ptr);
358         break;
359     case BIO_CTRL_FLUSH:
360         /* do a final write */
361         if (ctx->blockout == 0)
362             if (!block_out(b))
363                 return 0;
364
365         while (ctx->blockout) {
366             i = ok_write(b, NULL, 0);
367             if (i < 0) {
368                 ret = i;
369                 break;
370             }
371         }
372
373         ctx->finished = 1;
374         ctx->buf_off = ctx->buf_len = 0;
375         ctx->cont = (int)ret;
376
377         /* Finally flush the underlying BIO */
378         ret = BIO_ctrl(next, cmd, num, ptr);
379         break;
380     case BIO_C_DO_STATE_MACHINE:
381         BIO_clear_retry_flags(b);
382         ret = BIO_ctrl(next, cmd, num, ptr);
383         BIO_copy_next_retry(b);
384         break;
385     case BIO_CTRL_INFO:
386         ret = (long)ctx->cont;
387         break;
388     case BIO_C_SET_MD:
389         md = ptr;
390         if (!EVP_DigestInit_ex(ctx->md, md, NULL))
391             return 0;
392         BIO_set_init(b, 1);
393         break;
394     case BIO_C_GET_MD:
395         if (BIO_get_init(b)) {
396             ppmd = ptr;
397             *ppmd = EVP_MD_CTX_md(ctx->md);
398         } else
399             ret = 0;
400         break;
401     default:
402         ret = BIO_ctrl(next, cmd, num, ptr);
403         break;
404     }
405     return ret;
406 }
407
408 static long ok_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
409 {
410     BIO *next;
411
412     next = BIO_next(b);
413
414     if (next == NULL)
415         return 0;
416
417     return BIO_callback_ctrl(next, cmd, fp);
418 }
419
420 static void longswap(void *_ptr, size_t len)
421 {
422     DECLARE_IS_ENDIAN;
423
424     if (IS_LITTLE_ENDIAN) {
425         size_t i;
426         unsigned char *p = _ptr, c;
427
428         for (i = 0; i < len; i += 4) {
429             c = p[0], p[0] = p[3], p[3] = c;
430             c = p[1], p[1] = p[2], p[2] = c;
431         }
432     }
433 }
434
435 static int sig_out(BIO *b)
436 {
437     BIO_OK_CTX *ctx;
438     EVP_MD_CTX *md;
439     const EVP_MD *digest;
440     int md_size;
441     void *md_data;
442
443     ctx = BIO_get_data(b);
444     md = ctx->md;
445     digest = EVP_MD_CTX_md(md);
446     md_size = EVP_MD_size(digest);
447     md_data = EVP_MD_CTX_md_data(md);
448
449     if (ctx->buf_len + 2 * md_size > OK_BLOCK_SIZE)
450         return 1;
451
452     if (!EVP_DigestInit_ex(md, digest, NULL))
453         goto berr;
454     /*
455      * FIXME: there's absolutely no guarantee this makes any sense at all,
456      * particularly now EVP_MD_CTX has been restructured.
457      */
458     if (RAND_bytes(md_data, md_size) <= 0)
459         goto berr;
460     memcpy(&(ctx->buf[ctx->buf_len]), md_data, md_size);
461     longswap(&(ctx->buf[ctx->buf_len]), md_size);
462     ctx->buf_len += md_size;
463
464     if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN)))
465         goto berr;
466     if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
467         goto berr;
468     ctx->buf_len += md_size;
469     ctx->blockout = 1;
470     ctx->sigio = 0;
471     return 1;
472  berr:
473     BIO_clear_retry_flags(b);
474     return 0;
475 }
476
477 static int sig_in(BIO *b)
478 {
479     BIO_OK_CTX *ctx;
480     EVP_MD_CTX *md;
481     unsigned char tmp[EVP_MAX_MD_SIZE];
482     int ret = 0;
483     const EVP_MD *digest;
484     int md_size;
485     void *md_data;
486
487     ctx = BIO_get_data(b);
488     md = ctx->md;
489     digest = EVP_MD_CTX_md(md);
490     md_size = EVP_MD_size(digest);
491     md_data = EVP_MD_CTX_md_data(md);
492
493     if ((int)(ctx->buf_len - ctx->buf_off) < 2 * md_size)
494         return 1;
495
496     if (!EVP_DigestInit_ex(md, digest, NULL))
497         goto berr;
498     memcpy(md_data, &(ctx->buf[ctx->buf_off]), md_size);
499     longswap(md_data, md_size);
500     ctx->buf_off += md_size;
501
502     if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN)))
503         goto berr;
504     if (!EVP_DigestFinal_ex(md, tmp, NULL))
505         goto berr;
506     ret = memcmp(&(ctx->buf[ctx->buf_off]), tmp, md_size) == 0;
507     ctx->buf_off += md_size;
508     if (ret == 1) {
509         ctx->sigio = 0;
510         if (ctx->buf_len != ctx->buf_off) {
511             memmove(ctx->buf, &(ctx->buf[ctx->buf_off]),
512                     ctx->buf_len - ctx->buf_off);
513         }
514         ctx->buf_len -= ctx->buf_off;
515         ctx->buf_off = 0;
516     } else {
517         ctx->cont = 0;
518     }
519     return 1;
520  berr:
521     BIO_clear_retry_flags(b);
522     return 0;
523 }
524
525 static int block_out(BIO *b)
526 {
527     BIO_OK_CTX *ctx;
528     EVP_MD_CTX *md;
529     unsigned long tl;
530     const EVP_MD *digest;
531     int md_size;
532
533     ctx = BIO_get_data(b);
534     md = ctx->md;
535     digest = EVP_MD_CTX_md(md);
536     md_size = EVP_MD_size(digest);
537
538     tl = ctx->buf_len - OK_BLOCK_BLOCK;
539     ctx->buf[0] = (unsigned char)(tl >> 24);
540     ctx->buf[1] = (unsigned char)(tl >> 16);
541     ctx->buf[2] = (unsigned char)(tl >> 8);
542     ctx->buf[3] = (unsigned char)(tl);
543     if (!EVP_DigestUpdate(md,
544                           (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl))
545         goto berr;
546     if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
547         goto berr;
548     ctx->buf_len += md_size;
549     ctx->blockout = 1;
550     return 1;
551  berr:
552     BIO_clear_retry_flags(b);
553     return 0;
554 }
555
556 static int block_in(BIO *b)
557 {
558     BIO_OK_CTX *ctx;
559     EVP_MD_CTX *md;
560     unsigned long tl = 0;
561     unsigned char tmp[EVP_MAX_MD_SIZE];
562     int md_size;
563
564     ctx = BIO_get_data(b);
565     md = ctx->md;
566     md_size = EVP_MD_size(EVP_MD_CTX_md(md));
567
568     assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */
569     tl = ctx->buf[0];
570     tl <<= 8;
571     tl |= ctx->buf[1];
572     tl <<= 8;
573     tl |= ctx->buf[2];
574     tl <<= 8;
575     tl |= ctx->buf[3];
576
577     if (ctx->buf_len < tl + OK_BLOCK_BLOCK + md_size)
578         return 1;
579
580     if (!EVP_DigestUpdate(md,
581                           (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl))
582         goto berr;
583     if (!EVP_DigestFinal_ex(md, tmp, NULL))
584         goto berr;
585     if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, md_size) == 0) {
586         /* there might be parts from next block lurking around ! */
587         ctx->buf_off_save = tl + OK_BLOCK_BLOCK + md_size;
588         ctx->buf_len_save = ctx->buf_len;
589         ctx->buf_off = OK_BLOCK_BLOCK;
590         ctx->buf_len = tl + OK_BLOCK_BLOCK;
591         ctx->blockout = 1;
592     } else {
593         ctx->cont = 0;
594     }
595     return 1;
596  berr:
597     BIO_clear_retry_flags(b);
598     return 0;
599 }