debug.c 9.82 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;
}

55
void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
56 57
                              const char *file, int line,
                              const char *format, ... )
58 59
{
    va_list argp;
60 61
    char str[DEBUG_BUF_SIZE];
    int ret;
62

63 64
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
        return;
65 66

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

74 75 76 77 78
    if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 )
    {
        str[ret]     = '\n';
        str[ret + 1] = '\0';
    }
79

80
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
81 82
}

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

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

92 93 94 95 96 97 98 99
    /*
     * 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;

100
    mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n",
101
              text, ret, -ret );
102

103
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
104 105
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
106
void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level,
107
                      const char *file, int line, const char *text,
108
                      const unsigned char *buf, size_t len )
109
{
110
    char str[DEBUG_BUF_SIZE];
111
    char txt[17];
112
    size_t i, idx = 0;
113

114
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
115 116
        return;

117
    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n",
118
              text, (unsigned int) len );
119

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

122
    idx = 0;
123
    memset( txt, 0, sizeof( txt ) );
124 125 126 127 128 129 130 131
    for( i = 0; i < len; i++ )
    {
        if( i >= 4096 )
            break;

        if( i % 16 == 0 )
        {
            if( i > 0 )
132
            {
133
                mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
134
                ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
135

136
                idx = 0;
137
                memset( txt, 0, sizeof( txt ) );
138
            }
139

140
            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ",
141
                             (unsigned int) i );
142 143 144

        }

145
        idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x",
146
                         (unsigned int) buf[i] );
147
        txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ;
148 149 150
    }

    if( len > 0 )
151
    {
152
        for( /* i = i */; i % 16 != 0; i++ )
153
            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "   " );
154

155
        mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
156
        ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
157
    }
158 159
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
160 161
#if defined(MBEDTLS_ECP_C)
void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level,
162
                      const char *file, int line,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
163
                      const char *text, const mbedtls_ecp_point *X )
164
{
165
    char str[DEBUG_BUF_SIZE];
166

167
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
168 169
        return;

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

173
    mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
174
    mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y );
175
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
176
#endif /* MBEDTLS_ECP_C */
177

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
178 179
#if defined(MBEDTLS_BIGNUM_C)
void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
180
                      const char *file, int line,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
181
                      const char *text, const mbedtls_mpi *X )
182
{
183
    char str[DEBUG_BUF_SIZE];
184
    int j, k, zeros = 1;
185
    size_t i, n, idx = 0;
186

187
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold )
188 189
        return;

190
    for( n = X->n - 1; n > 0; n-- )
191 192 193
        if( X->p[n] != 0 )
            break;

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

198
    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
199
              text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) );
200

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

203
    idx = 0;
204
    for( i = n + 1, j = 0; i > 0; i-- )
205
    {
206
        if( zeros && X->p[i - 1] == 0 )
207 208
            continue;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
209
        for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- )
210
        {
211
            if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
212 213 214
                continue;
            else
                zeros = 0;
215

216 217 218
            if( j % 16 == 0 )
            {
                if( j > 0 )
219
                {
220
                    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
221
                    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
222
                    idx = 0;
223
                }
224
            }
225

226
            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int)
227
                             ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF );
228 229

            j++;
230
        }
231 232 233 234

    }

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

237
    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
238
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
239
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
240
#endif /* MBEDTLS_BIGNUM_C */
241

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
242 243
#if defined(MBEDTLS_X509_CRT_PARSE_C)
static void debug_print_pk( const mbedtls_ssl_context *ssl, int level,
244
                            const char *file, int line,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
245
                            const char *text, const mbedtls_pk_context *pk )
246 247
{
    size_t i;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
248
    mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
249 250 251 252
    char name[16];

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

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
253
    if( mbedtls_pk_debug( pk, items ) != 0 )
254
    {
255 256
        ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line,
                          "invalid PK context\n" );
257 258 259
        return;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
260
    for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ )
261
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
262
        if( items[i].type == MBEDTLS_PK_DEBUG_NONE )
263 264
            return;

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

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
268 269
        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
270
        else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
271 272 273
#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 );
274
        else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
275
#endif
276 277
            ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line,
                              "should not happen\n" );
278 279 280
    }
}

281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
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
306
void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
307
                      const char *file, int line,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
308
                      const char *text, const mbedtls_x509_crt *crt )
309
{
310 311
    char str[DEBUG_BUF_SIZE];
    int i = 0;
312

313
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold )
314 315
        return;

Paul Bakker's avatar
Paul Bakker committed
316
    while( crt != NULL )
317
    {
318
        char buf[1024];
319

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

323 324
        mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
        debug_print_line_by_line( ssl, level, file, line, buf );
325

326
        debug_print_pk( ssl, level, file, line, "crt->", &crt->pk );
327 328 329 330

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

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