Coverage Report

Created: 2026-04-01 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mbedtls/library/debug.c
Line
Count
Source
1
/*
2
 *  Debugging routines
3
 *
4
 *  Copyright The Mbed TLS Contributors
5
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6
 */
7
8
#include "common.h"
9
10
#if defined(MBEDTLS_DEBUG_C)
11
12
#include "mbedtls/platform.h"
13
14
#include "debug_internal.h"
15
#include "mbedtls/error.h"
16
17
#include <stdarg.h>
18
#include <stdio.h>
19
#include <string.h>
20
21
/* DEBUG_BUF_SIZE must be at least 2 */
22
0
#define DEBUG_BUF_SIZE      512
23
24
int mbedtls_debug_snprintf(char *dest, size_t maxlen,
25
                           const char *format, ...)
26
0
{
27
0
    va_list argp;
28
0
    va_start(argp, format);
29
0
    int ret = mbedtls_vsnprintf(dest, maxlen, format, argp);
30
0
    va_end(argp);
31
0
    return ret;
32
0
}
33
34
static int debug_threshold = 0;
35
36
void mbedtls_debug_set_threshold(int threshold)
37
0
{
38
0
    debug_threshold = threshold;
39
0
}
40
41
/*
42
 * All calls to f_dbg must be made via this function
43
 */
44
static inline void debug_send_line(const mbedtls_ssl_context *ssl, int level,
45
                                   const char *file, int line,
46
                                   const char *str)
47
0
{
48
    /*
49
     * If in a threaded environment, we need a thread identifier.
50
     * Since there is no portable way to get one, use the address of the ssl
51
     * context instead, as it shouldn't be shared between threads.
52
     */
53
0
#if defined(MBEDTLS_THREADING_C)
54
0
    char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */
55
0
    mbedtls_snprintf(idstr, sizeof(idstr), "%p: %s", (void *) ssl, str);
56
0
    ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, idstr);
57
#else
58
    ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, str);
59
#endif
60
0
}
61
62
MBEDTLS_PRINTF_ATTRIBUTE(5, 6)
63
void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,
64
                             const char *file, int line,
65
                             const char *format, ...)
66
3.00M
{
67
3.00M
    va_list argp;
68
3.00M
    char str[DEBUG_BUF_SIZE];
69
3.00M
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
70
71
3.00M
    MBEDTLS_STATIC_ASSERT(DEBUG_BUF_SIZE >= 2, "DEBUG_BUF_SIZE too small");
72
73
3.00M
    if (NULL == ssl              ||
74
3.00M
        NULL == ssl->conf        ||
75
3.00M
        NULL == ssl->conf->f_dbg ||
76
3.00M
        level > debug_threshold) {
77
3.00M
        return;
78
3.00M
    }
79
80
3.00M
    va_start(argp, format);
81
0
    ret = mbedtls_vsnprintf(str, DEBUG_BUF_SIZE, format, argp);
82
0
    va_end(argp);
83
84
0
    if (ret < 0) {
85
0
        ret = 0;
86
0
    } else {
87
0
        if (ret >= DEBUG_BUF_SIZE - 1) {
88
0
            ret = DEBUG_BUF_SIZE - 2;
89
0
        }
90
0
    }
91
0
    str[ret]     = '\n';
92
0
    str[ret + 1] = '\0';
93
94
0
    debug_send_line(ssl, level, file, line, str);
95
0
}
96
97
void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level,
98
                             const char *file, int line,
99
                             const char *text, int ret)
100
149k
{
101
149k
    char str[DEBUG_BUF_SIZE];
102
103
149k
    if (NULL == ssl              ||
104
149k
        NULL == ssl->conf        ||
105
149k
        NULL == ssl->conf->f_dbg ||
106
149k
        level > debug_threshold) {
107
149k
        return;
108
149k
    }
109
110
    /*
111
     * With non-blocking I/O and examples that just retry immediately,
112
     * the logs would be quickly flooded with WANT_READ, so ignore that.
113
     * Don't ignore WANT_WRITE however, since it is usually rare.
114
     */
115
0
    if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
116
0
        return;
117
0
    }
118
119
0
    mbedtls_snprintf(str, sizeof(str), "%s() returned %d (-0x%04x)\n",
120
0
                     text, ret, (unsigned int) -ret);
121
122
0
    debug_send_line(ssl, level, file, line, str);
