blob: 4a7c773407cd1be31451ad951bcb4ae5423caefd [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
25
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010026#include <stdio.h>
27#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020028
Gilles Peskinef4a6a052020-11-09 14:55:35 +010029#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
30 !defined(MBEDTLS_SSL_TLS_C)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020031int main( void )
32{
Gilles Peskinef4a6a052020-11-09 14:55:35 +010033 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
34 "MBEDTLS_SSL_TLS_C not defined.\n");
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020035 return( 0 );
36}
37#else
38
39#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
40#define _CRT_SECURE_NO_DEPRECATE 1
41#endif
42
Piotr Nowicki14d31052020-03-16 14:05:22 +010043#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010044#include <stdarg.h>
45#include <string.h>
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010046#include <time.h>
47#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010048#include "mbedtls/error.h"
49#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010050#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010051#include "mbedtls/x509_crt.h"
52#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010053
54/*
55 * This program version
56 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010057#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010058#define VER_MAJOR 0
59#define VER_MINOR 1
60
61/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020062 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010063 */
64#define SESSION_CONFIG_TIME_BIT ( 1 << 0 )
65#define SESSION_CONFIG_CRT_BIT ( 1 << 1 )
66#define SESSION_CONFIG_CLIENT_TICKET_BIT ( 1 << 2 )
67#define SESSION_CONFIG_MFL_BIT ( 1 << 3 )
68#define SESSION_CONFIG_TRUNC_HMAC_BIT ( 1 << 4 )
69#define SESSION_CONFIG_ETM_BIT ( 1 << 5 )
70#define SESSION_CONFIG_TICKET_BIT ( 1 << 6 )
71
72#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ( 1 << 0 )
73#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ( 1 << 1 )
74#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ( 1 << 2 )
75#define CONTEXT_CONFIG_ALPN_BIT ( 1 << 3 )
76
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010077#define TRANSFORM_RANDBYTE_LEN 64
78
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010079/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020080 * Minimum and maximum number of bytes for specific data: context, sessions,
81 * certificates, tickets and buffers in the program. The context and session
82 * size values have been calculated based on the 'print_deserialized_ssl_context()'
83 * and 'print_deserialized_ssl_session()' content.
84 */
85#define MIN_CONTEXT_LEN 84
86#define MIN_SESSION_LEN 88
87
88#define MAX_CONTEXT_LEN 875 /* without session data */
89#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
90#define MAX_CERTIFICATE_LEN ( ( 1 << 24 ) - 1 )
91#define MAX_TICKET_LEN ( ( 1 << 24 ) - 1 )
92
93#define MIN_SERIALIZED_DATA ( MIN_CONTEXT_LEN + MIN_SESSION_LEN )
94#define MAX_SERIALIZED_DATA ( MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
95 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN )
96
97#define MIN_BASE64_LEN ( MIN_SERIALIZED_DATA * 4 / 3 )
98#define MAX_BASE64_LEN ( MAX_SERIALIZED_DATA * 4 / 3 + 3 )
99
100/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100101 * A macro that prevents from reading out of the ssl buffer range.
102 */
103#define CHECK_SSL_END( LEN ) \
104do \
105{ \
106 if( end - ssl < (int)( LEN ) ) \
107 { \
108 printf_err( "%s", buf_ln_err ); \
109 return; \
110 } \
111} while( 0 )
112
113/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100114 * Global values
115 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100116FILE *b64_file = NULL; /* file with base64 codes to deserialize */
117char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
118char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
119char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200120const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100121const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100122
123/*
124 * Basic printing functions
125 */
126void print_version( )
127{
128 printf( "%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR );
129}
130
131void print_usage( )
132{
133 print_version();
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200134 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 +0100135 "in the text file. The program can deserialize many codes from one file, but they must be\n"
136 "separated, e.g. by a newline.\n\n" );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100137 printf(
138 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100139 "\t-f path - Path to the file with base64 code\n"
140 "\t-v - Show version\n"
141 "\t-h - Show this usage\n"
142 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200143 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100144 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
145 "\t flag. You can also use it if there are some problems with reading\n"
146 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200147 "\t--dtls-protocol=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 without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100149 "\n"
150 );
151}
152
153void printf_dbg( const char *str, ... )
154{
155 if( debug )
156 {
157 va_list args;
158 va_start( args, str );
159 printf( "debug: " );
160 vprintf( str, args );
161 fflush( stdout );
162 va_end( args );
163 }
164}
165
166void 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
224 if( ( b64_file = fopen( argv[i], "r" ) ) == NULL )
225 {
226 printf_err( "Cannot find file \"%s\"\n", argv[i] );
227 error_exit();
228 }
229 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100230 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
231 {
232 conf_keep_peer_certificate = 0;
233 }
234 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
235 {
236 conf_dtls_proto = 0;
237 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100238 else
239 {
240 print_usage();
241 error_exit();
242 }
243
244 i++;
245 }
246}
247
Piotr Nowicki14d31052020-03-16 14:05:22 +0100248/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100249 * This function prints base64 code to the stdout
250 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100251void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100252{
253 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100254 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100255 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100256 while( b < end )
257 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100258 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100259 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100260 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100261 i = 0;
262 }
263 printf( "%c", *b++ );
264 }
265 printf( "\n" );
266 fflush( stdout );
267}
268
269/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100270 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100271 *
272 * /p b buffer with data to print
273 * /p len number of bytes to print
274 * /p in_line number of bytes in one line
275 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100276 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100277void print_hex( const uint8_t *b, size_t len,
278 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100279{
280 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100281 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100282
283 if( prefix == NULL )
284 {
285 prefix = "";
286 }
287
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100288 while( b < end )
289 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100290 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100291 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100292 printf( "\n%s", prefix );
293 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100294 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100295 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100296 }
297 printf("\n");
298 fflush(stdout);
299}
300
301/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100302 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
303 */
304void print_time( const time_t *time )
305{
306 char buf[20];
307 struct tm *t = gmtime( time );
308 static const char format[] = "%Y-%m-%d %H:%M:%S";
309 if( NULL != t )
310 {
311 strftime( buf, sizeof( buf ), format, t );
312 printf( "%s\n", buf );
313 }
314 else
315 {
316 printf( "unknown\n" );
317 }
318}
319
320/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100321 * Print the input string if the bit is set in the value
322 */
323void print_if_bit( const char *str, int bit, int val )
324{
325 if( bit & val )
326 {
327 printf( "\t%s\n", str );
328 }
329}
330
331/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100332 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
333 */
334const char * get_enabled_str( int is_en )
335{
336 return ( is_en ) ? "enabled" : "disabled";
337}
338
339/*
340 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
341 */
342const char * get_mfl_str( int mfl_code )
343{
344 switch( mfl_code )
345 {
346 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
347 return "none";
348 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
349 return "512";
350 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
351 return "1024";
352 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
353 return "2048";
354 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
355 return "4096";
356 default:
357 return "error";
358 }
359}
360
361/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100362 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
363 * previously. After each call to this function, the internal file position
364 * indicator of the global b64_file is advanced.
365 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200366 * Note - This function checks the size of the input buffer and if necessary,
367 * increases it to the maximum MAX_BASE64_LEN
368 *
369 * /p b64 pointer to the pointer of the buffer for input data
370 * /p max_len pointer to the current buffer capacity. It can be changed if
371 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100372 *
373 * \retval number of bytes written in to the b64 buffer or 0 in case no more
374 * data was found
375 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200376size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100377{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200378 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100379 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100380 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000381 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100382
383 while( EOF != c )
384 {
385 char c_valid = 0;
386
Nayna Jaind696e7d2020-08-13 19:17:53 +0000387 c = fgetc( b64_file );
Piotr Nowicki14d31052020-03-16 14:05:22 +0100388
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200389 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100390 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200391 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100392 {
393 c_valid = 1;
394 pad = 2;
395 }
396 }
397 else if( ( c >= 'A' && c <= 'Z' ) ||
398 ( c >= 'a' && c <= 'z' ) ||
399 ( c >= '0' && c <= '9' ) ||
400 c == '+' || c == '/' )
401 {
402 c_valid = 1;
403 }
404 else if( c == '=' )
405 {
406 c_valid = 1;
407 pad = 1;
408 }
409 else if( c == '-' )
410 {
411 c = '+';
412 c_valid = 1;
413 }
414 else if( c == '_' )
415 {
416 c = '/';
417 c_valid = 1;
418 }
419
420 if( c_valid )
421 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200422 /* A string of characters that could be a base64 code. */
423 valid_balance++;
424
425 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100426 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200427 ( *b64 )[ len++ ] = c;
428 }
429 else if( *max_len < MAX_BASE64_LEN )
430 {
431 /* Current buffer is too small, but can be resized. */
432 void *ptr;
433 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
434 *max_len + 4096 : MAX_BASE64_LEN;
435
436 ptr = realloc( *b64, new_size );
437 if( NULL == ptr )
438 {
439 printf_err( alloc_err );
440 return 0;
441 }
442 *b64 = ptr;
443 *max_len = new_size;
444 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100445 }
446 else
447 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200448 /* Too much data so it will be treated as invalid */
449 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100450 }
451 }
452 else if( len > 0 )
453 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200454 /* End of a string that could be a base64 code, but need to check
455 * that the length of the characters is correct. */
456
457 valid_balance--;
458
459 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100460 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200461 printf_dbg( "The code found is too small to be a SSL context.\n" );
462 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100463 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200464 else if( len > *max_len )
465 {
466 printf_err( "The code found is too large by %u bytes.\n", len - *max_len );
467 len = pad = 0;
468 }
469 else if( len % 4 != 0 )
470 {
471 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
472 len = pad = 0;
473 }
474 else
475 {
476 /* Base64 code with valid character length. */
477 return len;
478 }
479 }
480 else
481 {
482 valid_balance--;
483 }
484
485 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
486 if( valid_balance < -100 )
487 {
488 printf_err( "Too many bad symbols detected. File check aborted.\n" );
489 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100490 }
491 }
492
493 printf_dbg( "End of file\n" );
494 return 0;
495}
496
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100497/*
498 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100499 * about the certificates from provided data.
500 *
501 * /p ssl pointer to serialized certificate
502 * /p len number of bytes in the buffer
503*/
504void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
505{
506 enum { STRLEN = 4096 };
507 mbedtls_x509_crt crt;
508 int ret;
509 char str[STRLEN];
510
511 printf( "\nCertificate:\n" );
512
513 mbedtls_x509_crt_init( &crt );
514 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
515 if( 0 != ret )
516 {
517 mbedtls_strerror( ret, str, STRLEN );
518 printf_err( "Invalid format of X.509 - %s\n", str );
519 printf( "Cannot deserialize:\n\t" );
520 print_hex( ssl, len, 25, "\t" );
521 }
522 else
523 {
524 mbedtls_x509_crt *current = &crt;
525
526 while( current != NULL )
527 {
528 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
529 if( 0 > ret )
530 {
531 mbedtls_strerror( ret, str, STRLEN );
532 printf_err( "Cannot write to the output - %s\n", str );
533 }
534 else
535 {
536 printf( "%s", str );
537 }
538
539 current = current->next;
540
541 if( current )
542 {
543 printf( "\n" );
544 }
545
546 }
547 }
548
549 mbedtls_x509_crt_free( &crt );
550}
551
552/*
553 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100554 * about the session from provided data. This function was built based on
555 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
556 * due to dependencies on the mbedTLS configuration.
557 *
558 * The data structure in the buffer:
559 * uint64 start_time;
560 * uint8 ciphersuite[2]; // defined by the standard
561 * uint8 compression; // 0 or 1
562 * uint8 session_id_len; // at most 32
563 * opaque session_id[32];
564 * opaque master[48]; // fixed length in the standard
565 * uint32 verify_result;
566 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
567 * opaque ticket<0..2^24-1>; // length 0 means no ticket
568 * uint32 ticket_lifetime;
569 * uint8 mfl_code; // up to 255 according to standard
570 * uint8 trunc_hmac; // 0 or 1
571 * uint8 encrypt_then_mac; // 0 or 1
572 *
573 * /p ssl pointer to serialized session
574 * /p len number of bytes in the buffer
575 * /p session_cfg_flag session configuration flags
576 */
577void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
578 int session_cfg_flag )
579{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100580 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
581 int ciphersuite_id;
582 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100583 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100584 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100585
586 printf( "\nSession info:\n" );
587
588 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
589 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100590 uint64_t start;
591 CHECK_SSL_END( 8 );
592 start = ( (uint64_t) ssl[0] << 56 ) |
593 ( (uint64_t) ssl[1] << 48 ) |
594 ( (uint64_t) ssl[2] << 40 ) |
595 ( (uint64_t) ssl[3] << 32 ) |
596 ( (uint64_t) ssl[4] << 24 ) |
597 ( (uint64_t) ssl[5] << 16 ) |
598 ( (uint64_t) ssl[6] << 8 ) |
599 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100600 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100601 printf( "\tstart time : " );
602 print_time( (time_t*) &start );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100603 }
604
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100605 CHECK_SSL_END( 2 );
606 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
607 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100608 ssl += 2;
609
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100610 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
611 if( ciphersuite_info == NULL )
612 {
613 printf_err( "Cannot find ciphersuite info\n" );
614 }
615 else
616 {
617 const mbedtls_cipher_info_t *cipher_info;
618 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100619
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100620 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
621 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
622
623 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
624 if( cipher_info == NULL )
625 {
626 printf_err( "Cannot find cipher info\n" );
627 }
628 else
629 {
630 printf( "\tcipher : %s\n", cipher_info->name );
631 }
632
633 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
634 if( md_info == NULL )
635 {
636 printf_err( "Cannot find Message-Digest info\n" );
637 }
638 else
639 {
Chris Jonesa1df4942021-03-11 17:44:43 +0000640 printf( "\tMessage-Digest : %s\n", mbedtls_md_get_name( md_info ) );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100641 }
642 }
643
644 CHECK_SSL_END( 1 );
645 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
646
647 /* Note - Here we can get session ID length from serialized data, but we
648 * use hardcoded 32-bytes length. This approach was taken from
649 * 'mbedtls_ssl_session_load()'. */
650 CHECK_SSL_END( 1 + 32 );
651 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
652 printf( "\tsession ID : ");
653 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100654 ssl += 32;
655
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100656 printf( "\tmaster secret : ");
657 CHECK_SSL_END( 48 );
658 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100659 ssl += 48;
660
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100661 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100662 verify_result = ( (uint32_t) ssl[0] << 24 ) |
663 ( (uint32_t) ssl[1] << 16 ) |
664 ( (uint32_t) ssl[2] << 8 ) |
665 ( (uint32_t) ssl[3] );
666 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100667 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100668
669 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
670 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100671 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100672 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100673 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100674 cert_len = ( (uint32_t) ssl[0] << 16 ) |
675 ( (uint32_t) ssl[1] << 8 ) |
676 ( (uint32_t) ssl[2] );
677 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100678 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100679
680 if( cert_len > 0 )
681 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100682 CHECK_SSL_END( cert_len );
683 print_deserialized_ssl_cert( ssl, cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100684 ssl += cert_len;
685 }
686 }
687 else
688 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100689 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100690
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100691 CHECK_SSL_END( 1 );
692 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100693 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100694 case MBEDTLS_MD_NONE:
695 printf( "none\n" );
696 break;
697 case MBEDTLS_MD_MD2:
698 printf( "MD2\n" );
699 break;
700 case MBEDTLS_MD_MD4:
701 printf( "MD4\n" );
702 break;
703 case MBEDTLS_MD_MD5:
704 printf( "MD5\n" );
705 break;
706 case MBEDTLS_MD_SHA1:
707 printf( "SHA1\n" );
708 break;
709 case MBEDTLS_MD_SHA224:
710 printf( "SHA224\n" );
711 break;
712 case MBEDTLS_MD_SHA256:
713 printf( "SHA256\n" );
714 break;
715 case MBEDTLS_MD_SHA384:
716 printf( "SHA384\n" );
717 break;
718 case MBEDTLS_MD_SHA512:
719 printf( "SHA512\n" );
720 break;
721 case MBEDTLS_MD_RIPEMD160:
722 printf( "RIPEMD160\n" );
723 break;
724 default:
725 printf( "undefined or erroneous\n" );
726 break;
727 }
728
729 CHECK_SSL_END( 1 );
730 cert_len = (uint32_t) *ssl++;
731 printf_dbg( "Message-Digest length: %u\n", cert_len );
732
733 if( cert_len > 0 )
734 {
735 printf( "\tPeer digest cert : " );
736 CHECK_SSL_END( cert_len );
737 print_hex( ssl, cert_len, 16, "\t " );
738 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100739 }
740 }
741 }
742
743 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
744 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100745 printf( "\nTicket:\n" );
746
747 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100748 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
749 ( (uint32_t) ssl[1] << 8 ) |
750 ( (uint32_t) ssl[2] );
751 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100752 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100753
754 if( ticket_len > 0 )
755 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100756 printf( "\t" );
757 CHECK_SSL_END( ticket_len );
758 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100759 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100760 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100761 }
762
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100763 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100764 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
765 ( (uint32_t) ssl[1] << 16 ) |
766 ( (uint32_t) ssl[2] << 8 ) |
767 ( (uint32_t) ssl[3] );
768 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100769 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
770 }
771
772 if( ssl < end )
773 {
774 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100775 }
776
777 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
778 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100779 CHECK_SSL_END( 1 );
780 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100781 }
782
783 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
784 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100785 CHECK_SSL_END( 1 );
786 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100787 }
788
789 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
790 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100791 CHECK_SSL_END( 1 );
792 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100793 }
794
795 if( 0 != ( end - ssl ) )
796 {
797 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
798 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100799}
800
801/*
802 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100803 * about the context from provided data. This function was built based on
804 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
805 * due to dependencies on the mbedTLS configuration and the configuration of
806 * the context when serialization was created.
807 *
808 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200809 * // header
810 * uint8 version[3];
811 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100812 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200813 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100814 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
815 * // transform sub-structure
816 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200817 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100818 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200819 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100820 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
821 * // fields from ssl_context
822 * uint32 badmac_seen; // DTLS: number of records with failing MAC
823 * uint64 in_window_top; // DTLS: last validated record seq_num
824 * uint64 in_window; // DTLS: bitmask for replay protection
825 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
826 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
827 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200828 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100829 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
830 *
831 * /p ssl pointer to serialized session
832 * /p len number of bytes in the buffer
833 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100834void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100835{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100836 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100837 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100838 int session_cfg_flag;
839 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100840
841 printf( "\nMbed TLS version:\n" );
842
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100843 CHECK_SSL_END( 3 + 2 + 3 );
844
845 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
846 printf( "\tminor %u\n", (uint32_t) *ssl++ );
847 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100848
849 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100850
851 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
852 ssl += 2;
853
854 context_cfg_flag = ( (int) ssl[0] << 16 ) |
855 ( (int) ssl[1] << 8 ) |
856 ( (int) ssl[2] ) ;
857 ssl += 3;
858
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100859 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
860 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
861
862 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
863 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
864 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
865 print_if_bit( "MBEDTLS_SSL_TRUNCATED_HMAC", SESSION_CONFIG_TRUNC_HMAC_BIT, session_cfg_flag );
866 print_if_bit( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag );
867 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag );
868 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS and client", SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag );
869
870 print_if_bit( "MBEDTLS_SSL_DTLS_CONNECTION_ID", CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag );
871 print_if_bit( "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT, context_cfg_flag );
872 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
873 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
874
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100875 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100876 session_len = ( (uint32_t) ssl[0] << 24 ) |
877 ( (uint32_t) ssl[1] << 16 ) |
878 ( (uint32_t) ssl[2] << 8 ) |
879 ( (uint32_t) ssl[3] );
880 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100881 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100882
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100883 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100884 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
885 ssl += session_len;
886
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100887 printf( "\nRandom bytes:\n\t");
888
889 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
890 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100891 ssl += TRANSFORM_RANDBYTE_LEN;
892
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100893 printf( "\nContext others:\n" );
894
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100895 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
896 {
897 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100898
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100899 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100900 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100901 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100902
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100903 printf( "\tin CID : " );
904 if( cid_len > 0 )
905 {
906 CHECK_SSL_END( cid_len );
907 print_hex( ssl, cid_len, 20, "\t" );
908 ssl += cid_len;
909 }
910 else
911 {
912 printf( "none\n" );
913 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100914
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100915 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100916 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100917 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100918
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100919 printf( "\tout CID : " );
920 if( cid_len > 0 )
921 {
922 CHECK_SSL_END( cid_len );
923 print_hex( ssl, cid_len, 20, "\t" );
924 ssl += cid_len;
925 }
926 else
927 {
928 printf( "none\n" );
929 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100930 }
931
932 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
933 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100934 uint32_t badmac_seen;
935
936 CHECK_SSL_END( 4 );
937 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
938 ( (uint32_t) ssl[1] << 16 ) |
939 ( (uint32_t) ssl[2] << 8 ) |
940 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100941 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100942 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100943
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100944 /* value 'in_window_top' from mbedtls_ssl_context */
945 printf( "\tlast validated record sequence no. : " );
946 CHECK_SSL_END( 8 );
947 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100948 ssl += 8;
949
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100950 /* value 'in_window' from mbedtls_ssl_context */
951 printf( "\tbitmask for replay detection : " );
952 CHECK_SSL_END( 8 );
953 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100954 ssl += 8;
955 }
956
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100957 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100958 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100959 CHECK_SSL_END( 1 );
960 printf( "\tDTLS datagram packing : %s\n",
961 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100962 }
963
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100964 /* value 'cur_out_ctr' from mbedtls_ssl_context */
965 printf( "\toutgoing record sequence no. : ");
966 CHECK_SSL_END( 8 );
967 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100968 ssl += 8;
969
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100970 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100971 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100972 uint16_t mtu;
973 CHECK_SSL_END( 2 );
974 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100975 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100976 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100977 }
978
979
980 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
981 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100982 uint8_t alpn_len;
983
984 CHECK_SSL_END( 1 );
985 alpn_len = *ssl++;
986 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
987
988 printf( "\tALPN negotiation : " );
989 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100990 if( alpn_len > 0 )
991 {
992 if( strlen( (const char*) ssl ) == alpn_len )
993 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100994 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100995 }
996 else
997 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100998 printf( "\n" );
999 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001000 }
1001 ssl += alpn_len;
1002 }
1003 else
1004 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001005 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001006 }
1007 }
1008
Piotr Nowicki4e192002020-03-18 17:27:29 +01001009 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001010 {
Piotr Nowicki4e192002020-03-18 17:27:29 +01001011 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001012 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +01001013 printf( "\n" );
1014}
1015
Piotr Nowicki9370f902020-03-13 14:43:22 +01001016int main( int argc, char *argv[] )
1017{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001018 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001019
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001020 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001021 uint8_t *b64_buf = NULL;
1022 uint8_t *ssl_buf = NULL;
1023 size_t b64_max_len = SSL_INIT_LEN;
1024 size_t ssl_max_len = SSL_INIT_LEN;
1025 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001026
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001027 /* The 'b64_file' is opened when parsing arguments to check that the
1028 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001029 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001030
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001031 if( NULL != b64_file )
1032 {
1033 b64_buf = malloc( SSL_INIT_LEN );
1034 ssl_buf = malloc( SSL_INIT_LEN );
1035
1036 if( NULL == b64_buf || NULL == ssl_buf )
1037 {
1038 printf_err( alloc_err );
1039 fclose( b64_file );
1040 b64_file = NULL;
1041 }
1042 }
1043
Piotr Nowicki14d31052020-03-16 14:05:22 +01001044 while( NULL != b64_file )
1045 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001046 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001047 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001048 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001049 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001050 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1051
1052 /* Allocate more memory if necessary. */
1053 if( ssl_required_len > ssl_max_len )
1054 {
1055 void *ptr = realloc( ssl_buf, ssl_required_len );
1056 if( NULL == ptr )
1057 {
1058 printf_err( alloc_err );
1059 fclose( b64_file );
1060 b64_file = NULL;
1061 break;
1062 }
1063 ssl_buf = ptr;
1064 ssl_max_len = ssl_required_len;
1065 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001066
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001067 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001068
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001069 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001070 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001071
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001072 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001073 if( ret != 0)
1074 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001075 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1076 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001077 continue;
1078 }
1079
1080 if( debug )
1081 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001082 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001083 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001084 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001085
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001086 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001087
Piotr Nowicki14d31052020-03-16 14:05:22 +01001088 }
1089 else
1090 {
1091 fclose( b64_file );
1092 b64_file = NULL;
1093 }
1094 }
1095
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001096 free( b64_buf );
1097 free( ssl_buf );
1098
1099 if( b64_counter > 0 )
1100 {
1101 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1102 }
1103 else
1104 {
1105 printf( "Finished. No valid base64 code found\n" );
1106 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001107
Piotr Nowicki9370f902020-03-13 14:43:22 +01001108 return 0;
1109}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001110
1111#endif /* MBEDTLS_X509_CRT_PARSE_C */