debug.c 10.1 KB
Newer Older
1 2 3
/*
 *  Debugging routines
 *
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
4
 *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakker's avatar
Paul Bakker committed
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker's avatar
Paul Bakker committed
7
 *
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
23
#if !defined(MBEDTLS_CONFIG_FILE)
24
#include "mbedtls/config.h"
25
#else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
26
#include MBEDTLS_CONFIG_FILE
27
#endif
28

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
29
#if defined(MBEDTLS_DEBUG_C)
30

31
#include "mbedtls/debug.h"
32 33

#include <stdarg.h>
34
#include <stdio.h>
35
#include <string.h>
36

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
37
#if defined(MBEDTLS_PLATFORM_C)
38
#include "mbedtls/platform.h"
39
#else
40 41 42 43
#include <stdlib.h>
#define mbedtls_calloc      calloc
#define mbedtls_free        free
#define mbedtls_snprintf    snprintf
44 45
#endif

46 47
#define DEBUG_BUF_SIZE      512

48
static int debug_threshold = 0;
49

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
50
void mbedtls_debug_set_threshold( int threshold )
51 52 53 54
{
    debug_threshold = threshold;
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
55
char *mbedtls_debug_fmt( const char *format, ... )
56 57
{
    va_list argp;
58 59 60 61
    char *str = mbedtls_calloc( DEBUG_BUF_SIZE, 1 );

    if( str == NULL )
        return( NULL );
62 63

    va_start( argp, format );
64
#if defined(_WIN32)
65
    _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp );
66
#else
67
    vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
68
#endif
69 70 71 72 73
    va_end( argp );

    return( str );
}

74 75 76 77 78 79 80 81 82
void mbedtls_debug_print_msg_free( const mbedtls_ssl_context *ssl, int level,
                      const char *file, int line, char *text )
{
    if( text != NULL )
        mbedtls_debug_print_msg( ssl, level, file, line, text );

    mbedtls_free( text );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
83
void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
84
                      const char *file, int line, const char *text )
85
{
86
    char str[DEBUG_BUF_SIZE];
87

88
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
89 90
        return;

91
    mbedtls_snprintf( str, sizeof( str ), "%s\n", text );
92

93
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
94 95
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
96
void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level,
97 98
                      const char *file, int line,
                      const char *text, int ret )
99
{
100
    char str[DEBUG_BUF_SIZE];
101

102
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
103 104
        return;

105 106 107 108 109 110 111 112
    /*
     * With non-blocking I/O and examples that just retry immediately,
     * the logs would be quickly flooded with WANT_READ, so ignore that.
     * Don't ignore WANT_WRITE however, since is is usually rare.
     */
    if( ret == MBEDTLS_ERR_SSL_WANT_READ )
        return;

113
    mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n",
114
              text, ret, -ret );
115

116
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
117 118
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
119
void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level,
120
                      const char *file, int line, const char *text,
121
                      const unsigned char *buf, size_t len )
122
{
123
    char str[DEBUG_BUF_SIZE];
124
    char txt[17];
125
    size_t i, idx = 0;
126

127
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
128 129
        return;

130
    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n",
131
              text, (unsigned int) len );
132

133
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
134

135
    idx = 0;
136
    memset( txt, 0, sizeof( txt ) );
137 138 139 140 141 142 143 144
    for( i = 0; i < len; i++ )
    {
        if( i >= 4096 )
            break;

        if( i % 16 == 0 )
        {
            if( i > 0 )
145
            {
146
                mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
147
                ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
148

149
                idx = 0;
150
                memset( txt, 0, sizeof( txt ) );
151
            }
152

153
            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ",
154
                             (unsigned int) i );
155 156 157

        }

158
        idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x",
159
                         (unsigned int) buf[i] );
160
        txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ;
161 162 163
    }

    if( len > 0 )
164
    {
165
        for( /* i = i */; i % 16 != 0; i++ )
166
            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "   " );
167

168
        mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
169
        ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
170
    }
171 172
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
173 174
#if defined(MBEDTLS_ECP_C)
void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level,
175
                      const char *file, int line,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
176
                      const char *text, const mbedtls_ecp_point *X )