123
0
}
124
125
void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level,
126
                             const char *file, int line, const char *text,
127
                             const unsigned char *buf, size_t len)
128
330k
{
129
330k
    char str[DEBUG_BUF_SIZE];
130
330k
    char txt[17];
131
330k
    size_t i, idx = 0;
132
133
330k
    if (NULL == ssl              ||
134
330k
        NULL == ssl->conf        ||
135
330k
        NULL == ssl->conf->f_dbg ||
136
330k
        level > debug_threshold) {
137
330k
        return;
138
330k
    }
139
140
0
    mbedtls_snprintf(str + idx, sizeof(str) - idx, "dumping '%s' (%u bytes)\n",
141
0
                     text, (unsigned int) len);
142
143
0
    debug_send_line(ssl, level, file, line, str);
144
145
0
    memset(txt, 0, sizeof(txt));
146
0
    for (i = 0; i < len; i++) {
147
0
        if (i >= 4096) {
148
0
            break;
149
0
        }
150
151
0
        if (i % 16 == 0) {
152
0
            if (i > 0) {
153
0
                mbedtls_snprintf(str + idx, sizeof(str) - idx, "  %s\n", txt);
154
0
                debug_send_line(ssl, level, file, line, str);
155
156
0
                idx = 0;
157
0
                memset(txt, 0, sizeof(txt));
158
0
            }
159
160
0
            idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "%04x: ",
161
0
                                    (unsigned int) i);
162
163
0
        }
164
165
0
        idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x",
166
0
                                (unsigned int) buf[i]);
167
0
        txt[i % 16] = (buf[i] > 31 && buf[i] < 127) ? buf[i] : '.';
168
0
    }
169
170
0
    if (len > 0) {
171
0
        for (/* i = i */; i % 16 != 0; i++) {
172
0
            idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "   ");
173
0
        }
174
175
0
        mbedtls_snprintf(str + idx, sizeof(str) - idx, "  %s\n", txt);
176
0
        debug_send_line(ssl, level, file, line, str);
177
0
    }
178
0
}
179
180
#if defined(MBEDTLS_ECP_LIGHT)
181
void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level,
182
                             const char *file, int line,
183
                             const char *text, const mbedtls_ecp_point *X)
184
1.28k
{
185
1.28k
    char str[DEBUG_BUF_SIZE];
186
187
1.28k
    if (NULL == ssl              ||
188
1.28k
        NULL == ssl->conf        ||
189
1.28k
        NULL == ssl->conf->f_dbg ||
190
1.28k
        level > debug_threshold) {
191
1.28k
        return;
192
1.28k
    }
193
194
0
    mbedtls_snprintf(str, sizeof(str), "%s(X)", text);
195
0
    mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->X);
196
197
0
    mbedtls_snprintf(str, sizeof(str), "%s(Y)", text);
198
0
    mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->Y);
199
0
}
200
#endif /* MBEDTLS_ECP_LIGHT */
201
202
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
203
static void mbedtls_debug_print_ec_coord(const mbedtls_ssl_context *ssl, int level,
204
                                         const char *file, int line, const char *text,
205
                                         const unsigned char *buf, size_t len)
206
{
207
    char str[DEBUG_BUF_SIZE];
208
    size_t i, idx = 0;
209
210
    mbedtls_snprintf(str + idx, sizeof(str) - idx, "value of '%s' (%u bits) is:\n",
211
                     text, (unsigned int) len * 8);
212
213
    debug_send_line(ssl, level, file, line, str);
214
215
    for (i = 0; i < len; i++) {
216
        if (i >= 4096) {
217
            break;
218
        }
219
220
        if (i % 16 == 0) {
221
            if (i > 0) {
222
                mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
223
                debug_send_line(ssl, level, file, line, str);
224
225
                idx = 0;
226
            }
227
        }
228
229
        idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x",
230
                                (unsigned int) buf[i]);
231
    }
232
233
    if (len > 0) {
234
        for (/* i = i */; i % 16 != 0; i++) {
235
            idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "   ");
236
        }
237
238
        mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
239
        debug_send_line(ssl, level, file, line, str);
240
    }
241
}
242
243
void mbedtls_debug_print_psa_ec(const mbedtls_ssl_context *ssl, int level,
244
                                const char *file, int line,
245
                                const char *text, const mbedtls_pk_context *pk)
