4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 #if defined(MBEDTLS_DEBUG_C)
24 #if defined(MBEDTLS_PLATFORM_C)
25 #include "mbedtls/platform.h"
28 #define mbedtls_calloc calloc
29 #define mbedtls_free free
30 #define mbedtls_time_t time_t
31 #define mbedtls_snprintf snprintf
32 #define mbedtls_vsnprintf vsnprintf
35 #include "mbedtls/debug.h"
36 #include "mbedtls/error.h"
42 #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
43 !defined(inline) && !defined(__cplusplus)
44 #define inline __inline
47 #define DEBUG_BUF_SIZE 512
49 static int debug_threshold
= 0;
51 void mbedtls_debug_set_threshold(int threshold
) {
52 debug_threshold
= threshold
;
56 * All calls to f_dbg must be made via this function
58 static inline void debug_send_line(const mbedtls_ssl_context
*ssl
, int level
,
59 const char *file
, int line
,
62 * If in a threaded environment, we need a thread identifier.
63 * Since there is no portable way to get one, use the address of the ssl
64 * context instead, as it shouldn't be shared between threads.
66 #if defined(MBEDTLS_THREADING_C)
67 char idstr
[20 + DEBUG_BUF_SIZE
]; /* 0x + 16 nibbles + ': ' */
68 mbedtls_snprintf(idstr
, sizeof(idstr
), "%p: %s", (void *)ssl
, str
);
69 ssl
->conf
->f_dbg(ssl
->conf
->p_dbg
, level
, file
, line
, idstr
);
71 ssl
->conf
->f_dbg(ssl
->conf
->p_dbg
, level
, file
, line
, str
);
75 MBEDTLS_PRINTF_ATTRIBUTE(5, 6)
76 void mbedtls_debug_print_msg(const mbedtls_ssl_context
*ssl
, int level
,
77 const char *file
, int line
,
78 const char *format
, ...) {
80 char str
[DEBUG_BUF_SIZE
];
81 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
85 NULL
== ssl
->conf
->f_dbg
||
86 level
> debug_threshold
) {
90 va_start(argp
, format
);
91 ret
= mbedtls_vsnprintf(str
, DEBUG_BUF_SIZE
, format
, argp
);
94 if (ret
>= 0 && ret
< DEBUG_BUF_SIZE
- 1) {
99 debug_send_line(ssl
, level
, file
, line
, str
);
102 void mbedtls_debug_print_ret(const mbedtls_ssl_context
*ssl
, int level
,
103 const char *file
, int line
,
104 const char *text
, int ret
) {
105 char str
[DEBUG_BUF_SIZE
];
109 NULL
== ssl
->conf
->f_dbg
||
110 level
> debug_threshold
) {
115 * With non-blocking I/O and examples that just retry immediately,
116 * the logs would be quickly flooded with WANT_READ, so ignore that.
117 * Don't ignore WANT_WRITE however, since is is usually rare.
119 if (ret
== MBEDTLS_ERR_SSL_WANT_READ
)
122 mbedtls_snprintf(str
, sizeof(str
), "%s() returned %d (-0x%04x)\n",
123 text
, ret
, (unsigned int) - ret
);
125 debug_send_line(ssl
, level
, file
, line
, str
);
128 void mbedtls_debug_print_buf(const mbedtls_ssl_context
*ssl
, int level
,
129 const char *file
, int line
, const char *text
,
130 const unsigned char *buf
, size_t len
) {
131 char str
[DEBUG_BUF_SIZE
];
137 NULL
== ssl
->conf
->f_dbg
||
138 level
> debug_threshold
) {
142 mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, "dumping '%s' (%u bytes)\n",
143 text
, (unsigned int) len
);
145 debug_send_line(ssl
, level
, file
, line
, str
);
148 memset(txt
, 0, sizeof(txt
));
149 for (i
= 0; i
< len
; i
++) {
155 mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, " %s\n", txt
);
156 debug_send_line(ssl
, level
, file
, line
, str
);
159 memset(txt
, 0, sizeof(txt
));
162 idx
+= mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, "%04x: ",
167 idx
+= mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, " %02x",
168 (unsigned int) buf
[i
]);
169 txt
[i
% 16] = (buf
[i
] > 31 && buf
[i
] < 127) ? buf
[i
] : '.' ;
173 for (/* i = i */; i
% 16 != 0; i
++)
174 idx
+= mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, " ");
176 mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, " %s\n", txt
);
177 debug_send_line(ssl
, level
, file
, line
, str
);
181 #if defined(MBEDTLS_ECP_C)
182 void mbedtls_debug_print_ecp(const mbedtls_ssl_context
*ssl
, int level
,
183 const char *file
, int line
,
184 const char *text
, const mbedtls_ecp_point
*X
) {
185 char str
[DEBUG_BUF_SIZE
];
189 NULL
== ssl
->conf
->f_dbg
||
190 level
> debug_threshold
) {
194 mbedtls_snprintf(str
, sizeof(str
), "%s(X)", text
);
195 mbedtls_debug_print_mpi(ssl
, level
, file
, line
, str
, &X
->X
);
197 mbedtls_snprintf(str
, sizeof(str
), "%s(Y)", text
);
198 mbedtls_debug_print_mpi(ssl
, level
, file
, line
, str
, &X
->Y
);
200 #endif /* MBEDTLS_ECP_C */
202 #if defined(MBEDTLS_BIGNUM_C)
203 void mbedtls_debug_print_mpi(const mbedtls_ssl_context
*ssl
, int level
,
204 const char *file
, int line
,
205 const char *text
, const mbedtls_mpi
*X
) {
206 char str
[DEBUG_BUF_SIZE
];
208 size_t i
, n
, idx
= 0;
212 NULL
== ssl
->conf
->f_dbg
||
214 level
> debug_threshold
) {
218 for (n
= X
->n
- 1; n
> 0; n
--)
222 for (j
= (sizeof(mbedtls_mpi_uint
) << 3) - 1; j
>= 0; j
--)
223 if (((X
->p
[n
] >> j
) & 1) != 0)
226 mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, "value of '%s' (%d bits) is:\n",
227 text
, (int)((n
* (sizeof(mbedtls_mpi_uint
) << 3)) + j
+ 1));
229 debug_send_line(ssl
, level
, file
, line
, str
);
232 for (i
= n
+ 1, j
= 0; i
> 0; i
--) {
233 if (zeros
&& X
->p
[i
- 1] == 0)
236 for (k
= sizeof(mbedtls_mpi_uint
) - 1; k
>= 0; k
--) {
237 if (zeros
&& ((X
->p
[i
- 1] >> (k
<< 3)) & 0xFF) == 0)
244 mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, "\n");
245 debug_send_line(ssl
, level
, file
, line
, str
);
250 idx
+= mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, " %02x", (unsigned int)
251 (X
->p
[i
- 1] >> (k
<< 3)) & 0xFF);
259 idx
+= mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, " 00");
261 mbedtls_snprintf(str
+ idx
, sizeof(str
) - idx
, "\n");
262 debug_send_line(ssl
, level
, file
, line
, str
);
264 #endif /* MBEDTLS_BIGNUM_C */
266 #if defined(MBEDTLS_X509_CRT_PARSE_C)
267 static void debug_print_pk(const mbedtls_ssl_context
*ssl
, int level
,
268 const char *file
, int line
,
269 const char *text
, const mbedtls_pk_context
*pk
) {
271 mbedtls_pk_debug_item items
[MBEDTLS_PK_DEBUG_MAX_ITEMS
];
274 memset(items
, 0, sizeof(items
));
276 if (mbedtls_pk_debug(pk
, items
) != 0) {
277 debug_send_line(ssl
, level
, file
, line
,
278 "invalid PK context\n");
282 for (i
= 0; i
< MBEDTLS_PK_DEBUG_MAX_ITEMS
; i
++) {
283 if (items
[i
].type
== MBEDTLS_PK_DEBUG_NONE
)
286 mbedtls_snprintf(name
, sizeof(name
), "%s%s", text
, items
[i
].name
);
287 name
[sizeof(name
) - 1] = '\0';
289 if (items
[i
].type
== MBEDTLS_PK_DEBUG_MPI
)
290 mbedtls_debug_print_mpi(ssl
, level
, file
, line
, name
, items
[i
].value
);
292 #if defined(MBEDTLS_ECP_C)
293 if (items
[i
].type
== MBEDTLS_PK_DEBUG_ECP
)
294 mbedtls_debug_print_ecp(ssl
, level
, file
, line
, name
, items
[i
].value
);
297 debug_send_line(ssl
, level
, file
, line
,
298 "should not happen\n");
302 static void debug_print_line_by_line(const mbedtls_ssl_context
*ssl
, int level
,
303 const char *file
, int line
, const char *text
) {
304 char str
[DEBUG_BUF_SIZE
];
305 const char *start
, *cur
;
308 for (cur
= text
; *cur
!= '\0'; cur
++) {
310 size_t len
= cur
- start
+ 1;
311 if (len
> DEBUG_BUF_SIZE
- 1)
312 len
= DEBUG_BUF_SIZE
- 1;
314 memcpy(str
, start
, len
);
317 debug_send_line(ssl
, level
, file
, line
, str
);
324 void mbedtls_debug_print_crt(const mbedtls_ssl_context
*ssl
, int level
,
325 const char *file
, int line
,
326 const char *text
, const mbedtls_x509_crt
*crt
) {
327 char str
[DEBUG_BUF_SIZE
];
332 NULL
== ssl
->conf
->f_dbg
||
334 level
> debug_threshold
) {
338 while (crt
!= NULL
) {
341 mbedtls_snprintf(str
, sizeof(str
), "%s #%d:\n", text
, ++i
);
342 debug_send_line(ssl
, level
, file
, line
, str
);
344 mbedtls_x509_crt_info(buf
, sizeof(buf
) - 1, "", crt
);
345 debug_print_line_by_line(ssl
, level
, file
, line
, buf
);
347 debug_print_pk(ssl
, level
, file
, line
, "crt->", &crt
->pk
);
352 #endif /* MBEDTLS_X509_CRT_PARSE_C */
354 #if defined(MBEDTLS_ECDH_C)
355 static void mbedtls_debug_printf_ecdh_internal(const mbedtls_ssl_context
*ssl
,
356 int level
, const char *file
,
358 const mbedtls_ecdh_context
*ecdh
,
359 mbedtls_debug_ecdh_attr attr
) {
360 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
361 const mbedtls_ecdh_context
*ctx
= ecdh
;
363 const mbedtls_ecdh_context_mbed
*ctx
= &ecdh
->ctx
.mbed_ecdh
;
367 case MBEDTLS_DEBUG_ECDH_Q
:
368 mbedtls_debug_print_ecp(ssl
, level
, file
, line
, "ECDH: Q",
371 case MBEDTLS_DEBUG_ECDH_QP
:
372 mbedtls_debug_print_ecp(ssl
, level
, file
, line
, "ECDH: Qp",
375 case MBEDTLS_DEBUG_ECDH_Z
:
376 mbedtls_debug_print_mpi(ssl
, level
, file
, line
, "ECDH: z",
384 void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context
*ssl
, int level
,
385 const char *file
, int line
,
386 const mbedtls_ecdh_context
*ecdh
,
387 mbedtls_debug_ecdh_attr attr
) {
388 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
389 mbedtls_debug_printf_ecdh_internal(ssl
, level
, file
, line
, ecdh
, attr
);
393 mbedtls_debug_printf_ecdh_internal(ssl
, level
, file
, line
, ecdh
,
398 #endif /* MBEDTLS_ECDH_C */
400 #endif /* MBEDTLS_DEBUG_C */