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