246
{
247
    char str[DEBUG_BUF_SIZE];
248
    const uint8_t *coord_start;
249
    size_t coord_len;
250
251
    if (NULL == ssl              ||
252
        NULL == ssl->conf        ||
253
        NULL == ssl->conf->f_dbg ||
254
        level > debug_threshold) {
255
        return;
256
    }
257
258
    /* For the description of pk->pk_raw content please refer to the description
259
     * psa_export_public_key() function. */
260
    coord_len = (pk->pub_raw_len - 1)/2;
261
262
    /* X coordinate */
263
    coord_start = pk->pub_raw + 1;
264
    mbedtls_snprintf(str, sizeof(str), "%s(X)", text);
265
    mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len);
266
267
    /* Y coordinate */
268
    coord_start = coord_start + coord_len;
269
    mbedtls_snprintf(str, sizeof(str), "%s(Y)", text);
270
    mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len);
271
}
272
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
273
274
#if defined(MBEDTLS_BIGNUM_C)
275
void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,
276
                             const char *file, int line,
277
                             const char *text, const mbedtls_mpi *X)
278
913
{
279
913
    char str[DEBUG_BUF_SIZE];
280
913
    size_t bitlen;
281
913
    size_t idx = 0;
282
283
913
    if (NULL == ssl              ||
284
913
        NULL == ssl->conf        ||
285
913
        NULL == ssl->conf->f_dbg ||
286
913
        NULL == X                ||
287
913
        level > debug_threshold) {
288
913
        return;
289
913
    }
290
291
0
    bitlen = mbedtls_mpi_bitlen(X);
292
293
0
    mbedtls_snprintf(str, sizeof(str), "value of '%s' (%u bits) is:\n",
294
0
                     text, (unsigned) bitlen);
295
0
    debug_send_line(ssl, level, file, line, str);
296
297
0
    if (bitlen == 0) {
298
0
        str[0] = ' '; str[1] = '0'; str[2] = '0';
299
0
        idx = 3;
300
0
    } else {
301
0
        int n;
302
0
        for (n = (int) ((bitlen - 1) / 8); n >= 0; n--) {
303
0
            size_t limb_offset = n / sizeof(mbedtls_mpi_uint);
304
0
            size_t offset_in_limb = n % sizeof(mbedtls_mpi_uint);
305
0
            unsigned char octet =
306
0
                (X->p[limb_offset] >> (offset_in_limb * 8)) & 0xff;
307
0
            mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", octet);
308
0
            idx += 3;
309
            /* Wrap lines after 16 octets that each take 3 columns */
310
0
            if (idx >= 3 * 16) {
311
0
                mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
312
0
                debug_send_line(ssl, level, file, line, str);
313
0
                idx = 0;
314
0
            }
315
0
        }
316
0
    }
317
318
0
    if (idx != 0) {
319
0
        mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
320
0
        debug_send_line(ssl, level, file, line, str);
321
0
    }
322
0
}
323
#endif /* MBEDTLS_BIGNUM_C */
324
325
#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO)
326
static void debug_print_pk(const mbedtls_ssl_context *ssl, int level,
327
                           const char *file, int line,
328
                           const char *text, const mbedtls_pk_context *pk)
329
0
{
330
0
    size_t i;
331
0
    mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
332
0
    char name[16];
333
334
0
    memset(items, 0, sizeof(items));
335
336
0
    if (mbedtls_pk_debug(pk, items) != 0) {
337
0
        debug_send_line(ssl, level, file, line,
338
0
                        "invalid PK context\n");
339
0
        return;
340
0
    }
341
342
0
    for (i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++) {
343
0
        if (items[i].type == MBEDTLS_PK_DEBUG_NONE) {
344
0
            return;
345
0
        }
346
347
0
        mbedtls_snprintf(name, sizeof(name), "%s%s", text, items[i].name);
348
0
        name[sizeof(name) - 1] = '\0';
349
350
0
#if defined(MBEDTLS_RSA_C)
351
0
        if (items[i].type == MBEDTLS_PK_DEBUG_MPI) {
352
0
            mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value);
353
0
        } else
354
0
#endif /* MBEDTLS_RSA_C */
355
0
#if defined(MBEDTLS_ECP_LIGHT)
356
0
        if (items[i].type == MBEDTLS_PK_DEBUG_ECP) {
357
0
            mbedtls_debug_print_ecp(ssl, level, file, line, name, items[i].value);
358
0
        } else
359
0
#endif /* MBEDTLS_ECP_LIGHT */
360
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
361
        if (items[i].type == MBEDTLS_PK_DEBUG_PSA_EC) {
362
            mbedtls_debug_print_psa_ec(ssl, level, file, line, name, items[i].value);
363
        } else
364
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
365
0
        { debug_send_line(ssl, level, file, line,
366
0
                          "should not happen\n"); }
367
0
    }
