1*1fa3bebfStb /* $OpenBSD: b_dump.c,v 1.30 2024/03/02 09:21:24 tb Exp $ */
25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
35b37fcf3Sryker * All rights reserved.
45b37fcf3Sryker *
55b37fcf3Sryker * This package is an SSL implementation written
65b37fcf3Sryker * by Eric Young (eay@cryptsoft.com).
75b37fcf3Sryker * The implementation was written so as to conform with Netscapes SSL.
85b37fcf3Sryker *
95b37fcf3Sryker * This library is free for commercial and non-commercial use as long as
105b37fcf3Sryker * the following conditions are aheared to. The following conditions
115b37fcf3Sryker * apply to all code found in this distribution, be it the RC4, RSA,
125b37fcf3Sryker * lhash, DES, etc., code; not just the SSL code. The SSL documentation
135b37fcf3Sryker * included with this distribution is covered by the same copyright terms
145b37fcf3Sryker * except that the holder is Tim Hudson (tjh@cryptsoft.com).
155b37fcf3Sryker *
165b37fcf3Sryker * Copyright remains Eric Young's, and as such any Copyright notices in
175b37fcf3Sryker * the code are not to be removed.
185b37fcf3Sryker * If this package is used in a product, Eric Young should be given attribution
195b37fcf3Sryker * as the author of the parts of the library used.
205b37fcf3Sryker * This can be in the form of a textual message at program startup or
215b37fcf3Sryker * in documentation (online or textual) provided with the package.
225b37fcf3Sryker *
235b37fcf3Sryker * Redistribution and use in source and binary forms, with or without
245b37fcf3Sryker * modification, are permitted provided that the following conditions
255b37fcf3Sryker * are met:
265b37fcf3Sryker * 1. Redistributions of source code must retain the copyright
275b37fcf3Sryker * notice, this list of conditions and the following disclaimer.
285b37fcf3Sryker * 2. Redistributions in binary form must reproduce the above copyright
295b37fcf3Sryker * notice, this list of conditions and the following disclaimer in the
305b37fcf3Sryker * documentation and/or other materials provided with the distribution.
315b37fcf3Sryker * 3. All advertising materials mentioning features or use of this software
325b37fcf3Sryker * must display the following acknowledgement:
335b37fcf3Sryker * "This product includes cryptographic software written by
345b37fcf3Sryker * Eric Young (eay@cryptsoft.com)"
355b37fcf3Sryker * The word 'cryptographic' can be left out if the rouines from the library
365b37fcf3Sryker * being used are not cryptographic related :-).
375b37fcf3Sryker * 4. If you include any Windows specific code (or a derivative thereof) from
385b37fcf3Sryker * the apps directory (application code) you must include an acknowledgement:
395b37fcf3Sryker * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
405b37fcf3Sryker *
415b37fcf3Sryker * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
425b37fcf3Sryker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
435b37fcf3Sryker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
445b37fcf3Sryker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
455b37fcf3Sryker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
465b37fcf3Sryker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
475b37fcf3Sryker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485b37fcf3Sryker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495b37fcf3Sryker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
505b37fcf3Sryker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
515b37fcf3Sryker * SUCH DAMAGE.
525b37fcf3Sryker *
535b37fcf3Sryker * The licence and distribution terms for any publically available version or
545b37fcf3Sryker * derivative of this code cannot be changed. i.e. this code cannot simply be
555b37fcf3Sryker * copied and put under another distribution licence
565b37fcf3Sryker * [including the GNU Public Licence.]
575b37fcf3Sryker */
585b37fcf3Sryker
592bd5848bStb #include <limits.h>
604469aa38Stb #include <stdint.h>
615b37fcf3Sryker #include <stdio.h>
62a8913c44Sjsing #include <string.h>
63f7683bc0Sjsing
6487d6f0d1Smiod #include <openssl/bio.h>
65bd79a156Stb #include <openssl/err.h>
665b37fcf3Sryker
674469aa38Stb #include "bytestring.h"
684469aa38Stb
694469aa38Stb #define MAX_BYTES_PER_LINE 16
704469aa38Stb
714469aa38Stb /*
724469aa38Stb * The byte string s is dumped as lines of the following form:
734469aa38Stb * indent | byte count (4 digits) | " - " | hex dump | " " | ASCII dump
744469aa38Stb * Each byte uses 4 characters (two hex digits followed by a space and one
754469aa38Stb * ASCII character).
764469aa38Stb */
775b37fcf3Sryker
78c3d505beSjsing int
BIO_dump_indent(BIO * bio,const char * s,int len,int indent)79bd79a156Stb BIO_dump_indent(BIO *bio, const char *s, int len, int indent)
80c109e398Sbeck {
814469aa38Stb CBB cbb;
824469aa38Stb CBS cbs;
834469aa38Stb int bytes_per_line, dumped, printed, trailing, written;
844469aa38Stb int ret = -1;
855b37fcf3Sryker
864469aa38Stb memset(&cbb, 0, sizeof(cbb));
875b37fcf3Sryker
884469aa38Stb if (len < 0)
894469aa38Stb goto err;
904469aa38Stb CBS_init(&cbs, s, len);
915b37fcf3Sryker
92c109e398Sbeck if (indent < 0)
93c109e398Sbeck indent = 0;
945c1da4ccSjsing if (indent > 64)
955c1da4ccSjsing indent = 64;
96c109e398Sbeck
974469aa38Stb /*
984469aa38Stb * Less obfuscated version of the original calculation attempting to
994469aa38Stb * ensure that the dump doesn't overshoot 80 characters per line. For
1004469aa38Stb * a very long string the byte count will still make it go past that.
1015b37fcf3Sryker */
1024469aa38Stb bytes_per_line = MAX_BYTES_PER_LINE;
1034469aa38Stb if (indent > 6)
1044469aa38Stb bytes_per_line -= (indent - 3) / 4;
1054469aa38Stb if (bytes_per_line <= 0)
1064469aa38Stb goto err;
10737f7320aSbeck
1084469aa38Stb /* Strip and count trailing spaces and NULs. */
1094469aa38Stb trailing = 0;
1104469aa38Stb while (CBS_len(&cbs) > 0) {
1114469aa38Stb uint8_t u8;
1124469aa38Stb
1134469aa38Stb if (!CBS_peek_last_u8(&cbs, &u8))
1144469aa38Stb goto err;
1154469aa38Stb if (u8 != '\0' && u8 != ' ')
1164469aa38Stb break;
1174469aa38Stb if (!CBS_get_last_u8(&cbs, &u8))
1184469aa38Stb goto err;
1194469aa38Stb trailing++;
1205b37fcf3Sryker }
1214469aa38Stb
1224469aa38Stb printed = 0;
1234469aa38Stb dumped = 0;
1244469aa38Stb while (CBS_len(&cbs) > 0) {
1254469aa38Stb CBS row;
1264469aa38Stb uint8_t ascii_dump[MAX_BYTES_PER_LINE];
1274469aa38Stb int missing, row_bytes;
1284469aa38Stb
1294469aa38Stb if ((row_bytes = CBS_len(&cbs)) > bytes_per_line)
1304469aa38Stb row_bytes = bytes_per_line;
1314469aa38Stb if (!CBS_get_bytes(&cbs, &row, row_bytes))
1324469aa38Stb goto err;
1334469aa38Stb
1344469aa38Stb /* Write out indent, byte count and initial " - ". */
1354469aa38Stb if ((written = BIO_printf(bio, "%*s%04x - ", indent, "",
1364469aa38Stb dumped)) < 0)
1374469aa38Stb goto err;
1382bd5848bStb if (printed > INT_MAX - written)
1392bd5848bStb goto err;
1404469aa38Stb printed += written;
1414469aa38Stb
1424469aa38Stb /*
1434469aa38Stb * Write out hex dump, prepare ASCII dump.
1444469aa38Stb */
1454469aa38Stb
1464469aa38Stb if (!CBB_init_fixed(&cbb, ascii_dump, sizeof(ascii_dump)))
1474469aa38Stb goto err;
1484469aa38Stb while (CBS_len(&row) > 0) {
1494469aa38Stb uint8_t u8;
1504469aa38Stb char sep = ' ';
1514469aa38Stb
1524469aa38Stb if (!CBS_get_u8(&row, &u8))
1534469aa38Stb goto err;
1544469aa38Stb
1554469aa38Stb /* Historic behavior: print a '-' after eighth byte. */
1564469aa38Stb if (row_bytes - CBS_len(&row) == 8)
1574469aa38Stb sep = '-';
1584469aa38Stb if ((written = BIO_printf(bio, "%02x%c", u8, sep)) < 0)
1594469aa38Stb goto err;
1602bd5848bStb if (printed > INT_MAX - written)
1612bd5848bStb goto err;
1624469aa38Stb printed += written;
1634469aa38Stb
1644469aa38Stb /* Locale-independent version of !isprint(u8). */
1654469aa38Stb if (u8 < ' ' || u8 > '~')
1664469aa38Stb u8 = '.';
1674469aa38Stb if (!CBB_add_u8(&cbb, u8))
1684469aa38Stb goto err;
1695b37fcf3Sryker }
1704469aa38Stb if (!CBB_finish(&cbb, NULL, NULL))
1714469aa38Stb goto err;
1724469aa38Stb
1734469aa38Stb /* Calculate number of bytes missing in dump of last line. */
1744469aa38Stb if ((missing = bytes_per_line - row_bytes) < 0)
1754469aa38Stb goto err;
1764469aa38Stb
1774469aa38Stb /* Pad missing bytes, add 2 spaces and print the ASCII dump. */
1784469aa38Stb if ((written = BIO_printf(bio, "%*s%.*s\n", 3 * missing + 2, "",
1794469aa38Stb row_bytes, ascii_dump)) < 0)
1804469aa38Stb goto err;
1812bd5848bStb if (printed > INT_MAX - written)
1822bd5848bStb goto err;
1834469aa38Stb printed += written;
1844469aa38Stb
1854469aa38Stb dumped += row_bytes;
1864469aa38Stb }
1874469aa38Stb
1884469aa38Stb if (trailing > 0) {
1894469aa38Stb if ((written = BIO_printf(bio, "%*s%04x - <SPACES/NULS>\n",
1904469aa38Stb indent, "", dumped + trailing)) < 0)
1914469aa38Stb goto err;
1922bd5848bStb if (printed > INT_MAX - written)
1932bd5848bStb goto err;
1944469aa38Stb printed += written;
1954469aa38Stb }
1964469aa38Stb
1974469aa38Stb ret = printed;
1984469aa38Stb
1994469aa38Stb err:
2004469aa38Stb CBB_cleanup(&cbb);
2014469aa38Stb
2024469aa38Stb return ret;
2035b37fcf3Sryker }
204bd79a156Stb LCRYPTO_ALIAS(BIO_dump_indent);
2054fcf65c5Sdjm
206bd79a156Stb int
BIO_dump(BIO * bio,const char * s,int len)207bd79a156Stb BIO_dump(BIO *bio, const char *s, int len)
2084fcf65c5Sdjm {
209bd79a156Stb return BIO_dump_indent(bio, s, len, 0);
210bd79a156Stb }
211bd79a156Stb LCRYPTO_ALIAS(BIO_dump);
212