xref: /reactos/dll/3rdparty/mbedtls/debug.c (revision 94a413ae)
1 /*
2  *  Debugging routines
3  *
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  *
7  *  This file is provided under the Apache License 2.0, or the
8  *  GNU General Public License v2.0 or later.
9  *
10  *  **********
11  *  Apache License 2.0:
12  *
13  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
14  *  not use this file except in compliance with the License.
15  *  You may obtain a copy of the License at
16  *
17  *  http://www.apache.org/licenses/LICENSE-2.0
18  *
19  *  Unless required by applicable law or agreed to in writing, software
20  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the License for the specific language governing permissions and
23  *  limitations under the License.
24  *
25  *  **********
26  *
27  *  **********
28  *  GNU General Public License v2.0 or later:
29  *
30  *  This program is free software; you can redistribute it and/or modify
31  *  it under the terms of the GNU General Public License as published by
32  *  the Free Software Foundation; either version 2 of the License, or
33  *  (at your option) any later version.
34  *
35  *  This program is distributed in the hope that it will be useful,
36  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
37  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  *  GNU General Public License for more details.
39  *
40  *  You should have received a copy of the GNU General Public License along
41  *  with this program; if not, write to the Free Software Foundation, Inc.,
42  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43  *
44  *  **********
45  *
46  *  This file is part of mbed TLS (https://tls.mbed.org)
47  */
48 
49 #if !defined(MBEDTLS_CONFIG_FILE)
50 #include "mbedtls/config.h"
51 #else
52 #include MBEDTLS_CONFIG_FILE
53 #endif
54 
55 #if defined(MBEDTLS_DEBUG_C)
56 
57 #if defined(MBEDTLS_PLATFORM_C)
58 #include "mbedtls/platform.h"
59 #else
60 #include <stdlib.h>
61 #define mbedtls_calloc      calloc
62 #define mbedtls_free        free
63 #define mbedtls_time_t      time_t
64 #define mbedtls_snprintf    snprintf
65 #endif
66 
67 #include "mbedtls/debug.h"
68 
69 #include <stdarg.h>
70 #include <stdio.h>
71 #include <string.h>
72 
73 #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
74     !defined(inline) && !defined(__cplusplus)
75 #define inline __inline
76 #endif
77 
78 #define DEBUG_BUF_SIZE      512
79 
80 static int debug_threshold = 0;
81 
82 void mbedtls_debug_set_threshold( int threshold )
83 {
84     debug_threshold = threshold;
85 }
86 
87 /*
88  * All calls to f_dbg must be made via this function
89  */
90 static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level,
91                                     const char *file, int line,
92                                     const char *str )
93 {
94     /*
95      * If in a threaded environment, we need a thread identifier.
96      * Since there is no portable way to get one, use the address of the ssl
97      * context instead, as it shouldn't be shared between threads.
98      */
99 #if defined(MBEDTLS_THREADING_C)
100     char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */
101     mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str );
102     ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr );
103 #else
104     ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
105 #endif
106 }
107 
108 void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
109                               const char *file, int line,
110                               const char *format, ... )
111 {
112     va_list argp;
113     char str[DEBUG_BUF_SIZE];
114     int ret;
115 
116     if( NULL == ssl              ||
117         NULL == ssl->conf        ||
118         NULL == ssl->conf->f_dbg ||
119         level > debug_threshold )
120     {
121         return;
122     }
123 
124     va_start( argp, format );
125 #if defined(_WIN32)
126 #if defined(_TRUNCATE) && !defined(__MINGW32__)
127     ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp );
128 #else
129     ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
130     if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE )
131     {
132         str[DEBUG_BUF_SIZE-1] = '\0';
133         ret = -1;
134     }
135 #endif
136 #else
137     ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
138 #endif
139     va_end( argp );
140 
141     if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 )
142     {
143         str[ret]     = '\n';
144         str[ret + 1] = '\0';
145     }
146 
147     debug_send_line( ssl, level, file, line, str );
148 }
149 
150 void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level,
151                       const char *file, int line,
152                       const char *text, int ret )
153 {
154     char str[DEBUG_BUF_SIZE];
155 
156     if( NULL == ssl              ||
157         NULL == ssl->conf        ||
158         NULL == ssl->conf->f_dbg ||
159         level > debug_threshold )
160     {
161         return;
162     }
163 
164     /*
165      * With non-blocking I/O and examples that just retry immediately,
166      * the logs would be quickly flooded with WANT_READ, so ignore that.
167      * Don't ignore WANT_WRITE however, since is is usually rare.
168      */
169     if( ret == MBEDTLS_ERR_SSL_WANT_READ )
170         return;
171 
172     mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n",
173               text, ret, -ret );
174 
175     debug_send_line( ssl, level, file, line, str );
176 }
177 
178 void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level,
179                       const char *file, int line, const char *text,
180                       const unsigned char *buf, size_t len )
181 {
182     char str[DEBUG_BUF_SIZE];
183     char txt[17];
184     size_t i, idx = 0;
185 
186     if( NULL == ssl              ||
187         NULL == ssl->conf        ||
188         NULL == ssl->conf->f_dbg ||
189         level > debug_threshold )
190     {
191         return;
192     }
193 
194     mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n",
195               text, (unsigned int) len );
196 
197     debug_send_line( ssl, level, file, line, str );
198 
199     idx = 0;
200     memset( txt, 0, sizeof( txt ) );
201     for( i = 0; i < len; i++ )
202     {
203         if( i >= 4096 )
204             break;
205 
206         if( i % 16 == 0 )
207         {
208             if( i > 0 )
209             {
210                 mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
211                 debug_send_line( ssl, level, file, line, str );
212 
213                 idx = 0;
214                 memset( txt, 0, sizeof( txt ) );
215             }
216 
217             idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ",
218                              (unsigned int) i );
219 
220         }
221 
222         idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x",
223                          (unsigned int) buf[i] );
224         txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ;
225     }
226 
227     if( len > 0 )
228     {
229         for( /* i = i */; i % 16 != 0; i++ )
230             idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "   " );
231 
232         mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
233         debug_send_line( ssl, level, file, line, str );
234     }
235 }
236 
237 #if defined(MBEDTLS_ECP_C)
238 void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level,
239                       const char *file, int line,
240                       const char *text, const mbedtls_ecp_point *X )
241 {
242     char str[DEBUG_BUF_SIZE];
243 
244     if( NULL == ssl              ||
245         NULL == ssl->conf        ||
246         NULL == ssl->conf->f_dbg ||
247         level > debug_threshold )
248     {
249         return;
250     }
251 
252     mbedtls_snprintf( str, sizeof( str ), "%s(X)", text );
253     mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X );
254 
255     mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text );
256     mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y );
257 }
258 #endif /* MBEDTLS_ECP_C */
259 
260 #if defined(MBEDTLS_BIGNUM_C)
261 void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
262                       const char *file, int line,
263                       const char *text, const mbedtls_mpi *X )
264 {
265     char str[DEBUG_BUF_SIZE];
266     int j, k, zeros = 1;
267     size_t i, n, idx = 0;
268 
269     if( NULL == ssl              ||
270         NULL == ssl->conf        ||
271         NULL == ssl->conf->f_dbg ||
272         NULL == X                ||
273         level > debug_threshold )
274     {
275         return;
276     }
277 
278     for( n = X->n - 1; n > 0; n-- )
279         if( X->p[n] != 0 )
280             break;
281 
282     for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- )
283         if( ( ( X->p[n] >> j ) & 1 ) != 0 )
284             break;
285 
286     mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n",
287               text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) );
288 
289     debug_send_line( ssl, level, file, line, str );
290 
291     idx = 0;
292     for( i = n + 1, j = 0; i > 0; i-- )
293     {
294         if( zeros && X->p[i - 1] == 0 )
295             continue;
296 
297         for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- )
298         {
299             if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
300                 continue;
301             else
302                 zeros = 0;
303 
304             if( j % 16 == 0 )
305             {
306                 if( j > 0 )
307                 {
308                     mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
309                     debug_send_line( ssl, level, file, line, str );
310                     idx = 0;
311                 }
312             }
313 
314             idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int)
315                              ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF );
316 
317             j++;
318         }
319 
320     }
321 
322     if( zeros == 1 )
323         idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" );
324 
325     mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
326     debug_send_line( ssl, level, file, line, str );
327 }
328 #endif /* MBEDTLS_BIGNUM_C */
329 
330 #if defined(MBEDTLS_X509_CRT_PARSE_C)
331 static void debug_print_pk( const mbedtls_ssl_context *ssl, int level,
332                             const char *file, int line,
333                             const char *text, const mbedtls_pk_context *pk )
334 {
335     size_t i;
336     mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
337     char name[16];
338 
339     memset( items, 0, sizeof( items ) );
340 
341     if( mbedtls_pk_debug( pk, items ) != 0 )
342     {
343         debug_send_line( ssl, level, file, line,
344                           "invalid PK context\n" );
345         return;
346     }
347 
348     for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ )
349     {
350         if( items[i].type == MBEDTLS_PK_DEBUG_NONE )
351             return;
352 
353         mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name );
354         name[sizeof( name ) - 1] = '\0';
355 
356         if( items[i].type == MBEDTLS_PK_DEBUG_MPI )
357             mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value );
358         else
359 #if defined(MBEDTLS_ECP_C)
360         if( items[i].type == MBEDTLS_PK_DEBUG_ECP )
361             mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value );
362         else
363 #endif
364             debug_send_line( ssl, level, file, line,
365                               "should not happen\n" );
366     }
367 }
368 
369 static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level,
370                                       const char *file, int line, const char *text )
371 {
372     char str[DEBUG_BUF_SIZE];
373     const char *start, *cur;
374 
375     start = text;
376     for( cur = text; *cur != '\0'; cur++ )
377     {
378         if( *cur == '\n' )
379         {
380             size_t len = cur - start + 1;
381             if( len > DEBUG_BUF_SIZE - 1 )
382                 len = DEBUG_BUF_SIZE - 1;
383 
384             memcpy( str, start, len );
385             str[len] = '\0';
386 
387             debug_send_line( ssl, level, file, line, str );
388 
389             start = cur + 1;
390         }
391     }
392 }
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 {
398     char str[DEBUG_BUF_SIZE];
399     int i = 0;
400 
401     if( NULL == ssl              ||
402         NULL == ssl->conf        ||
403         NULL == ssl->conf->f_dbg ||
404         NULL == crt              ||
405         level > debug_threshold )
406     {
407         return;
408     }
409 
410     while( crt != NULL )
411     {
412         char buf[1024];
413 
414         mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i );
415         debug_send_line( ssl, level, file, line, str );
416 
417         mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
418         debug_print_line_by_line( ssl, level, file, line, buf );
419 
420         debug_print_pk( ssl, level, file, line, "crt->", &crt->pk );
421 
422         crt = crt->next;
423     }
424 }
425 #endif /* MBEDTLS_X509_CRT_PARSE_C */
426 
427 #endif /* MBEDTLS_DEBUG_C */
428