blob: bb84f5294469a87ef47ca3f0984e99fcc7d9edad [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
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020020#if !defined(MBEDTLS_CONFIG_FILE)
21#include "mbedtls/config.h"
22#else
23#include MBEDTLS_CONFIG_FILE
Piotr Nowickif86192f2020-03-26 11:45:42 +010024#endif
Paul Elliott8f20bab2021-12-09 14:48:47 +000025#include "mbedtls/debug.h"
Piotr Nowickif86192f2020-03-26 11:45:42 +010026
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010027#include <stdio.h>
28#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020029
Gilles Peskinef4a6a052020-11-09 14:55:35 +010030#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
31 !defined(MBEDTLS_SSL_TLS_C)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020032int main( void )
33{
Gilles Peskinef4a6a052020-11-09 14:55:35 +010034 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
35 "MBEDTLS_SSL_TLS_C not defined.\n");
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020036 return( 0 );
37}
38#else
39
40#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
41#define _CRT_SECURE_NO_DEPRECATE 1
42#endif
43
Piotr Nowicki14d31052020-03-16 14:05:22 +010044#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010045#include <stdarg.h>
46#include <string.h>
Raoul Strackx2db000f2020-06-22 14:08:57 +020047#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010048#include <time.h>
Raoul Strackx2db000f2020-06-22 14:08:57 +020049#endif
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010050#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010051#include "mbedtls/error.h"
52#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010053#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010054#include "mbedtls/md_internal.h"
55#include "mbedtls/x509_crt.h"
56#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010057
58/*
59 * This program version
60 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010061#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010062#define VER_MAJOR 0
63#define VER_MINOR 1
64
65/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020066 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010067 */
68#define SESSION_CONFIG_TIME_BIT ( 1 << 0 )
69#define SESSION_CONFIG_CRT_BIT ( 1 << 1 )
70#define SESSION_CONFIG_CLIENT_TICKET_BIT ( 1 << 2 )
71#define SESSION_CONFIG_MFL_BIT ( 1 << 3 )
72#define SESSION_CONFIG_TRUNC_HMAC_BIT ( 1 << 4 )
73#define SESSION_CONFIG_ETM_BIT ( 1 << 5 )
74#define SESSION_CONFIG_TICKET_BIT ( 1 << 6 )
75
76#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ( 1 << 0 )
77#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ( 1 << 1 )
78#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ( 1 << 2 )
79#define CONTEXT_CONFIG_ALPN_BIT ( 1 << 3 )
80
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010081#define TRANSFORM_RANDBYTE_LEN 64
82
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010083/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020084 * Minimum and maximum number of bytes for specific data: context, sessions,
85 * certificates, tickets and buffers in the program. The context and session
86 * size values have been calculated based on the 'print_deserialized_ssl_context()'
87 * and 'print_deserialized_ssl_session()' content.
88 */
89#define MIN_CONTEXT_LEN 84
90#define MIN_SESSION_LEN 88
91
92#define MAX_CONTEXT_LEN 875 /* without session data */
93#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
94#define MAX_CERTIFICATE_LEN ( ( 1 << 24 ) - 1 )
95#define MAX_TICKET_LEN ( ( 1 << 24 ) - 1 )
96
97#define MIN_SERIALIZED_DATA ( MIN_CONTEXT_LEN + MIN_SESSION_LEN )
98#define MAX_SERIALIZED_DATA ( MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
99 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN )
100
101#define MIN_BASE64_LEN ( MIN_SERIALIZED_DATA * 4 / 3 )
102#define MAX_BASE64_LEN ( MAX_SERIALIZED_DATA * 4 / 3 + 3 )
103
104/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100105 * A macro that prevents from reading out of the ssl buffer range.
106 */
107#define CHECK_SSL_END( LEN ) \
108do \
109{ \
110 if( end - ssl < (int)( LEN ) ) \
111 { \
112 printf_err( "%s", buf_ln_err ); \
113 return; \
114 } \
115} while( 0 )
116
117/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100118 * Global values
119 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100120FILE *b64_file = NULL; /* file with base64 codes to deserialize */
121char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
122char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
123char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200124const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100125const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100126
127/*
128 * Basic printing functions
129 */
130void print_version( )
131{
132 printf( "%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR );
133}
134
135void print_usage( )
136{
137 print_version();
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200138 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 +0100139 "in the text file. The program can deserialize many codes from one file, but they must be\n"
140 "separated, e.g. by a newline.\n\n" );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100141 printf(
142 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100143 "\t-f path - Path to the file with base64 code\n"
144 "\t-v - Show version\n"
145 "\t-h - Show this usage\n"
146 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200147 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100148 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
149 "\t flag. You can also use it if there are some problems with reading\n"
150 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200151 "\t--dtls-protocol=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100152 "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100153 "\n"
154 );
155}
156
157void printf_dbg( const char *str, ... )
158{
159 if( debug )
160 {
161 va_list args;
162 va_start( args, str );
163 printf( "debug: " );
164 vprintf( str, args );
165 fflush( stdout );
166 va_end( args );
167 }
168}
169
Paul Elliott8f20bab2021-12-09 14:48:47 +0000170MBEDTLS_PRINTF_ATTRIBUTE( 1, 2 )
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100171void printf_err( const char *str, ... )
172{
173 va_list args;
174 va_start( args, str );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100175 fflush( stdout );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100176 fprintf( stderr, "ERROR: " );
177 vfprintf( stderr, str, args );
178 fflush( stderr );
179 va_end( args );
180}
181
182/*
183 * Exit from the program in case of error
184 */
185void error_exit()
186{
187 if( NULL != b64_file )
188 {
189 fclose( b64_file );
190 }
191 exit( -1 );
192}
193
194/*
195 * This function takes the input arguments of this program
196 */
197void parse_arguments( int argc, char *argv[] )
198{
199 int i = 1;
200
201 if( argc < 2 )
202 {
203 print_usage();
204 error_exit();
205 }
206
207 while( i < argc )
208 {
209 if( strcmp( argv[i], "-d" ) == 0 )
210 {
211 debug = 1;
212 }
213 else if( strcmp( argv[i], "-h" ) == 0 )
214 {
215 print_usage();
216 }
217 else if( strcmp( argv[i], "-v" ) == 0 )
218 {
219 print_version();
220 }
221 else if( strcmp( argv[i], "-f" ) == 0 )
222 {
223 if( ++i >= argc )
224 {
225 printf_err( "File path is empty\n" );
226 error_exit();
227 }
228
Paul Elliott110afd02021-12-09 12:48:51 +0000229 if( NULL != b64_file )
230 {
231 printf_err( "Cannot specify more than one file with -f\n" );
232 error_exit( );
233 }
234
235 if( ( b64_file = fopen( argv[i], "r" )) == NULL )
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100236 {
237 printf_err( "Cannot find file \"%s\"\n", argv[i] );
238 error_exit();
239 }
240 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100241 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
242 {
243 conf_keep_peer_certificate = 0;
244 }
245 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
246 {
247 conf_dtls_proto = 0;
248 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100249 else
250 {
251 print_usage();
252 error_exit();
253 }
254
255 i++;
256 }
257}
258
Piotr Nowicki14d31052020-03-16 14:05:22 +0100259/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100260 * This function prints base64 code to the stdout
261 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100262void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100263{
264 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100265 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100266 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100267 while( b < end )
268 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100269 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100270 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100271 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100272 i = 0;
273 }
274 printf( "%c", *b++ );
275 }
276 printf( "\n" );
277 fflush( stdout );
278}
279
280/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100281 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100282 *
283 * /p b buffer with data to print
284 * /p len number of bytes to print
285 * /p in_line number of bytes in one line
286 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100287 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100288void print_hex( const uint8_t *b, size_t len,
289 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100290{
291 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100292 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100293
294 if( prefix == NULL )
295 {
296 prefix = "";
297 }
298
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100299 while( b < end )
300 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100301 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100302 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100303 printf( "\n%s", prefix );
304 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100305 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100306 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100307 }
308 printf("\n");
309 fflush(stdout);
310}
311
312/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100313 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
314 */
Andrzej Kurek478181d2022-02-28 05:51:57 -0500315void print_time( const uint64_t *time )
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100316{
Andrzej Kurek478181d2022-02-28 05:51:57 -0500317#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100318 char buf[20];
Andrzej Kurek478181d2022-02-28 05:51:57 -0500319 struct tm *t = gmtime( (time_t*) time );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100320 static const char format[] = "%Y-%m-%d %H:%M:%S";
321 if( NULL != t )
322 {
323 strftime( buf, sizeof( buf ), format, t );
324 printf( "%s\n", buf );
325 }
326 else
327 {
328 printf( "unknown\n" );
329 }
Andrzej Kurek478181d2022-02-28 05:51:57 -0500330#else
331 (void) time;
332 printf( "not supported\n" );
Raoul Strackx2db000f2020-06-22 14:08:57 +0200333#endif
Andrzej Kurek478181d2022-02-28 05:51:57 -0500334}
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100335
336/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100337 * Print the input string if the bit is set in the value
338 */
339void print_if_bit( const char *str, int bit, int val )
340{
341 if( bit & val )
342 {
343 printf( "\t%s\n", str );
344 }
345}
346
347/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100348 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
349 */
350const char * get_enabled_str( int is_en )
351{
352 return ( is_en ) ? "enabled" : "disabled";
353}
354
355/*
356 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
357 */
358const char * get_mfl_str( int mfl_code )
359{
360 switch( mfl_code )
361 {
362 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
363 return "none";
364 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
365 return "512";
366 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
367 return "1024";
368 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
369 return "2048";
370 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
371 return "4096";
372 default:
373 return "error";
374 }
375}
376
377/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100378 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
379 * previously. After each call to this function, the internal file position
380 * indicator of the global b64_file is advanced.
381 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200382 * Note - This function checks the size of the input buffer and if necessary,
383 * increases it to the maximum MAX_BASE64_LEN
384 *
385 * /p b64 pointer to the pointer of the buffer for input data
386 * /p max_len pointer to the current buffer capacity. It can be changed if
387 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100388 *
389 * \retval number of bytes written in to the b64 buffer or 0 in case no more
390 * data was found
391 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200392size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100393{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200394 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100395 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100396 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000397 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100398
399 while( EOF != c )
400 {
401 char c_valid = 0;
402
Nayna Jaind696e7d2020-08-13 19:17:53 +0000403 c = fgetc( b64_file );
Piotr Nowicki14d31052020-03-16 14:05:22 +0100404
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200405 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100406 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200407 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100408 {
409 c_valid = 1;
410 pad = 2;
411 }
412 }
413 else if( ( c >= 'A' && c <= 'Z' ) ||
414 ( c >= 'a' && c <= 'z' ) ||
415 ( c >= '0' && c <= '9' ) ||
416 c == '+' || c == '/' )
417 {
418 c_valid = 1;
419 }
420 else if( c == '=' )
421 {
422 c_valid = 1;
423 pad = 1;
424 }
425 else if( c == '-' )
426 {
427 c = '+';
428 c_valid = 1;
429 }
430 else if( c == '_' )
431 {
432 c = '/';
433 c_valid = 1;
434 }
435
436 if( c_valid )
437 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200438 /* A string of characters that could be a base64 code. */
439 valid_balance++;
440
441 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100442 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200443 ( *b64 )[ len++ ] = c;
444 }
445 else if( *max_len < MAX_BASE64_LEN )
446 {
447 /* Current buffer is too small, but can be resized. */
448 void *ptr;
449 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
450 *max_len + 4096 : MAX_BASE64_LEN;
451
452 ptr = realloc( *b64, new_size );
453 if( NULL == ptr )
454 {
455 printf_err( alloc_err );
456 return 0;
457 }
458 *b64 = ptr;
459 *max_len = new_size;
460 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100461 }
462 else
463 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200464 /* Too much data so it will be treated as invalid */
465 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100466 }
467 }
468 else if( len > 0 )
469 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200470 /* End of a string that could be a base64 code, but need to check
471 * that the length of the characters is correct. */
472
473 valid_balance--;
474
475 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100476 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200477 printf_dbg( "The code found is too small to be a SSL context.\n" );
478 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100479 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200480 else if( len > *max_len )
481 {
Paul Elliott8f20bab2021-12-09 14:48:47 +0000482 printf_err( "The code found is too large by %" MBEDTLS_PRINTF_SIZET " bytes.\n",
483 len - *max_len );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200484 len = pad = 0;
485 }
486 else if( len % 4 != 0 )
487 {
488 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
489 len = pad = 0;
490 }
491 else
492 {
493 /* Base64 code with valid character length. */
494 return len;
495 }
496 }
497 else
498 {
499 valid_balance--;
500 }
501
502 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
503 if( valid_balance < -100 )
504 {
505 printf_err( "Too many bad symbols detected. File check aborted.\n" );
506 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100507 }
508 }
509
510 printf_dbg( "End of file\n" );
511 return 0;
512}
513
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100514/*
515 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100516 * about the certificates from provided data.
517 *
518 * /p ssl pointer to serialized certificate
519 * /p len number of bytes in the buffer
520*/
521void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
522{
523 enum { STRLEN = 4096 };
524 mbedtls_x509_crt crt;
525 int ret;
526 char str[STRLEN];
527
528 printf( "\nCertificate:\n" );
529
530 mbedtls_x509_crt_init( &crt );
531 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
532 if( 0 != ret )
533 {
534 mbedtls_strerror( ret, str, STRLEN );
535 printf_err( "Invalid format of X.509 - %s\n", str );
536 printf( "Cannot deserialize:\n\t" );
537 print_hex( ssl, len, 25, "\t" );
538 }
539 else
540 {
541 mbedtls_x509_crt *current = &crt;
542
543 while( current != NULL )
544 {
545 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
546 if( 0 > ret )
547 {
548 mbedtls_strerror( ret, str, STRLEN );
549 printf_err( "Cannot write to the output - %s\n", str );
550 }
551 else
552 {
553 printf( "%s", str );
554 }
555
556 current = current->next;
557
558 if( current )
559 {
560 printf( "\n" );
561 }
562
563 }
564 }
565
566 mbedtls_x509_crt_free( &crt );
567}
568
569/*
570 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100571 * about the session from provided data. This function was built based on
572 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
573 * due to dependencies on the mbedTLS configuration.
574 *
575 * The data structure in the buffer:
576 * uint64 start_time;
577 * uint8 ciphersuite[2]; // defined by the standard
578 * uint8 compression; // 0 or 1
579 * uint8 session_id_len; // at most 32
580 * opaque session_id[32];
581 * opaque master[48]; // fixed length in the standard
582 * uint32 verify_result;
583 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
584 * opaque ticket<0..2^24-1>; // length 0 means no ticket
585 * uint32 ticket_lifetime;
586 * uint8 mfl_code; // up to 255 according to standard
587 * uint8 trunc_hmac; // 0 or 1
588 * uint8 encrypt_then_mac; // 0 or 1
589 *
590 * /p ssl pointer to serialized session
591 * /p len number of bytes in the buffer
592 * /p session_cfg_flag session configuration flags
593 */
594void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
595 int session_cfg_flag )
596{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100597 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
598 int ciphersuite_id;
599 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100600 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100601 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100602
603 printf( "\nSession info:\n" );
604
605 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
606 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100607 uint64_t start;
608 CHECK_SSL_END( 8 );
609 start = ( (uint64_t) ssl[0] << 56 ) |
610 ( (uint64_t) ssl[1] << 48 ) |
611 ( (uint64_t) ssl[2] << 40 ) |
612 ( (uint64_t) ssl[3] << 32 ) |
613 ( (uint64_t) ssl[4] << 24 ) |
614 ( (uint64_t) ssl[5] << 16 ) |
615 ( (uint64_t) ssl[6] << 8 ) |
616 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100617 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100618 printf( "\tstart time : " );
Andrzej Kurek478181d2022-02-28 05:51:57 -0500619 print_time( &start );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100620 }
621
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100622 CHECK_SSL_END( 2 );
623 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
624 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100625 ssl += 2;
626
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100627 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
628 if( ciphersuite_info == NULL )
629 {
630 printf_err( "Cannot find ciphersuite info\n" );
631 }
632 else
633 {
634 const mbedtls_cipher_info_t *cipher_info;
635 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100636
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100637 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
638 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
639
640 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
641 if( cipher_info == NULL )
642 {
643 printf_err( "Cannot find cipher info\n" );
644 }
645 else
646 {
647 printf( "\tcipher : %s\n", cipher_info->name );
648 }
649
650 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
651 if( md_info == NULL )
652 {
653 printf_err( "Cannot find Message-Digest info\n" );
654 }
655 else
656 {
657 printf( "\tMessage-Digest : %s\n", md_info->name );
658 }
659 }
660
661 CHECK_SSL_END( 1 );
662 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
663
664 /* Note - Here we can get session ID length from serialized data, but we
665 * use hardcoded 32-bytes length. This approach was taken from
666 * 'mbedtls_ssl_session_load()'. */
667 CHECK_SSL_END( 1 + 32 );
668 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
669 printf( "\tsession ID : ");
670 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100671 ssl += 32;
672
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100673 printf( "\tmaster secret : ");
674 CHECK_SSL_END( 48 );
675 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100676 ssl += 48;
677
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100678 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100679 verify_result = ( (uint32_t) ssl[0] << 24 ) |
680 ( (uint32_t) ssl[1] << 16 ) |
681 ( (uint32_t) ssl[2] << 8 ) |
682 ( (uint32_t) ssl[3] );
683 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100684 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100685
686 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
687 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100688 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100689 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100690 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100691 cert_len = ( (uint32_t) ssl[0] << 16 ) |
692 ( (uint32_t) ssl[1] << 8 ) |
693 ( (uint32_t) ssl[2] );
694 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100695 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100696
697 if( cert_len > 0 )
698 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100699 CHECK_SSL_END( cert_len );
700 print_deserialized_ssl_cert( ssl, cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100701 ssl += cert_len;
702 }
703 }
704 else
705 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100706 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100707
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100708 CHECK_SSL_END( 1 );
709 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100710 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100711 case MBEDTLS_MD_NONE:
712 printf( "none\n" );
713 break;
714 case MBEDTLS_MD_MD2:
715 printf( "MD2\n" );
716 break;
717 case MBEDTLS_MD_MD4:
718 printf( "MD4\n" );
719 break;
720 case MBEDTLS_MD_MD5:
721 printf( "MD5\n" );
722 break;
723 case MBEDTLS_MD_SHA1:
724 printf( "SHA1\n" );
725 break;
726 case MBEDTLS_MD_SHA224:
727 printf( "SHA224\n" );
728 break;
729 case MBEDTLS_MD_SHA256:
730 printf( "SHA256\n" );
731 break;
732 case MBEDTLS_MD_SHA384:
733 printf( "SHA384\n" );
734 break;
735 case MBEDTLS_MD_SHA512:
736 printf( "SHA512\n" );
737 break;
738 case MBEDTLS_MD_RIPEMD160:
739 printf( "RIPEMD160\n" );
740 break;
741 default:
742 printf( "undefined or erroneous\n" );
743 break;
744 }
745
746 CHECK_SSL_END( 1 );
747 cert_len = (uint32_t) *ssl++;
748 printf_dbg( "Message-Digest length: %u\n", cert_len );
749
750 if( cert_len > 0 )
751 {
752 printf( "\tPeer digest cert : " );
753 CHECK_SSL_END( cert_len );
754 print_hex( ssl, cert_len, 16, "\t " );
755 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100756 }
757 }
758 }
759
760 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
761 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100762 printf( "\nTicket:\n" );
763
764 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100765 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
766 ( (uint32_t) ssl[1] << 8 ) |
767 ( (uint32_t) ssl[2] );
768 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100769 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100770
771 if( ticket_len > 0 )
772 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100773 printf( "\t" );
774 CHECK_SSL_END( ticket_len );
775 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100776 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100777 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100778 }
779
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100780 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100781 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
782 ( (uint32_t) ssl[1] << 16 ) |
783 ( (uint32_t) ssl[2] << 8 ) |
784 ( (uint32_t) ssl[3] );
785 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100786 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
787 }
788
789 if( ssl < end )
790 {
791 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100792 }
793
794 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
795 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100796 CHECK_SSL_END( 1 );
797 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100798 }
799
800 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
801 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100802 CHECK_SSL_END( 1 );
803 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100804 }
805
806 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
807 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100808 CHECK_SSL_END( 1 );
809 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100810 }
811
812 if( 0 != ( end - ssl ) )
813 {
814 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
815 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100816}
817
818/*
819 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100820 * about the context from provided data. This function was built based on
821 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
822 * due to dependencies on the mbedTLS configuration and the configuration of
823 * the context when serialization was created.
824 *
825 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200826 * // header
827 * uint8 version[3];
828 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100829 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200830 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100831 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
832 * // transform sub-structure
833 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200834 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100835 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200836 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100837 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
838 * // fields from ssl_context
839 * uint32 badmac_seen; // DTLS: number of records with failing MAC
840 * uint64 in_window_top; // DTLS: last validated record seq_num
841 * uint64 in_window; // DTLS: bitmask for replay protection
842 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
843 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
844 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200845 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100846 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
847 *
848 * /p ssl pointer to serialized session
849 * /p len number of bytes in the buffer
850 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100851void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100852{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100853 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100854 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100855 int session_cfg_flag;
856 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100857
858 printf( "\nMbed TLS version:\n" );
859
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100860 CHECK_SSL_END( 3 + 2 + 3 );
861
862 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
863 printf( "\tminor %u\n", (uint32_t) *ssl++ );
864 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100865
866 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100867
868 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
869 ssl += 2;
870
871 context_cfg_flag = ( (int) ssl[0] << 16 ) |
872 ( (int) ssl[1] << 8 ) |
873 ( (int) ssl[2] ) ;
874 ssl += 3;
875
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100876 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
877 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
878
879 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
880 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
881 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
882 print_if_bit( "MBEDTLS_SSL_TRUNCATED_HMAC", SESSION_CONFIG_TRUNC_HMAC_BIT, session_cfg_flag );
883 print_if_bit( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag );
884 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag );
885 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS and client", SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag );
886
887 print_if_bit( "MBEDTLS_SSL_DTLS_CONNECTION_ID", CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag );
888 print_if_bit( "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT, context_cfg_flag );
889 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
890 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
891
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100892 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100893 session_len = ( (uint32_t) ssl[0] << 24 ) |
894 ( (uint32_t) ssl[1] << 16 ) |
895 ( (uint32_t) ssl[2] << 8 ) |
896 ( (uint32_t) ssl[3] );
897 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100898 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100899
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100900 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100901 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
902 ssl += session_len;
903
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100904 printf( "\nRandom bytes:\n\t");
905
906 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
907 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100908 ssl += TRANSFORM_RANDBYTE_LEN;
909
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100910 printf( "\nContext others:\n" );
911
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100912 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
913 {
914 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100915
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100916 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100917 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100918 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100919
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100920 printf( "\tin CID : " );
921 if( cid_len > 0 )
922 {
923 CHECK_SSL_END( cid_len );
924 print_hex( ssl, cid_len, 20, "\t" );
925 ssl += cid_len;
926 }
927 else
928 {
929 printf( "none\n" );
930 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100931
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100932 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100933 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100934 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100935
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100936 printf( "\tout CID : " );
937 if( cid_len > 0 )
938 {
939 CHECK_SSL_END( cid_len );
940 print_hex( ssl, cid_len, 20, "\t" );
941 ssl += cid_len;
942 }
943 else
944 {
945 printf( "none\n" );
946 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100947 }
948
949 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
950 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100951 uint32_t badmac_seen;
952
953 CHECK_SSL_END( 4 );
954 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
955 ( (uint32_t) ssl[1] << 16 ) |
956 ( (uint32_t) ssl[2] << 8 ) |
957 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100958 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100959 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100960
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100961 /* value 'in_window_top' from mbedtls_ssl_context */
962 printf( "\tlast validated record sequence no. : " );
963 CHECK_SSL_END( 8 );
964 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100965 ssl += 8;
966
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100967 /* value 'in_window' from mbedtls_ssl_context */
968 printf( "\tbitmask for replay detection : " );
969 CHECK_SSL_END( 8 );
970 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100971 ssl += 8;
972 }
973
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100974 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100975 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100976 CHECK_SSL_END( 1 );
977 printf( "\tDTLS datagram packing : %s\n",
978 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100979 }
980
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100981 /* value 'cur_out_ctr' from mbedtls_ssl_context */
982 printf( "\toutgoing record sequence no. : ");
983 CHECK_SSL_END( 8 );
984 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100985 ssl += 8;
986
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100987 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100988 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100989 uint16_t mtu;
990 CHECK_SSL_END( 2 );
991 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100992 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100993 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100994 }
995
996
997 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
998 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100999 uint8_t alpn_len;
1000
1001 CHECK_SSL_END( 1 );
1002 alpn_len = *ssl++;
1003 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
1004
1005 printf( "\tALPN negotiation : " );
1006 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001007 if( alpn_len > 0 )
1008 {
1009 if( strlen( (const char*) ssl ) == alpn_len )
1010 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001011 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001012 }
1013 else
1014 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001015 printf( "\n" );
1016 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001017 }
1018 ssl += alpn_len;
1019 }
1020 else
1021 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001022 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001023 }
1024 }
1025
Piotr Nowicki4e192002020-03-18 17:27:29 +01001026 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001027 {
Piotr Nowicki4e192002020-03-18 17:27:29 +01001028 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001029 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +01001030 printf( "\n" );
1031}
1032
Piotr Nowicki9370f902020-03-13 14:43:22 +01001033int main( int argc, char *argv[] )
1034{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001035 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001036
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001037 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001038 uint8_t *b64_buf = NULL;
1039 uint8_t *ssl_buf = NULL;
1040 size_t b64_max_len = SSL_INIT_LEN;
1041 size_t ssl_max_len = SSL_INIT_LEN;
1042 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001043
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001044 /* The 'b64_file' is opened when parsing arguments to check that the
1045 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001046 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001047
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001048 if( NULL != b64_file )
1049 {
1050 b64_buf = malloc( SSL_INIT_LEN );
1051 ssl_buf = malloc( SSL_INIT_LEN );
1052
1053 if( NULL == b64_buf || NULL == ssl_buf )
1054 {
1055 printf_err( alloc_err );
1056 fclose( b64_file );
1057 b64_file = NULL;
1058 }
1059 }
1060
Piotr Nowicki14d31052020-03-16 14:05:22 +01001061 while( NULL != b64_file )
1062 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001063 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001064 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001065 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001066 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001067 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1068
1069 /* Allocate more memory if necessary. */
1070 if( ssl_required_len > ssl_max_len )
1071 {
1072 void *ptr = realloc( ssl_buf, ssl_required_len );
1073 if( NULL == ptr )
1074 {
1075 printf_err( alloc_err );
1076 fclose( b64_file );
1077 b64_file = NULL;
1078 break;
1079 }
1080 ssl_buf = ptr;
1081 ssl_max_len = ssl_required_len;
1082 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001083
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001084 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001085
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001086 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001087 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001088
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001089 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001090 if( ret != 0)
1091 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001092 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1093 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001094 continue;
1095 }
1096
1097 if( debug )
1098 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001099 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001100 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001101 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001102
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001103 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001104
Piotr Nowicki14d31052020-03-16 14:05:22 +01001105 }
1106 else
1107 {
1108 fclose( b64_file );
1109 b64_file = NULL;
1110 }
1111 }
1112
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001113 free( b64_buf );
1114 free( ssl_buf );
1115
1116 if( b64_counter > 0 )
1117 {
1118 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1119 }
1120 else
1121 {
1122 printf( "Finished. No valid base64 code found\n" );
1123 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001124
Piotr Nowicki9370f902020-03-13 14:43:22 +01001125 return 0;
1126}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001127
1128#endif /* MBEDTLS_X509_CRT_PARSE_C */