bio_b64.c: prevent base64 filter BIO from decoding out-of-bound data
authorDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Wed, 21 Feb 2018 00:45:14 +0000 (01:45 +0100)
committerDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Tue, 27 Feb 2018 17:38:33 +0000 (18:38 +0100)
Fixes #5405, #1381

The base64 filter BIO reads its input in chunks of B64_BLOCK_SIZE bytes.
When processing input in PEM format it can happen in rare cases that

- the trailing PEM marker crosses the boundary of a chunk, and
- the beginning of the following chunk contains valid base64 encoded data.

This happened in issue #5405, where the PEM marker was split into
"-----END CER" and "TIFICATE-----" at the end of the first chunk.

The decoding of the first chunk terminated correctly at the '-' character,
which is treated as an EOF marker, and b64_read() returned. However,
when called the second time, b64_read() read the next chunk and interpreted
the string "TIFICATE" as valid base64 encoded data, adding 6 extra bytes
'4c 81 48 08 04 c4'.

This patch restores the assignment of the error code to 'ctx->cont', which
was deleted accidentally in commit 5562cfaca4f3 and which prevents b64_read()
from reading additional data on subsequent calls.

This issue was observed and reported by Annie Yousar.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5422)

crypto/evp/bio_b64.c

index cade6f8f95d88ff2e2564d0e8548a77b18fcf003..e70fc322d86ee0b8c28516e8fd50fbf6f8230a6a 100644 (file)
@@ -289,6 +289,14 @@ static int b64_read(BIO *b, char *out, int outl)
                                  (unsigned char *)ctx->tmp, i);
             ctx->tmp_len = 0;
         }
+        /*
+         * If eof or an error was signalled, then the condition
+         * 'ctx->cont <= 0' will prevent b64_read() from reading
+         * more data on subsequent calls. This assignment was
+         * deleted accidentally in commit 5562cfaca4f3.
+         */
+        ctx->cont = i;
+
         ctx->buf_off = 0;
         if (i < 0) {
             ret_code = 0;