368
0
}
369
370
static void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level,
371
                                     const char *file, int line, const char *text)
372
0
{
373
0
    char str[DEBUG_BUF_SIZE];
374
0
    const char *start, *cur;
375
376
0
    start = text;
377
0
    for (cur = text; *cur != '\0'; cur++) {
378
0
        if (*cur == '\n') {
379
0
            size_t len = (size_t) (cur - start) + 1;
380
0
            if (len > DEBUG_BUF_SIZE - 1) {
381
0
                len = DEBUG_BUF_SIZE - 1;
382
0
            }
383
384
0
            memcpy(str, start, len);
385
0
            str[len] = '\0';
386
387
0
            debug_send_line(ssl, level, file, line, str);
388
389
0
            start = cur + 1;
390
0
        }
391
0
    }
392
0
}
393
394
void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,
395
                             const char *file, int line,
396
                             const char *text, const mbedtls_x509_crt *crt)
397
5.14k
{
398
5.14k
    char str[DEBUG_BUF_SIZE];
399
5.14k
    int i = 0;
400
401
5.14k
    if (NULL == ssl              ||
402
5.14k
        NULL == ssl->conf        ||
403
5.14k
        NULL == ssl->conf->f_dbg ||
404
5.14k
        NULL == crt              ||
405
5.14k
        level > debug_threshold) {
406
5.14k
        return;
407
5.14k
    }
408
409
0
    while (crt != NULL) {
410
0
        char buf[1024];
411
412
0
        mbedtls_snprintf(str, sizeof(str), "%s #%d:\n", text, ++i);
413
0
        debug_send_line(ssl, level, file, line, str);
414
415
0
        mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
416
0
        debug_print_line_by_line(ssl, level, file, line, buf);
417
418
0
        debug_print_pk(ssl, level, file, line, "crt->", &crt->pk);
419
420
0
        crt = crt->next;
421
0
    }
422
0
}
423
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */
424
425
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \
426
    defined(MBEDTLS_ECDH_C)
427
static void mbedtls_debug_printf_ecdh_internal(const mbedtls_ssl_context *ssl,
428
                                               int level, const char *file,
429
                                               int line,
430
                                               const mbedtls_ecdh_context *ecdh,
431
                                               mbedtls_debug_ecdh_attr attr)
432
1.63k
{
433
1.63k
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
434
1.63k
    const mbedtls_ecdh_context *ctx = ecdh;
435
#else
436
    const mbedtls_ecdh_context_mbed *ctx = &ecdh->ctx.mbed_ecdh;
437
#endif
438
439
1.63k
    switch (attr) {
440
416
        case MBEDTLS_DEBUG_ECDH_Q:
441
416
            mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Q",
442
416
                                    &ctx->Q);
443
416
            break;
444
871
        case MBEDTLS_DEBUG_ECDH_QP:
445
871
            mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Qp",
446
871
                                    &ctx->Qp);
447
871
            break;
448
344
        case MBEDTLS_DEBUG_ECDH_Z:
449
344
            mbedtls_debug_print_mpi(ssl, level, file, line, "ECDH: z",
450
344
                                    &ctx->z);
451
344
            break;
452
0
        default:
453
0
            break;
454
1.63k
    }
455
1.63k
}
456
457
void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level,
458
                               const char *file, int line,
459
                               const mbedtls_ecdh_context *ecdh,
460
                               mbedtls_debug_ecdh_attr attr)
461
1.63k
{
462
1.63k
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
463
1.63k
    mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh, attr);
464
#else
465
    switch (ecdh->var) {
466
        default:
467
            mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh,
468
                                               attr);
469
    }
470
#endif
471
1.63k
}
472
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED &&
473
          MBEDTLS_ECDH_C */
474
475
#endif /* MBEDTLS_DEBUG_C */