blob: 62c3cc52b70725b7fa6d1fa0ee006f5b85032f40 [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>
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010045#include <time.h>
46#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010047#include "mbedtls/error.h"
48#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010049#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010050#include "mbedtls/x509_crt.h"
51#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010052
53/*
54 * This program version
55 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010056#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010057#define VER_MAJOR 0
58#define VER_MINOR 1
59
60/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020061 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010062 */
63#define SESSION_CONFIG_TIME_BIT ( 1 << 0 )
64#define SESSION_CONFIG_CRT_BIT ( 1 << 1 )
65#define SESSION_CONFIG_CLIENT_TICKET_BIT ( 1 << 2 )
66#define SESSION_CONFIG_MFL_BIT ( 1 << 3 )
67#define SESSION_CONFIG_TRUNC_HMAC_BIT ( 1 << 4 )
68#define SESSION_CONFIG_ETM_BIT ( 1 << 5 )
69#define SESSION_CONFIG_TICKET_BIT ( 1 << 6 )
70
71#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ( 1 << 0 )
72#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ( 1 << 1 )
73#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ( 1 << 2 )
74#define CONTEXT_CONFIG_ALPN_BIT ( 1 << 3 )
75
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010076#define TRANSFORM_RANDBYTE_LEN 64
77
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010078/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020079 * Minimum and maximum number of bytes for specific data: context, sessions,
80 * certificates, tickets and buffers in the program. The context and session
81 * size values have been calculated based on the 'print_deserialized_ssl_context()'
82 * and 'print_deserialized_ssl_session()' content.
83 */
84#define MIN_CONTEXT_LEN 84
85#define MIN_SESSION_LEN 88
86
87#define MAX_CONTEXT_LEN 875 /* without session data */
88#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
89#define MAX_CERTIFICATE_LEN ( ( 1 << 24 ) - 1 )
90#define MAX_TICKET_LEN ( ( 1 << 24 ) - 1 )
91
92#define MIN_SERIALIZED_DATA ( MIN_CONTEXT_LEN + MIN_SESSION_LEN )
93#define MAX_SERIALIZED_DATA ( MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
94 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN )
95
96#define MIN_BASE64_LEN ( MIN_SERIALIZED_DATA * 4 / 3 )
97#define MAX_BASE64_LEN ( MAX_SERIALIZED_DATA * 4 / 3 + 3 )
98
99/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100100 * A macro that prevents from reading out of the ssl buffer range.
101 */
102#define CHECK_SSL_END( LEN ) \
103do \
104{ \
105 if( end - ssl < (int)( LEN ) ) \
106 { \
107 printf_err( "%s", buf_ln_err ); \
108 return; \
109 } \
110} while( 0 )
111
112/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100113 * Global values
114 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100115FILE *b64_file = NULL; /* file with base64 codes to deserialize */
116char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
117char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
118char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200119const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100120const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100121
122/*
123 * Basic printing functions
124 */
125void print_version( )
126{
127 printf( "%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR );
128}
129
130void print_usage( )
131{
132 print_version();
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200133 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 +0100134 "in the text file. The program can deserialize many codes from one file, but they must be\n"
135 "separated, e.g. by a newline.\n\n" );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100136 printf(
137 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100138 "\t-f path - Path to the file with base64 code\n"
139 "\t-v - Show version\n"
140 "\t-h - Show this usage\n"
141 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200142 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100143 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
144 "\t flag. You can also use it if there are some problems with reading\n"
145 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200146 "\t--dtls-protocol=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100147 "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100148 "\n"
149 );
150}
151
152void printf_dbg( const char *str, ... )
153{
154 if( debug )
155 {
156 va_list args;
157 va_start( args, str );
158 printf( "debug: " );
159 vprintf( str, args );
160 fflush( stdout );
161 va_end( args );
162 }
163}
164
Paul Elliottef9ccca2021-12-09 14:48:47 +0000165MBEDTLS_PRINTF_ATTRIBUTE( 1, 2 )
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100166void printf_err( const char *str, ... )
167{
168 va_list args;
169 va_start( args, str );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100170 fflush( stdout );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100171 fprintf( stderr, "ERROR: " );
172 vfprintf( stderr, str, args );
173 fflush( stderr );
174 va_end( args );
175}
176
177/*
178 * Exit from the program in case of error
179 */
180void error_exit()
181{
182 if( NULL != b64_file )
183 {
184 fclose( b64_file );
185 }
186 exit( -1 );
187}
188
189/*
190 * This function takes the input arguments of this program
191 */
192void parse_arguments( int argc, char *argv[] )
193{
194 int i = 1;
195
196 if( argc < 2 )
197 {
198 print_usage();
199 error_exit();
200 }
201
202 while( i < argc )
203 {
204 if( strcmp( argv[i], "-d" ) == 0 )
205 {
206 debug = 1;
207 }
208 else if( strcmp( argv[i], "-h" ) == 0 )
209 {
210 print_usage();
211 }
212 else if( strcmp( argv[i], "-v" ) == 0 )
213 {
214 print_version();
215 }
216 else if( strcmp( argv[i], "-f" ) == 0 )
217 {
218 if( ++i >= argc )
219 {
220 printf_err( "File path is empty\n" );
221 error_exit();
222 }
223
Paul Elliott3820c152021-12-09 12:48:51 +0000224 if( NULL != b64_file )
225 {
226 printf_err( "Cannot specify more than one file with -f\n" );
227 error_exit( );
228 }
229
230 if( ( b64_file = fopen( argv[i], "r" )) == NULL )
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100231 {
232 printf_err( "Cannot find file \"%s\"\n", argv[i] );
233 error_exit();
234 }
235 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100236 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
237 {
238 conf_keep_peer_certificate = 0;
239 }
240 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
241 {
242 conf_dtls_proto = 0;
243 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100244 else
245 {
246 print_usage();
247 error_exit();
248 }
249
250 i++;
251 }
252}
253
Piotr Nowicki14d31052020-03-16 14:05:22 +0100254/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100255 * This function prints base64 code to the stdout
256 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100257void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100258{
259 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100260 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100261 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100262 while( b < end )
263 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100264 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100265 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100266 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100267 i = 0;
268 }
269 printf( "%c", *b++ );
270 }
271 printf( "\n" );
272 fflush( stdout );
273}
274
275/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100276 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100277 *
278 * /p b buffer with data to print
279 * /p len number of bytes to print
280 * /p in_line number of bytes in one line
281 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100282 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100283void print_hex( const uint8_t *b, size_t len,
284 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100285{
286 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100287 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100288
289 if( prefix == NULL )
290 {
291 prefix = "";
292 }
293
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100294 while( b < end )
295 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100296 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100297 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100298 printf( "\n%s", prefix );
299 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100300 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100301 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100302 }
303 printf("\n");
304 fflush(stdout);
305}
306
307/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100308 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
309 */
310void print_time( const time_t *time )
311{
312 char buf[20];
313 struct tm *t = gmtime( time );
314 static const char format[] = "%Y-%m-%d %H:%M:%S";
315 if( NULL != t )
316 {
317 strftime( buf, sizeof( buf ), format, t );
318 printf( "%s\n", buf );
319 }
320 else
321 {
322 printf( "unknown\n" );
323 }
324}
325
326/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100327 * Print the input string if the bit is set in the value
328 */
329void print_if_bit( const char *str, int bit, int val )
330{
331 if( bit & val )
332 {
333 printf( "\t%s\n", str );
334 }
335}
336
337/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100338 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
339 */
340const char * get_enabled_str( int is_en )
341{
342 return ( is_en ) ? "enabled" : "disabled";
343}
344
345/*
346 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
347 */
348const char * get_mfl_str( int mfl_code )
349{
350 switch( mfl_code )
351 {
352 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
353 return "none";
354 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
355 return "512";
356 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
357 return "1024";
358 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
359 return "2048";
360 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
361 return "4096";
362 default:
363 return "error";
364 }
365}
366
367/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100368 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
369 * previously. After each call to this function, the internal file position
370 * indicator of the global b64_file is advanced.
371 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200372 * Note - This function checks the size of the input buffer and if necessary,
373 * increases it to the maximum MAX_BASE64_LEN
374 *
375 * /p b64 pointer to the pointer of the buffer for input data
376 * /p max_len pointer to the current buffer capacity. It can be changed if
377 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100378 *
379 * \retval number of bytes written in to the b64 buffer or 0 in case no more
380 * data was found
381 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200382size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100383{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200384 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100385 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100386 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000387 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100388
389 while( EOF != c )
390 {
391 char c_valid = 0;
392
Nayna Jaind696e7d2020-08-13 19:17:53 +0000393 c = fgetc( b64_file );
Piotr Nowicki14d31052020-03-16 14:05:22 +0100394
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200395 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100396 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200397 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100398 {
399 c_valid = 1;
400 pad = 2;
401 }
402 }
403 else if( ( c >= 'A' && c <= 'Z' ) ||
404 ( c >= 'a' && c <= 'z' ) ||
405 ( c >= '0' && c <= '9' ) ||
406 c == '+' || c == '/' )
407 {
408 c_valid = 1;
409 }
410 else if( c == '=' )
411 {
412 c_valid = 1;
413 pad = 1;
414 }
415 else if( c == '-' )
416 {
417 c = '+';
418 c_valid = 1;
419 }
420 else if( c == '_' )
421 {
422 c = '/';
423 c_valid = 1;
424 }
425
426 if( c_valid )
427 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200428 /* A string of characters that could be a base64 code. */
429 valid_balance++;
430
431 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100432 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200433 ( *b64 )[ len++ ] = c;
434 }
435 else if( *max_len < MAX_BASE64_LEN )
436 {
437 /* Current buffer is too small, but can be resized. */
438 void *ptr;
439 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
440 *max_len + 4096 : MAX_BASE64_LEN;
441
442 ptr = realloc( *b64, new_size );
443 if( NULL == ptr )
444 {
445 printf_err( alloc_err );
446 return 0;
447 }
448 *b64 = ptr;
449 *max_len = new_size;
450 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100451 }
452 else
453 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200454 /* Too much data so it will be treated as invalid */
455 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100456 }
457 }
458 else if( len > 0 )
459 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200460 /* End of a string that could be a base64 code, but need to check
461 * that the length of the characters is correct. */
462
463 valid_balance--;
464
465 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100466 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200467 printf_dbg( "The code found is too small to be a SSL context.\n" );
468 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100469 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200470 else if( len > *max_len )
471 {
Paul Elliottef9ccca2021-12-09 14:48:47 +0000472 printf_err( "The code found is too large by %" MBEDTLS_PRINTF_SIZET " bytes.\n",
473 len - *max_len );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200474 len = pad = 0;
475 }
476 else if( len % 4 != 0 )
477 {
478 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
479 len = pad = 0;
480 }
481 else
482 {
483 /* Base64 code with valid character length. */
484 return len;
485 }
486 }
487 else
488 {
489 valid_balance--;
490 }
491
492 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
493 if( valid_balance < -100 )
494 {
495 printf_err( "Too many bad symbols detected. File check aborted.\n" );
496 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100497 }
498 }
499
500 printf_dbg( "End of file\n" );
501 return 0;
502}
503
Hanno Becker2c2722d2020-10-09 09:36:23 +0100504#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100505/*
506 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100507 * about the certificates from provided data.
508 *
509 * /p ssl pointer to serialized certificate
510 * /p len number of bytes in the buffer
511*/
512void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
513{
514 enum { STRLEN = 4096 };
515 mbedtls_x509_crt crt;
516 int ret;
517 char str[STRLEN];
518
519 printf( "\nCertificate:\n" );
520
521 mbedtls_x509_crt_init( &crt );
522 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
523 if( 0 != ret )
524 {
525 mbedtls_strerror( ret, str, STRLEN );
526 printf_err( "Invalid format of X.509 - %s\n", str );
527 printf( "Cannot deserialize:\n\t" );
528 print_hex( ssl, len, 25, "\t" );
529 }
530 else
531 {
532 mbedtls_x509_crt *current = &crt;
533
534 while( current != NULL )
535 {
536 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
537 if( 0 > ret )
538 {
539 mbedtls_strerror( ret, str, STRLEN );
540 printf_err( "Cannot write to the output - %s\n", str );
541 }
542 else
543 {
544 printf( "%s", str );
545 }
546
547 current = current->next;
548
549 if( current )
550 {
551 printf( "\n" );
552 }
553
554 }
555 }
556
557 mbedtls_x509_crt_free( &crt );
558}
Hanno Becker2c2722d2020-10-09 09:36:23 +0100559#endif /* !MBEDTLS_X509_REMOVE_INFO */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100560
561/*
562 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100563 * about the session from provided data. This function was built based on
564 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
565 * due to dependencies on the mbedTLS configuration.
566 *
567 * The data structure in the buffer:
568 * uint64 start_time;
569 * uint8 ciphersuite[2]; // defined by the standard
570 * uint8 compression; // 0 or 1
571 * uint8 session_id_len; // at most 32
572 * opaque session_id[32];
573 * opaque master[48]; // fixed length in the standard
574 * uint32 verify_result;
575 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
576 * opaque ticket<0..2^24-1>; // length 0 means no ticket
577 * uint32 ticket_lifetime;
578 * uint8 mfl_code; // up to 255 according to standard
579 * uint8 trunc_hmac; // 0 or 1
580 * uint8 encrypt_then_mac; // 0 or 1
581 *
582 * /p ssl pointer to serialized session
583 * /p len number of bytes in the buffer
584 * /p session_cfg_flag session configuration flags
585 */
586void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
587 int session_cfg_flag )
588{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100589 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
590 int ciphersuite_id;
591 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100592 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100593 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100594
595 printf( "\nSession info:\n" );
596
597 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
598 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100599 uint64_t start;
600 CHECK_SSL_END( 8 );
601 start = ( (uint64_t) ssl[0] << 56 ) |
602 ( (uint64_t) ssl[1] << 48 ) |
603 ( (uint64_t) ssl[2] << 40 ) |
604 ( (uint64_t) ssl[3] << 32 ) |
605 ( (uint64_t) ssl[4] << 24 ) |
606 ( (uint64_t) ssl[5] << 16 ) |
607 ( (uint64_t) ssl[6] << 8 ) |
608 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100609 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100610 printf( "\tstart time : " );
611 print_time( (time_t*) &start );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100612 }
613
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100614 CHECK_SSL_END( 2 );
615 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
616 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100617 ssl += 2;
618
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100619 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
620 if( ciphersuite_info == NULL )
621 {
622 printf_err( "Cannot find ciphersuite info\n" );
623 }
624 else
625 {
626 const mbedtls_cipher_info_t *cipher_info;
627 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100628
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100629 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
630 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
631
632 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
633 if( cipher_info == NULL )
634 {
635 printf_err( "Cannot find cipher info\n" );
636 }
637 else
638 {
639 printf( "\tcipher : %s\n", cipher_info->name );
640 }
641
642 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
643 if( md_info == NULL )
644 {
645 printf_err( "Cannot find Message-Digest info\n" );
646 }
647 else
648 {
Chris Jonesa1df4942021-03-11 17:44:43 +0000649 printf( "\tMessage-Digest : %s\n", mbedtls_md_get_name( md_info ) );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100650 }
651 }
652
653 CHECK_SSL_END( 1 );
654 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
655
656 /* Note - Here we can get session ID length from serialized data, but we
657 * use hardcoded 32-bytes length. This approach was taken from
658 * 'mbedtls_ssl_session_load()'. */
659 CHECK_SSL_END( 1 + 32 );
660 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
661 printf( "\tsession ID : ");
662 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100663 ssl += 32;
664
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100665 printf( "\tmaster secret : ");
666 CHECK_SSL_END( 48 );
667 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100668 ssl += 48;
669
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100670 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100671 verify_result = ( (uint32_t) ssl[0] << 24 ) |
672 ( (uint32_t) ssl[1] << 16 ) |
673 ( (uint32_t) ssl[2] << 8 ) |
674 ( (uint32_t) ssl[3] );
675 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100676 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100677
678 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
679 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100680 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100681 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100682 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100683 cert_len = ( (uint32_t) ssl[0] << 16 ) |
684 ( (uint32_t) ssl[1] << 8 ) |
685 ( (uint32_t) ssl[2] );
686 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100687 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100688
689 if( cert_len > 0 )
690 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100691 CHECK_SSL_END( cert_len );
Hanno Becker2c2722d2020-10-09 09:36:23 +0100692#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100693 print_deserialized_ssl_cert( ssl, cert_len );
Hanno Becker2c2722d2020-10-09 09:36:23 +0100694#endif
Piotr Nowicki4e192002020-03-18 17:27:29 +0100695 ssl += cert_len;
696 }
697 }
698 else
699 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100700 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100701
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100702 CHECK_SSL_END( 1 );
703 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100704 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100705 case MBEDTLS_MD_NONE:
706 printf( "none\n" );
707 break;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100708 case MBEDTLS_MD_MD5:
709 printf( "MD5\n" );
710 break;
711 case MBEDTLS_MD_SHA1:
712 printf( "SHA1\n" );
713 break;
714 case MBEDTLS_MD_SHA224:
715 printf( "SHA224\n" );
716 break;
717 case MBEDTLS_MD_SHA256:
718 printf( "SHA256\n" );
719 break;
720 case MBEDTLS_MD_SHA384:
721 printf( "SHA384\n" );
722 break;
723 case MBEDTLS_MD_SHA512:
724 printf( "SHA512\n" );
725 break;
726 case MBEDTLS_MD_RIPEMD160:
727 printf( "RIPEMD160\n" );
728 break;
729 default:
730 printf( "undefined or erroneous\n" );
731 break;
732 }
733
734 CHECK_SSL_END( 1 );
735 cert_len = (uint32_t) *ssl++;
736 printf_dbg( "Message-Digest length: %u\n", cert_len );
737
738 if( cert_len > 0 )
739 {
740 printf( "\tPeer digest cert : " );
741 CHECK_SSL_END( cert_len );
742 print_hex( ssl, cert_len, 16, "\t " );
743 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100744 }
745 }
746 }
747
748 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
749 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100750 printf( "\nTicket:\n" );
751
752 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100753 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
754 ( (uint32_t) ssl[1] << 8 ) |
755 ( (uint32_t) ssl[2] );
756 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100757 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100758
759 if( ticket_len > 0 )
760 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100761 printf( "\t" );
762 CHECK_SSL_END( ticket_len );
763 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100764 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100765 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100766 }
767
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100768 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100769 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
770 ( (uint32_t) ssl[1] << 16 ) |
771 ( (uint32_t) ssl[2] << 8 ) |
772 ( (uint32_t) ssl[3] );
773 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100774 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
775 }
776
777 if( ssl < end )
778 {
779 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100780 }
781
782 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
783 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100784 CHECK_SSL_END( 1 );
785 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100786 }
787
788 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
789 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100790 CHECK_SSL_END( 1 );
791 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100792 }
793
794 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
795 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100796 CHECK_SSL_END( 1 );
797 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100798 }
799
800 if( 0 != ( end - ssl ) )
801 {
802 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
803 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100804}
805
806/*
807 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100808 * about the context from provided data. This function was built based on
809 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
810 * due to dependencies on the mbedTLS configuration and the configuration of
811 * the context when serialization was created.
812 *
813 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200814 * // header
815 * uint8 version[3];
816 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100817 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200818 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100819 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
820 * // transform sub-structure
821 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200822 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100823 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200824 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100825 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
826 * // fields from ssl_context
827 * uint32 badmac_seen; // DTLS: number of records with failing MAC
828 * uint64 in_window_top; // DTLS: last validated record seq_num
829 * uint64 in_window; // DTLS: bitmask for replay protection
830 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
831 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
832 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200833 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100834 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
835 *
836 * /p ssl pointer to serialized session
837 * /p len number of bytes in the buffer
838 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100839void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100840{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100841 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100842 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100843 int session_cfg_flag;
844 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100845
846 printf( "\nMbed TLS version:\n" );
847
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100848 CHECK_SSL_END( 3 + 2 + 3 );
849
850 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
851 printf( "\tminor %u\n", (uint32_t) *ssl++ );
852 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100853
854 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100855
856 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
857 ssl += 2;
858
859 context_cfg_flag = ( (int) ssl[0] << 16 ) |
860 ( (int) ssl[1] << 8 ) |
861 ( (int) ssl[2] ) ;
862 ssl += 3;
863
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100864 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
865 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
866
867 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
868 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
869 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100870 print_if_bit( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag );
871 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag );
872 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS and client", SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag );
873
874 print_if_bit( "MBEDTLS_SSL_DTLS_CONNECTION_ID", CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100875 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
876 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
877
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100878 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100879 session_len = ( (uint32_t) ssl[0] << 24 ) |
880 ( (uint32_t) ssl[1] << 16 ) |
881 ( (uint32_t) ssl[2] << 8 ) |
882 ( (uint32_t) ssl[3] );
883 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100884 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100885
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100886 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100887 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
888 ssl += session_len;
889
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100890 printf( "\nRandom bytes:\n\t");
891
892 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
893 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100894 ssl += TRANSFORM_RANDBYTE_LEN;
895
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100896 printf( "\nContext others:\n" );
897
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100898 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
899 {
900 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100901
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100902 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100903 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100904 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100905
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100906 printf( "\tin CID : " );
907 if( cid_len > 0 )
908 {
909 CHECK_SSL_END( cid_len );
910 print_hex( ssl, cid_len, 20, "\t" );
911 ssl += cid_len;
912 }
913 else
914 {
915 printf( "none\n" );
916 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100917
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100918 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100919 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100920 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100921
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100922 printf( "\tout CID : " );
923 if( cid_len > 0 )
924 {
925 CHECK_SSL_END( cid_len );
926 print_hex( ssl, cid_len, 20, "\t" );
927 ssl += cid_len;
928 }
929 else
930 {
931 printf( "none\n" );
932 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100933 }
934
935 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
936 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100937 uint32_t badmac_seen;
938
939 CHECK_SSL_END( 4 );
940 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
941 ( (uint32_t) ssl[1] << 16 ) |
942 ( (uint32_t) ssl[2] << 8 ) |
943 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100944 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100945 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100946
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100947 /* value 'in_window_top' from mbedtls_ssl_context */
948 printf( "\tlast validated record sequence no. : " );
949 CHECK_SSL_END( 8 );
950 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100951 ssl += 8;
952
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100953 /* value 'in_window' from mbedtls_ssl_context */
954 printf( "\tbitmask for replay detection : " );
955 CHECK_SSL_END( 8 );
956 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100957 ssl += 8;
958 }
959
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100960 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100961 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100962 CHECK_SSL_END( 1 );
963 printf( "\tDTLS datagram packing : %s\n",
964 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100965 }
966
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100967 /* value 'cur_out_ctr' from mbedtls_ssl_context */
968 printf( "\toutgoing record sequence no. : ");
969 CHECK_SSL_END( 8 );
970 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100971 ssl += 8;
972
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100973 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100974 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100975 uint16_t mtu;
976 CHECK_SSL_END( 2 );
977 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100978 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100979 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100980 }
981
982
983 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
984 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100985 uint8_t alpn_len;
986
987 CHECK_SSL_END( 1 );
988 alpn_len = *ssl++;
989 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
990
991 printf( "\tALPN negotiation : " );
992 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100993 if( alpn_len > 0 )
994 {
995 if( strlen( (const char*) ssl ) == alpn_len )
996 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100997 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100998 }
999 else
1000 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001001 printf( "\n" );
1002 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001003 }
1004 ssl += alpn_len;
1005 }
1006 else
1007 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001008 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001009 }
1010 }
1011
Piotr Nowicki4e192002020-03-18 17:27:29 +01001012 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001013 {
Piotr Nowicki4e192002020-03-18 17:27:29 +01001014 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001015 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +01001016 printf( "\n" );
1017}
1018
Piotr Nowicki9370f902020-03-13 14:43:22 +01001019int main( int argc, char *argv[] )
1020{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001021 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001022
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001023 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001024 uint8_t *b64_buf = NULL;
1025 uint8_t *ssl_buf = NULL;
1026 size_t b64_max_len = SSL_INIT_LEN;
1027 size_t ssl_max_len = SSL_INIT_LEN;
1028 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001029
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001030 /* The 'b64_file' is opened when parsing arguments to check that the
1031 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001032 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001033
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001034 if( NULL != b64_file )
1035 {
1036 b64_buf = malloc( SSL_INIT_LEN );
1037 ssl_buf = malloc( SSL_INIT_LEN );
1038
1039 if( NULL == b64_buf || NULL == ssl_buf )
1040 {
1041 printf_err( alloc_err );
1042 fclose( b64_file );
1043 b64_file = NULL;
1044 }
1045 }
1046
Piotr Nowicki14d31052020-03-16 14:05:22 +01001047 while( NULL != b64_file )
1048 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001049 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001050 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001051 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001052 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001053 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1054
1055 /* Allocate more memory if necessary. */
1056 if( ssl_required_len > ssl_max_len )
1057 {
1058 void *ptr = realloc( ssl_buf, ssl_required_len );
1059 if( NULL == ptr )
1060 {
1061 printf_err( alloc_err );
1062 fclose( b64_file );
1063 b64_file = NULL;
1064 break;
1065 }
1066 ssl_buf = ptr;
1067 ssl_max_len = ssl_required_len;
1068 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001069
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001070 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001071
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001072 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001073 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001074
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001075 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001076 if( ret != 0)
1077 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001078 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1079 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001080 continue;
1081 }
1082
1083 if( debug )
1084 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001085 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001086 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001087 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001088
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001089 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001090
Piotr Nowicki14d31052020-03-16 14:05:22 +01001091 }
1092 else
1093 {
1094 fclose( b64_file );
1095 b64_file = NULL;
1096 }
1097 }
1098
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001099 free( b64_buf );
1100 free( ssl_buf );
1101
1102 if( b64_counter > 0 )
1103 {
1104 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1105 }
1106 else
1107 {
1108 printf( "Finished. No valid base64 code found\n" );
1109 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001110
Piotr Nowicki9370f902020-03-13 14:43:22 +01001111 return 0;
1112}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001113
1114#endif /* MBEDTLS_X509_CRT_PARSE_C */