1/* BEGIN_HEADER */
2#include "debug_internal.h"
3#include "string.h"
4#include "mbedtls/pk.h"
5#if defined(MBEDTLS_PK_HAVE_PRIVATE_HEADER)
6#include <mbedtls/private/pk_private.h>
7#endif /* MBEDTLS_PK_HAVE_PRIVATE_HEADER */
8#include <test/ssl_helpers.h>
9
10#if defined(_WIN32)
11#   include <stdlib.h>
12#   include <crtdbg.h>
13#endif
14
15// Dummy type for builds without MBEDTLS_HAVE_TIME
16#if !defined(MBEDTLS_HAVE_TIME)
17typedef int64_t mbedtls_ms_time_t;
18#endif
19
20typedef enum {
21    PRINTF_SIZET,
22    PRINTF_LONGLONG,
23    PRINTF_MS_TIME,
24} printf_format_indicator_t;
25
26const char *const printf_formats[] = {
27    [PRINTF_SIZET]    = "%" MBEDTLS_PRINTF_SIZET,
28    [PRINTF_LONGLONG] = "%" MBEDTLS_PRINTF_LONGLONG,
29    [PRINTF_MS_TIME]  = "%" MBEDTLS_PRINTF_MS_TIME,
30};
31
32struct buffer_data {
33    char buf[2000];
34    char *ptr;
35};
36
37#if defined(MBEDTLS_SSL_TLS_C)
38static void string_debug(void *data, int level, const char *file, int line, const char *str)
39{
40    struct buffer_data *buffer = (struct buffer_data *) data;
41    char *p = buffer->ptr;
42    ((void) level);
43
44    memcpy(p, file, strlen(file));
45    p += strlen(file);
46
47    *p++ = '(';
48    *p++ = '0' + (line / 1000) % 10;
49    *p++ = '0' + (line / 100) % 10;
50    *p++ = '0' + (line / 10) % 10;
51    *p++ = '0' + (line / 1) % 10;
52    *p++ = ')';
53    *p++ = ':';
54    *p++ = ' ';
55
56#if defined(MBEDTLS_THREADING_C)
57    /* Skip "thread ID" (up to the first space) as it is not predictable */
58    while (*str++ != ' ') {
59        ;
60    }
61#endif
62
63    memcpy(p, str, strlen(str));
64    p += strlen(str);
65
66    /* Detect if debug messages output partial lines and mark them */
67    if (p[-1] != '\n') {
68        *p++ = '*';
69    }
70
71    buffer->ptr = p;
72}
73#endif /* MBEDTLS_SSL_TLS_C */
74
75#if defined(_WIN32)
76static void noop_invalid_parameter_handler(
77    const wchar_t *expression,
78    const wchar_t *function,
79    const wchar_t *file,
80    unsigned int line,
81    uintptr_t pReserved)
82{
83    (void) expression;
84    (void) function;
85    (void) file;
86    (void) line;
87    (void) pReserved;
88}
89#endif /* _WIN32 */
90
91/* END_HEADER */
92
93/* BEGIN_DEPENDENCIES
94 * depends_on:MBEDTLS_DEBUG_C
95 * END_DEPENDENCIES
96 */
97
98/* BEGIN_CASE */
99void printf_int_expr(int format_indicator, intmax_t sizeof_x, intmax_t x, char *result)
100{
101#if defined(_WIN32)
102    /* Windows treats any invalid format specifiers passsed to the CRT as fatal assertion failures.
103       Disable this behaviour temporarily, so the rest of the test cases can complete. */
104    _invalid_parameter_handler saved_handler =
105        _set_invalid_parameter_handler(noop_invalid_parameter_handler);
106
107    // Disable assertion pop-up window in Debug builds
108    int saved_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_REPORT_MODE);
109    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
110#endif
111
112    const char *format = printf_formats[format_indicator];
113    char *output = NULL;
114    const size_t n = strlen(result);
115
116    /* Nominal case: buffer just large enough */
117    TEST_CALLOC(output, n + 1);
118    if ((size_t) sizeof_x <= sizeof(int)) { // Any smaller integers would be promoted to an int due to calling a vararg function
119        TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, (int) x));
120    } else if (sizeof_x == sizeof(long)) {
121        TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, (long) x));
122    } else if (sizeof_x == sizeof(long long)) {
123        TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, (long long) x));
124    } else {
125        TEST_FAIL(
126            "sizeof_x <= sizeof(int) || sizeof_x == sizeof(long) || sizeof_x == sizeof(long long)");
127    }
128    TEST_MEMORY_COMPARE(result, n + 1, output, n + 1);
129
130exit:
131    mbedtls_free(output);
132    output = NULL;
133
134#if defined(_WIN32)
135    // Restore default Windows behaviour
136    _set_invalid_parameter_handler(saved_handler);
137    _CrtSetReportMode(_CRT_ASSERT, saved_report_mode);
138    (void) saved_report_mode;
139#endif
140}
141/* END_CASE */
142
143/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C */
144void debug_print_msg_threshold(int threshold, int level, char *file,
145                               int line, char *result_str)
146{
147    mbedtls_ssl_context ssl;
148    mbedtls_ssl_config conf;
149    struct buffer_data buffer;
150
151    mbedtls_ssl_init(&ssl);
152    mbedtls_ssl_config_init(&conf);
153    MD_OR_USE_PSA_INIT();
154    memset(buffer.buf, 0, 2000);
155    buffer.ptr = buffer.buf;
156
157    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
158                                           MBEDTLS_SSL_IS_CLIENT,
159                                           MBEDTLS_SSL_TRANSPORT_STREAM,
160                                           MBEDTLS_SSL_PRESET_DEFAULT),
161               0);
162    mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
163
164    TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
165
166    mbedtls_debug_set_threshold(threshold);
167
168    mbedtls_debug_print_msg(&ssl, level, file, line,
169                            "Text message, 2 == %d", 2);
170
171    TEST_ASSERT(strcmp(buffer.buf, result_str) == 0);
172
173exit:
174    mbedtls_ssl_free(&ssl);
175    mbedtls_ssl_config_free(&conf);
176    MD_OR_USE_PSA_DONE();
177}
178/* END_CASE */
179
180/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C */
181void mbedtls_debug_print_ret(char *file, int line, char *text, int value,
182                             char *result_str)
183{
184    mbedtls_ssl_context ssl;
185    mbedtls_ssl_config conf;
186    struct buffer_data buffer;
187
188    mbedtls_ssl_init(&ssl);
189    mbedtls_ssl_config_init(&conf);
190    MD_OR_USE_PSA_INIT();
191    memset(buffer.buf, 0, 2000);
192    buffer.ptr = buffer.buf;
193
194    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
195                                           MBEDTLS_SSL_IS_CLIENT,
196                                           MBEDTLS_SSL_TRANSPORT_STREAM,
197                                           MBEDTLS_SSL_PRESET_DEFAULT),
198               0);
199    mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
200
201    TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
202
203    mbedtls_debug_print_ret(&ssl, 0, file, line, text, value);
204
205    TEST_ASSERT(strcmp(buffer.buf, result_str) == 0);
206
207exit:
208    mbedtls_ssl_free(&ssl);
209    mbedtls_ssl_config_free(&conf);
210    MD_OR_USE_PSA_DONE();
211}
212/* END_CASE */
213
214/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C */
215void mbedtls_debug_print_buf(char *file, int line, char *text,
216                             data_t *data, char *result_str)
217{
218    mbedtls_ssl_context ssl;
219    mbedtls_ssl_config conf;
220    struct buffer_data buffer;
221
222    mbedtls_ssl_init(&ssl);
223    mbedtls_ssl_config_init(&conf);
224    MD_OR_USE_PSA_INIT();
225    memset(buffer.buf, 0, 2000);
226    buffer.ptr = buffer.buf;
227
228    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
229                                           MBEDTLS_SSL_IS_CLIENT,
230                                           MBEDTLS_SSL_TRANSPORT_STREAM,
231                                           MBEDTLS_SSL_PRESET_DEFAULT),
232               0);
233    mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
234
235    TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
236
237    mbedtls_debug_print_buf(&ssl, 0, file, line, text, data->x, data->len);
238
239    TEST_ASSERT(strcmp(buffer.buf, result_str) == 0);
240
241exit:
242    mbedtls_ssl_free(&ssl);
243    mbedtls_ssl_config_free(&conf);
244    MD_OR_USE_PSA_DONE();
245}
246/* END_CASE */
247
248/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:!MBEDTLS_X509_REMOVE_INFO */
249void mbedtls_debug_print_crt(char *crt_file, char *file, int line,
250                             char *prefix, char *result_str)
251{
252    mbedtls_x509_crt   crt;
253    mbedtls_ssl_context ssl;
254    mbedtls_ssl_config conf;
255    struct buffer_data buffer;
256
257    mbedtls_ssl_init(&ssl);
258    mbedtls_ssl_config_init(&conf);
259    mbedtls_x509_crt_init(&crt);
260    MD_OR_USE_PSA_INIT();
261
262    memset(buffer.buf, 0, 2000);
263    buffer.ptr = buffer.buf;
264
265    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
266                                           MBEDTLS_SSL_IS_CLIENT,
267                                           MBEDTLS_SSL_TRANSPORT_STREAM,
268                                           MBEDTLS_SSL_PRESET_DEFAULT),
269               0);
270    mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
271
272    TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
273
274    TEST_ASSERT(mbedtls_x509_crt_parse_file(&crt, crt_file) == 0);
275    mbedtls_debug_print_crt(&ssl, 0, file, line, prefix, &crt);
276
277    TEST_ASSERT(strcmp(buffer.buf, result_str) == 0);
278
279exit:
280    mbedtls_x509_crt_free(&crt);
281    mbedtls_ssl_free(&ssl);
282    mbedtls_ssl_config_free(&conf);
283    MD_OR_USE_PSA_DONE();
284}
285/* END_CASE */
286
287/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C:MBEDTLS_BIGNUM_C */
288void mbedtls_debug_print_mpi(char *value, char *file, int line,
289                             char *prefix, char *result_str)
290{
291    mbedtls_ssl_context ssl;
292    mbedtls_ssl_config conf;
293    struct buffer_data buffer;
294    mbedtls_mpi val;
295
296    mbedtls_ssl_init(&ssl);
297    mbedtls_ssl_config_init(&conf);
298    mbedtls_mpi_init(&val);
299    MD_OR_USE_PSA_INIT();
300    memset(buffer.buf, 0, 2000);
301    buffer.ptr = buffer.buf;
302
303    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
304                                           MBEDTLS_SSL_IS_CLIENT,
305                                           MBEDTLS_SSL_TRANSPORT_STREAM,
306                                           MBEDTLS_SSL_PRESET_DEFAULT),
307               0);
308    mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
309
310    TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
311
312    TEST_ASSERT(mbedtls_test_read_mpi(&val, value) == 0);
313
314    mbedtls_debug_print_mpi(&ssl, 0, file, line, prefix, &val);
315
316    TEST_ASSERT(strcmp(buffer.buf, result_str) == 0);
317
318exit:
319    mbedtls_mpi_free(&val);
320    mbedtls_ssl_free(&ssl);
321    mbedtls_ssl_config_free(&conf);
322    MD_OR_USE_PSA_DONE();
323}
324/* END_CASE */
325