177
{
178
    char str[DEBUG_BUF_SIZE];
179

180
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
181 182
        return;

183
    mbedtls_snprintf( str, sizeof( str ), "%s(X)", text );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
184
    mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X );
185

186
    mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
187
    mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y );
188
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
189
#endif /* MBEDTLS_ECP_C */
190

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
191 192
#if defined(MBEDTLS_BIGNUM_C)
void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
193
                      const char *file, int line,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
194
                      const char *text, const mbedtls_mpi *X )
195
{
196
    char str[DEBUG_BUF_SIZE];
197
    int j, k, zeros = 1;
198
    size_t i, n, idx = 0;
199

200
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold )
201 202
        return;

203
    for( n = X->n - 1; n > 0; n-- )
204 205 206
        if( X->p[n] != 0 )
            break;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
207
    for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- )
208 209 210
        if( ( ( X->p[n] >> j ) & 1 ) != 0 )
            break;

211
    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n",
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
212
              text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) );
213

214
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
215

216
    idx = 0;
217
    for( i = n + 1, j = 0; i > 0; i-- )
218
    {
219
        if( zeros && X->p[i - 1] == 0 )
220 221
            continue;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
222
        for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- )
223
        {
224
            if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
225 226 227
                continue;
            else
                zeros = 0;
228

229 230 231
            if( j % 16 == 0 )
            {
                if( j > 0 )
232
                {
233
                    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
234
                    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
235
                    idx = 0;
236
                }
237
            }
238

239
            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int)
240
                             ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF );
241 242

            j++;
243
        }
244 245 246 247

    }

    if( zeros == 1 )
248
        idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" );
249

250
    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
251
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
252
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
253
#endif /* MBEDTLS_BIGNUM_C */
254

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
255 256
#if defined(MBEDTLS_X509_CRT_PARSE_C)
static void debug_print_pk( const mbedtls_ssl_context *ssl, int level,
257
                            const char *file, int line,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
258
                            const char *text, const mbedtls_pk_context *pk )
259 260
{
    size_t i;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
261
    mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
262 263 264 265
    char name[16];

    memset( items, 0, sizeof( items ) );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
266
    if( mbedtls_pk_debug( pk, items ) != 0 )
267
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
268
        mbedtls_debug_print_msg( ssl, level, file, line, "invalid PK context" );
269 270 271
        return;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
272
    for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ )
273
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
274
        if( items[i].type == MBEDTLS_PK_DEBUG_NONE )
275 276
            return;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
277
        mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name );
278 279
        name[sizeof( name ) - 1] = '\0';

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
280 281
        if( items[i].type == MBEDTLS_PK_DEBUG_MPI )
            mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
282
        else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
283 284 285
#if defined(MBEDTLS_ECP_C)
        if( items[i].type == MBEDTLS_PK_DEBUG_ECP )
            mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value );
286
        else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
287
#endif
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
288
            mbedtls_debug_print_msg( ssl, level, file, line, "should not happen" );
289 290 291
    }
}

292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level,
                                      const char *file, int line, const char *text )
{
    char str[DEBUG_BUF_SIZE];
    const char *start, *cur;

    start = text;
    for( cur = text; *cur != '\0'; cur++ )
    {
        if( *cur == '\n' )
        {
            size_t len = cur - start + 1;
            if( len > DEBUG_BUF_SIZE - 1 )
                len = DEBUG_BUF_SIZE - 1;

            memcpy( str, start, len );
            str[len] = '\0';

            ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );

            start = cur + 1;
        }
    }
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
317
void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
318
                      const char *file, int line,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
319
                      const char *text, const mbedtls_x509_crt *crt )
320
{
321 322
    char str[DEBUG_BUF_SIZE];
    int i = 0;
323

324
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold )
325 326
        return;

Paul Bakker's avatar
Paul Bakker committed
327
    while( crt != NULL )
328
    {
329
        char buf[1024];
330

331 332
        mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i );
        ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
333

334 335
        mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
        debug_print_line_by_line( ssl, level, file, line, buf );
336

337
        debug_print_pk( ssl, level, file, line, "crt->", &crt->pk );
338 339 340 341

        crt = crt->next;
    }
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
342
#endif /* MBEDTLS_X509_CRT_PARSE_C */
343

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
344
#endif /* MBEDTLS_DEBUG_C */