Coverage Report

Created: 2025-03-01 06:26

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