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