mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers debug.c Source File

debug.c

00001 /*
00002  *  Debugging routines
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 
00022 #if !defined(MBEDTLS_CONFIG_FILE)
00023 #include "mbedtls/config.h"
00024 #else
00025 #include MBEDTLS_CONFIG_FILE
00026 #endif
00027 
00028 #if defined(MBEDTLS_DEBUG_C)
00029 
00030 #include "mbedtls/debug.h"
00031 
00032 #include <stdarg.h>
00033 #include <stdio.h>
00034 #include <string.h>
00035 
00036 #if defined(MBEDTLS_PLATFORM_C)
00037 #include "mbedtls/platform.h"
00038 #else
00039 #include <stdlib.h>
00040 #define mbedtls_calloc      calloc
00041 #define mbedtls_free        free
00042 #define mbedtls_snprintf    snprintf
00043 #endif
00044 
00045 #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
00046     !defined(inline) && !defined(__cplusplus)
00047 #define inline __inline
00048 #endif
00049 
00050 #define DEBUG_BUF_SIZE      512
00051 
00052 static int debug_threshold = 0;
00053 
00054 void mbedtls_debug_set_threshold( int threshold )
00055 {
00056     debug_threshold = threshold;
00057 }
00058 
00059 /*
00060  * All calls to f_dbg must be made via this function
00061  */
00062 static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level,
00063                                     const char *file, int line,
00064                                     const char *str )
00065 {
00066     /*
00067      * If in a threaded environment, we need a thread identifier.
00068      * Since there is no portable way to get one, use the address of the ssl
00069      * context instead, as it shouldn't be shared between threads.
00070      */
00071 #if defined(MBEDTLS_THREADING_C)
00072     char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */
00073     mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", ssl, str );
00074     ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr );
00075 #else
00076     ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
00077 #endif
00078 }
00079 
00080 void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
00081                               const char *file, int line,
00082                               const char *format, ... )
00083 {
00084     va_list argp;
00085     char str[DEBUG_BUF_SIZE];
00086     int ret;
00087 
00088     if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
00089         return;
00090 
00091     va_start( argp, format );
00092 #if defined(_WIN32)
00093 #if defined(_TRUNCATE)
00094     ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp );
00095 #else
00096     ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
00097     if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE )
00098     {
00099         str[DEBUG_BUF_SIZE-1] = '\0';
00100         ret = -1;
00101     }
00102 #endif
00103 #else
00104     ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
00105 #endif
00106     va_end( argp );
00107 
00108     if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 )
00109     {
00110         str[ret]     = '\n';
00111         str[ret + 1] = '\0';
00112     }
00113 
00114     debug_send_line( ssl, level, file, line, str );
00115 }
00116 
00117 void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level,
00118                       const char *file, int line,
00119                       const char *text, int ret )
00120 {
00121     char str[DEBUG_BUF_SIZE];
00122 
00123     if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
00124         return;
00125 
00126     /*
00127      * With non-blocking I/O and examples that just retry immediately,
00128      * the logs would be quickly flooded with WANT_READ, so ignore that.
00129      * Don't ignore WANT_WRITE however, since is is usually rare.
00130      */
00131     if( ret == MBEDTLS_ERR_SSL_WANT_READ )
00132         return;
00133 
00134     mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n",
00135               text, ret, -ret );
00136 
00137     debug_send_line( ssl, level, file, line, str );
00138 }
00139 
00140 void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level,
00141                       const char *file, int line, const char *text,
00142                       const unsigned char *buf, size_t len )
00143 {
00144     char str[DEBUG_BUF_SIZE];
00145     char txt[17];
00146     size_t i, idx = 0;
00147 
00148     if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
00149         return;
00150 
00151     mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n",
00152               text, (unsigned int) len );
00153 
00154     debug_send_line( ssl, level, file, line, str );
00155 
00156     idx = 0;
00157     memset( txt, 0, sizeof( txt ) );
00158     for( i = 0; i < len; i++ )
00159     {
00160         if( i >= 4096 )
00161             break;
00162 
00163         if( i % 16 == 0 )
00164         {
00165             if( i > 0 )
00166             {
00167                 mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
00168                 debug_send_line( ssl, level, file, line, str );
00169 
00170                 idx = 0;
00171                 memset( txt, 0, sizeof( txt ) );
00172             }
00173 
00174             idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ",
00175                              (unsigned int) i );
00176 
00177         }
00178 
00179         idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x",
00180                          (unsigned int) buf[i] );
00181         txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ;
00182     }
00183 
00184     if( len > 0 )
00185     {
00186         for( /* i = i */; i % 16 != 0; i++ )
00187             idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "   " );
00188 
00189         mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
00190         debug_send_line( ssl, level, file, line, str );
00191     }
00192 }
00193 
00194 #if defined(MBEDTLS_ECP_C)
00195 void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level,
00196                       const char *file, int line,
00197                       const char *text, const mbedtls_ecp_point *X )
00198 {
00199     char str[DEBUG_BUF_SIZE];
00200 
00201     if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
00202         return;
00203 
00204     mbedtls_snprintf( str, sizeof( str ), "%s(X)", text );
00205     mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X  );
00206 
00207     mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text );
00208     mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y  );
00209 }
00210 #endif /* MBEDTLS_ECP_C */
00211 
00212 #if defined(MBEDTLS_BIGNUM_C)
00213 void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
00214                       const char *file, int line,
00215                       const char *text, const mbedtls_mpi *X )
00216 {
00217     char str[DEBUG_BUF_SIZE];
00218     int j, k, zeros = 1;
00219     size_t i, n, idx = 0;
00220 
00221     if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold )
00222         return;
00223 
00224     for( n = X->n  - 1; n > 0; n-- )
00225         if( X->p [n] != 0 )
00226             break;
00227 
00228     for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- )
00229         if( ( ( X->p [n] >> j ) & 1 ) != 0 )
00230             break;
00231 
00232     mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n",
00233               text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) );
00234 
00235     debug_send_line( ssl, level, file, line, str );
00236 
00237     idx = 0;
00238     for( i = n + 1, j = 0; i > 0; i-- )
00239     {
00240         if( zeros && X->p [i - 1] == 0 )
00241             continue;
00242 
00243         for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- )
00244         {
00245             if( zeros && ( ( X->p [i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
00246                 continue;
00247             else
00248                 zeros = 0;
00249 
00250             if( j % 16 == 0 )
00251             {
00252                 if( j > 0 )
00253                 {
00254                     mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
00255                     debug_send_line( ssl, level, file, line, str );
00256                     idx = 0;
00257                 }
00258             }
00259 
00260             idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int)
00261                              ( X->p [i - 1] >> ( k << 3 ) ) & 0xFF );
00262 
00263             j++;
00264         }
00265 
00266     }
00267 
00268     if( zeros == 1 )
00269         idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" );
00270 
00271     mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
00272     debug_send_line( ssl, level, file, line, str );
00273 }
00274 #endif /* MBEDTLS_BIGNUM_C */
00275 
00276 #if defined(MBEDTLS_X509_CRT_PARSE_C)
00277 static void debug_print_pk( const mbedtls_ssl_context *ssl, int level,
00278                             const char *file, int line,
00279                             const char *text, const mbedtls_pk_context *pk )
00280 {
00281     size_t i;
00282     mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
00283     char name[16];
00284 
00285     memset( items, 0, sizeof( items ) );
00286 
00287     if( mbedtls_pk_debug( pk, items ) != 0 )
00288     {
00289         debug_send_line( ssl, level, file, line,
00290                           "invalid PK context\n" );
00291         return;
00292     }
00293 
00294     for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ )
00295     {
00296         if( items[i].type == MBEDTLS_PK_DEBUG_NONE )
00297             return;
00298 
00299         mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name );
00300         name[sizeof( name ) - 1] = '\0';
00301 
00302         if( items[i].type == MBEDTLS_PK_DEBUG_MPI )
00303             mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value );
00304         else
00305 #if defined(MBEDTLS_ECP_C)
00306         if( items[i].type == MBEDTLS_PK_DEBUG_ECP )
00307             mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value );
00308         else
00309 #endif
00310             debug_send_line( ssl, level, file, line,
00311                               "should not happen\n" );
00312     }
00313 }
00314 
00315 static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level,
00316                                       const char *file, int line, const char *text )
00317 {
00318     char str[DEBUG_BUF_SIZE];
00319     const char *start, *cur;
00320 
00321     start = text;
00322     for( cur = text; *cur != '\0'; cur++ )
00323     {
00324         if( *cur == '\n' )
00325         {
00326             size_t len = cur - start + 1;
00327             if( len > DEBUG_BUF_SIZE - 1 )
00328                 len = DEBUG_BUF_SIZE - 1;
00329 
00330             memcpy( str, start, len );
00331             str[len] = '\0';
00332 
00333             debug_send_line( ssl, level, file, line, str );
00334 
00335             start = cur + 1;
00336         }
00337     }
00338 }
00339 
00340 void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
00341                       const char *file, int line,
00342                       const char *text, const mbedtls_x509_crt *crt )
00343 {
00344     char str[DEBUG_BUF_SIZE];
00345     int i = 0;
00346 
00347     if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold )
00348         return;
00349 
00350     while( crt != NULL )
00351     {
00352         char buf[1024];
00353 
00354         mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i );
00355         debug_send_line( ssl, level, file, line, str );
00356 
00357         mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
00358         debug_print_line_by_line( ssl, level, file, line, buf );
00359 
00360         debug_print_pk( ssl, level, file, line, "crt->", &crt->pk );
00361 
00362         crt = crt->next;
00363     }
00364 }
00365 #endif /* MBEDTLS_X509_CRT_PARSE_C */
00366 
00367 #endif /* MBEDTLS_DEBUG_C */