debug.c 10 KB
Newer Older
1 2 3
/*
 *  Debugging routines
 *
4
 *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
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.
 */

23
#if !defined(MBEDTLS_CONFIG_FILE)
24
#include "mbedtls/config.h"
25
#else
26
#include MBEDTLS_CONFIG_FILE
27
#endif
28

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

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

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
#if defined(_TRUNCATE)
69
    ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp );
70 71 72 73 74 75 76 77
#else
    ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
    if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE )
    {
        str[DEBUG_BUF_SIZE-1] = '\0';
        ret = -1;
    }
#endif
78
#else
79
    ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
80
#endif
81 82
    va_end( argp );

83 84 85 86 87
    if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 )
    {
        str[ret]     = '\n';
        str[ret + 1] = '\0';
    }
88

89
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
90 91
}

92
void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level,
93 94
                      const char *file, int line,
                      const char *text, int ret )
95
{
96
    char str[DEBUG_BUF_SIZE];
97

98
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
99 100
        return;

101 102 103 104 105 106 107 108
    /*
     * 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;

109
    mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n",
110
              text, ret, -ret );
111

112
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
113 114
}

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( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
124 125
        return;

126
    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n",
127
              text, (unsigned int) len );
128

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

131
    idx = 0;
132
    memset( txt, 0, sizeof( txt ) );
133 134 135 136 137 138 139 140
    for( i = 0; i < len; i++ )
    {
        if( i >= 4096 )
            break;

        if( i % 16 == 0 )
        {
            if( i > 0 )
141
            {
142
                mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
143
                ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
144

145
                idx = 0;
146
                memset( txt, 0, sizeof( txt ) );
147
            }
148

149
            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ",
150
                             (unsigned int) i );
151 152 153

        }

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

    if( len > 0 )
160
    {
161
        for( /* i = i */; i % 16 != 0; i++ )
162
            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "   " );
163

164
        mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
165
        ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
166
    }
167 168
}

169 170
#if defined(MBEDTLS_ECP_C)
void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level,
171
                      const char *file, int line,
172
                      const char *text, const mbedtls_ecp_point *X )
173
{
174
    char str[DEBUG_BUF_SIZE];
175

176
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
177 178
        return;

179
    mbedtls_snprintf( str, sizeof( str ), "%s(X)", text );
180
    mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X );
181

182
    mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text );
183
    mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y );
184
}
185
#endif /* MBEDTLS_ECP_C */
186

187 188
#if defined(MBEDTLS_BIGNUM_C)
void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
189
                      const char *file, int line,
190
                      const char *text, const mbedtls_mpi *X )
191
{
192
    char str[DEBUG_BUF_SIZE];
193
    int j, k, zeros = 1;
194
    size_t i, n, idx = 0;
195

196
    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold )
197 198
        return;

199
    for( n = X->n - 1; n > 0; n-- )
200 201 202
        if( X->p[n] != 0 )
            break;

203
    for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- )
204 205 206
        if( ( ( X->p[n] >> j ) & 1 ) != 0 )
            break;

207
    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n",
208
              text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) );
209

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

212
    idx = 0;
213
    for( i = n + 1, j = 0; i > 0; i-- )
214
    {
215
        if( zeros && X->p[i - 1] == 0 )
216 217
            continue;

218
        for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- )
219
        {
220
            if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
221 222 223
                continue;
            else
                zeros = 0;
224

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

235
            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int)
236
                             ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF );
237 238

            j++;
239
        }
240 241 242 243

    }

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

246
    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
247
    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
248
}
249
#endif /* MBEDTLS_BIGNUM_C */
250

251 252
#if defined(MBEDTLS_X509_CRT_PARSE_C)
static void debug_print_pk( const mbedtls_ssl_context *ssl, int level,
253
                            const char *file, int line,
254
                            const char *text, const mbedtls_pk_context *pk )
255 256
{
    size_t i;
257
    mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
258 259 260 261
    char name[16];

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

262
    if( mbedtls_pk_debug( pk, items ) != 0 )
263
    {
264 265
        ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line,
                          "invalid PK context\n" );
266 267 268
        return;
    }

269
    for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ )
270
    {
271
        if( items[i].type == MBEDTLS_PK_DEBUG_NONE )
272 273
            return;

274
        mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name );
275 276
        name[sizeof( name ) - 1] = '\0';

277 278
        if( items[i].type == MBEDTLS_PK_DEBUG_MPI )
            mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value );
279
        else
280 281 282
#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 );
283
        else
284
#endif
285 286
            ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line,
                              "should not happen\n" );
287 288 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
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;
        }
    }
}

315
void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
316
                      const char *file, int line,
317
                      const char *text, const mbedtls_x509_crt *crt )
318
{
319 320
    char str[DEBUG_BUF_SIZE];
    int i = 0;
321

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

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

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

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

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

        crt = crt->next;
    }
}
340
#endif /* MBEDTLS_X509_CRT_PARSE_C */
341

342
#endif /* MBEDTLS_DEBUG_C */