blob: df8819a804394940eba62a1bb099ced0eb71042d [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
29#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C)
30int main( void )
31{
32 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C not defined.\n");
33 return( 0 );
34}
35#else
36
37#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
38#define _CRT_SECURE_NO_DEPRECATE 1
39#endif
40
Piotr Nowicki14d31052020-03-16 14:05:22 +010041#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010042#include <stdarg.h>
43#include <string.h>
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010044#include <time.h>
45#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010046#include "mbedtls/error.h"
47#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010048#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010049#include "mbedtls/md_internal.h"
50#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
165void printf_err( const char *str, ... )
166{
167 va_list args;
168 va_start( args, str );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100169 fflush( stdout );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100170 fprintf( stderr, "ERROR: " );
171 vfprintf( stderr, str, args );
172 fflush( stderr );
173 va_end( args );
174}
175
176/*
177 * Exit from the program in case of error
178 */
179void error_exit()
180{
181 if( NULL != b64_file )
182 {
183 fclose( b64_file );
184 }
185 exit( -1 );
186}
187
188/*
189 * This function takes the input arguments of this program
190 */
191void parse_arguments( int argc, char *argv[] )
192{
193 int i = 1;
194
195 if( argc < 2 )
196 {
197 print_usage();
198 error_exit();
199 }
200
201 while( i < argc )
202 {
203 if( strcmp( argv[i], "-d" ) == 0 )
204 {
205 debug = 1;
206 }
207 else if( strcmp( argv[i], "-h" ) == 0 )
208 {
209 print_usage();
210 }
211 else if( strcmp( argv[i], "-v" ) == 0 )
212 {
213 print_version();
214 }
215 else if( strcmp( argv[i], "-f" ) == 0 )
216 {
217 if( ++i >= argc )
218 {
219 printf_err( "File path is empty\n" );
220 error_exit();
221 }
222
223 if( ( b64_file = fopen( argv[i], "r" ) ) == NULL )
224 {
225 printf_err( "Cannot find file \"%s\"\n", argv[i] );
226 error_exit();
227 }
228 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100229 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
230 {
231 conf_keep_peer_certificate = 0;
232 }
233 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
234 {
235 conf_dtls_proto = 0;
236 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100237 else
238 {
239 print_usage();
240 error_exit();
241 }
242
243 i++;
244 }
245}
246
Piotr Nowicki14d31052020-03-16 14:05:22 +0100247/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100248 * This function prints base64 code to the stdout
249 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100250void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100251{
252 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100253 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100254 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100255 while( b < end )
256 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100257 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100258 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100259 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100260 i = 0;
261 }
262 printf( "%c", *b++ );
263 }
264 printf( "\n" );
265 fflush( stdout );
266}
267
268/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100269 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100270 *
271 * /p b buffer with data to print
272 * /p len number of bytes to print
273 * /p in_line number of bytes in one line
274 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100275 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100276void print_hex( const uint8_t *b, size_t len,
277 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100278{
279 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100280 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100281
282 if( prefix == NULL )
283 {
284 prefix = "";
285 }
286
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100287 while( b < end )
288 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100289 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100290 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100291 printf( "\n%s", prefix );
292 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100293 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100294 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100295 }
296 printf("\n");
297 fflush(stdout);
298}
299
300/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100301 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
302 */
303void print_time( const time_t *time )
304{
305 char buf[20];
306 struct tm *t = gmtime( time );
307 static const char format[] = "%Y-%m-%d %H:%M:%S";
308 if( NULL != t )
309 {
310 strftime( buf, sizeof( buf ), format, t );
311 printf( "%s\n", buf );
312 }
313 else
314 {
315 printf( "unknown\n" );
316 }
317}
318
319/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100320 * Print the input string if the bit is set in the value
321 */
322void print_if_bit( const char *str, int bit, int val )
323{
324 if( bit & val )
325 {
326 printf( "\t%s\n", str );
327 }
328}
329
330/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100331 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
332 */
333const char * get_enabled_str( int is_en )
334{
335 return ( is_en ) ? "enabled" : "disabled";
336}
337
338/*
339 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
340 */
341const char * get_mfl_str( int mfl_code )
342{
343 switch( mfl_code )
344 {
345 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
346 return "none";
347 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
348 return "512";
349 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
350 return "1024";
351 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
352 return "2048";
353 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
354 return "4096";
355 default:
356 return "error";
357 }
358}
359
360/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100361 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
362 * previously. After each call to this function, the internal file position
363 * indicator of the global b64_file is advanced.
364 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200365 * Note - This function checks the size of the input buffer and if necessary,
366 * increases it to the maximum MAX_BASE64_LEN
367 *
368 * /p b64 pointer to the pointer of the buffer for input data
369 * /p max_len pointer to the current buffer capacity. It can be changed if
370 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100371 *
372 * \retval number of bytes written in to the b64 buffer or 0 in case no more
373 * data was found
374 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200375size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100376{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200377 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100378 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100379 char pad = 0;
380 char c = 0;
381
382 while( EOF != c )
383 {
384 char c_valid = 0;
385
386 c = (char) fgetc( b64_file );
387
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200388 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100389 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200390 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100391 {
392 c_valid = 1;
393 pad = 2;
394 }
395 }
396 else if( ( c >= 'A' && c <= 'Z' ) ||
397 ( c >= 'a' && c <= 'z' ) ||
398 ( c >= '0' && c <= '9' ) ||
399 c == '+' || c == '/' )
400 {
401 c_valid = 1;
402 }
403 else if( c == '=' )
404 {
405 c_valid = 1;
406 pad = 1;
407 }
408 else if( c == '-' )
409 {
410 c = '+';
411 c_valid = 1;
412 }
413 else if( c == '_' )
414 {
415 c = '/';
416 c_valid = 1;
417 }
418
419 if( c_valid )
420 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200421 /* A string of characters that could be a base64 code. */
422 valid_balance++;
423
424 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100425 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200426 ( *b64 )[ len++ ] = c;
427 }
428 else if( *max_len < MAX_BASE64_LEN )
429 {
430 /* Current buffer is too small, but can be resized. */
431 void *ptr;
432 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
433 *max_len + 4096 : MAX_BASE64_LEN;
434
435 ptr = realloc( *b64, new_size );
436 if( NULL == ptr )
437 {
438 printf_err( alloc_err );
439 return 0;
440 }
441 *b64 = ptr;
442 *max_len = new_size;
443 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100444 }
445 else
446 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200447 /* Too much data so it will be treated as invalid */
448 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100449 }
450 }
451 else if( len > 0 )
452 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200453 /* End of a string that could be a base64 code, but need to check
454 * that the length of the characters is correct. */
455
456 valid_balance--;
457
458 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100459 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200460 printf_dbg( "The code found is too small to be a SSL context.\n" );
461 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100462 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200463 else if( len > *max_len )
464 {
465 printf_err( "The code found is too large by %u bytes.\n", len - *max_len );
466 len = pad = 0;
467 }
468 else if( len % 4 != 0 )
469 {
470 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
471 len = pad = 0;
472 }
473 else
474 {
475 /* Base64 code with valid character length. */
476 return len;
477 }
478 }
479 else
480 {
481 valid_balance--;
482 }
483
484 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
485 if( valid_balance < -100 )
486 {
487 printf_err( "Too many bad symbols detected. File check aborted.\n" );
488 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100489 }
490 }
491
492 printf_dbg( "End of file\n" );
493 return 0;
494}
495
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100496/*
497 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100498 * about the certificates from provided data.
499 *
500 * /p ssl pointer to serialized certificate
501 * /p len number of bytes in the buffer
502*/
503void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
504{
505 enum { STRLEN = 4096 };
506 mbedtls_x509_crt crt;
507 int ret;
508 char str[STRLEN];
509
510 printf( "\nCertificate:\n" );
511
512 mbedtls_x509_crt_init( &crt );
513 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
514 if( 0 != ret )
515 {
516 mbedtls_strerror( ret, str, STRLEN );
517 printf_err( "Invalid format of X.509 - %s\n", str );
518 printf( "Cannot deserialize:\n\t" );
519 print_hex( ssl, len, 25, "\t" );
520 }
521 else
522 {
523 mbedtls_x509_crt *current = &crt;
524
525 while( current != NULL )
526 {
527 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
528 if( 0 > ret )
529 {
530 mbedtls_strerror( ret, str, STRLEN );
531 printf_err( "Cannot write to the output - %s\n", str );
532 }
533 else
534 {
535 printf( "%s", str );
536 }
537
538 current = current->next;
539
540 if( current )
541 {
542 printf( "\n" );
543 }
544
545 }
546 }
547
548 mbedtls_x509_crt_free( &crt );
549}
550
551/*
552 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100553 * about the session from provided data. This function was built based on
554 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
555 * due to dependencies on the mbedTLS configuration.
556 *
557 * The data structure in the buffer:
558 * uint64 start_time;
559 * uint8 ciphersuite[2]; // defined by the standard
560 * uint8 compression; // 0 or 1
561 * uint8 session_id_len; // at most 32
562 * opaque session_id[32];
563 * opaque master[48]; // fixed length in the standard
564 * uint32 verify_result;
565 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
566 * opaque ticket<0..2^24-1>; // length 0 means no ticket
567 * uint32 ticket_lifetime;
568 * uint8 mfl_code; // up to 255 according to standard
569 * uint8 trunc_hmac; // 0 or 1
570 * uint8 encrypt_then_mac; // 0 or 1
571 *
572 * /p ssl pointer to serialized session
573 * /p len number of bytes in the buffer
574 * /p session_cfg_flag session configuration flags
575 */
576void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
577 int session_cfg_flag )
578{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100579 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
580 int ciphersuite_id;
581 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100582 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100583 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100584
585 printf( "\nSession info:\n" );
586
587 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
588 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100589 uint64_t start;
590 CHECK_SSL_END( 8 );
591 start = ( (uint64_t) ssl[0] << 56 ) |
592 ( (uint64_t) ssl[1] << 48 ) |
593 ( (uint64_t) ssl[2] << 40 ) |
594 ( (uint64_t) ssl[3] << 32 ) |
595 ( (uint64_t) ssl[4] << 24 ) |
596 ( (uint64_t) ssl[5] << 16 ) |
597 ( (uint64_t) ssl[6] << 8 ) |
598 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100599 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100600 printf( "\tstart time : " );
601 print_time( (time_t*) &start );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100602 }
603
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100604 CHECK_SSL_END( 2 );
605 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
606 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100607 ssl += 2;
608
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100609 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
610 if( ciphersuite_info == NULL )
611 {
612 printf_err( "Cannot find ciphersuite info\n" );
613 }
614 else
615 {
616 const mbedtls_cipher_info_t *cipher_info;
617 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100618
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100619 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
620 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
621
622 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
623 if( cipher_info == NULL )
624 {
625 printf_err( "Cannot find cipher info\n" );
626 }
627 else
628 {
629 printf( "\tcipher : %s\n", cipher_info->name );
630 }
631
632 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
633 if( md_info == NULL )
634 {
635 printf_err( "Cannot find Message-Digest info\n" );
636 }
637 else
638 {
639 printf( "\tMessage-Digest : %s\n", md_info->name );
640 }
641 }
642
643 CHECK_SSL_END( 1 );
644 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
645
646 /* Note - Here we can get session ID length from serialized data, but we
647 * use hardcoded 32-bytes length. This approach was taken from
648 * 'mbedtls_ssl_session_load()'. */
649 CHECK_SSL_END( 1 + 32 );
650 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
651 printf( "\tsession ID : ");
652 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100653 ssl += 32;
654
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100655 printf( "\tmaster secret : ");
656 CHECK_SSL_END( 48 );
657 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100658 ssl += 48;
659
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100660 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100661 verify_result = ( (uint32_t) ssl[0] << 24 ) |
662 ( (uint32_t) ssl[1] << 16 ) |
663 ( (uint32_t) ssl[2] << 8 ) |
664 ( (uint32_t) ssl[3] );
665 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100666 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100667
668 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
669 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100670 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100671 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100672 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100673 cert_len = ( (uint32_t) ssl[0] << 16 ) |
674 ( (uint32_t) ssl[1] << 8 ) |
675 ( (uint32_t) ssl[2] );
676 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100677 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100678
679 if( cert_len > 0 )
680 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100681 CHECK_SSL_END( cert_len );
682 print_deserialized_ssl_cert( ssl, cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100683 ssl += cert_len;
684 }
685 }
686 else
687 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100688 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100689
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100690 CHECK_SSL_END( 1 );
691 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100692 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100693 case MBEDTLS_MD_NONE:
694 printf( "none\n" );
695 break;
696 case MBEDTLS_MD_MD2:
697 printf( "MD2\n" );
698 break;
699 case MBEDTLS_MD_MD4:
700 printf( "MD4\n" );
701 break;
702 case MBEDTLS_MD_MD5:
703 printf( "MD5\n" );
704 break;
705 case MBEDTLS_MD_SHA1:
706 printf( "SHA1\n" );
707 break;
708 case MBEDTLS_MD_SHA224:
709 printf( "SHA224\n" );
710 break;
711 case MBEDTLS_MD_SHA256:
712 printf( "SHA256\n" );
713 break;
714 case MBEDTLS_MD_SHA384:
715 printf( "SHA384\n" );
716 break;
717 case MBEDTLS_MD_SHA512:
718 printf( "SHA512\n" );
719 break;
720 case MBEDTLS_MD_RIPEMD160:
721 printf( "RIPEMD160\n" );
722 break;
723 default:
724 printf( "undefined or erroneous\n" );
725 break;
726 }
727
728 CHECK_SSL_END( 1 );
729 cert_len = (uint32_t) *ssl++;
730 printf_dbg( "Message-Digest length: %u\n", cert_len );
731
732 if( cert_len > 0 )
733 {
734 printf( "\tPeer digest cert : " );
735 CHECK_SSL_END( cert_len );
736 print_hex( ssl, cert_len, 16, "\t " );
737 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100738 }
739 }
740 }
741
742 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
743 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100744 printf( "\nTicket:\n" );
745
746 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100747 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
748 ( (uint32_t) ssl[1] << 8 ) |
749 ( (uint32_t) ssl[2] );
750 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100751 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100752
753 if( ticket_len > 0 )
754 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100755 printf( "\t" );
756 CHECK_SSL_END( ticket_len );
757 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100758 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100759 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100760 }
761
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100762 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100763 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
764 ( (uint32_t) ssl[1] << 16 ) |
765 ( (uint32_t) ssl[2] << 8 ) |
766 ( (uint32_t) ssl[3] );
767 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100768 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
769 }
770
771 if( ssl < end )
772 {
773 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100774 }
775
776 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
777 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100778 CHECK_SSL_END( 1 );
779 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100780 }
781
782 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
783 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100784 CHECK_SSL_END( 1 );
785 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100786 }
787
788 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
789 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100790 CHECK_SSL_END( 1 );
791 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100792 }
793
794 if( 0 != ( end - ssl ) )
795 {
796 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
797 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100798}
799
800/*
801 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100802 * about the context from provided data. This function was built based on
803 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
804 * due to dependencies on the mbedTLS configuration and the configuration of
805 * the context when serialization was created.
806 *
807 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200808 * // header
809 * uint8 version[3];
810 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100811 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200812 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100813 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
814 * // transform sub-structure
815 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200816 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100817 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200818 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100819 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
820 * // fields from ssl_context
821 * uint32 badmac_seen; // DTLS: number of records with failing MAC
822 * uint64 in_window_top; // DTLS: last validated record seq_num
823 * uint64 in_window; // DTLS: bitmask for replay protection
824 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
825 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
826 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200827 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100828 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
829 *
830 * /p ssl pointer to serialized session
831 * /p len number of bytes in the buffer
832 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100833void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100834{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100835 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100836 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100837 int session_cfg_flag;
838 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100839
840 printf( "\nMbed TLS version:\n" );
841
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100842 CHECK_SSL_END( 3 + 2 + 3 );
843
844 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
845 printf( "\tminor %u\n", (uint32_t) *ssl++ );
846 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100847
848 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100849
850 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
851 ssl += 2;
852
853 context_cfg_flag = ( (int) ssl[0] << 16 ) |
854 ( (int) ssl[1] << 8 ) |
855 ( (int) ssl[2] ) ;
856 ssl += 3;
857
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100858 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
859 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
860
861 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
862 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
863 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
864 print_if_bit( "MBEDTLS_SSL_TRUNCATED_HMAC", SESSION_CONFIG_TRUNC_HMAC_BIT, session_cfg_flag );
865 print_if_bit( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag );
866 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag );
867 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS and client", SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag );
868
869 print_if_bit( "MBEDTLS_SSL_DTLS_CONNECTION_ID", CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag );
870 print_if_bit( "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT, context_cfg_flag );
871 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
872 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
873
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100874 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100875 session_len = ( (uint32_t) ssl[0] << 24 ) |
876 ( (uint32_t) ssl[1] << 16 ) |
877 ( (uint32_t) ssl[2] << 8 ) |
878 ( (uint32_t) ssl[3] );
879 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100880 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100881
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100882 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100883 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
884 ssl += session_len;
885
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100886 printf( "\nRandom bytes:\n\t");
887
888 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
889 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100890 ssl += TRANSFORM_RANDBYTE_LEN;
891
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100892 printf( "\nContext others:\n" );
893
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100894 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
895 {
896 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100897
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100898 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100899 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100900 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100901
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100902 printf( "\tin CID : " );
903 if( cid_len > 0 )
904 {
905 CHECK_SSL_END( cid_len );
906 print_hex( ssl, cid_len, 20, "\t" );
907 ssl += cid_len;
908 }
909 else
910 {
911 printf( "none\n" );
912 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100913
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100914 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100915 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100916 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100917
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100918 printf( "\tout CID : " );
919 if( cid_len > 0 )
920 {
921 CHECK_SSL_END( cid_len );
922 print_hex( ssl, cid_len, 20, "\t" );
923 ssl += cid_len;
924 }
925 else
926 {
927 printf( "none\n" );
928 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100929 }
930
931 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
932 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100933 uint32_t badmac_seen;
934
935 CHECK_SSL_END( 4 );
936 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
937 ( (uint32_t) ssl[1] << 16 ) |
938 ( (uint32_t) ssl[2] << 8 ) |
939 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100940 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100941 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100942
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100943 /* value 'in_window_top' from mbedtls_ssl_context */
944 printf( "\tlast validated record sequence no. : " );
945 CHECK_SSL_END( 8 );
946 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100947 ssl += 8;
948
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100949 /* value 'in_window' from mbedtls_ssl_context */
950 printf( "\tbitmask for replay detection : " );
951 CHECK_SSL_END( 8 );
952 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100953 ssl += 8;
954 }
955
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100956 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100957 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100958 CHECK_SSL_END( 1 );
959 printf( "\tDTLS datagram packing : %s\n",
960 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100961 }
962
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100963 /* value 'cur_out_ctr' from mbedtls_ssl_context */
964 printf( "\toutgoing record sequence no. : ");
965 CHECK_SSL_END( 8 );
966 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100967 ssl += 8;
968
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100969 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100970 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100971 uint16_t mtu;
972 CHECK_SSL_END( 2 );
973 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100974 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100975 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100976 }
977
978
979 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
980 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100981 uint8_t alpn_len;
982
983 CHECK_SSL_END( 1 );
984 alpn_len = *ssl++;
985 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
986
987 printf( "\tALPN negotiation : " );
988 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100989 if( alpn_len > 0 )
990 {
991 if( strlen( (const char*) ssl ) == alpn_len )
992 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100993 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100994 }
995 else
996 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100997 printf( "\n" );
998 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100999 }
1000 ssl += alpn_len;
1001 }
1002 else
1003 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001004 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001005 }
1006 }
1007
Piotr Nowicki4e192002020-03-18 17:27:29 +01001008 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001009 {
Piotr Nowicki4e192002020-03-18 17:27:29 +01001010 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001011 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +01001012 printf( "\n" );
1013}
1014
Piotr Nowicki9370f902020-03-13 14:43:22 +01001015int main( int argc, char *argv[] )
1016{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001017 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001018
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001019 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001020 uint8_t *b64_buf = NULL;
1021 uint8_t *ssl_buf = NULL;
1022 size_t b64_max_len = SSL_INIT_LEN;
1023 size_t ssl_max_len = SSL_INIT_LEN;
1024 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001025
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001026 /* The 'b64_file' is opened when parsing arguments to check that the
1027 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001028 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001029
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001030 if( NULL != b64_file )
1031 {
1032 b64_buf = malloc( SSL_INIT_LEN );
1033 ssl_buf = malloc( SSL_INIT_LEN );
1034
1035 if( NULL == b64_buf || NULL == ssl_buf )
1036 {
1037 printf_err( alloc_err );
1038 fclose( b64_file );
1039 b64_file = NULL;
1040 }
1041 }
1042
Piotr Nowicki14d31052020-03-16 14:05:22 +01001043 while( NULL != b64_file )
1044 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001045 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001046 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001047 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001048 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001049 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1050
1051 /* Allocate more memory if necessary. */
1052 if( ssl_required_len > ssl_max_len )
1053 {
1054 void *ptr = realloc( ssl_buf, ssl_required_len );
1055 if( NULL == ptr )
1056 {
1057 printf_err( alloc_err );
1058 fclose( b64_file );
1059 b64_file = NULL;
1060 break;
1061 }
1062 ssl_buf = ptr;
1063 ssl_max_len = ssl_required_len;
1064 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001065
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001066 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001067
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001068 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001069 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001070
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001071 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001072 if( ret != 0)
1073 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001074 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1075 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001076 continue;
1077 }
1078
1079 if( debug )
1080 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001081 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001082 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001083 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001084
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001085 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001086
Piotr Nowicki14d31052020-03-16 14:05:22 +01001087 }
1088 else
1089 {
1090 fclose( b64_file );
1091 b64_file = NULL;
1092 }
1093 }
1094
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001095 free( b64_buf );
1096 free( ssl_buf );
1097
1098 if( b64_counter > 0 )
1099 {
1100 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1101 }
1102 else
1103 {
1104 printf( "Finished. No valid base64 code found\n" );
1105 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001106
Piotr Nowicki9370f902020-03-13 14:43:22 +01001107 return 0;
1108}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001109
1110#endif /* MBEDTLS_X509_CRT_PARSE_C */