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 "ssl_misc.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 #define DEBUG_BUF_SIZE      512
23 
24 static int debug_threshold = 0;
25 
mbedtls_debug_set_threshold(int threshold)26 void mbedtls_debug_set_threshold(int threshold)
27 {
28     debug_threshold = threshold;
29 }
30 
31 /*
32  * All calls to f_dbg must be made via this function
33  */
debug_send_line(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * str)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 {
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 #if defined(MBEDTLS_THREADING_C)
44     char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */
45     mbedtls_snprintf(idstr, sizeof(idstr), "%p: %s", (void *) ssl, str);
46     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 }
51 
52 MBEDTLS_PRINTF_ATTRIBUTE(5, 6)
mbedtls_debug_print_msg(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * format,...)53 void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,
54                              const char *file, int line,
55                              const char *format, ...)
56 {
57     va_list argp;
58     char str[DEBUG_BUF_SIZE];
59     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
60 
61     MBEDTLS_STATIC_ASSERT(DEBUG_BUF_SIZE >= 2, "DEBUG_BUF_SIZE too small");
62 
63     if (NULL == ssl              ||
64         NULL == ssl->conf        ||
65         NULL == ssl->conf->f_dbg ||
66         level > debug_threshold) {
67         return;
68     }
69 
70     va_start(argp, format);
71     ret = mbedtls_vsnprintf(str, DEBUG_BUF_SIZE, format, argp);
72     va_end(argp);
73 
74     if (ret < 0) {
75         ret = 0;
76     } else {
77         if (ret >= DEBUG_BUF_SIZE - 1) {
78             ret = DEBUG_BUF_SIZE - 2;
79         }
80     }
81     str[ret]     = '\n';
82     str[ret + 1] = '\0';
83 
84     debug_send_line(ssl, level, file, line, str);
85 }
86 
mbedtls_debug_print_ret(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * text,int ret)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 {
91     char str[DEBUG_BUF_SIZE];
92 
93     if (NULL == ssl              ||
94         NULL == ssl->conf        ||
95         NULL == ssl->conf->f_dbg ||
96         level > debug_threshold) {
97         return;
98     }
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     if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
106         return;
107     }
108 
109     mbedtls_snprintf(str, sizeof(str), "%s() returned %d (-0x%04x)\n",
110                      text, ret, (unsigned int) -ret);
111 
112     debug_send_line(ssl, level, file, line, str);
113 }
114 
mbedtls_debug_print_buf(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * text,const unsigned char * buf,size_t len)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 {
119     char str[DEBUG_BUF_SIZE];
120     char txt[17];
121     size_t i, idx = 0;
122 
123     if (NULL == ssl              ||
124         NULL == ssl->conf        ||
125         NULL == ssl->conf->f_dbg ||
126         level > debug_threshold) {
127         return;
128     }
129 
130     mbedtls_snprintf(str + idx, sizeof(str) - idx, "dumping '%s' (%u bytes)\n",
131                      text, (unsigned int) len);
132 
133     debug_send_line(ssl, level, file, line, str);
134 
135     memset(txt, 0, sizeof(txt));
136     for (i = 0; i < len; i++) {
137         if (i >= 4096) {
138             break;
139         }
140 
141         if (i % 16 == 0) {
142             if (i > 0) {
143                 mbedtls_snprintf(str + idx, sizeof(str) - idx, "  %s\n", txt);
144                 debug_send_line(ssl, level, file, line, str);
145 
146                 idx = 0;
147                 memset(txt, 0, sizeof(txt));
148             }
149 
150             idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "%04x: ",
151                                     (unsigned int) i);
152 
153         }
154 
155         idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x",
156                                 (unsigned int) buf[i]);
157         txt[i % 16] = (buf[i] > 31 && buf[i] < 127) ? buf[i] : '.';
158     }
159 
160     if (len > 0) {
161         for (/* i = i */; i % 16 != 0; i++) {
162             idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "   ");
163         }
164 
165         mbedtls_snprintf(str + idx, sizeof(str) - idx, "  %s\n", txt);
166         debug_send_line(ssl, level, file, line, str);
167     }
168 }
169 
170 #if defined(MBEDTLS_BIGNUM_C)
mbedtls_debug_print_mpi(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * text,const mbedtls_mpi * X)171 void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,
172                              const char *file, int line,
173                              const char *text, const mbedtls_mpi *X)
174 {
175     char str[DEBUG_BUF_SIZE];
176     size_t bitlen;
177     size_t idx = 0;
178 
179     if (NULL == ssl              ||
180         NULL == ssl->conf        ||
181         NULL == ssl->conf->f_dbg ||
182         NULL == X                ||
183         level > debug_threshold) {
184         return;
185     }
186 
187     bitlen = mbedtls_mpi_bitlen(X);
188 
189     mbedtls_snprintf(str, sizeof(str), "value of '%s' (%u bits) is:\n",
190                      text, (unsigned) bitlen);
191     debug_send_line(ssl, level, file, line, str);
192 
193     if (bitlen == 0) {
194         str[0] = ' '; str[1] = '0'; str[2] = '0';
195         idx = 3;
196     } else {
197         int n;
198         for (n = (int) ((bitlen - 1) / 8); n >= 0; n--) {
199             size_t limb_offset = n / sizeof(mbedtls_mpi_uint);
200             size_t offset_in_limb = n % sizeof(mbedtls_mpi_uint);
201             unsigned char octet =
202                 (X->p[limb_offset] >> (offset_in_limb * 8)) & 0xff;
203             mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", octet);
204             idx += 3;
205             /* Wrap lines after 16 octets that each take 3 columns */
206             if (idx >= 3 * 16) {
207                 mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
208                 debug_send_line(ssl, level, file, line, str);
209                 idx = 0;
210             }
211         }
212     }
213 
214     if (idx != 0) {
215         mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
216         debug_send_line(ssl, level, file, line, str);
217     }
218 }
219 #endif /* MBEDTLS_BIGNUM_C */
220 
221 #if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO)
222 
223 /* no-check-names will be removed in mbedtls#10229. */
224 #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) || defined(MBEDTLS_PK_USE_PSA_RSA_DATA) //no-check-names
mbedtls_debug_print_integer(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * text,const unsigned char * buf,size_t bitlen)225 static void mbedtls_debug_print_integer(const mbedtls_ssl_context *ssl, int level,
226                                         const char *file, int line, const char *text,
227                                         const unsigned char *buf, size_t bitlen)
228 {
229     char str[DEBUG_BUF_SIZE];
230     size_t i, len_bytes = PSA_BITS_TO_BYTES(bitlen), idx = 0;
231 
232     mbedtls_snprintf(str + idx, sizeof(str) - idx, "value of '%s' (%u bits) is:\n",
233                      text, (unsigned int) bitlen);
234 
235     debug_send_line(ssl, level, file, line, str);
236 
237     for (i = 0; i < len_bytes; i++) {
238         if (i >= 4096) {
239             break;
240         }
241 
242         if (i % 16 == 0) {
243             if (i > 0) {
244                 mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
245                 debug_send_line(ssl, level, file, line, str);
246 
247                 idx = 0;
248             }
249         }
250 
251         idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x",
252                                 (unsigned int) buf[i]);
253     }
254 
255     if (len_bytes > 0) {
256         mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
257         debug_send_line(ssl, level, file, line, str);
258     }
259 }
260 /* no-check-names will be removed in mbedtls#10229. */
261 #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY || MBEDTLS_PK_USE_PSA_RSA_DATA */ //no-check-names
262 
263 #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
mbedtls_debug_print_psa_ec(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * text,const mbedtls_pk_context * pk)264 static void mbedtls_debug_print_psa_ec(const mbedtls_ssl_context *ssl, int level,
265                                        const char *file, int line,
266                                        const char *text, const mbedtls_pk_context *pk)
267 {
268     char str[DEBUG_BUF_SIZE];
269     const uint8_t *coord_start;
270     size_t coord_len;
271 
272     if (NULL == ssl              ||
273         NULL == ssl->conf        ||
274         NULL == ssl->conf->f_dbg ||
275         level > debug_threshold) {
276         return;
277     }
278 
279     /* For the description of pk->pk_raw content please refer to the description
280      * psa_export_public_key() function. */
281     coord_len = (pk->pub_raw_len - 1)/2;
282 
283     /* X coordinate */
284     coord_start = pk->pub_raw + 1;
285     mbedtls_snprintf(str, sizeof(str), "%s(X)", text);
286     mbedtls_debug_print_integer(ssl, level, file, line, str, coord_start, coord_len * 8);
287 
288     /* Y coordinate */
289     coord_start = coord_start + coord_len;
290     mbedtls_snprintf(str, sizeof(str), "%s(Y)", text);
291     mbedtls_debug_print_integer(ssl, level, file, line, str, coord_start, coord_len * 8);
292 }
293 #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
294 
295 /* no-check-names will be removed in mbedtls#10229. */
296 #if defined(MBEDTLS_PK_USE_PSA_RSA_DATA) //no-check-names
debug_count_valid_bits(unsigned char ** buf,size_t len)297 static size_t debug_count_valid_bits(unsigned char **buf, size_t len)
298 {
299     size_t i, bits;
300 
301     /* Ignore initial null bytes (if any). */
302     while ((len > 0) && (**buf == 0x00)) {
303         (*buf)++;
304         len--;
305     }
306 
307     if (len == 0) {
308         return 0;
309     }
310 
311     bits = len * 8;
312 
313     /* Ignore initial null bits (if any). */
314     for (i = 7; i > 0; i--) {
315         if ((**buf & (0x1 << i)) != 0) {
316             break;
317         }
318         bits--;
319     }
320 
321     return bits;
322 }
323 
mbedtls_debug_print_psa_rsa(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * text,const mbedtls_pk_context * pk)324 static void mbedtls_debug_print_psa_rsa(const mbedtls_ssl_context *ssl, int level,
325                                         const char *file, int line,
326                                         const char *text, const mbedtls_pk_context *pk)
327 {
328     char str[DEBUG_BUF_SIZE];
329     /* no-check-names will be removed in mbedtls#10229. */
330     unsigned char key_der[MBEDTLS_PK_MAX_RSA_PUBKEY_RAW_LEN]; //no-check-names
331     unsigned char *start_cur;
332     unsigned char *end_cur;
333     size_t len, bits;
334     int ret;
335 
336     if (NULL == ssl              ||
337         NULL == ssl->conf        ||
338         NULL == ssl->conf->f_dbg ||
339         level > debug_threshold) {
340         return;
341     }
342 
343     if (pk->pub_raw_len > sizeof(key_der)) {
344         snprintf(str, sizeof(str),
345                  "RSA public key too large: %" MBEDTLS_PRINTF_SIZET " > %" MBEDTLS_PRINTF_SIZET,
346                  pk->pub_raw_len, sizeof(key_der));
347         debug_send_line(ssl, level, file, line, str);
348         return;
349     }
350 
351     memcpy(key_der, pk->pub_raw, pk->pub_raw_len);
352     start_cur = key_der;
353     end_cur = key_der + pk->pub_raw_len;
354 
355     /* This integer parsing solution should be replaced with mbedtls_asn1_get_integer().
356      * See #10238. */
357     ret = mbedtls_asn1_get_tag(&start_cur, end_cur, &len,
358                                MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED);
359     if (ret != 0) {
360         return;
361     }
362 
363     ret = mbedtls_asn1_get_tag(&start_cur, end_cur, &len, MBEDTLS_ASN1_INTEGER);
364     if (ret != 0) {
365         return;
366     }
367 
368     bits = debug_count_valid_bits(&start_cur, len);
369     if (bits == 0) {
370         return;
371     }
372     len = PSA_BITS_TO_BYTES(bits);
373 
374     mbedtls_snprintf(str, sizeof(str), "%s.N", text);
375     mbedtls_debug_print_integer(ssl, level, file, line, str, start_cur, bits);
376 
377     start_cur += len;
378 
379     ret = mbedtls_asn1_get_tag(&start_cur, end_cur, &len, MBEDTLS_ASN1_INTEGER);
380     if (ret != 0) {
381         return;
382     }
383 
384     bits = debug_count_valid_bits(&start_cur, len);
385     if (bits == 0) {
386         return;
387     }
388 
389     mbedtls_snprintf(str, sizeof(str), "%s.E", text);
390     mbedtls_debug_print_integer(ssl, level, file, line, str, start_cur, bits);
391 }
392 /* no-check-names will be removed in mbedtls#10229. */
393 #endif /* MBEDTLS_PK_USE_PSA_RSA_DATA */ //no-check-names
394 
debug_print_pk(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * text,const mbedtls_pk_context * pk)395 static void debug_print_pk(const mbedtls_ssl_context *ssl, int level,
396                            const char *file, int line,
397                            const char *text, const mbedtls_pk_context *pk)
398 {
399     size_t i;
400     mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
401     char name[16];
402 
403     memset(items, 0, sizeof(items));
404 
405     if (mbedtls_pk_debug(pk, items) != 0) {
406         debug_send_line(ssl, level, file, line,
407                         "invalid PK context\n");
408         return;
409     }
410 
411     for (i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++) {
412         if (items[i].type == MBEDTLS_PK_DEBUG_NONE) {
413             return;
414         }
415 
416         mbedtls_snprintf(name, sizeof(name), "%s%s", text, items[i].name);
417         name[sizeof(name) - 1] = '\0';
418 
419 #if defined(MBEDTLS_RSA_C)
420         if (items[i].type == MBEDTLS_PK_DEBUG_MPI) {
421             mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value);
422         } else
423 #endif /* MBEDTLS_RSA_C */
424 /* no-check-names will be removed in mbedtls#10229. */
425 #if defined(MBEDTLS_PK_USE_PSA_RSA_DATA) //no-check-names
426         if (items[i].type == MBEDTLS_PK_DEBUG_PSA_RSA) { //no-check-names
427             mbedtls_debug_print_psa_rsa(ssl, level, file, line, name, items[i].value);
428         } else
429 #endif /* MBEDTLS_PK_USE_PSA_RSA_DATA */ //no-check-names
430 #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
431         if (items[i].type == MBEDTLS_PK_DEBUG_PSA_EC) {
432             mbedtls_debug_print_psa_ec(ssl, level, file, line, name, items[i].value);
433         } else
434 #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
435         { debug_send_line(ssl, level, file, line,
436                           "should not happen\n"); }
437     }
438 }
439 
debug_print_line_by_line(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * text)440 static void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level,
441                                      const char *file, int line, const char *text)
442 {
443     char str[DEBUG_BUF_SIZE];
444     const char *start, *cur;
445 
446     start = text;
447     for (cur = text; *cur != '\0'; cur++) {
448         if (*cur == '\n') {
449             size_t len = (size_t) (cur - start) + 1;
450             if (len > DEBUG_BUF_SIZE - 1) {
451                 len = DEBUG_BUF_SIZE - 1;
452             }
453 
454             memcpy(str, start, len);
455             str[len] = '\0';
456 
457             debug_send_line(ssl, level, file, line, str);
458 
459             start = cur + 1;
460         }
461     }
462 }
463 
mbedtls_debug_print_crt(const mbedtls_ssl_context * ssl,int level,const char * file,int line,const char * text,const mbedtls_x509_crt * crt)464 void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,
465                              const char *file, int line,
466                              const char *text, const mbedtls_x509_crt *crt)
467 {
468     char str[DEBUG_BUF_SIZE];
469     int i = 0;
470 
471     if (NULL == ssl              ||
472         NULL == ssl->conf        ||
473         NULL == ssl->conf->f_dbg ||
474         NULL == crt              ||
475         level > debug_threshold) {
476         return;
477     }
478 
479     while (crt != NULL) {
480         char buf[1024];
481 
482         mbedtls_snprintf(str, sizeof(str), "%s #%d:\n", text, ++i);
483         debug_send_line(ssl, level, file, line, str);
484 
485         mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
486         debug_print_line_by_line(ssl, level, file, line, buf);
487 
488         debug_print_pk(ssl, level, file, line, "crt->", &crt->pk);
489 
490         crt = crt->next;
491     }
492 }
493 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */
494 
495 #endif /* MBEDTLS_DEBUG_C */
496