blob: cc889d46c09971292580eee2720a6936237362f1 [file] [log] [blame]
Piotr Nowicki9370f902020-03-13 14:43:22 +01001/*
2 * MbedTLS SSL context deserializer from base64 code
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Piotr Nowicki9370f902020-03-13 14:43:22 +01005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Piotr Nowicki9370f902020-03-13 14:43:22 +010018 */
19
Mateusz Starzyk6c2e9b62021-05-19 17:54:54 +020020#define MBEDTLS_ALLOW_PRIVATE_ACCESS
21
Bence Szépkútic662b362021-05-27 11:25:03 +020022#include "mbedtls/build_info.h"
Paul Elliottef9ccca2021-12-09 14:48:47 +000023#include "mbedtls/debug.h"
Piotr Nowickif86192f2020-03-26 11:45:42 +010024
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010025#include <stdio.h>
26#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020027
Gilles Peskinef4a6a052020-11-09 14:55:35 +010028#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
29 !defined(MBEDTLS_SSL_TLS_C)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020030int main( void )
31{
Gilles Peskinef4a6a052020-11-09 14:55:35 +010032 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
33 "MBEDTLS_SSL_TLS_C not defined.\n");
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020034 return( 0 );
35}
36#else
37
38#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
39#define _CRT_SECURE_NO_DEPRECATE 1
40#endif
41
Piotr Nowicki14d31052020-03-16 14:05:22 +010042#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010043#include <stdarg.h>
44#include <string.h>
Raoul Strackx9ed9bc92020-06-22 14:08:57 +020045#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010046#include <time.h>
Raoul Strackx9ed9bc92020-06-22 14:08:57 +020047#endif
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010048#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010049#include "mbedtls/error.h"
50#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010051#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010052#include "mbedtls/x509_crt.h"
53#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010054
55/*
56 * This program version
57 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010058#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010059#define VER_MAJOR 0
60#define VER_MINOR 1
61
62/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020063 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010064 */
65#define SESSION_CONFIG_TIME_BIT ( 1 << 0 )
66#define SESSION_CONFIG_CRT_BIT ( 1 << 1 )
67#define SESSION_CONFIG_CLIENT_TICKET_BIT ( 1 << 2 )
68#define SESSION_CONFIG_MFL_BIT ( 1 << 3 )
69#define SESSION_CONFIG_TRUNC_HMAC_BIT ( 1 << 4 )
70#define SESSION_CONFIG_ETM_BIT ( 1 << 5 )
71#define SESSION_CONFIG_TICKET_BIT ( 1 << 6 )
72
73#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ( 1 << 0 )
74#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ( 1 << 1 )
75#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ( 1 << 2 )
76#define CONTEXT_CONFIG_ALPN_BIT ( 1 << 3 )
77
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010078#define TRANSFORM_RANDBYTE_LEN 64
79
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010080/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020081 * Minimum and maximum number of bytes for specific data: context, sessions,
82 * certificates, tickets and buffers in the program. The context and session
83 * size values have been calculated based on the 'print_deserialized_ssl_context()'
84 * and 'print_deserialized_ssl_session()' content.
85 */
86#define MIN_CONTEXT_LEN 84
87#define MIN_SESSION_LEN 88
88
89#define MAX_CONTEXT_LEN 875 /* without session data */
90#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
91#define MAX_CERTIFICATE_LEN ( ( 1 << 24 ) - 1 )
92#define MAX_TICKET_LEN ( ( 1 << 24 ) - 1 )
93
94#define MIN_SERIALIZED_DATA ( MIN_CONTEXT_LEN + MIN_SESSION_LEN )
95#define MAX_SERIALIZED_DATA ( MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
96 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN )
97
98#define MIN_BASE64_LEN ( MIN_SERIALIZED_DATA * 4 / 3 )
99#define MAX_BASE64_LEN ( MAX_SERIALIZED_DATA * 4 / 3 + 3 )
100
101/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100102 * A macro that prevents from reading out of the ssl buffer range.
103 */
104#define CHECK_SSL_END( LEN ) \
105do \
106{ \
107 if( end - ssl < (int)( LEN ) ) \
108 { \
109 printf_err( "%s", buf_ln_err ); \
110 return; \
111 } \
112} while( 0 )
113
114/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100115 * Global values
116 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100117FILE *b64_file = NULL; /* file with base64 codes to deserialize */
118char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
119char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
120char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200121const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100122const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100123
124/*
125 * Basic printing functions
126 */
127void print_version( )
128{
129 printf( "%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR );
130}
131
132void print_usage( )
133{
134 print_version();
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200135 printf( "\nThis program is used to deserialize an Mbed TLS SSL session from the base64 code provided\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100136 "in the text file. The program can deserialize many codes from one file, but they must be\n"
137 "separated, e.g. by a newline.\n\n" );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100138 printf(
139 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100140 "\t-f path - Path to the file with base64 code\n"
141 "\t-v - Show version\n"
142 "\t-h - Show this usage\n"
143 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200144 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100145 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
146 "\t flag. You can also use it if there are some problems with reading\n"
147 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200148 "\t--dtls-protocol=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100149 "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100150 "\n"
151 );
152}
153
154void printf_dbg( const char *str, ... )
155{
156 if( debug )
157 {
158 va_list args;
159 va_start( args, str );
160 printf( "debug: " );
161 vprintf( str, args );
162 fflush( stdout );
163 va_end( args );
164 }
165}
166
Paul Elliottef9ccca2021-12-09 14:48:47 +0000167MBEDTLS_PRINTF_ATTRIBUTE( 1, 2 )
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100168void printf_err( const char *str, ... )
169{
170 va_list args;
171 va_start( args, str );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100172 fflush( stdout );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100173 fprintf( stderr, "ERROR: " );
174 vfprintf( stderr, str, args );
175 fflush( stderr );
176 va_end( args );
177}
178
179/*
180 * Exit from the program in case of error
181 */
182void error_exit()
183{
184 if( NULL != b64_file )
185 {
186 fclose( b64_file );
187 }
188 exit( -1 );
189}
190
191/*
192 * This function takes the input arguments of this program
193 */
194void parse_arguments( int argc, char *argv[] )
195{
196 int i = 1;
197
198 if( argc < 2 )
199 {
200 print_usage();
201 error_exit();
202 }
203
204 while( i < argc )
205 {
206 if( strcmp( argv[i], "-d" ) == 0 )
207 {
208 debug = 1;
209 }
210 else if( strcmp( argv[i], "-h" ) == 0 )
211 {
212 print_usage();
213 }
214 else if( strcmp( argv[i], "-v" ) == 0 )
215 {
216 print_version();
217 }
218 else if( strcmp( argv[i], "-f" ) == 0 )
219 {
220 if( ++i >= argc )
221 {
222 printf_err( "File path is empty\n" );
223 error_exit();
224 }
225
Paul Elliott3820c152021-12-09 12:48:51 +0000226 if( NULL != b64_file )
227 {
228 printf_err( "Cannot specify more than one file with -f\n" );
229 error_exit( );
230 }
231
232 if( ( b64_file = fopen( argv[i], "r" )) == NULL )
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100233 {
234 printf_err( "Cannot find file \"%s\"\n", argv[i] );
235 error_exit();
236 }
237 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100238 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
239 {
240 conf_keep_peer_certificate = 0;
241 }
242 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
243 {
244 conf_dtls_proto = 0;
245 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100246 else
247 {
248 print_usage();
249 error_exit();
250 }
251
252 i++;
253 }
254}
255
Piotr Nowicki14d31052020-03-16 14:05:22 +0100256/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100257 * This function prints base64 code to the stdout
258 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100259void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100260{
261 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100262 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100263 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100264 while( b < end )
265 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100266 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100267 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100268 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100269 i = 0;
270 }
271 printf( "%c", *b++ );
272 }
273 printf( "\n" );
274 fflush( stdout );
275}
276
277/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100278 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100279 *
280 * /p b buffer with data to print
281 * /p len number of bytes to print
282 * /p in_line number of bytes in one line
283 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100284 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100285void print_hex( const uint8_t *b, size_t len,
286 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100287{
288 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100289 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100290
291 if( prefix == NULL )
292 {
293 prefix = "";
294 }
295
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100296 while( b < end )
297 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100298 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100299 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100300 printf( "\n%s", prefix );
301 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100302 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100303 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100304 }
305 printf("\n");
306 fflush(stdout);
307}
308
309/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100310 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
311 */
Raoul Strackx9ed9bc92020-06-22 14:08:57 +0200312#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100313void print_time( const time_t *time )
314{
315 char buf[20];
316 struct tm *t = gmtime( time );
317 static const char format[] = "%Y-%m-%d %H:%M:%S";
318 if( NULL != t )
319 {
320 strftime( buf, sizeof( buf ), format, t );
321 printf( "%s\n", buf );
322 }
323 else
324 {
325 printf( "unknown\n" );
326 }
327}
Raoul Strackx9ed9bc92020-06-22 14:08:57 +0200328#endif
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100329
330/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100331 * Print the input string if the bit is set in the value
332 */
333void print_if_bit( const char *str, int bit, int val )
334{
335 if( bit & val )
336 {
337 printf( "\t%s\n", str );
338 }
339}
340
341/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100342 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
343 */
344const char * get_enabled_str( int is_en )
345{
346 return ( is_en ) ? "enabled" : "disabled";
347}
348
349/*
350 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
351 */
352const char * get_mfl_str( int mfl_code )
353{
354 switch( mfl_code )
355 {
356 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
357 return "none";
358 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
359 return "512";
360 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
361 return "1024";
362 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
363 return "2048";
364 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
365 return "4096";
366 default:
367 return "error";
368 }
369}
370
371/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100372 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
373 * previously. After each call to this function, the internal file position
374 * indicator of the global b64_file is advanced.
375 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200376 * Note - This function checks the size of the input buffer and if necessary,
377 * increases it to the maximum MAX_BASE64_LEN
378 *
379 * /p b64 pointer to the pointer of the buffer for input data
380 * /p max_len pointer to the current buffer capacity. It can be changed if
381 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100382 *
383 * \retval number of bytes written in to the b64 buffer or 0 in case no more
384 * data was found
385 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200386size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100387{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200388 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100389 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100390 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000391 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100392
393 while( EOF != c )
394 {
395 char c_valid = 0;
396
Nayna Jaind696e7d2020-08-13 19:17:53 +0000397 c = fgetc( b64_file );
Piotr Nowicki14d31052020-03-16 14:05:22 +0100398
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200399 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100400 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200401 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100402 {
403 c_valid = 1;
404 pad = 2;
405 }
406 }
407 else if( ( c >= 'A' && c <= 'Z' ) ||
408 ( c >= 'a' && c <= 'z' ) ||
409 ( c >= '0' && c <= '9' ) ||
410 c == '+' || c == '/' )
411 {
412 c_valid = 1;
413 }
414 else if( c == '=' )
415 {
416 c_valid = 1;
417 pad = 1;
418 }
419 else if( c == '-' )
420 {
421 c = '+';
422 c_valid = 1;
423 }
424 else if( c == '_' )
425 {
426 c = '/';
427 c_valid = 1;
428 }
429
430 if( c_valid )
431 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200432 /* A string of characters that could be a base64 code. */
433 valid_balance++;
434
435 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100436 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200437 ( *b64 )[ len++ ] = c;
438 }
439 else if( *max_len < MAX_BASE64_LEN )
440 {
441 /* Current buffer is too small, but can be resized. */
442 void *ptr;
443 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
444 *max_len + 4096 : MAX_BASE64_LEN;
445
446 ptr = realloc( *b64, new_size );
447 if( NULL == ptr )
448 {
449 printf_err( alloc_err );
450 return 0;
451 }
452 *b64 = ptr;
453 *max_len = new_size;
454 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100455 }
456 else
457 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200458 /* Too much data so it will be treated as invalid */
459 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100460 }
461 }
462 else if( len > 0 )
463 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200464 /* End of a string that could be a base64 code, but need to check
465 * that the length of the characters is correct. */
466
467 valid_balance--;
468
469 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100470 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200471 printf_dbg( "The code found is too small to be a SSL context.\n" );
472 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100473 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200474 else if( len > *max_len )
475 {
Paul Elliottef9ccca2021-12-09 14:48:47 +0000476 printf_err( "The code found is too large by %" MBEDTLS_PRINTF_SIZET " bytes.\n",
477 len - *max_len );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200478 len = pad = 0;
479 }
480 else if( len % 4 != 0 )
481 {
482 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
483 len = pad = 0;
484 }
485 else
486 {
487 /* Base64 code with valid character length. */
488 return len;
489 }
490 }
491 else
492 {
493 valid_balance--;
494 }
495
496 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
497 if( valid_balance < -100 )
498 {
499 printf_err( "Too many bad symbols detected. File check aborted.\n" );
500 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100501 }
502 }
503
504 printf_dbg( "End of file\n" );
505 return 0;
506}
507
Hanno Becker2c2722d2020-10-09 09:36:23 +0100508#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100509/*
510 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100511 * about the certificates from provided data.
512 *
513 * /p ssl pointer to serialized certificate
514 * /p len number of bytes in the buffer
515*/
516void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
517{
518 enum { STRLEN = 4096 };
519 mbedtls_x509_crt crt;
520 int ret;
521 char str[STRLEN];
522
523 printf( "\nCertificate:\n" );
524
525 mbedtls_x509_crt_init( &crt );
526 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
527 if( 0 != ret )
528 {
529 mbedtls_strerror( ret, str, STRLEN );
530 printf_err( "Invalid format of X.509 - %s\n", str );
531 printf( "Cannot deserialize:\n\t" );
532 print_hex( ssl, len, 25, "\t" );
533 }
534 else
535 {
536 mbedtls_x509_crt *current = &crt;
537
538 while( current != NULL )
539 {
540 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
541 if( 0 > ret )
542 {
543 mbedtls_strerror( ret, str, STRLEN );
544 printf_err( "Cannot write to the output - %s\n", str );
545 }
546 else
547 {
548 printf( "%s", str );
549 }
550
551 current = current->next;
552
553 if( current )
554 {
555 printf( "\n" );
556 }
557
558 }
559 }
560
561 mbedtls_x509_crt_free( &crt );
562}
Hanno Becker2c2722d2020-10-09 09:36:23 +0100563#endif /* !MBEDTLS_X509_REMOVE_INFO */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100564
565/*
566 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100567 * about the session from provided data. This function was built based on
568 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
569 * due to dependencies on the mbedTLS configuration.
570 *
571 * The data structure in the buffer:
572 * uint64 start_time;
573 * uint8 ciphersuite[2]; // defined by the standard
574 * uint8 compression; // 0 or 1
575 * uint8 session_id_len; // at most 32
576 * opaque session_id[32];
577 * opaque master[48]; // fixed length in the standard
578 * uint32 verify_result;
579 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
580 * opaque ticket<0..2^24-1>; // length 0 means no ticket
581 * uint32 ticket_lifetime;
582 * uint8 mfl_code; // up to 255 according to standard
583 * uint8 trunc_hmac; // 0 or 1
584 * uint8 encrypt_then_mac; // 0 or 1
585 *
586 * /p ssl pointer to serialized session
587 * /p len number of bytes in the buffer
588 * /p session_cfg_flag session configuration flags
589 */
590void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
591 int session_cfg_flag )
592{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100593 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
594 int ciphersuite_id;
595 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100596 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100597 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100598
599 printf( "\nSession info:\n" );
600
601 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
602 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100603 uint64_t start;
604 CHECK_SSL_END( 8 );
605 start = ( (uint64_t) ssl[0] << 56 ) |
606 ( (uint64_t) ssl[1] << 48 ) |
607 ( (uint64_t) ssl[2] << 40 ) |
608 ( (uint64_t) ssl[3] << 32 ) |
609 ( (uint64_t) ssl[4] << 24 ) |
610 ( (uint64_t) ssl[5] << 16 ) |
611 ( (uint64_t) ssl[6] << 8 ) |
612 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100613 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100614 printf( "\tstart time : " );
Raoul Strackx9ed9bc92020-06-22 14:08:57 +0200615#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100616 print_time( (time_t*) &start );
Raoul Strackx9ed9bc92020-06-22 14:08:57 +0200617#else
618 (void) start;
619 printf( "not supported\n" );
620#endif
Piotr Nowicki4e192002020-03-18 17:27:29 +0100621 }
622
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100623 CHECK_SSL_END( 2 );
624 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
625 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100626 ssl += 2;
627
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100628 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
629 if( ciphersuite_info == NULL )
630 {
631 printf_err( "Cannot find ciphersuite info\n" );
632 }
633 else
634 {
635 const mbedtls_cipher_info_t *cipher_info;
636 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100637
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100638 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
639 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
640
641 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
642 if( cipher_info == NULL )
643 {
644 printf_err( "Cannot find cipher info\n" );
645 }
646 else
647 {
648 printf( "\tcipher : %s\n", cipher_info->name );
649 }
650
651 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
652 if( md_info == NULL )
653 {
654 printf_err( "Cannot find Message-Digest info\n" );
655 }
656 else
657 {
Chris Jonesa1df4942021-03-11 17:44:43 +0000658 printf( "\tMessage-Digest : %s\n", mbedtls_md_get_name( md_info ) );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100659 }
660 }
661
662 CHECK_SSL_END( 1 );
663 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
664
665 /* Note - Here we can get session ID length from serialized data, but we
666 * use hardcoded 32-bytes length. This approach was taken from
667 * 'mbedtls_ssl_session_load()'. */
668 CHECK_SSL_END( 1 + 32 );
669 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
670 printf( "\tsession ID : ");
671 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100672 ssl += 32;
673
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100674 printf( "\tmaster secret : ");
675 CHECK_SSL_END( 48 );
676 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100677 ssl += 48;
678
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100679 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100680 verify_result = ( (uint32_t) ssl[0] << 24 ) |
681 ( (uint32_t) ssl[1] << 16 ) |
682 ( (uint32_t) ssl[2] << 8 ) |
683 ( (uint32_t) ssl[3] );
684 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100685 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100686
687 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
688 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100689 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100690 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100691 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100692 cert_len = ( (uint32_t) ssl[0] << 16 ) |
693 ( (uint32_t) ssl[1] << 8 ) |
694 ( (uint32_t) ssl[2] );
695 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100696 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100697
698 if( cert_len > 0 )
699 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100700 CHECK_SSL_END( cert_len );
Hanno Becker2c2722d2020-10-09 09:36:23 +0100701#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100702 print_deserialized_ssl_cert( ssl, cert_len );
Hanno Becker2c2722d2020-10-09 09:36:23 +0100703#endif
Piotr Nowicki4e192002020-03-18 17:27:29 +0100704 ssl += cert_len;
705 }
706 }
707 else
708 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100709 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100710
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100711 CHECK_SSL_END( 1 );
712 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100713 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100714 case MBEDTLS_MD_NONE:
715 printf( "none\n" );
716 break;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100717 case MBEDTLS_MD_MD5:
718 printf( "MD5\n" );
719 break;
720 case MBEDTLS_MD_SHA1:
721 printf( "SHA1\n" );
722 break;
723 case MBEDTLS_MD_SHA224:
724 printf( "SHA224\n" );
725 break;
726 case MBEDTLS_MD_SHA256:
727 printf( "SHA256\n" );
728 break;
729 case MBEDTLS_MD_SHA384:
730 printf( "SHA384\n" );
731 break;
732 case MBEDTLS_MD_SHA512:
733 printf( "SHA512\n" );
734 break;
735 case MBEDTLS_MD_RIPEMD160:
736 printf( "RIPEMD160\n" );
737 break;
738 default:
739 printf( "undefined or erroneous\n" );
740 break;
741 }
742
743 CHECK_SSL_END( 1 );
744 cert_len = (uint32_t) *ssl++;
745 printf_dbg( "Message-Digest length: %u\n", cert_len );
746
747 if( cert_len > 0 )
748 {
749 printf( "\tPeer digest cert : " );
750 CHECK_SSL_END( cert_len );
751 print_hex( ssl, cert_len, 16, "\t " );
752 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100753 }
754 }
755 }
756
757 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
758 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100759 printf( "\nTicket:\n" );
760
761 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100762 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
763 ( (uint32_t) ssl[1] << 8 ) |
764 ( (uint32_t) ssl[2] );
765 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100766 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100767
768 if( ticket_len > 0 )
769 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100770 printf( "\t" );
771 CHECK_SSL_END( ticket_len );
772 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100773 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100774 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100775 }
776
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100777 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100778 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
779 ( (uint32_t) ssl[1] << 16 ) |
780 ( (uint32_t) ssl[2] << 8 ) |
781 ( (uint32_t) ssl[3] );
782 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100783 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
784 }
785
786 if( ssl < end )
787 {
788 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100789 }
790
791 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
792 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100793 CHECK_SSL_END( 1 );
794 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100795 }
796
797 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
798 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100799 CHECK_SSL_END( 1 );
800 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100801 }
802
803 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
804 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100805 CHECK_SSL_END( 1 );
806 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100807 }
808
809 if( 0 != ( end - ssl ) )
810 {
811 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
812 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100813}
814
815/*
816 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100817 * about the context from provided data. This function was built based on
818 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
819 * due to dependencies on the mbedTLS configuration and the configuration of
820 * the context when serialization was created.
821 *
822 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200823 * // header
824 * uint8 version[3];
825 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100826 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200827 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100828 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
829 * // transform sub-structure
830 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200831 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100832 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200833 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100834 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
835 * // fields from ssl_context
836 * uint32 badmac_seen; // DTLS: number of records with failing MAC
837 * uint64 in_window_top; // DTLS: last validated record seq_num
838 * uint64 in_window; // DTLS: bitmask for replay protection
839 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
840 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
841 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200842 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100843 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
844 *
845 * /p ssl pointer to serialized session
846 * /p len number of bytes in the buffer
847 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100848void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100849{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100850 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100851 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100852 int session_cfg_flag;
853 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100854
855 printf( "\nMbed TLS version:\n" );
856
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100857 CHECK_SSL_END( 3 + 2 + 3 );
858
859 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
860 printf( "\tminor %u\n", (uint32_t) *ssl++ );
861 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100862
863 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100864
865 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
866 ssl += 2;
867
868 context_cfg_flag = ( (int) ssl[0] << 16 ) |
869 ( (int) ssl[1] << 8 ) |
870 ( (int) ssl[2] ) ;
871 ssl += 3;
872
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100873 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
874 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
875
876 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
877 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
878 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100879 print_if_bit( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag );
880 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag );
881 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS and client", SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag );
882
883 print_if_bit( "MBEDTLS_SSL_DTLS_CONNECTION_ID", CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100884 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
885 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
886
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100887 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100888 session_len = ( (uint32_t) ssl[0] << 24 ) |
889 ( (uint32_t) ssl[1] << 16 ) |
890 ( (uint32_t) ssl[2] << 8 ) |
891 ( (uint32_t) ssl[3] );
892 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100893 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100894
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100895 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100896 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
897 ssl += session_len;
898
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100899 printf( "\nRandom bytes:\n\t");
900
901 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
902 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100903 ssl += TRANSFORM_RANDBYTE_LEN;
904
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100905 printf( "\nContext others:\n" );
906
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100907 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
908 {
909 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100910
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100911 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100912 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100913 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100914
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100915 printf( "\tin CID : " );
916 if( cid_len > 0 )
917 {
918 CHECK_SSL_END( cid_len );
919 print_hex( ssl, cid_len, 20, "\t" );
920 ssl += cid_len;
921 }
922 else
923 {
924 printf( "none\n" );
925 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100926
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100927 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100928 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100929 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100930
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100931 printf( "\tout CID : " );
932 if( cid_len > 0 )
933 {
934 CHECK_SSL_END( cid_len );
935 print_hex( ssl, cid_len, 20, "\t" );
936 ssl += cid_len;
937 }
938 else
939 {
940 printf( "none\n" );
941 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100942 }
943
944 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
945 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100946 uint32_t badmac_seen;
947
948 CHECK_SSL_END( 4 );
949 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
950 ( (uint32_t) ssl[1] << 16 ) |
951 ( (uint32_t) ssl[2] << 8 ) |
952 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100953 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100954 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100955
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100956 /* value 'in_window_top' from mbedtls_ssl_context */
957 printf( "\tlast validated record sequence no. : " );
958 CHECK_SSL_END( 8 );
959 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100960 ssl += 8;
961
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100962 /* value 'in_window' from mbedtls_ssl_context */
963 printf( "\tbitmask for replay detection : " );
964 CHECK_SSL_END( 8 );
965 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100966 ssl += 8;
967 }
968
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100969 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100970 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100971 CHECK_SSL_END( 1 );
972 printf( "\tDTLS datagram packing : %s\n",
973 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100974 }
975
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100976 /* value 'cur_out_ctr' from mbedtls_ssl_context */
977 printf( "\toutgoing record sequence no. : ");
978 CHECK_SSL_END( 8 );
979 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100980 ssl += 8;
981
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100982 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100983 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100984 uint16_t mtu;
985 CHECK_SSL_END( 2 );
986 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100987 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100988 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100989 }
990
991
992 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
993 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100994 uint8_t alpn_len;
995
996 CHECK_SSL_END( 1 );
997 alpn_len = *ssl++;
998 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
999
1000 printf( "\tALPN negotiation : " );
1001 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001002 if( alpn_len > 0 )
1003 {
1004 if( strlen( (const char*) ssl ) == alpn_len )
1005 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001006 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001007 }
1008 else
1009 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001010 printf( "\n" );
1011 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001012 }
1013 ssl += alpn_len;
1014 }
1015 else
1016 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001017 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001018 }
1019 }
1020
Piotr Nowicki4e192002020-03-18 17:27:29 +01001021 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001022 {
Piotr Nowicki4e192002020-03-18 17:27:29 +01001023 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001024 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +01001025 printf( "\n" );
1026}
1027
Piotr Nowicki9370f902020-03-13 14:43:22 +01001028int main( int argc, char *argv[] )
1029{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001030 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001031
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001032 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001033 uint8_t *b64_buf = NULL;
1034 uint8_t *ssl_buf = NULL;
1035 size_t b64_max_len = SSL_INIT_LEN;
1036 size_t ssl_max_len = SSL_INIT_LEN;
1037 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001038
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001039 /* The 'b64_file' is opened when parsing arguments to check that the
1040 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001041 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001042
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001043 if( NULL != b64_file )
1044 {
1045 b64_buf = malloc( SSL_INIT_LEN );
1046 ssl_buf = malloc( SSL_INIT_LEN );
1047
1048 if( NULL == b64_buf || NULL == ssl_buf )
1049 {
1050 printf_err( alloc_err );
1051 fclose( b64_file );
1052 b64_file = NULL;
1053 }
1054 }
1055
Piotr Nowicki14d31052020-03-16 14:05:22 +01001056 while( NULL != b64_file )
1057 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001058 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001059 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001060 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001061 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001062 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1063
1064 /* Allocate more memory if necessary. */
1065 if( ssl_required_len > ssl_max_len )
1066 {
1067 void *ptr = realloc( ssl_buf, ssl_required_len );
1068 if( NULL == ptr )
1069 {
1070 printf_err( alloc_err );
1071 fclose( b64_file );
1072 b64_file = NULL;
1073 break;
1074 }
1075 ssl_buf = ptr;
1076 ssl_max_len = ssl_required_len;
1077 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001078
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001079 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001080
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001081 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001082 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001083
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001084 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001085 if( ret != 0)
1086 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001087 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1088 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001089 continue;
1090 }
1091
1092 if( debug )
1093 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001094 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001095 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001096 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001097
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001098 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001099
Piotr Nowicki14d31052020-03-16 14:05:22 +01001100 }
1101 else
1102 {
1103 fclose( b64_file );
1104 b64_file = NULL;
1105 }
1106 }
1107
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001108 free( b64_buf );
1109 free( ssl_buf );
1110
1111 if( b64_counter > 0 )
1112 {
1113 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1114 }
1115 else
1116 {
1117 printf( "Finished. No valid base64 code found\n" );
1118 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001119
Piotr Nowicki9370f902020-03-13 14:43:22 +01001120 return 0;
1121}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001122
1123#endif /* MBEDTLS_X509_CRT_PARSE_C */