Copyright consolidation 09/10
[openssl.git] / crypto / bio / b_dump.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  * Stolen from tjh's ssl/ssl_trc.c stuff.
12  */
13
14 #include <stdio.h>
15 #include "bio_lcl.h"
16
17 #define TRUNCATE
18 #define DUMP_WIDTH      16
19 #define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH-((i-(i>6?6:i)+3)/4))
20
21 int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u),
22                 void *u, const char *s, int len)
23 {
24     return BIO_dump_indent_cb(cb, u, s, len, 0);
25 }
26
27 int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u),
28                        void *u, const char *s, int len, int indent)
29 {
30     int ret = 0;
31     char buf[288 + 1], tmp[20], str[128 + 1];
32     int i, j, rows, trc;
33     unsigned char ch;
34     int dump_width;
35
36     trc = 0;
37
38 #ifdef TRUNCATE
39     for (; (len > 0) && ((s[len - 1] == ' ') || (s[len - 1] == '\0')); len--)
40         trc++;
41 #endif
42
43     if (indent < 0)
44         indent = 0;
45     if (indent) {
46         if (indent > 128)
47             indent = 128;
48         memset(str, ' ', indent);
49     }
50     str[indent] = '\0';
51
52     dump_width = DUMP_WIDTH_LESS_INDENT(indent);
53     rows = (len / dump_width);
54     if ((rows * dump_width) < len)
55         rows++;
56     for (i = 0; i < rows; i++) {
57         OPENSSL_strlcpy(buf, str, sizeof buf);
58         BIO_snprintf(tmp, sizeof tmp, "%04x - ", i * dump_width);
59         OPENSSL_strlcat(buf, tmp, sizeof buf);
60         for (j = 0; j < dump_width; j++) {
61             if (((i * dump_width) + j) >= len) {
62                 OPENSSL_strlcat(buf, "   ", sizeof buf);
63             } else {
64                 ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff;
65                 BIO_snprintf(tmp, sizeof tmp, "%02x%c", ch,
66                              j == 7 ? '-' : ' ');
67                 OPENSSL_strlcat(buf, tmp, sizeof buf);
68             }
69         }
70         OPENSSL_strlcat(buf, "  ", sizeof buf);
71         for (j = 0; j < dump_width; j++) {
72             if (((i * dump_width) + j) >= len)
73                 break;
74             ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff;
75 #ifndef CHARSET_EBCDIC
76             BIO_snprintf(tmp, sizeof tmp, "%c",
77                          ((ch >= ' ') && (ch <= '~')) ? ch : '.');
78 #else
79             BIO_snprintf(tmp, sizeof tmp, "%c",
80                          ((ch >= os_toascii[' ']) && (ch <= os_toascii['~']))
81                          ? os_toebcdic[ch]
82                          : '.');
83 #endif
84             OPENSSL_strlcat(buf, tmp, sizeof buf);
85         }
86         OPENSSL_strlcat(buf, "\n", sizeof buf);
87         /*
88          * if this is the last call then update the ddt_dump thing so that we
89          * will move the selection point in the debug window
90          */
91         ret += cb((void *)buf, strlen(buf), u);
92     }
93 #ifdef TRUNCATE
94     if (trc > 0) {
95         BIO_snprintf(buf, sizeof buf, "%s%04x - <SPACES/NULS>\n", str,
96                      len + trc);
97         ret += cb((void *)buf, strlen(buf), u);
98     }
99 #endif
100     return (ret);
101 }
102
103 #ifndef OPENSSL_NO_STDIO
104 static int write_fp(const void *data, size_t len, void *fp)
105 {
106     return UP_fwrite(data, len, 1, fp);
107 }
108
109 int BIO_dump_fp(FILE *fp, const char *s, int len)
110 {
111     return BIO_dump_cb(write_fp, fp, s, len);
112 }
113
114 int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent)
115 {
116     return BIO_dump_indent_cb(write_fp, fp, s, len, indent);
117 }
118 #endif
119
120 static int write_bio(const void *data, size_t len, void *bp)
121 {
122     return BIO_write((BIO *)bp, (const char *)data, len);
123 }
124
125 int BIO_dump(BIO *bp, const char *s, int len)
126 {
127     return BIO_dump_cb(write_bio, bp, s, len);
128 }
129
130 int BIO_dump_indent(BIO *bp, const char *s, int len, int indent)
131 {
132     return BIO_dump_indent_cb(write_bio, bp, s, len, indent);
133 }
134
135 int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
136                    int datalen)
137 {
138     int i, j = 0;
139
140     if (datalen < 1)
141         return 1;
142
143     for (i = 0; i < datalen - 1; i++) {
144         if (i && !j)
145             BIO_printf(out, "%*s", indent, "");
146
147         BIO_printf(out, "%02X:", data[i]);
148
149         j = (j + 1) % width;
150         if (!j)
151             BIO_printf(out, "\n");
152     }
153
154     if (i && !j)
155         BIO_printf(out, "%*s", indent, "");
156     BIO_printf(out, "%02X", data[datalen - 1]);
157     return 1;
158 }